xref: /csrg-svn/sys/ufs/lfs/lfs_syscalls.c (revision 69420)
151882Sbostic /*-
267037Sbostic  * Copyright (c) 1991, 1993, 1994
363375Sbostic  *	The Regents of the University of California.  All rights reserved.
451882Sbostic  *
551882Sbostic  * %sccs.include.redist.c%
651882Sbostic  *
7*69420Smckusick  *	@(#)lfs_syscalls.c	8.10 (Berkeley) 05/14/95
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>
2155941Sbostic #include <ufs/ufs/ufs_extern.h>
2251882Sbostic 
2351882Sbostic #include <ufs/lfs/lfs.h>
2451882Sbostic #include <ufs/lfs/lfs_extern.h>
2556479Smargo #define BUMP_FIP(SP) \
2656479Smargo 	(SP)->fip = (FINFO *) (&(SP)->fip->fi_blocks[(SP)->fip->fi_nblocks])
2751882Sbostic 
2856479Smargo #define INC_FINFO(SP) ++((SEGSUM *)((SP)->segsum))->ss_nfinfo
2956479Smargo #define DEC_FINFO(SP) --((SEGSUM *)((SP)->segsum))->ss_nfinfo
3056479Smargo 
3156479Smargo /*
3256479Smargo  * Before committing to add something to a segment summary, make sure there
3356479Smargo  * is enough room.  S is the bytes added to the summary.
3456479Smargo  */
3556479Smargo #define	CHECK_SEG(s)			\
3656479Smargo if (sp->sum_bytes_left < (s)) {		\
3756479Smargo 	(void) lfs_writeseg(fs, sp);	\
3856479Smargo }
3955941Sbostic struct buf *lfs_fakebuf __P((struct vnode *, int, size_t, caddr_t));
4055941Sbostic 
4169292Smckusick int debug_cleaner = 0;
4269292Smckusick int clean_vnlocked = 0;
4369292Smckusick int clean_inlocked = 0;
4469292Smckusick 
4551882Sbostic /*
4651882Sbostic  * lfs_markv:
4751882Sbostic  *
4851882Sbostic  * This will mark inodes and blocks dirty, so they are written into the log.
4951882Sbostic  * It will block until all the blocks have been written.  The segment create
5051882Sbostic  * time passed in the block_info and inode_info structures is used to decide
5151882Sbostic  * if the data is valid for each block (in case some process dirtied a block
5251882Sbostic  * or inode that is being cleaned between the determination that a block is
5351882Sbostic  * live and the lfs_markv call).
5451882Sbostic  *
5551882Sbostic  *  0 on success
5651882Sbostic  * -1/errno is return on error.
5751882Sbostic  */
5857770Smargo struct lfs_markv_args {
5965738Sbostic 	fsid_t *fsidp;		/* file system */
6057770Smargo 	BLOCK_INFO *blkiov;	/* block array */
6157770Smargo 	int blkcnt;		/* count of block array entries */
6257770Smargo };
6351882Sbostic int
lfs_markv(p,uap,retval)6451882Sbostic lfs_markv(p, uap, retval)
6551882Sbostic 	struct proc *p;
6657770Smargo 	struct lfs_markv_args *uap;
6751882Sbostic 	int *retval;
6851882Sbostic {
6955941Sbostic 	struct segment *sp;
7051882Sbostic 	BLOCK_INFO *blkp;
7151882Sbostic 	IFILE *ifp;
7255941Sbostic 	struct buf *bp, **bpp;
7352087Sbostic 	struct inode *ip;
7451882Sbostic 	struct lfs *fs;
7551882Sbostic 	struct mount *mntp;
7651882Sbostic 	struct vnode *vp;
7765738Sbostic 	fsid_t fsid;
7852173Sbostic 	void *start;
7952087Sbostic 	ino_t lastino;
8068550Smckusick 	ufs_daddr_t b_daddr, v_daddr;
8151882Sbostic 	u_long bsize;
8251882Sbostic 	int cnt, error;
8351882Sbostic 
8451882Sbostic 	if (error = suser(p->p_ucred, &p->p_acflag))
8551882Sbostic 		return (error);
8665738Sbostic 
8765738Sbostic 	if (error = copyin(uap->fsidp, &fsid, sizeof(fsid_t)))
8865738Sbostic 		return (error);
8968614Smckusick 	if ((mntp = vfs_getvfs(&fsid)) == NULL)
9051882Sbostic 		return (EINVAL);
9151882Sbostic 
9251882Sbostic 	cnt = uap->blkcnt;
9352996Sbostic 	start = malloc(cnt * sizeof(BLOCK_INFO), M_SEGMENT, M_WAITOK);
9455941Sbostic 	if (error = copyin(uap->blkiov, start, cnt * sizeof(BLOCK_INFO)))
9555941Sbostic 		goto err1;
9651882Sbostic 
9755941Sbostic 	/* Mark blocks/inodes dirty.  */
9852087Sbostic 	fs = VFSTOUFS(mntp)->um_lfs;
9952820Sbostic 	bsize = fs->lfs_bsize;
10055941Sbostic 	error = 0;
10155941Sbostic 
10257073Smargo 	lfs_seglock(fs, SEGM_SYNC | SEGM_CLEAN);
10357073Smargo 	sp = fs->lfs_sp;
10455941Sbostic 	for (v_daddr = LFS_UNUSED_DADDR, lastino = LFS_UNUSED_INUM,
10555941Sbostic 	    blkp = start; cnt--; ++blkp) {
10652087Sbostic 		/*
10752087Sbostic 		 * Get the IFILE entry (only once) and see if the file still
10852087Sbostic 		 * exists.
10952087Sbostic 		 */
11052087Sbostic 		if (lastino != blkp->bi_inode) {
11155941Sbostic 			if (lastino != LFS_UNUSED_INUM) {
11256479Smargo 				/* Finish up last file */
11367037Sbostic 				if (sp->fip->fi_nblocks == 0) {
11456479Smargo 					DEC_FINFO(sp);
11556479Smargo 					sp->sum_bytes_left +=
11668550Smckusick 					    sizeof(FINFO) - sizeof(ufs_daddr_t);
11767037Sbostic 				} else {
11867037Sbostic 					lfs_updatemeta(sp);
11967037Sbostic 					BUMP_FIP(sp);
12067037Sbostic 				}
12156479Smargo 
12267037Sbostic 				lfs_writeinode(fs, sp, ip);
12367037Sbostic 				lfs_vunref(vp);
12455941Sbostic 			}
12556479Smargo 
12656479Smargo 			/* Start a new file */
12756479Smargo 			CHECK_SEG(sizeof(FINFO));
12868550Smckusick 			sp->sum_bytes_left -= sizeof(FINFO) - sizeof(ufs_daddr_t);
12956479Smargo 			INC_FINFO(sp);
13056479Smargo 			sp->start_lbp = &sp->fip->fi_blocks[0];
13156479Smargo 			sp->vp = NULL;
13256369Smargo 			sp->fip->fi_version = blkp->bi_version;
13356369Smargo 			sp->fip->fi_nblocks = 0;
13456369Smargo 			sp->fip->fi_ino = blkp->bi_inode;
13552087Sbostic 			lastino = blkp->bi_inode;
13656161Sbostic 			if (blkp->bi_inode == LFS_IFILE_INUM)
13756161Sbostic 				v_daddr = fs->lfs_idaddr;
13856161Sbostic 			else {
13956161Sbostic 				LFS_IENTRY(ifp, fs, blkp->bi_inode, bp);
14056161Sbostic 				v_daddr = ifp->if_daddr;
14156161Sbostic 				brelse(bp);
14256161Sbostic 			}
14355941Sbostic 			if (v_daddr == LFS_UNUSED_DADDR)
14452087Sbostic 				continue;
14556479Smargo 
14655941Sbostic 			/* Get the vnode/inode. */
14755941Sbostic 			if (lfs_fastvget(mntp, blkp->bi_inode, v_daddr, &vp,
14856369Smargo 			    blkp->bi_lbn == LFS_UNUSED_LBN ?
14956369Smargo 			    blkp->bi_bp : NULL)) {
15055941Sbostic #ifdef DIAGNOSTIC
15155941Sbostic 				printf("lfs_markv: VFS_VGET failed (%d)\n",
15255941Sbostic 				    blkp->bi_inode);
15369292Smckusick 				panic("lfs_markv VFS_VGET FAILED");
15455941Sbostic #endif
15556029Sbostic 				lastino = LFS_UNUSED_INUM;
15656479Smargo 				v_daddr = LFS_UNUSED_DADDR;
15755941Sbostic 				continue;
15855941Sbostic 			}
15956029Sbostic 			sp->vp = vp;
16055941Sbostic 			ip = VTOI(vp);
16155941Sbostic 		} else if (v_daddr == LFS_UNUSED_DADDR)
16255941Sbostic 			continue;
16352087Sbostic 
16455941Sbostic 		/* If this BLOCK_INFO didn't contain a block, keep going. */
16555941Sbostic 		if (blkp->bi_lbn == LFS_UNUSED_LBN)
16651882Sbostic 			continue;
16756479Smargo 		if (VOP_BMAP(vp, blkp->bi_lbn, NULL, &b_daddr, NULL) ||
16856161Sbostic 		    b_daddr != blkp->bi_daddr)
16952173Sbostic 			continue;
17055941Sbostic 		/*
17155941Sbostic 		 * If we got to here, then we are keeping the block.  If it
17255941Sbostic 		 * is an indirect block, we want to actually put it in the
17355941Sbostic 		 * buffer cache so that it can be updated in the finish_meta
17455941Sbostic 		 * section.  If it's not, we need to allocate a fake buffer
17555941Sbostic 		 * so that writeseg can perform the copyin and write the buffer.
17655941Sbostic 		 */
17755941Sbostic 		if (blkp->bi_lbn >= 0)	/* Data Block */
17855941Sbostic 			bp = lfs_fakebuf(vp, blkp->bi_lbn, bsize,
17955941Sbostic 			    blkp->bi_bp);
18055941Sbostic 		else {
18157806Smckusick 			bp = getblk(vp, blkp->bi_lbn, bsize, 0, 0);
18256625Smargo 			if (!(bp->b_flags & (B_DELWRI | B_DONE | B_CACHE)) &&
18364527Sbostic 			    (error = copyin(blkp->bi_bp, bp->b_data,
18469292Smckusick 			    blkp->bi_size)))
18555941Sbostic 				goto err2;
18655941Sbostic 			if (error = VOP_BWRITE(bp))
18755941Sbostic 				goto err2;
18852087Sbostic 		}
18956029Sbostic 		while (lfs_gatherblock(sp, bp, NULL));
19051882Sbostic 	}
19156029Sbostic 	if (sp->vp) {
19267037Sbostic 		if (sp->fip->fi_nblocks == 0) {
19367037Sbostic 			DEC_FINFO(sp);
19467037Sbostic 			sp->sum_bytes_left +=
19568550Smckusick 			    sizeof(FINFO) - sizeof(ufs_daddr_t);
19667037Sbostic 		} else
19767037Sbostic 			lfs_updatemeta(sp);
19867037Sbostic 
19956029Sbostic 		lfs_writeinode(fs, sp, ip);
20057073Smargo 		lfs_vunref(vp);
20156029Sbostic 	}
20255941Sbostic 	(void) lfs_writeseg(fs, sp);
20355941Sbostic 	lfs_segunlock(fs);
20452173Sbostic 	free(start, M_SEGMENT);
20555941Sbostic 	return (error);
20667037Sbostic 
20755941Sbostic /*
20867037Sbostic  * XXX
20967037Sbostic  * If we come in to error 2, we might have indirect blocks that were
21055941Sbostic  * updated and now have bad block pointers.  I don't know what to do
21155941Sbostic  * about this.
21255941Sbostic  */
21351882Sbostic 
21457073Smargo err2:	lfs_vunref(vp);
21555941Sbostic 	/* Free up fakebuffers */
21655941Sbostic 	for (bpp = --sp->cbpp; bpp >= sp->bpp; --bpp)
21755941Sbostic 		if ((*bpp)->b_flags & B_CALL) {
21855941Sbostic 			brelvp(*bpp);
21955941Sbostic 			free(*bpp, M_SEGMENT);
22055941Sbostic 		} else
22155941Sbostic 			brelse(*bpp);
22255941Sbostic 	lfs_segunlock(fs);
22365738Sbostic err1:
22452173Sbostic 	free(start, M_SEGMENT);
22567037Sbostic 	return (error);
22651882Sbostic }
22751882Sbostic 
22851882Sbostic /*
22951882Sbostic  * lfs_bmapv:
23051882Sbostic  *
23152087Sbostic  * This will fill in the current disk address for arrays of blocks.
23251882Sbostic  *
23351882Sbostic  *  0 on success
23451882Sbostic  * -1/errno is return on error.
23551882Sbostic  */
23657770Smargo struct lfs_bmapv_args {
23765738Sbostic 	fsid_t *fsidp;		/* file system */
23857770Smargo 	BLOCK_INFO *blkiov;	/* block array */
23957770Smargo 	int blkcnt;		/* count of block array entries */
24057770Smargo };
24151882Sbostic int
lfs_bmapv(p,uap,retval)24251882Sbostic lfs_bmapv(p, uap, retval)
24351882Sbostic 	struct proc *p;
24457770Smargo 	struct lfs_bmapv_args *uap;
24551882Sbostic 	int *retval;
24651882Sbostic {
24751882Sbostic 	BLOCK_INFO *blkp;
24851882Sbostic 	struct mount *mntp;
24969292Smckusick 	struct ufsmount *ump;
25051882Sbostic 	struct vnode *vp;
25165738Sbostic 	fsid_t fsid;
25252173Sbostic 	void *start;
25368550Smckusick 	ufs_daddr_t daddr;
25452173Sbostic 	int cnt, error, step;
25551882Sbostic 
25651882Sbostic 	if (error = suser(p->p_ucred, &p->p_acflag))
25751882Sbostic 		return (error);
25865738Sbostic 
25965738Sbostic 	if (error = copyin(uap->fsidp, &fsid, sizeof(fsid_t)))
26065738Sbostic 		return (error);
26168614Smckusick 	if ((mntp = vfs_getvfs(&fsid)) == NULL)
26251882Sbostic 		return (EINVAL);
26351882Sbostic 
26451882Sbostic 	cnt = uap->blkcnt;
26552173Sbostic 	start = blkp = malloc(cnt * sizeof(BLOCK_INFO), M_SEGMENT, M_WAITOK);
26651882Sbostic 	if (error = copyin(uap->blkiov, blkp, cnt * sizeof(BLOCK_INFO))) {
26751882Sbostic 		free(blkp, M_SEGMENT);
26851882Sbostic 		return (error);
26951882Sbostic 	}
27051882Sbostic 
27152173Sbostic 	for (step = cnt; step--; ++blkp) {
27256161Sbostic 		if (blkp->bi_lbn == LFS_UNUSED_LBN)
27356161Sbostic 			continue;
27469292Smckusick 		/*
27569292Smckusick 		 * A regular call to VFS_VGET could deadlock
27669292Smckusick 		 * here.  Instead, we try an unlocked access.
27769292Smckusick 		 */
27869292Smckusick 		ump = VFSTOUFS(mntp);
27969292Smckusick 		if ((vp =
28069292Smckusick 		    ufs_ihashlookup(ump->um_dev, blkp->bi_inode)) != NULL) {
28169292Smckusick 			if (VOP_BMAP(vp, blkp->bi_lbn, NULL, &daddr, NULL))
28269292Smckusick 				daddr = LFS_UNUSED_DADDR;
28369292Smckusick 		} else if (VFS_VGET(mntp, blkp->bi_inode, &vp))
28452173Sbostic 			daddr = LFS_UNUSED_DADDR;
28569292Smckusick 		else  {
28656479Smargo 			if (VOP_BMAP(vp, blkp->bi_lbn, NULL, &daddr, NULL))
28752173Sbostic 				daddr = LFS_UNUSED_DADDR;
28852173Sbostic 			vput(vp);
28952173Sbostic 		}
29052173Sbostic 		blkp->bi_daddr = daddr;
29152173Sbostic         }
29252173Sbostic 	copyout(start, uap->blkiov, cnt * sizeof(BLOCK_INFO));
29352173Sbostic 	free(start, M_SEGMENT);
29451882Sbostic 	return (0);
29551882Sbostic }
29651882Sbostic 
29751882Sbostic /*
29851882Sbostic  * lfs_segclean:
29951882Sbostic  *
30051882Sbostic  * Mark the segment clean.
30151882Sbostic  *
30251882Sbostic  *  0 on success
30351882Sbostic  * -1/errno is return on error.
30451882Sbostic  */
30557770Smargo struct lfs_segclean_args {
30665738Sbostic 	fsid_t *fsidp;		/* file system */
30757770Smargo 	u_long segment;		/* segment number */
30857770Smargo };
30951882Sbostic int
lfs_segclean(p,uap,retval)31051882Sbostic lfs_segclean(p, uap, retval)
31151882Sbostic 	struct proc *p;
31257770Smargo 	struct lfs_segclean_args *uap;
31351882Sbostic 	int *retval;
31451882Sbostic {
31551928Sbostic 	CLEANERINFO *cip;
31651882Sbostic 	SEGUSE *sup;
31751882Sbostic 	struct buf *bp;
31851882Sbostic 	struct mount *mntp;
31951882Sbostic 	struct lfs *fs;
32065738Sbostic 	fsid_t fsid;
32151882Sbostic 	int error;
32251882Sbostic 
32351882Sbostic 	if (error = suser(p->p_ucred, &p->p_acflag))
32451882Sbostic 		return (error);
32565738Sbostic 
32665738Sbostic 	if (error = copyin(uap->fsidp, &fsid, sizeof(fsid_t)))
32765738Sbostic 		return (error);
32868614Smckusick 	if ((mntp = vfs_getvfs(&fsid)) == NULL)
32951882Sbostic 		return (EINVAL);
33051882Sbostic 
33151882Sbostic 	fs = VFSTOUFS(mntp)->um_lfs;
33251928Sbostic 
33356369Smargo 	if (datosn(fs, fs->lfs_curseg) == uap->segment)
33456369Smargo 		return (EBUSY);
33556369Smargo 
33651882Sbostic 	LFS_SEGENTRY(sup, fs, uap->segment, bp);
33756369Smargo 	if (sup->su_flags & SEGUSE_ACTIVE) {
33856369Smargo 		brelse(bp);
33967037Sbostic 		return (EBUSY);
34056369Smargo 	}
34155941Sbostic 	fs->lfs_avail += fsbtodb(fs, fs->lfs_ssize) - 1;
34255593Sbostic 	fs->lfs_bfree += (sup->su_nsums * LFS_SUMMARY_SIZE / DEV_BSIZE) +
34355593Sbostic 	    sup->su_ninos * btodb(fs->lfs_bsize);
34451882Sbostic 	sup->su_flags &= ~SEGUSE_DIRTY;
34555941Sbostic 	(void) VOP_BWRITE(bp);
34651928Sbostic 
34751928Sbostic 	LFS_CLEANERINFO(cip, fs, bp);
34851928Sbostic 	++cip->clean;
34951928Sbostic 	--cip->dirty;
35055941Sbostic 	(void) VOP_BWRITE(bp);
35155941Sbostic 	wakeup(&fs->lfs_avail);
35251882Sbostic 	return (0);
35351882Sbostic }
35451882Sbostic 
35551882Sbostic /*
35651882Sbostic  * lfs_segwait:
35751882Sbostic  *
35851882Sbostic  * This will block until a segment in file system fsid is written.  A timeout
35951882Sbostic  * in milliseconds may be specified which will awake the cleaner automatically.
36051882Sbostic  * An fsid of -1 means any file system, and a timeout of 0 means forever.
36151882Sbostic  *
36251882Sbostic  *  0 on success
36351882Sbostic  *  1 on timeout
36451882Sbostic  * -1/errno is return on error.
36551882Sbostic  */
36657770Smargo struct lfs_segwait_args {
36765738Sbostic 	fsid_t *fsidp;		/* file system */
36857770Smargo 	struct timeval *tv;	/* timeout */
36957770Smargo };
37051882Sbostic int
lfs_segwait(p,uap,retval)37151882Sbostic lfs_segwait(p, uap, retval)
37251882Sbostic 	struct proc *p;
37357770Smargo 	struct lfs_segwait_args *uap;
37451882Sbostic 	int *retval;
37551882Sbostic {
37651882Sbostic 	extern int lfs_allclean_wakeup;
37751882Sbostic 	struct mount *mntp;
37851882Sbostic 	struct timeval atv;
37965738Sbostic 	fsid_t fsid;
38051882Sbostic 	void *addr;
38151882Sbostic 	u_long timeout;
38251882Sbostic 	int error, s;
38351882Sbostic 
38455941Sbostic 	if (error = suser(p->p_ucred, &p->p_acflag)) {
38551882Sbostic 		return (error);
38655941Sbostic }
38751882Sbostic #ifdef WHEN_QUADS_WORK
38865738Sbostic 	if (error = copyin(uap->fsidp, &fsid, sizeof(fsid_t)))
38965738Sbostic 		return (error);
39065738Sbostic 	if (fsid == (fsid_t)-1)
39151882Sbostic 		addr = &lfs_allclean_wakeup;
39251882Sbostic 	else {
39368614Smckusick 		if ((mntp = vfs_getvfs(&fsid)) == NULL)
39451882Sbostic 			return (EINVAL);
39551882Sbostic 		addr = &VFSTOUFS(mntp)->um_lfs->lfs_nextseg;
39651882Sbostic 	}
39751882Sbostic #else
39865738Sbostic 	if (error = copyin(uap->fsidp, &fsid, sizeof(fsid_t)))
39965738Sbostic 		return (error);
40068614Smckusick 	if ((mntp = vfs_getvfs(&fsid)) == NULL)
40151882Sbostic 		addr = &lfs_allclean_wakeup;
40251882Sbostic 	else
40351882Sbostic 		addr = &VFSTOUFS(mntp)->um_lfs->lfs_nextseg;
40451882Sbostic #endif
40551882Sbostic 
40651882Sbostic 	if (uap->tv) {
40751882Sbostic 		if (error = copyin(uap->tv, &atv, sizeof(struct timeval)))
40851882Sbostic 			return (error);
40951882Sbostic 		if (itimerfix(&atv))
41051882Sbostic 			return (EINVAL);
41154764Smckusick 		s = splclock();
41254764Smckusick 		timevaladd(&atv, (struct timeval *)&time);
41351882Sbostic 		timeout = hzto(&atv);
41454277Sbostic 		splx(s);
41551882Sbostic 	} else
41651882Sbostic 		timeout = 0;
41751882Sbostic 
41851882Sbostic 	error = tsleep(addr, PCATCH | PUSER, "segment", timeout);
41951882Sbostic 	return (error == ERESTART ? EINTR : 0);
42051882Sbostic }
42155941Sbostic 
42255941Sbostic /*
42355941Sbostic  * VFS_VGET call specialized for the cleaner.  The cleaner already knows the
42455941Sbostic  * daddr from the ifile, so don't look it up again.  If the cleaner is
42555941Sbostic  * processing IINFO structures, it may have the ondisk inode already, so
42655941Sbostic  * don't go retrieving it again.
42755941Sbostic  */
42855941Sbostic int
lfs_fastvget(mp,ino,daddr,vpp,dinp)42955941Sbostic lfs_fastvget(mp, ino, daddr, vpp, dinp)
43055941Sbostic 	struct mount *mp;
43155941Sbostic 	ino_t ino;
43268550Smckusick 	ufs_daddr_t daddr;
43355941Sbostic 	struct vnode **vpp;
43455941Sbostic 	struct dinode *dinp;
43555941Sbostic {
43655941Sbostic 	register struct inode *ip;
43755941Sbostic 	struct vnode *vp;
43855941Sbostic 	struct ufsmount *ump;
43955941Sbostic 	struct buf *bp;
44055941Sbostic 	dev_t dev;
44155941Sbostic 	int error;
44255941Sbostic 
44355941Sbostic 	ump = VFSTOUFS(mp);
44455941Sbostic 	dev = ump->um_dev;
44557073Smargo 	/*
44657073Smargo 	 * This is playing fast and loose.  Someone may have the inode
44757073Smargo 	 * locked, in which case they are going to be distinctly unhappy
44857073Smargo 	 * if we trash something.
44957073Smargo 	 */
45057073Smargo 	if ((*vpp = ufs_ihashlookup(dev, ino)) != NULL) {
45157073Smargo 		lfs_vref(*vpp);
45257073Smargo 		if ((*vpp)->v_flag & VXLOCK)
45369292Smckusick 			clean_vnlocked++;
45456191Smargo 		ip = VTOI(*vpp);
455*69420Smckusick 		if (lockstatus(&ip->i_lock))
45669292Smckusick 			clean_inlocked++;
45769292Smckusick 		if (!(ip->i_flag & IN_MODIFIED))
45856369Smargo 			++ump->um_lfs->lfs_uinodes;
45964612Sbostic 		ip->i_flag |= IN_MODIFIED;
46055941Sbostic 		return (0);
46156191Smargo 	}
46255941Sbostic 
46355941Sbostic 	/* Allocate new vnode/inode. */
46455941Sbostic 	if (error = lfs_vcreate(mp, ino, &vp)) {
46555941Sbostic 		*vpp = NULL;
46655941Sbostic 		return (error);
46755941Sbostic 	}
46855941Sbostic 
46955941Sbostic 	/*
47055941Sbostic 	 * Put it onto its hash chain and lock it so that other requests for
47155941Sbostic 	 * this inode will block if they arrive while we are sleeping waiting
47255941Sbostic 	 * for old data structures to be purged or for the contents of the
47355941Sbostic 	 * disk portion of this inode to be read.
47455941Sbostic 	 */
47555941Sbostic 	ip = VTOI(vp);
47655941Sbostic 	ufs_ihashins(ip);
47755941Sbostic 
47855941Sbostic 	/*
47955941Sbostic 	 * XXX
48055941Sbostic 	 * This may not need to be here, logically it should go down with
48155941Sbostic 	 * the i_devvp initialization.
48255941Sbostic 	 * Ask Kirk.
48355941Sbostic 	 */
48455941Sbostic 	ip->i_lfs = ump->um_lfs;
48555941Sbostic 
48655941Sbostic 	/* Read in the disk contents for the inode, copy into the inode. */
48755941Sbostic 	if (dinp)
48855941Sbostic 		if (error = copyin(dinp, &ip->i_din, sizeof(struct dinode)))
48955941Sbostic 			return (error);
49055941Sbostic 	else {
49155941Sbostic 		if (error = bread(ump->um_devvp, daddr,
49255941Sbostic 		    (int)ump->um_lfs->lfs_bsize, NOCRED, &bp)) {
49355941Sbostic 			/*
49455941Sbostic 			 * The inode does not contain anything useful, so it
49555941Sbostic 			 * would be misleading to leave it on its hash chain.
49655941Sbostic 			 * Iput() will return it to the free list.
49755941Sbostic 			 */
49855941Sbostic 			ufs_ihashrem(ip);
49955941Sbostic 
50055941Sbostic 			/* Unlock and discard unneeded inode. */
50157073Smargo 			lfs_vunref(vp);
50255941Sbostic 			brelse(bp);
50355941Sbostic 			*vpp = NULL;
50455941Sbostic 			return (error);
50555941Sbostic 		}
50664527Sbostic 		ip->i_din =
50764527Sbostic 		    *lfs_ifind(ump->um_lfs, ino, (struct dinode *)bp->b_data);
50855941Sbostic 		brelse(bp);
50955941Sbostic 	}
51055941Sbostic 
51155941Sbostic 	/*
51255941Sbostic 	 * Initialize the vnode from the inode, check for aliases.  In all
51355941Sbostic 	 * cases re-init ip, the underlying vnode/inode may have changed.
51455941Sbostic 	 */
51555941Sbostic 	if (error = ufs_vinit(mp, lfs_specop_p, LFS_FIFOOPS, &vp)) {
51657073Smargo 		lfs_vunref(vp);
51755941Sbostic 		*vpp = NULL;
51855941Sbostic 		return (error);
51955941Sbostic 	}
52055941Sbostic 	/*
52155941Sbostic 	 * Finish inode initialization now that aliasing has been resolved.
52255941Sbostic 	 */
52355941Sbostic 	ip->i_devvp = ump->um_devvp;
52464612Sbostic 	ip->i_flag |= IN_MODIFIED;
52555941Sbostic 	++ump->um_lfs->lfs_uinodes;
52655941Sbostic 	VREF(ip->i_devvp);
52755941Sbostic 	*vpp = vp;
52855941Sbostic 	return (0);
52955941Sbostic }
53055941Sbostic struct buf *
lfs_fakebuf(vp,lbn,size,uaddr)53155941Sbostic lfs_fakebuf(vp, lbn, size, uaddr)
53255941Sbostic 	struct vnode *vp;
53355941Sbostic 	int lbn;
53455941Sbostic 	size_t size;
53555941Sbostic 	caddr_t uaddr;
53655941Sbostic {
53755941Sbostic 	struct buf *bp;
53855941Sbostic 
53955941Sbostic 	bp = lfs_newbuf(vp, lbn, 0);
54055941Sbostic 	bp->b_saveaddr = uaddr;
54155941Sbostic 	bp->b_bufsize = size;
54255941Sbostic 	bp->b_bcount = size;
54355941Sbostic 	bp->b_flags |= B_INVAL;
54467037Sbostic 	return (bp);
54555941Sbostic }
546