xref: /csrg-svn/sys/ufs/lfs/lfs_syscalls.c (revision 52087)
151882Sbostic /*-
251882Sbostic  * Copyright (c) 1991 The Regents of the University of California.
351882Sbostic  * All rights reserved.
451882Sbostic  *
551882Sbostic  * %sccs.include.redist.c%
651882Sbostic  *
7*52087Sbostic  *	@(#)lfs_syscalls.c	7.5 (Berkeley) 12/31/91
851882Sbostic  */
951882Sbostic 
1051882Sbostic #include <sys/param.h>
1151882Sbostic #include <sys/proc.h>
1251882Sbostic #include <sys/buf.h>
1351882Sbostic #include <sys/mount.h>
1451882Sbostic #include <sys/vnode.h>
1551882Sbostic #include <sys/malloc.h>
1651882Sbostic #include <sys/kernel.h>
1751882Sbostic 
1851882Sbostic #include <ufs/ufs/quota.h>
1951882Sbostic #include <ufs/ufs/inode.h>
2051882Sbostic #include <ufs/ufs/ufsmount.h>
2151882Sbostic 
2251882Sbostic #include <ufs/lfs/lfs.h>
2351882Sbostic #include <ufs/lfs/lfs_extern.h>
2451882Sbostic 
2551882Sbostic /*
2651882Sbostic  * lfs_markv:
2751882Sbostic  *
2851882Sbostic  * This will mark inodes and blocks dirty, so they are written into the log.
2951882Sbostic  * It will block until all the blocks have been written.  The segment create
3051882Sbostic  * time passed in the block_info and inode_info structures is used to decide
3151882Sbostic  * if the data is valid for each block (in case some process dirtied a block
3251882Sbostic  * or inode that is being cleaned between the determination that a block is
3351882Sbostic  * live and the lfs_markv call).
3451882Sbostic  *
3551882Sbostic  *  0 on success
3651882Sbostic  * -1/errno is return on error.
3751882Sbostic  */
3851882Sbostic int
3951882Sbostic lfs_markv(p, uap, retval)
4051882Sbostic 	struct proc *p;
4151882Sbostic 	struct args {
4251882Sbostic 		fsid_t fsid;		/* file system */
4351882Sbostic 		BLOCK_INFO *blkiov;	/* block array */
4451882Sbostic 		int blkcnt;		/* count of block array entries */
4551882Sbostic 		INODE_INFO *inoiov;	/* inode array */
4651882Sbostic 		int inocnt;		/* count of inode array entries */
4751882Sbostic 	} *uap;
4851882Sbostic 	int *retval;
4951882Sbostic {
5051882Sbostic 	BLOCK_INFO *blkp;
5151882Sbostic 	IFILE *ifp;
5251882Sbostic 	INODE_INFO *inop;
5351882Sbostic 	struct buf *bp;
54*52087Sbostic 	struct inode *ip;
5551882Sbostic 	struct lfs *fs;
5651882Sbostic 	struct mount *mntp;
5751882Sbostic 	struct vnode *vp;
58*52087Sbostic 	ino_t lastino;
5951882Sbostic 	daddr_t daddr;
6051882Sbostic 	u_long bsize;
6151882Sbostic 	int cnt, error;
6251882Sbostic 
6351882Sbostic 	if (error = suser(p->p_ucred, &p->p_acflag))
6451882Sbostic 		return (error);
6551882Sbostic 
6651882Sbostic 	if ((mntp = getvfs(&uap->fsid)) == NULL)
6751882Sbostic 		return (EINVAL);
6851882Sbostic 
6951882Sbostic 	cnt = uap->blkcnt;
7051882Sbostic 	blkp = malloc(cnt * sizeof(BLOCK_INFO), M_SEGMENT, M_WAITOK);
7151882Sbostic 	if (error = copyin(uap->blkiov, blkp, cnt * sizeof(BLOCK_INFO))) {
7251882Sbostic 		free(blkp, M_SEGMENT);
7351882Sbostic 		return (error);
7451882Sbostic 	}
7551882Sbostic 
7651882Sbostic 	/*
77*52087Sbostic 	 * Mark blocks/inodes dirty.  Note that errors are mostly ignored.  If
78*52087Sbostic 	 * we can't get the info, the block is probably not all that useful,
79*52087Sbostic 	 * and hopefully subsequent calls from the cleaner will fix everything.
8051882Sbostic 	 */
81*52087Sbostic 	fs = VFSTOUFS(mntp)->um_lfs;
8251882Sbostic 	bsize = VFSTOUFS(mntp)->um_lfs->lfs_bsize;
83*52087Sbostic 	for (lastino = LFS_UNUSED_INUM; cnt--; ++blkp) {
84*52087Sbostic 		/*
85*52087Sbostic 		 * Get the IFILE entry (only once) and see if the file still
86*52087Sbostic 		 * exists.
87*52087Sbostic 		 */
88*52087Sbostic 		if (lastino != blkp->bi_inode) {
89*52087Sbostic 			lastino = blkp->bi_inode;
90*52087Sbostic 			LFS_IENTRY(ifp, fs, blkp->bi_inode, bp);
91*52087Sbostic 			daddr = ifp->if_daddr;
92*52087Sbostic 			brelse(bp);
93*52087Sbostic 			if (daddr == LFS_UNUSED_DADDR)
94*52087Sbostic 				continue;
95*52087Sbostic 		}
96*52087Sbostic 
97*52087Sbostic 		/*
98*52087Sbostic 		 * Get the vnode/inode.  If the inode modification time is
99*52087Sbostic 		 * earlier than the segment in which the block was found then
100*52087Sbostic 		 * they have to be valid, skip other checks.
101*52087Sbostic 		 */
102*52087Sbostic 		if (lfs_vget(mntp, blkp->bi_inode, &vp))
10351882Sbostic 			continue;
104*52087Sbostic 		ip = VTOI(vp);
105*52087Sbostic 		if (ip->i_mtime > blkp->bi_segcreate) {
106*52087Sbostic 			/* Check to see if the block has been replaced. */
107*52087Sbostic 			if (lfs_bmap(vp, blkp->bi_lbn, NULL, &daddr))
108*52087Sbostic 				continue;
109*52087Sbostic 			if (daddr != blkp->bi_daddr)
110*52087Sbostic 				continue;
111*52087Sbostic 		}
112*52087Sbostic 
113*52087Sbostic 		/* Get the block (from core or the cleaner) and write it. */
11451882Sbostic 		bp = getblk(vp, blkp->bi_lbn, bsize);
11551882Sbostic 		if (!(bp->b_flags & B_CACHE) &&
11651882Sbostic 		    (error = copyin(blkp->bi_bp, bp->b_un.b_daddr, bsize))) {
11751882Sbostic 			brelse(bp);
11851882Sbostic 			free(blkp, M_SEGMENT);
11951882Sbostic 			return (error);
12051882Sbostic 		}
12151882Sbostic 		lfs_bwrite(bp);
12251882Sbostic 	}
12351882Sbostic 	free(blkp, M_SEGMENT);
12451882Sbostic 
12551882Sbostic 	cnt = uap->inocnt;
12651882Sbostic 	inop = malloc(cnt * sizeof(INODE_INFO), M_SEGMENT, M_WAITOK);
12751882Sbostic 	if (error = copyin(uap->inoiov, inop, cnt * sizeof(INODE_INFO))) {
12851882Sbostic 		free(inop, M_SEGMENT);
12951882Sbostic 		return (error);
13051882Sbostic 	}
13151882Sbostic 
13251882Sbostic 	for (; cnt--; ++inop) {
13351882Sbostic 		LFS_IENTRY(ifp, fs, inop->ii_inode, bp);
13451882Sbostic 		daddr = ifp->if_daddr;
135*52087Sbostic 		brelse(bp);
13651882Sbostic 		if (daddr != inop->ii_daddr)
13751882Sbostic 			continue;
13851882Sbostic 		/*
13951882Sbostic 		 * XXX
14051882Sbostic 		 * This is grossly inefficient since the cleaner just handed
14151882Sbostic 		 * us a copy of the inode and we're going to have to seek
14251882Sbostic 		 * to get our own.  The fix requires creating a version of
14351882Sbostic 		 * lfs_vget that takes the copy and uses it instead of reading
14451882Sbostic 		 * from disk, if it's not already in the cache.
14551882Sbostic 		 */
14651882Sbostic 		if (!lfs_vget(mntp, inop->ii_inode, &vp))
14751882Sbostic 			VTOI(vp)->i_flag |= IMOD;
14851882Sbostic 	}
14951882Sbostic 	free(inop, M_SEGMENT);
15051882Sbostic 	return (lfs_segwrite(mntp, 1));
15151882Sbostic }
15251882Sbostic 
15351882Sbostic /*
15451882Sbostic  * lfs_bmapv:
15551882Sbostic  *
156*52087Sbostic  * This will fill in the current disk address for arrays of blocks.
15751882Sbostic  *
15851882Sbostic  *  0 on success
15951882Sbostic  * -1/errno is return on error.
16051882Sbostic  */
16151882Sbostic int
16251882Sbostic lfs_bmapv(p, uap, retval)
16351882Sbostic 	struct proc *p;
16451882Sbostic 	struct args {
16551882Sbostic 		fsid_t fsid;		/* file system */
16651882Sbostic 		BLOCK_INFO *blkiov;	/* block array */
16751882Sbostic 		int blkcnt;		/* count of block array entries */
16851882Sbostic 	} *uap;
16951882Sbostic 	int *retval;
17051882Sbostic {
17151882Sbostic 	BLOCK_INFO *blkp;
17251882Sbostic 	struct mount *mntp;
17351882Sbostic 	struct vnode *vp;
17451882Sbostic 	daddr_t daddr;
17551882Sbostic 	int cnt, error;
17651882Sbostic 
17751882Sbostic 	if (error = suser(p->p_ucred, &p->p_acflag))
17851882Sbostic 		return (error);
17951882Sbostic 
18051882Sbostic 	if ((mntp = getvfs(&uap->fsid)) == NULL)
18151882Sbostic 		return (EINVAL);
18251882Sbostic 
18351882Sbostic 	cnt = uap->blkcnt;
18451882Sbostic 	blkp = malloc(cnt * sizeof(BLOCK_INFO), M_SEGMENT, M_WAITOK);
18551882Sbostic 	if (error = copyin(uap->blkiov, blkp, cnt * sizeof(BLOCK_INFO))) {
18651882Sbostic 		free(blkp, M_SEGMENT);
18751882Sbostic 		return (error);
18851882Sbostic 	}
18951882Sbostic 
19051882Sbostic 	for (; cnt--; ++blkp)
19151882Sbostic 		blkp->bi_daddr =
19251882Sbostic 		    lfs_vget(mntp, blkp->bi_inode, &vp) ||
19351882Sbostic 		    lfs_bmap(vp, blkp->bi_lbn, NULL, &daddr) ?
19451882Sbostic 			LFS_UNUSED_DADDR : daddr;
19551882Sbostic 	free(blkp, M_SEGMENT);
19651882Sbostic 	return (0);
19751882Sbostic }
19851882Sbostic 
19951882Sbostic /*
20051882Sbostic  * lfs_segclean:
20151882Sbostic  *
20251882Sbostic  * Mark the segment clean.
20351882Sbostic  *
20451882Sbostic  *  0 on success
20551882Sbostic  * -1/errno is return on error.
20651882Sbostic  */
20751882Sbostic int
20851882Sbostic lfs_segclean(p, uap, retval)
20951882Sbostic 	struct proc *p;
21051882Sbostic 	struct args {
21151882Sbostic 		fsid_t fsid;		/* file system */
21251882Sbostic 		u_long segment;		/* segment number */
21351882Sbostic 	} *uap;
21451882Sbostic 	int *retval;
21551882Sbostic {
21651928Sbostic 	CLEANERINFO *cip;
21751882Sbostic 	SEGUSE *sup;
21851882Sbostic 	struct buf *bp;
21951882Sbostic 	struct mount *mntp;
22051882Sbostic 	struct lfs *fs;
22151882Sbostic 	int error;
22251882Sbostic 
22351882Sbostic 	if (error = suser(p->p_ucred, &p->p_acflag))
22451882Sbostic 		return (error);
22551882Sbostic 
22651882Sbostic 	if ((mntp = getvfs(&uap->fsid)) == NULL)
22751882Sbostic 		return (EINVAL);
22851882Sbostic 
22951882Sbostic 	fs = VFSTOUFS(mntp)->um_lfs;
23051928Sbostic 
23151882Sbostic 	LFS_SEGENTRY(sup, fs, uap->segment, bp);
23251882Sbostic 	sup->su_flags &= ~SEGUSE_DIRTY;
23351966Sbostic 	sup->su_nbytes = sup->su_flags & SEGUSE_SUPERBLOCK ? LFS_SBPAD : 0;
234*52087Sbostic 	LFS_UBWRITE(bp);
23551928Sbostic 
23651928Sbostic 	LFS_CLEANERINFO(cip, fs, bp);
23751928Sbostic 	++cip->clean;
23851928Sbostic 	--cip->dirty;
239*52087Sbostic 	LFS_UBWRITE(bp);
24051928Sbostic 
24151882Sbostic 	return (0);
24251882Sbostic }
24351882Sbostic 
24451882Sbostic /*
24551882Sbostic  * lfs_segwait:
24651882Sbostic  *
24751882Sbostic  * This will block until a segment in file system fsid is written.  A timeout
24851882Sbostic  * in milliseconds may be specified which will awake the cleaner automatically.
24951882Sbostic  * An fsid of -1 means any file system, and a timeout of 0 means forever.
25051882Sbostic  *
25151882Sbostic  *  0 on success
25251882Sbostic  *  1 on timeout
25351882Sbostic  * -1/errno is return on error.
25451882Sbostic  */
25551882Sbostic int
25651882Sbostic lfs_segwait(p, uap, retval)
25751882Sbostic 	struct proc *p;
25851882Sbostic 	struct args {
25951882Sbostic 		fsid_t fsid;		/* file system */
26051882Sbostic 		struct timeval *tv;	/* timeout */
26151882Sbostic 	} *uap;
26251882Sbostic 	int *retval;
26351882Sbostic {
26451882Sbostic 	extern int lfs_allclean_wakeup;
26551882Sbostic 	struct mount *mntp;
26651882Sbostic 	struct timeval atv;
26751882Sbostic 	void *addr;
26851882Sbostic 	u_long timeout;
26951882Sbostic 	int error, s;
27051882Sbostic 
27151882Sbostic 	if (error = suser(p->p_ucred, &p->p_acflag))
27251882Sbostic 		return (error);
27351882Sbostic 
27451882Sbostic #ifdef WHEN_QUADS_WORK
27551882Sbostic 	if (uap->fsid == (fsid_t)-1)
27651882Sbostic 		addr = &lfs_allclean_wakeup;
27751882Sbostic 	else {
27851882Sbostic 		if ((mntp = getvfs(&uap->fsid)) == NULL)
27951882Sbostic 			return (EINVAL);
28051882Sbostic 		addr = &VFSTOUFS(mntp)->um_lfs->lfs_nextseg;
28151882Sbostic 	}
28251882Sbostic #else
28351882Sbostic 	if ((mntp = getvfs(&uap->fsid)) == NULL)
28451882Sbostic 		addr = &lfs_allclean_wakeup;
28551882Sbostic 	else
28651882Sbostic 		addr = &VFSTOUFS(mntp)->um_lfs->lfs_nextseg;
28751882Sbostic #endif
28851882Sbostic 
28951882Sbostic 	if (uap->tv) {
29051882Sbostic 		if (error = copyin(uap->tv, &atv, sizeof(struct timeval)))
29151882Sbostic 			return (error);
29251882Sbostic 		if (itimerfix(&atv))
29351882Sbostic 			return (EINVAL);
29451882Sbostic 		s = splhigh(); timevaladd(&atv, &time); splx(s);
29551882Sbostic 		timeout = hzto(&atv);
29651882Sbostic 	} else
29751882Sbostic 		timeout = 0;
29851882Sbostic 
29951882Sbostic 	error = tsleep(addr, PCATCH | PUSER, "segment", timeout);
30051882Sbostic 	return (error == ERESTART ? EINTR : 0);
30151882Sbostic }
302