xref: /csrg-svn/sys/ufs/lfs/lfs_syscalls.c (revision 67402)
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*67402Smckusick  *	@(#)lfs_syscalls.c	8.6 (Berkeley) 06/16/94
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 
4151882Sbostic /*
4251882Sbostic  * lfs_markv:
4351882Sbostic  *
4451882Sbostic  * This will mark inodes and blocks dirty, so they are written into the log.
4551882Sbostic  * It will block until all the blocks have been written.  The segment create
4651882Sbostic  * time passed in the block_info and inode_info structures is used to decide
4751882Sbostic  * if the data is valid for each block (in case some process dirtied a block
4851882Sbostic  * or inode that is being cleaned between the determination that a block is
4951882Sbostic  * live and the lfs_markv call).
5051882Sbostic  *
5151882Sbostic  *  0 on success
5251882Sbostic  * -1/errno is return on error.
5351882Sbostic  */
5457770Smargo struct lfs_markv_args {
5565738Sbostic 	fsid_t *fsidp;		/* file system */
5657770Smargo 	BLOCK_INFO *blkiov;	/* block array */
5757770Smargo 	int blkcnt;		/* count of block array entries */
5857770Smargo };
5951882Sbostic int
6051882Sbostic lfs_markv(p, uap, retval)
6151882Sbostic 	struct proc *p;
6257770Smargo 	struct lfs_markv_args *uap;
6351882Sbostic 	int *retval;
6451882Sbostic {
6555941Sbostic 	struct segment *sp;
6651882Sbostic 	BLOCK_INFO *blkp;
6751882Sbostic 	IFILE *ifp;
6855941Sbostic 	struct buf *bp, **bpp;
6952087Sbostic 	struct inode *ip;
7051882Sbostic 	struct lfs *fs;
7151882Sbostic 	struct mount *mntp;
7251882Sbostic 	struct vnode *vp;
7365738Sbostic 	fsid_t fsid;
7452173Sbostic 	void *start;
7552087Sbostic 	ino_t lastino;
7655941Sbostic 	daddr_t b_daddr, v_daddr;
7751882Sbostic 	u_long bsize;
7851882Sbostic 	int cnt, error;
7951882Sbostic 
8051882Sbostic 	if (error = suser(p->p_ucred, &p->p_acflag))
8151882Sbostic 		return (error);
8265738Sbostic 
8365738Sbostic 	if (error = copyin(uap->fsidp, &fsid, sizeof(fsid_t)))
8465738Sbostic 		return (error);
8565738Sbostic 	if ((mntp = getvfs(&fsid)) == NULL)
8651882Sbostic 		return (EINVAL);
8751882Sbostic 
8851882Sbostic 	cnt = uap->blkcnt;
8952996Sbostic 	start = malloc(cnt * sizeof(BLOCK_INFO), M_SEGMENT, M_WAITOK);
9055941Sbostic 	if (error = copyin(uap->blkiov, start, cnt * sizeof(BLOCK_INFO)))
9155941Sbostic 		goto err1;
9251882Sbostic 
9355941Sbostic 	/* Mark blocks/inodes dirty.  */
9452087Sbostic 	fs = VFSTOUFS(mntp)->um_lfs;
9552820Sbostic 	bsize = fs->lfs_bsize;
9655941Sbostic 	error = 0;
9755941Sbostic 
9857073Smargo 	lfs_seglock(fs, SEGM_SYNC | SEGM_CLEAN);
9957073Smargo 	sp = fs->lfs_sp;
10055941Sbostic 	for (v_daddr = LFS_UNUSED_DADDR, lastino = LFS_UNUSED_INUM,
10155941Sbostic 	    blkp = start; cnt--; ++blkp) {
10252087Sbostic 		/*
10352087Sbostic 		 * Get the IFILE entry (only once) and see if the file still
10452087Sbostic 		 * exists.
10552087Sbostic 		 */
10652087Sbostic 		if (lastino != blkp->bi_inode) {
10755941Sbostic 			if (lastino != LFS_UNUSED_INUM) {
10856479Smargo 				/* Finish up last file */
10967037Sbostic 				if (sp->fip->fi_nblocks == 0) {
11056479Smargo 					DEC_FINFO(sp);
11156479Smargo 					sp->sum_bytes_left +=
11267037Sbostic 					    sizeof(FINFO) - sizeof(daddr_t);
11367037Sbostic 				} else {
11467037Sbostic 					lfs_updatemeta(sp);
11567037Sbostic 					BUMP_FIP(sp);
11667037Sbostic 				}
11756479Smargo 
11867037Sbostic 				lfs_writeinode(fs, sp, ip);
11967037Sbostic 				lfs_vunref(vp);
12055941Sbostic 			}
12156479Smargo 
12256479Smargo 			/* Start a new file */
12356479Smargo 			CHECK_SEG(sizeof(FINFO));
12456479Smargo 			sp->sum_bytes_left -= sizeof(FINFO) - sizeof(daddr_t);
12556479Smargo 			INC_FINFO(sp);
12656479Smargo 			sp->start_lbp = &sp->fip->fi_blocks[0];
12756479Smargo 			sp->vp = NULL;
12856369Smargo 			sp->fip->fi_version = blkp->bi_version;
12956369Smargo 			sp->fip->fi_nblocks = 0;
13056369Smargo 			sp->fip->fi_ino = blkp->bi_inode;
13152087Sbostic 			lastino = blkp->bi_inode;
13256161Sbostic 			if (blkp->bi_inode == LFS_IFILE_INUM)
13356161Sbostic 				v_daddr = fs->lfs_idaddr;
13456161Sbostic 			else {
13556161Sbostic 				LFS_IENTRY(ifp, fs, blkp->bi_inode, bp);
13656161Sbostic 				v_daddr = ifp->if_daddr;
13756161Sbostic 				brelse(bp);
13856161Sbostic 			}
13955941Sbostic 			if (v_daddr == LFS_UNUSED_DADDR)
14052087Sbostic 				continue;
14156479Smargo 
14255941Sbostic 			/* Get the vnode/inode. */
14355941Sbostic 			if (lfs_fastvget(mntp, blkp->bi_inode, v_daddr, &vp,
14456369Smargo 			    blkp->bi_lbn == LFS_UNUSED_LBN ?
14556369Smargo 			    blkp->bi_bp : NULL)) {
14655941Sbostic #ifdef DIAGNOSTIC
14755941Sbostic 				printf("lfs_markv: VFS_VGET failed (%d)\n",
14855941Sbostic 				    blkp->bi_inode);
14955941Sbostic #endif
15056029Sbostic 				lastino = LFS_UNUSED_INUM;
15156479Smargo 				v_daddr = LFS_UNUSED_DADDR;
15255941Sbostic 				continue;
15355941Sbostic 			}
15456029Sbostic 			sp->vp = vp;
15555941Sbostic 			ip = VTOI(vp);
15655941Sbostic 		} else if (v_daddr == LFS_UNUSED_DADDR)
15755941Sbostic 			continue;
15852087Sbostic 
15955941Sbostic 		/* If this BLOCK_INFO didn't contain a block, keep going. */
16055941Sbostic 		if (blkp->bi_lbn == LFS_UNUSED_LBN)
16151882Sbostic 			continue;
16256479Smargo 		if (VOP_BMAP(vp, blkp->bi_lbn, NULL, &b_daddr, NULL) ||
16356161Sbostic 		    b_daddr != blkp->bi_daddr)
16452173Sbostic 			continue;
16555941Sbostic 		/*
16655941Sbostic 		 * If we got to here, then we are keeping the block.  If it
16755941Sbostic 		 * is an indirect block, we want to actually put it in the
16855941Sbostic 		 * buffer cache so that it can be updated in the finish_meta
16955941Sbostic 		 * section.  If it's not, we need to allocate a fake buffer
17055941Sbostic 		 * so that writeseg can perform the copyin and write the buffer.
17155941Sbostic 		 */
17255941Sbostic 		if (blkp->bi_lbn >= 0)	/* Data Block */
17355941Sbostic 			bp = lfs_fakebuf(vp, blkp->bi_lbn, bsize,
17455941Sbostic 			    blkp->bi_bp);
17555941Sbostic 		else {
17657806Smckusick 			bp = getblk(vp, blkp->bi_lbn, bsize, 0, 0);
17756625Smargo 			if (!(bp->b_flags & (B_DELWRI | B_DONE | B_CACHE)) &&
17864527Sbostic 			    (error = copyin(blkp->bi_bp, bp->b_data,
17955941Sbostic 			    bsize)))
18055941Sbostic 				goto err2;
18155941Sbostic 			if (error = VOP_BWRITE(bp))
18255941Sbostic 				goto err2;
18352087Sbostic 		}
18456029Sbostic 		while (lfs_gatherblock(sp, bp, NULL));
18551882Sbostic 	}
18656029Sbostic 	if (sp->vp) {
18767037Sbostic 		if (sp->fip->fi_nblocks == 0) {
18867037Sbostic 			DEC_FINFO(sp);
18967037Sbostic 			sp->sum_bytes_left +=
19067037Sbostic 			    sizeof(FINFO) - sizeof(daddr_t);
19167037Sbostic 		} else
19267037Sbostic 			lfs_updatemeta(sp);
19367037Sbostic 
19456029Sbostic 		lfs_writeinode(fs, sp, ip);
19557073Smargo 		lfs_vunref(vp);
19656029Sbostic 	}
19755941Sbostic 	(void) lfs_writeseg(fs, sp);
19855941Sbostic 	lfs_segunlock(fs);
19952173Sbostic 	free(start, M_SEGMENT);
20055941Sbostic 	return (error);
20167037Sbostic 
20255941Sbostic /*
20367037Sbostic  * XXX
20467037Sbostic  * If we come in to error 2, we might have indirect blocks that were
20555941Sbostic  * updated and now have bad block pointers.  I don't know what to do
20655941Sbostic  * about this.
20755941Sbostic  */
20851882Sbostic 
20957073Smargo err2:	lfs_vunref(vp);
21055941Sbostic 	/* Free up fakebuffers */
21155941Sbostic 	for (bpp = --sp->cbpp; bpp >= sp->bpp; --bpp)
21255941Sbostic 		if ((*bpp)->b_flags & B_CALL) {
21355941Sbostic 			brelvp(*bpp);
21455941Sbostic 			free(*bpp, M_SEGMENT);
21555941Sbostic 		} else
21655941Sbostic 			brelse(*bpp);
21755941Sbostic 	lfs_segunlock(fs);
21865738Sbostic err1:
21952173Sbostic 	free(start, M_SEGMENT);
22067037Sbostic 	return (error);
22151882Sbostic }
22251882Sbostic 
22351882Sbostic /*
22451882Sbostic  * lfs_bmapv:
22551882Sbostic  *
22652087Sbostic  * This will fill in the current disk address for arrays of blocks.
22751882Sbostic  *
22851882Sbostic  *  0 on success
22951882Sbostic  * -1/errno is return on error.
23051882Sbostic  */
23157770Smargo struct lfs_bmapv_args {
23265738Sbostic 	fsid_t *fsidp;		/* file system */
23357770Smargo 	BLOCK_INFO *blkiov;	/* block array */
23457770Smargo 	int blkcnt;		/* count of block array entries */
23557770Smargo };
23651882Sbostic int
23751882Sbostic lfs_bmapv(p, uap, retval)
23851882Sbostic 	struct proc *p;
23957770Smargo 	struct lfs_bmapv_args *uap;
24051882Sbostic 	int *retval;
24151882Sbostic {
24251882Sbostic 	BLOCK_INFO *blkp;
24351882Sbostic 	struct mount *mntp;
24451882Sbostic 	struct vnode *vp;
24565738Sbostic 	fsid_t fsid;
24652173Sbostic 	void *start;
24751882Sbostic 	daddr_t daddr;
24852173Sbostic 	int cnt, error, step;
24951882Sbostic 
25051882Sbostic 	if (error = suser(p->p_ucred, &p->p_acflag))
25151882Sbostic 		return (error);
25265738Sbostic 
25365738Sbostic 	if (error = copyin(uap->fsidp, &fsid, sizeof(fsid_t)))
25465738Sbostic 		return (error);
25565738Sbostic 	if ((mntp = getvfs(&fsid)) == NULL)
25651882Sbostic 		return (EINVAL);
25751882Sbostic 
25851882Sbostic 	cnt = uap->blkcnt;
25952173Sbostic 	start = blkp = malloc(cnt * sizeof(BLOCK_INFO), M_SEGMENT, M_WAITOK);
26051882Sbostic 	if (error = copyin(uap->blkiov, blkp, cnt * sizeof(BLOCK_INFO))) {
26151882Sbostic 		free(blkp, M_SEGMENT);
26251882Sbostic 		return (error);
26351882Sbostic 	}
26451882Sbostic 
26552173Sbostic 	for (step = cnt; step--; ++blkp) {
26656161Sbostic 		if (blkp->bi_lbn == LFS_UNUSED_LBN)
26756161Sbostic 			continue;
26857073Smargo 		/* Could be a deadlock ? */
26954662Smckusick 		if (VFS_VGET(mntp, blkp->bi_inode, &vp))
27052173Sbostic 			daddr = LFS_UNUSED_DADDR;
27152173Sbostic 		else {
27256479Smargo 			if (VOP_BMAP(vp, blkp->bi_lbn, NULL, &daddr, NULL))
27352173Sbostic 				daddr = LFS_UNUSED_DADDR;
27452173Sbostic 			vput(vp);
27552173Sbostic 		}
27652173Sbostic 		blkp->bi_daddr = daddr;
27752173Sbostic         }
27852173Sbostic 	copyout(start, uap->blkiov, cnt * sizeof(BLOCK_INFO));
27952173Sbostic 	free(start, M_SEGMENT);
28051882Sbostic 	return (0);
28151882Sbostic }
28251882Sbostic 
28351882Sbostic /*
28451882Sbostic  * lfs_segclean:
28551882Sbostic  *
28651882Sbostic  * Mark the segment clean.
28751882Sbostic  *
28851882Sbostic  *  0 on success
28951882Sbostic  * -1/errno is return on error.
29051882Sbostic  */
29157770Smargo struct lfs_segclean_args {
29265738Sbostic 	fsid_t *fsidp;		/* file system */
29357770Smargo 	u_long segment;		/* segment number */
29457770Smargo };
29551882Sbostic int
29651882Sbostic lfs_segclean(p, uap, retval)
29751882Sbostic 	struct proc *p;
29857770Smargo 	struct lfs_segclean_args *uap;
29951882Sbostic 	int *retval;
30051882Sbostic {
30151928Sbostic 	CLEANERINFO *cip;
30251882Sbostic 	SEGUSE *sup;
30351882Sbostic 	struct buf *bp;
30451882Sbostic 	struct mount *mntp;
30551882Sbostic 	struct lfs *fs;
30665738Sbostic 	fsid_t fsid;
30751882Sbostic 	int error;
30851882Sbostic 
30951882Sbostic 	if (error = suser(p->p_ucred, &p->p_acflag))
31051882Sbostic 		return (error);
31165738Sbostic 
31265738Sbostic 	if (error = copyin(uap->fsidp, &fsid, sizeof(fsid_t)))
31365738Sbostic 		return (error);
31465738Sbostic 	if ((mntp = getvfs(&fsid)) == NULL)
31551882Sbostic 		return (EINVAL);
31651882Sbostic 
31751882Sbostic 	fs = VFSTOUFS(mntp)->um_lfs;
31851928Sbostic 
31956369Smargo 	if (datosn(fs, fs->lfs_curseg) == uap->segment)
32056369Smargo 		return (EBUSY);
32156369Smargo 
32251882Sbostic 	LFS_SEGENTRY(sup, fs, uap->segment, bp);
32356369Smargo 	if (sup->su_flags & SEGUSE_ACTIVE) {
32456369Smargo 		brelse(bp);
32567037Sbostic 		return (EBUSY);
32656369Smargo 	}
32755941Sbostic 	fs->lfs_avail += fsbtodb(fs, fs->lfs_ssize) - 1;
32855593Sbostic 	fs->lfs_bfree += (sup->su_nsums * LFS_SUMMARY_SIZE / DEV_BSIZE) +
32955593Sbostic 	    sup->su_ninos * btodb(fs->lfs_bsize);
33051882Sbostic 	sup->su_flags &= ~SEGUSE_DIRTY;
33155941Sbostic 	(void) VOP_BWRITE(bp);
33251928Sbostic 
33351928Sbostic 	LFS_CLEANERINFO(cip, fs, bp);
33451928Sbostic 	++cip->clean;
33551928Sbostic 	--cip->dirty;
33655941Sbostic 	(void) VOP_BWRITE(bp);
33755941Sbostic 	wakeup(&fs->lfs_avail);
33851882Sbostic 	return (0);
33951882Sbostic }
34051882Sbostic 
34151882Sbostic /*
34251882Sbostic  * lfs_segwait:
34351882Sbostic  *
34451882Sbostic  * This will block until a segment in file system fsid is written.  A timeout
34551882Sbostic  * in milliseconds may be specified which will awake the cleaner automatically.
34651882Sbostic  * An fsid of -1 means any file system, and a timeout of 0 means forever.
34751882Sbostic  *
34851882Sbostic  *  0 on success
34951882Sbostic  *  1 on timeout
35051882Sbostic  * -1/errno is return on error.
35151882Sbostic  */
35257770Smargo struct lfs_segwait_args {
35365738Sbostic 	fsid_t *fsidp;		/* file system */
35457770Smargo 	struct timeval *tv;	/* timeout */
35557770Smargo };
35651882Sbostic int
35751882Sbostic lfs_segwait(p, uap, retval)
35851882Sbostic 	struct proc *p;
35957770Smargo 	struct lfs_segwait_args *uap;
36051882Sbostic 	int *retval;
36151882Sbostic {
36251882Sbostic 	extern int lfs_allclean_wakeup;
36351882Sbostic 	struct mount *mntp;
36451882Sbostic 	struct timeval atv;
36565738Sbostic 	fsid_t fsid;
36651882Sbostic 	void *addr;
36751882Sbostic 	u_long timeout;
36851882Sbostic 	int error, s;
36951882Sbostic 
37055941Sbostic 	if (error = suser(p->p_ucred, &p->p_acflag)) {
37151882Sbostic 		return (error);
37255941Sbostic }
37351882Sbostic #ifdef WHEN_QUADS_WORK
37465738Sbostic 	if (error = copyin(uap->fsidp, &fsid, sizeof(fsid_t)))
37565738Sbostic 		return (error);
37665738Sbostic 	if (fsid == (fsid_t)-1)
37751882Sbostic 		addr = &lfs_allclean_wakeup;
37851882Sbostic 	else {
37965738Sbostic 		if ((mntp = getvfs(&fsid)) == NULL)
38051882Sbostic 			return (EINVAL);
38151882Sbostic 		addr = &VFSTOUFS(mntp)->um_lfs->lfs_nextseg;
38251882Sbostic 	}
38351882Sbostic #else
38465738Sbostic 	if (error = copyin(uap->fsidp, &fsid, sizeof(fsid_t)))
38565738Sbostic 		return (error);
38665738Sbostic 	if ((mntp = getvfs(&fsid)) == NULL)
38751882Sbostic 		addr = &lfs_allclean_wakeup;
38851882Sbostic 	else
38951882Sbostic 		addr = &VFSTOUFS(mntp)->um_lfs->lfs_nextseg;
39051882Sbostic #endif
39151882Sbostic 
39251882Sbostic 	if (uap->tv) {
39351882Sbostic 		if (error = copyin(uap->tv, &atv, sizeof(struct timeval)))
39451882Sbostic 			return (error);
39551882Sbostic 		if (itimerfix(&atv))
39651882Sbostic 			return (EINVAL);
39754764Smckusick 		s = splclock();
39854764Smckusick 		timevaladd(&atv, (struct timeval *)&time);
39951882Sbostic 		timeout = hzto(&atv);
40054277Sbostic 		splx(s);
40151882Sbostic 	} else
40251882Sbostic 		timeout = 0;
40351882Sbostic 
40451882Sbostic 	error = tsleep(addr, PCATCH | PUSER, "segment", timeout);
40551882Sbostic 	return (error == ERESTART ? EINTR : 0);
40651882Sbostic }
40755941Sbostic 
40855941Sbostic /*
40955941Sbostic  * VFS_VGET call specialized for the cleaner.  The cleaner already knows the
41055941Sbostic  * daddr from the ifile, so don't look it up again.  If the cleaner is
41155941Sbostic  * processing IINFO structures, it may have the ondisk inode already, so
41255941Sbostic  * don't go retrieving it again.
41355941Sbostic  */
41455941Sbostic int
41555941Sbostic lfs_fastvget(mp, ino, daddr, vpp, dinp)
41655941Sbostic 	struct mount *mp;
41755941Sbostic 	ino_t ino;
41855941Sbostic 	daddr_t daddr;
41955941Sbostic 	struct vnode **vpp;
42055941Sbostic 	struct dinode *dinp;
42155941Sbostic {
42255941Sbostic 	register struct inode *ip;
42355941Sbostic 	struct vnode *vp;
42455941Sbostic 	struct ufsmount *ump;
42555941Sbostic 	struct buf *bp;
42655941Sbostic 	dev_t dev;
42755941Sbostic 	int error;
42855941Sbostic 
42955941Sbostic 	ump = VFSTOUFS(mp);
43055941Sbostic 	dev = ump->um_dev;
43157073Smargo 	/*
43257073Smargo 	 * This is playing fast and loose.  Someone may have the inode
43357073Smargo 	 * locked, in which case they are going to be distinctly unhappy
43457073Smargo 	 * if we trash something.
43557073Smargo 	 */
43657073Smargo 	if ((*vpp = ufs_ihashlookup(dev, ino)) != NULL) {
43757073Smargo 		lfs_vref(*vpp);
43857073Smargo 		if ((*vpp)->v_flag & VXLOCK)
43957073Smargo 			printf ("Cleaned vnode VXLOCKED\n");
44056191Smargo 		ip = VTOI(*vpp);
441*67402Smckusick 		if (ip->i_flag & IN_LOCKED)
44264612Sbostic 			printf("cleaned vnode locked\n");
44364612Sbostic 		if (!(ip->i_flag & IN_MODIFIED)) {
44456369Smargo 			++ump->um_lfs->lfs_uinodes;
44564612Sbostic 			ip->i_flag |= IN_MODIFIED;
44656369Smargo 		}
44764612Sbostic 		ip->i_flag |= IN_MODIFIED;
44855941Sbostic 		return (0);
44956191Smargo 	}
45055941Sbostic 
45155941Sbostic 	/* Allocate new vnode/inode. */
45255941Sbostic 	if (error = lfs_vcreate(mp, ino, &vp)) {
45355941Sbostic 		*vpp = NULL;
45455941Sbostic 		return (error);
45555941Sbostic 	}
45655941Sbostic 
45755941Sbostic 	/*
45855941Sbostic 	 * Put it onto its hash chain and lock it so that other requests for
45955941Sbostic 	 * this inode will block if they arrive while we are sleeping waiting
46055941Sbostic 	 * for old data structures to be purged or for the contents of the
46155941Sbostic 	 * disk portion of this inode to be read.
46255941Sbostic 	 */
46355941Sbostic 	ip = VTOI(vp);
46455941Sbostic 	ufs_ihashins(ip);
46555941Sbostic 
46655941Sbostic 	/*
46755941Sbostic 	 * XXX
46855941Sbostic 	 * This may not need to be here, logically it should go down with
46955941Sbostic 	 * the i_devvp initialization.
47055941Sbostic 	 * Ask Kirk.
47155941Sbostic 	 */
47255941Sbostic 	ip->i_lfs = ump->um_lfs;
47355941Sbostic 
47455941Sbostic 	/* Read in the disk contents for the inode, copy into the inode. */
47555941Sbostic 	if (dinp)
47655941Sbostic 		if (error = copyin(dinp, &ip->i_din, sizeof(struct dinode)))
47755941Sbostic 			return (error);
47855941Sbostic 	else {
47955941Sbostic 		if (error = bread(ump->um_devvp, daddr,
48055941Sbostic 		    (int)ump->um_lfs->lfs_bsize, NOCRED, &bp)) {
48155941Sbostic 			/*
48255941Sbostic 			 * The inode does not contain anything useful, so it
48355941Sbostic 			 * would be misleading to leave it on its hash chain.
48455941Sbostic 			 * Iput() will return it to the free list.
48555941Sbostic 			 */
48655941Sbostic 			ufs_ihashrem(ip);
48755941Sbostic 
48855941Sbostic 			/* Unlock and discard unneeded inode. */
48957073Smargo 			lfs_vunref(vp);
49055941Sbostic 			brelse(bp);
49155941Sbostic 			*vpp = NULL;
49255941Sbostic 			return (error);
49355941Sbostic 		}
49464527Sbostic 		ip->i_din =
49564527Sbostic 		    *lfs_ifind(ump->um_lfs, ino, (struct dinode *)bp->b_data);
49655941Sbostic 		brelse(bp);
49755941Sbostic 	}
49855941Sbostic 
49956054Sbostic 	/* Inode was just read from user space or disk, make sure it's locked */
50064612Sbostic 	ip->i_flag |= IN_LOCKED;
50156054Sbostic 
50255941Sbostic 	/*
50355941Sbostic 	 * Initialize the vnode from the inode, check for aliases.  In all
50455941Sbostic 	 * cases re-init ip, the underlying vnode/inode may have changed.
50555941Sbostic 	 */
50655941Sbostic 	if (error = ufs_vinit(mp, lfs_specop_p, LFS_FIFOOPS, &vp)) {
50757073Smargo 		lfs_vunref(vp);
50855941Sbostic 		*vpp = NULL;
50955941Sbostic 		return (error);
51055941Sbostic 	}
51155941Sbostic 	/*
51255941Sbostic 	 * Finish inode initialization now that aliasing has been resolved.
51355941Sbostic 	 */
51455941Sbostic 	ip->i_devvp = ump->um_devvp;
51564612Sbostic 	ip->i_flag |= IN_MODIFIED;
51655941Sbostic 	++ump->um_lfs->lfs_uinodes;
51755941Sbostic 	VREF(ip->i_devvp);
51855941Sbostic 	*vpp = vp;
51955941Sbostic 	return (0);
52055941Sbostic }
52155941Sbostic struct buf *
52255941Sbostic lfs_fakebuf(vp, lbn, size, uaddr)
52355941Sbostic 	struct vnode *vp;
52455941Sbostic 	int lbn;
52555941Sbostic 	size_t size;
52655941Sbostic 	caddr_t uaddr;
52755941Sbostic {
52855941Sbostic 	struct buf *bp;
52955941Sbostic 
53055941Sbostic 	bp = lfs_newbuf(vp, lbn, 0);
53155941Sbostic 	bp->b_saveaddr = uaddr;
53255941Sbostic 	bp->b_bufsize = size;
53355941Sbostic 	bp->b_bcount = size;
53455941Sbostic 	bp->b_flags |= B_INVAL;
53567037Sbostic 	return (bp);
53655941Sbostic }
537