xref: /csrg-svn/sys/ufs/lfs/lfs_syscalls.c (revision 51882)
1*51882Sbostic /*-
2*51882Sbostic  * Copyright (c) 1991 The Regents of the University of California.
3*51882Sbostic  * All rights reserved.
4*51882Sbostic  *
5*51882Sbostic  * %sccs.include.redist.c%
6*51882Sbostic  *
7*51882Sbostic  *	@(#)lfs_syscalls.c	7.1 (Berkeley) 12/11/91
8*51882Sbostic  */
9*51882Sbostic 
10*51882Sbostic #include <sys/param.h>
11*51882Sbostic #include <sys/proc.h>
12*51882Sbostic #include <sys/buf.h>
13*51882Sbostic #include <sys/mount.h>
14*51882Sbostic #include <sys/vnode.h>
15*51882Sbostic #include <sys/malloc.h>
16*51882Sbostic #include <sys/kernel.h>
17*51882Sbostic 
18*51882Sbostic #include <ufs/ufs/quota.h>
19*51882Sbostic #include <ufs/ufs/inode.h>
20*51882Sbostic #include <ufs/ufs/ufsmount.h>
21*51882Sbostic 
22*51882Sbostic #include <ufs/lfs/lfs.h>
23*51882Sbostic #include <ufs/lfs/lfs_extern.h>
24*51882Sbostic 
25*51882Sbostic /*
26*51882Sbostic  * lfs_markv:
27*51882Sbostic  *
28*51882Sbostic  * This will mark inodes and blocks dirty, so they are written into the log.
29*51882Sbostic  * It will block until all the blocks have been written.  The segment create
30*51882Sbostic  * time passed in the block_info and inode_info structures is used to decide
31*51882Sbostic  * if the data is valid for each block (in case some process dirtied a block
32*51882Sbostic  * or inode that is being cleaned between the determination that a block is
33*51882Sbostic  * live and the lfs_markv call).
34*51882Sbostic  *
35*51882Sbostic  *  0 on success
36*51882Sbostic  * -1/errno is return on error.
37*51882Sbostic  */
38*51882Sbostic int
39*51882Sbostic lfs_markv(p, uap, retval)
40*51882Sbostic 	struct proc *p;
41*51882Sbostic 	struct args {
42*51882Sbostic 		fsid_t fsid;		/* file system */
43*51882Sbostic 		BLOCK_INFO *blkiov;	/* block array */
44*51882Sbostic 		int blkcnt;		/* count of block array entries */
45*51882Sbostic 		INODE_INFO *inoiov;	/* inode array */
46*51882Sbostic 		int inocnt;		/* count of inode array entries */
47*51882Sbostic 	} *uap;
48*51882Sbostic 	int *retval;
49*51882Sbostic {
50*51882Sbostic 	BLOCK_INFO *blkp;
51*51882Sbostic 	IFILE *ifp;
52*51882Sbostic 	INODE_INFO *inop;
53*51882Sbostic 	struct buf *bp;
54*51882Sbostic 	struct lfs *fs;
55*51882Sbostic 	struct mount *mntp;
56*51882Sbostic 	struct vnode *vp;
57*51882Sbostic 	daddr_t daddr;
58*51882Sbostic 	u_long bsize;
59*51882Sbostic 	int cnt, error;
60*51882Sbostic 
61*51882Sbostic 	if (error = suser(p->p_ucred, &p->p_acflag))
62*51882Sbostic 		return (error);
63*51882Sbostic 
64*51882Sbostic 	if ((mntp = getvfs(&uap->fsid)) == NULL)
65*51882Sbostic 		return (EINVAL);
66*51882Sbostic 
67*51882Sbostic 	cnt = uap->blkcnt;
68*51882Sbostic 	blkp = malloc(cnt * sizeof(BLOCK_INFO), M_SEGMENT, M_WAITOK);
69*51882Sbostic 	if (error = copyin(uap->blkiov, blkp, cnt * sizeof(BLOCK_INFO))) {
70*51882Sbostic 		free(blkp, M_SEGMENT);
71*51882Sbostic 		return (error);
72*51882Sbostic 	}
73*51882Sbostic 
74*51882Sbostic 	/*
75*51882Sbostic 	 * Mark blocks/inodes dirty.  For blocks, we get the vnode, and check
76*51882Sbostic 	 * to see if the modified or disk address is newer than the cleaner
77*51882Sbostic 	 * thinks.  If so, we're done.  Otherwise, we get the block, from core
78*51882Sbostic 	 * if we have it, otherwise from the cleaner, and write it.  Note that
79*51882Sbostic 	 * errors are mostly ignored.  If we can't get the info, the block is
80*51882Sbostic 	 * probably not all that useful, and hopefully subsequent calls from
81*51882Sbostic 	 * the cleaner will fix everything.
82*51882Sbostic 	 */
83*51882Sbostic 	bsize = VFSTOUFS(mntp)->um_lfs->lfs_bsize;
84*51882Sbostic 	for (; cnt--; ++blkp) {
85*51882Sbostic 		if (lfs_vget(mntp, blkp->bi_inode, &vp) ||
86*51882Sbostic 		    VTOI(vp)->i_mtime >= blkp->bi_segcreate ||
87*51882Sbostic 		    lfs_bmap(vp, blkp->bi_lbn, NULL, &daddr) ||
88*51882Sbostic 		    daddr != blkp->bi_daddr)
89*51882Sbostic 			continue;
90*51882Sbostic 		bp = getblk(vp, blkp->bi_lbn, bsize);
91*51882Sbostic 		if (!(bp->b_flags & B_CACHE) &&
92*51882Sbostic 		    (error = copyin(blkp->bi_bp, bp->b_un.b_daddr, bsize))) {
93*51882Sbostic 			brelse(bp);
94*51882Sbostic 			free(blkp, M_SEGMENT);
95*51882Sbostic 			return (error);
96*51882Sbostic 		}
97*51882Sbostic 		lfs_bwrite(bp);
98*51882Sbostic 		brelse(bp);
99*51882Sbostic 	}
100*51882Sbostic 	free(blkp, M_SEGMENT);
101*51882Sbostic 
102*51882Sbostic 	cnt = uap->inocnt;
103*51882Sbostic 	inop = malloc(cnt * sizeof(INODE_INFO), M_SEGMENT, M_WAITOK);
104*51882Sbostic 	if (error = copyin(uap->inoiov, inop, cnt * sizeof(INODE_INFO))) {
105*51882Sbostic 		free(inop, M_SEGMENT);
106*51882Sbostic 		return (error);
107*51882Sbostic 	}
108*51882Sbostic 
109*51882Sbostic 	fs = VFSTOUFS(mntp)->um_lfs;
110*51882Sbostic 	for (; cnt--; ++inop) {
111*51882Sbostic 		LFS_IENTRY(ifp, fs, inop->ii_inode, bp);
112*51882Sbostic 		daddr = ifp->if_daddr;
113*51882Sbostic 		brelse(bp);
114*51882Sbostic 		if (daddr != inop->ii_daddr)
115*51882Sbostic 			continue;
116*51882Sbostic 		/*
117*51882Sbostic 		 * XXX
118*51882Sbostic 		 * This is grossly inefficient since the cleaner just handed
119*51882Sbostic 		 * us a copy of the inode and we're going to have to seek
120*51882Sbostic 		 * to get our own.  The fix requires creating a version of
121*51882Sbostic 		 * lfs_vget that takes the copy and uses it instead of reading
122*51882Sbostic 		 * from disk, if it's not already in the cache.
123*51882Sbostic 		 */
124*51882Sbostic 		if (!lfs_vget(mntp, inop->ii_inode, &vp))
125*51882Sbostic 			VTOI(vp)->i_flag |= IMOD;
126*51882Sbostic 	}
127*51882Sbostic 	free(inop, M_SEGMENT);
128*51882Sbostic 	return (lfs_segwrite(mntp, 1));
129*51882Sbostic }
130*51882Sbostic 
131*51882Sbostic /*
132*51882Sbostic  * lfs_bmapv:
133*51882Sbostic  *
134*51882Sbostic  * This will fill in the current disk address for arrays of inodes and blocks.
135*51882Sbostic  *
136*51882Sbostic  *  0 on success
137*51882Sbostic  * -1/errno is return on error.
138*51882Sbostic  */
139*51882Sbostic int
140*51882Sbostic lfs_bmapv(p, uap, retval)
141*51882Sbostic 	struct proc *p;
142*51882Sbostic 	struct args {
143*51882Sbostic 		fsid_t fsid;		/* file system */
144*51882Sbostic 		BLOCK_INFO *blkiov;	/* block array */
145*51882Sbostic 		int blkcnt;		/* count of block array entries */
146*51882Sbostic 	} *uap;
147*51882Sbostic 	int *retval;
148*51882Sbostic {
149*51882Sbostic 	BLOCK_INFO *blkp;
150*51882Sbostic 	struct mount *mntp;
151*51882Sbostic 	struct vnode *vp;
152*51882Sbostic 	daddr_t daddr;
153*51882Sbostic 	int cnt, error;
154*51882Sbostic 
155*51882Sbostic 	if (error = suser(p->p_ucred, &p->p_acflag))
156*51882Sbostic 		return (error);
157*51882Sbostic 
158*51882Sbostic 	if ((mntp = getvfs(&uap->fsid)) == NULL)
159*51882Sbostic 		return (EINVAL);
160*51882Sbostic 
161*51882Sbostic 	cnt = uap->blkcnt;
162*51882Sbostic 	blkp = malloc(cnt * sizeof(BLOCK_INFO), M_SEGMENT, M_WAITOK);
163*51882Sbostic 	if (error = copyin(uap->blkiov, blkp, cnt * sizeof(BLOCK_INFO))) {
164*51882Sbostic 		free(blkp, M_SEGMENT);
165*51882Sbostic 		return (error);
166*51882Sbostic 	}
167*51882Sbostic 
168*51882Sbostic 	for (; cnt--; ++blkp)
169*51882Sbostic 		blkp->bi_daddr =
170*51882Sbostic 		    lfs_vget(mntp, blkp->bi_inode, &vp) ||
171*51882Sbostic 		    lfs_bmap(vp, blkp->bi_lbn, NULL, &daddr) ?
172*51882Sbostic 			LFS_UNUSED_DADDR : daddr;
173*51882Sbostic 	free(blkp, M_SEGMENT);
174*51882Sbostic 	return (0);
175*51882Sbostic }
176*51882Sbostic 
177*51882Sbostic /*
178*51882Sbostic  * lfs_segclean:
179*51882Sbostic  *
180*51882Sbostic  * Mark the segment clean.
181*51882Sbostic  *
182*51882Sbostic  *  0 on success
183*51882Sbostic  * -1/errno is return on error.
184*51882Sbostic  */
185*51882Sbostic int
186*51882Sbostic lfs_segclean(p, uap, retval)
187*51882Sbostic 	struct proc *p;
188*51882Sbostic 	struct args {
189*51882Sbostic 		fsid_t fsid;		/* file system */
190*51882Sbostic 		u_long segment;		/* segment number */
191*51882Sbostic 	} *uap;
192*51882Sbostic 	int *retval;
193*51882Sbostic {
194*51882Sbostic 	SEGUSE *sup;
195*51882Sbostic 	struct buf *bp;
196*51882Sbostic 	struct mount *mntp;
197*51882Sbostic 	struct lfs *fs;
198*51882Sbostic 	int error;
199*51882Sbostic 
200*51882Sbostic 	if (error = suser(p->p_ucred, &p->p_acflag))
201*51882Sbostic 		return (error);
202*51882Sbostic 
203*51882Sbostic 	if ((mntp = getvfs(&uap->fsid)) == NULL)
204*51882Sbostic 		return (EINVAL);
205*51882Sbostic 
206*51882Sbostic 	fs = VFSTOUFS(mntp)->um_lfs;
207*51882Sbostic 	LFS_SEGENTRY(sup, fs, uap->segment, bp);
208*51882Sbostic 	sup->su_flags &= ~SEGUSE_DIRTY;
209*51882Sbostic 	brelse(bp);
210*51882Sbostic 	return (0);
211*51882Sbostic }
212*51882Sbostic 
213*51882Sbostic /*
214*51882Sbostic  * lfs_segwait:
215*51882Sbostic  *
216*51882Sbostic  * This will block until a segment in file system fsid is written.  A timeout
217*51882Sbostic  * in milliseconds may be specified which will awake the cleaner automatically.
218*51882Sbostic  * An fsid of -1 means any file system, and a timeout of 0 means forever.
219*51882Sbostic  *
220*51882Sbostic  *  0 on success
221*51882Sbostic  *  1 on timeout
222*51882Sbostic  * -1/errno is return on error.
223*51882Sbostic  */
224*51882Sbostic int
225*51882Sbostic lfs_segwait(p, uap, retval)
226*51882Sbostic 	struct proc *p;
227*51882Sbostic 	struct args {
228*51882Sbostic 		fsid_t fsid;		/* file system */
229*51882Sbostic 		struct timeval *tv;	/* timeout */
230*51882Sbostic 	} *uap;
231*51882Sbostic 	int *retval;
232*51882Sbostic {
233*51882Sbostic 	extern int lfs_allclean_wakeup;
234*51882Sbostic 	struct mount *mntp;
235*51882Sbostic 	struct timeval atv;
236*51882Sbostic 	void *addr;
237*51882Sbostic 	u_long timeout;
238*51882Sbostic 	int error, s;
239*51882Sbostic 
240*51882Sbostic 	if (error = suser(p->p_ucred, &p->p_acflag))
241*51882Sbostic 		return (error);
242*51882Sbostic 
243*51882Sbostic #ifdef WHEN_QUADS_WORK
244*51882Sbostic 	if (uap->fsid == (fsid_t)-1)
245*51882Sbostic 		addr = &lfs_allclean_wakeup;
246*51882Sbostic 	else {
247*51882Sbostic 		if ((mntp = getvfs(&uap->fsid)) == NULL)
248*51882Sbostic 			return (EINVAL);
249*51882Sbostic 		addr = &VFSTOUFS(mntp)->um_lfs->lfs_nextseg;
250*51882Sbostic 	}
251*51882Sbostic #else
252*51882Sbostic 	if ((mntp = getvfs(&uap->fsid)) == NULL)
253*51882Sbostic 		addr = &lfs_allclean_wakeup;
254*51882Sbostic 	else
255*51882Sbostic 		addr = &VFSTOUFS(mntp)->um_lfs->lfs_nextseg;
256*51882Sbostic #endif
257*51882Sbostic 
258*51882Sbostic 	if (uap->tv) {
259*51882Sbostic 		if (error = copyin(uap->tv, &atv, sizeof(struct timeval)))
260*51882Sbostic 			return (error);
261*51882Sbostic 		if (itimerfix(&atv))
262*51882Sbostic 			return (EINVAL);
263*51882Sbostic 		s = splhigh(); timevaladd(&atv, &time); splx(s);
264*51882Sbostic 		timeout = hzto(&atv);
265*51882Sbostic 	} else
266*51882Sbostic 		timeout = 0;
267*51882Sbostic 
268*51882Sbostic 	error = tsleep(addr, PCATCH | PUSER, "segment", timeout);
269*51882Sbostic 	return (error == ERESTART ? EINTR : 0);
270*51882Sbostic }
271