xref: /csrg-svn/sys/ufs/lfs/lfs_syscalls.c (revision 56369)
151882Sbostic /*-
251882Sbostic  * Copyright (c) 1991 The Regents of the University of California.
351882Sbostic  * All rights reserved.
451882Sbostic  *
551882Sbostic  * %sccs.include.redist.c%
651882Sbostic  *
7*56369Smargo  *	@(#)lfs_syscalls.c	7.24 (Berkeley) 10/01/92
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>
2556191Smargo #define INC_FINFO(SP) \
2656191Smargo 	++((SEGSUM *)((SP)->segsum))->ss_nfinfo
2751882Sbostic 
2855941Sbostic struct buf *lfs_fakebuf __P((struct vnode *, int, size_t, caddr_t));
2955941Sbostic 
3051882Sbostic /*
3151882Sbostic  * lfs_markv:
3251882Sbostic  *
3351882Sbostic  * This will mark inodes and blocks dirty, so they are written into the log.
3451882Sbostic  * It will block until all the blocks have been written.  The segment create
3551882Sbostic  * time passed in the block_info and inode_info structures is used to decide
3651882Sbostic  * if the data is valid for each block (in case some process dirtied a block
3751882Sbostic  * or inode that is being cleaned between the determination that a block is
3851882Sbostic  * live and the lfs_markv call).
3951882Sbostic  *
4051882Sbostic  *  0 on success
4151882Sbostic  * -1/errno is return on error.
4251882Sbostic  */
4351882Sbostic int
4451882Sbostic lfs_markv(p, uap, retval)
4551882Sbostic 	struct proc *p;
4651882Sbostic 	struct args {
4751882Sbostic 		fsid_t fsid;		/* file system */
4851882Sbostic 		BLOCK_INFO *blkiov;	/* block array */
4951882Sbostic 		int blkcnt;		/* count of block array entries */
5051882Sbostic 	} *uap;
5151882Sbostic 	int *retval;
5251882Sbostic {
5355941Sbostic 	struct segment *sp;
5451882Sbostic 	BLOCK_INFO *blkp;
5551882Sbostic 	IFILE *ifp;
5655941Sbostic 	struct buf *bp, **bpp;
5752087Sbostic 	struct inode *ip;
5851882Sbostic 	struct lfs *fs;
5951882Sbostic 	struct mount *mntp;
6051882Sbostic 	struct vnode *vp;
6152173Sbostic 	void *start;
6252087Sbostic 	ino_t lastino;
6355941Sbostic 	daddr_t b_daddr, v_daddr;
6451882Sbostic 	u_long bsize;
6551882Sbostic 	int cnt, error;
6651882Sbostic 
6751882Sbostic 	if (error = suser(p->p_ucred, &p->p_acflag))
6851882Sbostic 		return (error);
6951882Sbostic 	if ((mntp = getvfs(&uap->fsid)) == NULL)
7051882Sbostic 		return (EINVAL);
7155941Sbostic 	/* Initialize a segment. */
7255941Sbostic 	sp = malloc(sizeof(struct segment), M_SEGMENT, M_WAITOK);
7355941Sbostic 	sp->bpp = malloc(((LFS_SUMMARY_SIZE - sizeof(SEGSUM)) /
7455941Sbostic 	    sizeof(daddr_t) + 1) * sizeof(struct buf *), M_SEGMENT, M_WAITOK);
7555941Sbostic 	sp->seg_flags = SEGM_CKP;
7656029Sbostic 	sp->vp = NULL;
7751882Sbostic 
7851882Sbostic 	cnt = uap->blkcnt;
7952996Sbostic 	start = malloc(cnt * sizeof(BLOCK_INFO), M_SEGMENT, M_WAITOK);
8055941Sbostic 	if (error = copyin(uap->blkiov, start, cnt * sizeof(BLOCK_INFO)))
8155941Sbostic 		goto err1;
8251882Sbostic 
8355941Sbostic 	/* Mark blocks/inodes dirty.  */
8452087Sbostic 	fs = VFSTOUFS(mntp)->um_lfs;
8552820Sbostic 	bsize = fs->lfs_bsize;
8655941Sbostic 	error = 0;
8755941Sbostic 
8855941Sbostic 	lfs_seglock(fs);
8955941Sbostic 	lfs_initseg(fs, sp);
9055941Sbostic 	sp->seg_flags |= SEGM_CLEAN;
9155941Sbostic 	for (v_daddr = LFS_UNUSED_DADDR, lastino = LFS_UNUSED_INUM,
9255941Sbostic 	    blkp = start; cnt--; ++blkp) {
9352087Sbostic 		/*
9452087Sbostic 		 * Get the IFILE entry (only once) and see if the file still
9552087Sbostic 		 * exists.
9652087Sbostic 		 */
9752087Sbostic 		if (lastino != blkp->bi_inode) {
9855941Sbostic 			if (lastino != LFS_UNUSED_INUM) {
9956029Sbostic 				lfs_updatemeta(sp);
10055941Sbostic 				lfs_writeinode(fs, sp, ip);
10155941Sbostic 				vput(vp);
10256191Smargo 				if (sp->fip->fi_nblocks) {
10356191Smargo 					INC_FINFO(sp);
10456191Smargo 					sp->fip =
10556191Smargo 					(FINFO *) (&sp->fip->fi_blocks[sp->fip->fi_nblocks]);
10656191Smargo 				}
10756191Smargo 				sp->start_lbp = &sp->fip->fi_blocks[0];
10856161Sbostic 				sp->vp = NULL;
10955941Sbostic 			}
110*56369Smargo 			sp->fip->fi_version = blkp->bi_version;
111*56369Smargo 			sp->fip->fi_nblocks = 0;
112*56369Smargo 			sp->fip->fi_ino = blkp->bi_inode;
11352087Sbostic 			lastino = blkp->bi_inode;
11456161Sbostic 			if (blkp->bi_inode == LFS_IFILE_INUM)
11556161Sbostic 				v_daddr = fs->lfs_idaddr;
11656161Sbostic 			else {
11756161Sbostic 				LFS_IENTRY(ifp, fs, blkp->bi_inode, bp);
11856161Sbostic 				v_daddr = ifp->if_daddr;
11956161Sbostic 				brelse(bp);
12056161Sbostic 			}
12155941Sbostic 			if (v_daddr == LFS_UNUSED_DADDR)
12252087Sbostic 				continue;
12355941Sbostic 			/* Get the vnode/inode. */
12455941Sbostic 			if (lfs_fastvget(mntp, blkp->bi_inode, v_daddr, &vp,
125*56369Smargo 			    blkp->bi_lbn == LFS_UNUSED_LBN ?
126*56369Smargo 			    blkp->bi_bp : NULL)) {
12755941Sbostic #ifdef DIAGNOSTIC
12855941Sbostic 				printf("lfs_markv: VFS_VGET failed (%d)\n",
12955941Sbostic 				    blkp->bi_inode);
13055941Sbostic #endif
13156029Sbostic 				lastino = LFS_UNUSED_INUM;
13255941Sbostic 				v_daddr == LFS_UNUSED_DADDR;
13355941Sbostic 				continue;
13455941Sbostic 			}
13556029Sbostic 			sp->vp = vp;
13655941Sbostic 			ip = VTOI(vp);
13755941Sbostic 		} else if (v_daddr == LFS_UNUSED_DADDR)
13855941Sbostic 			continue;
13952087Sbostic 
14055941Sbostic 		/* If this BLOCK_INFO didn't contain a block, keep going. */
14155941Sbostic 		if (blkp->bi_lbn == LFS_UNUSED_LBN)
14251882Sbostic 			continue;
14356161Sbostic 		if (VOP_BMAP(vp, blkp->bi_lbn, NULL, &b_daddr) ||
14456161Sbostic 		    b_daddr != blkp->bi_daddr)
14552173Sbostic 			continue;
14655941Sbostic 		/*
14755941Sbostic 		 * If we got to here, then we are keeping the block.  If it
14855941Sbostic 		 * is an indirect block, we want to actually put it in the
14955941Sbostic 		 * buffer cache so that it can be updated in the finish_meta
15055941Sbostic 		 * section.  If it's not, we need to allocate a fake buffer
15155941Sbostic 		 * so that writeseg can perform the copyin and write the buffer.
15255941Sbostic 		 */
15355941Sbostic 		if (blkp->bi_lbn >= 0)	/* Data Block */
15455941Sbostic 			bp = lfs_fakebuf(vp, blkp->bi_lbn, bsize,
15555941Sbostic 			    blkp->bi_bp);
15655941Sbostic 		else {
15755941Sbostic 			bp = getblk(vp, blkp->bi_lbn, bsize);
15855941Sbostic 			if (!(bp->b_flags & B_CACHE) &&
15955941Sbostic 			    (error = copyin(blkp->bi_bp, bp->b_un.b_addr,
16055941Sbostic 			    bsize)))
16155941Sbostic 				goto err2;
16255941Sbostic 			if (error = VOP_BWRITE(bp))
16355941Sbostic 				goto err2;
16452087Sbostic 		}
16556029Sbostic 		while (lfs_gatherblock(sp, bp, NULL));
16651882Sbostic 	}
16756029Sbostic 	if (sp->vp) {
16856191Smargo 		if (sp->fip->fi_nblocks)
16956191Smargo 			INC_FINFO(sp);
17056029Sbostic 		lfs_updatemeta(sp);
17156029Sbostic 		lfs_writeinode(fs, sp, ip);
17256029Sbostic 		vput(vp);
17356029Sbostic 	}
17455941Sbostic 	(void) lfs_writeseg(fs, sp);
17555941Sbostic 	lfs_segunlock(fs);
17652173Sbostic 	free(start, M_SEGMENT);
17755941Sbostic 	free(sp->bpp, M_SEGMENT);
17855941Sbostic 	free(sp, M_SEGMENT);
17955941Sbostic 	return (error);
18055941Sbostic /*
18155941Sbostic  * XXX If we come in to error 2, we might have indirect blocks that were
18255941Sbostic  * updated and now have bad block pointers.  I don't know what to do
18355941Sbostic  * about this.
18455941Sbostic  */
18551882Sbostic 
18655941Sbostic err2:	vput(vp);
18755941Sbostic 	/* Free up fakebuffers */
18855941Sbostic 	for (bpp = --sp->cbpp; bpp >= sp->bpp; --bpp)
18955941Sbostic 		if ((*bpp)->b_flags & B_CALL) {
19055941Sbostic 			brelvp(*bpp);
19155941Sbostic 			free(*bpp, M_SEGMENT);
19255941Sbostic 		} else
19355941Sbostic 			brelse(*bpp);
19455941Sbostic 	lfs_segunlock(fs);
19555941Sbostic err1:
19655941Sbostic 	free(sp->bpp, M_SEGMENT);
19755941Sbostic 	free(sp, M_SEGMENT);
19852173Sbostic 	free(start, M_SEGMENT);
19955941Sbostic 	return(error);
20051882Sbostic }
20151882Sbostic 
20251882Sbostic /*
20351882Sbostic  * lfs_bmapv:
20451882Sbostic  *
20552087Sbostic  * This will fill in the current disk address for arrays of blocks.
20651882Sbostic  *
20751882Sbostic  *  0 on success
20851882Sbostic  * -1/errno is return on error.
20951882Sbostic  */
21051882Sbostic int
21151882Sbostic lfs_bmapv(p, uap, retval)
21251882Sbostic 	struct proc *p;
21351882Sbostic 	struct args {
21451882Sbostic 		fsid_t fsid;		/* file system */
21551882Sbostic 		BLOCK_INFO *blkiov;	/* block array */
21651882Sbostic 		int blkcnt;		/* count of block array entries */
21751882Sbostic 	} *uap;
21851882Sbostic 	int *retval;
21951882Sbostic {
22051882Sbostic 	BLOCK_INFO *blkp;
22151882Sbostic 	struct mount *mntp;
22251882Sbostic 	struct vnode *vp;
22352173Sbostic 	void *start;
22451882Sbostic 	daddr_t daddr;
22552173Sbostic 	int cnt, error, step;
22651882Sbostic 
22751882Sbostic 	if (error = suser(p->p_ucred, &p->p_acflag))
22851882Sbostic 		return (error);
22951882Sbostic 	if ((mntp = getvfs(&uap->fsid)) == NULL)
23051882Sbostic 		return (EINVAL);
23151882Sbostic 
23251882Sbostic 	cnt = uap->blkcnt;
23352173Sbostic 	start = blkp = malloc(cnt * sizeof(BLOCK_INFO), M_SEGMENT, M_WAITOK);
23451882Sbostic 	if (error = copyin(uap->blkiov, blkp, cnt * sizeof(BLOCK_INFO))) {
23551882Sbostic 		free(blkp, M_SEGMENT);
23651882Sbostic 		return (error);
23751882Sbostic 	}
23851882Sbostic 
23952173Sbostic 	for (step = cnt; step--; ++blkp) {
24056161Sbostic 		if (blkp->bi_lbn == LFS_UNUSED_LBN)
24156161Sbostic 			continue;
24254662Smckusick 		if (VFS_VGET(mntp, blkp->bi_inode, &vp))
24352173Sbostic 			daddr = LFS_UNUSED_DADDR;
24452173Sbostic 		else {
24553531Sheideman 			if (VOP_BMAP(vp, blkp->bi_lbn, NULL, &daddr))
24652173Sbostic 				daddr = LFS_UNUSED_DADDR;
24752173Sbostic 			vput(vp);
24852173Sbostic 		}
24952173Sbostic 		blkp->bi_daddr = daddr;
25052173Sbostic         }
25152173Sbostic 	copyout(start, uap->blkiov, cnt * sizeof(BLOCK_INFO));
25252173Sbostic 	free(start, M_SEGMENT);
25351882Sbostic 	return (0);
25451882Sbostic }
25551882Sbostic 
25651882Sbostic /*
25751882Sbostic  * lfs_segclean:
25851882Sbostic  *
25951882Sbostic  * Mark the segment clean.
26051882Sbostic  *
26151882Sbostic  *  0 on success
26251882Sbostic  * -1/errno is return on error.
26351882Sbostic  */
26451882Sbostic int
26551882Sbostic lfs_segclean(p, uap, retval)
26651882Sbostic 	struct proc *p;
26751882Sbostic 	struct args {
26851882Sbostic 		fsid_t fsid;		/* file system */
26951882Sbostic 		u_long segment;		/* segment number */
27051882Sbostic 	} *uap;
27151882Sbostic 	int *retval;
27251882Sbostic {
27351928Sbostic 	CLEANERINFO *cip;
27451882Sbostic 	SEGUSE *sup;
27551882Sbostic 	struct buf *bp;
27651882Sbostic 	struct mount *mntp;
27751882Sbostic 	struct lfs *fs;
27851882Sbostic 	int error;
27951882Sbostic 
28051882Sbostic 	if (error = suser(p->p_ucred, &p->p_acflag))
28151882Sbostic 		return (error);
28251882Sbostic 	if ((mntp = getvfs(&uap->fsid)) == NULL)
28351882Sbostic 		return (EINVAL);
28451882Sbostic 
28551882Sbostic 	fs = VFSTOUFS(mntp)->um_lfs;
28651928Sbostic 
287*56369Smargo 	if (datosn(fs, fs->lfs_curseg) == uap->segment)
288*56369Smargo 		return (EBUSY);
289*56369Smargo 
29051882Sbostic 	LFS_SEGENTRY(sup, fs, uap->segment, bp);
291*56369Smargo 	if (sup->su_flags & SEGUSE_ACTIVE) {
292*56369Smargo 		brelse(bp);
293*56369Smargo 		return(EBUSY);
294*56369Smargo 	}
29555941Sbostic 	fs->lfs_avail += fsbtodb(fs, fs->lfs_ssize) - 1;
29655593Sbostic 	fs->lfs_bfree += (sup->su_nsums * LFS_SUMMARY_SIZE / DEV_BSIZE) +
29755593Sbostic 	    sup->su_ninos * btodb(fs->lfs_bsize);
29851882Sbostic 	sup->su_flags &= ~SEGUSE_DIRTY;
29955941Sbostic 	(void) VOP_BWRITE(bp);
30051928Sbostic 
30151928Sbostic 	LFS_CLEANERINFO(cip, fs, bp);
30251928Sbostic 	++cip->clean;
30351928Sbostic 	--cip->dirty;
30455941Sbostic 	(void) VOP_BWRITE(bp);
30555941Sbostic 	wakeup(&fs->lfs_avail);
30651882Sbostic 	return (0);
30751882Sbostic }
30851882Sbostic 
30951882Sbostic /*
31051882Sbostic  * lfs_segwait:
31151882Sbostic  *
31251882Sbostic  * This will block until a segment in file system fsid is written.  A timeout
31351882Sbostic  * in milliseconds may be specified which will awake the cleaner automatically.
31451882Sbostic  * An fsid of -1 means any file system, and a timeout of 0 means forever.
31551882Sbostic  *
31651882Sbostic  *  0 on success
31751882Sbostic  *  1 on timeout
31851882Sbostic  * -1/errno is return on error.
31951882Sbostic  */
32051882Sbostic int
32151882Sbostic lfs_segwait(p, uap, retval)
32251882Sbostic 	struct proc *p;
32351882Sbostic 	struct args {
32451882Sbostic 		fsid_t fsid;		/* file system */
32551882Sbostic 		struct timeval *tv;	/* timeout */
32651882Sbostic 	} *uap;
32751882Sbostic 	int *retval;
32851882Sbostic {
32951882Sbostic 	extern int lfs_allclean_wakeup;
33051882Sbostic 	struct mount *mntp;
33151882Sbostic 	struct timeval atv;
33251882Sbostic 	void *addr;
33351882Sbostic 	u_long timeout;
33451882Sbostic 	int error, s;
33551882Sbostic 
33655941Sbostic 	if (error = suser(p->p_ucred, &p->p_acflag)) {
33751882Sbostic 		return (error);
33855941Sbostic }
33951882Sbostic #ifdef WHEN_QUADS_WORK
34051882Sbostic 	if (uap->fsid == (fsid_t)-1)
34151882Sbostic 		addr = &lfs_allclean_wakeup;
34251882Sbostic 	else {
34351882Sbostic 		if ((mntp = getvfs(&uap->fsid)) == NULL)
34451882Sbostic 			return (EINVAL);
34551882Sbostic 		addr = &VFSTOUFS(mntp)->um_lfs->lfs_nextseg;
34651882Sbostic 	}
34751882Sbostic #else
34851882Sbostic 	if ((mntp = getvfs(&uap->fsid)) == NULL)
34951882Sbostic 		addr = &lfs_allclean_wakeup;
35051882Sbostic 	else
35151882Sbostic 		addr = &VFSTOUFS(mntp)->um_lfs->lfs_nextseg;
35251882Sbostic #endif
35351882Sbostic 
35451882Sbostic 	if (uap->tv) {
35551882Sbostic 		if (error = copyin(uap->tv, &atv, sizeof(struct timeval)))
35651882Sbostic 			return (error);
35751882Sbostic 		if (itimerfix(&atv))
35851882Sbostic 			return (EINVAL);
35954764Smckusick 		s = splclock();
36054764Smckusick 		timevaladd(&atv, (struct timeval *)&time);
36151882Sbostic 		timeout = hzto(&atv);
36254277Sbostic 		splx(s);
36351882Sbostic 	} else
36451882Sbostic 		timeout = 0;
36551882Sbostic 
36651882Sbostic 	error = tsleep(addr, PCATCH | PUSER, "segment", timeout);
36751882Sbostic 	return (error == ERESTART ? EINTR : 0);
36851882Sbostic }
36955941Sbostic 
37055941Sbostic /*
37155941Sbostic  * VFS_VGET call specialized for the cleaner.  The cleaner already knows the
37255941Sbostic  * daddr from the ifile, so don't look it up again.  If the cleaner is
37355941Sbostic  * processing IINFO structures, it may have the ondisk inode already, so
37455941Sbostic  * don't go retrieving it again.
37555941Sbostic  */
37655941Sbostic int
37755941Sbostic lfs_fastvget(mp, ino, daddr, vpp, dinp)
37855941Sbostic 	struct mount *mp;
37955941Sbostic 	ino_t ino;
38055941Sbostic 	daddr_t daddr;
38155941Sbostic 	struct vnode **vpp;
38255941Sbostic 	struct dinode *dinp;
38355941Sbostic {
38455941Sbostic 	register struct inode *ip;
38555941Sbostic 	struct vnode *vp;
38655941Sbostic 	struct ufsmount *ump;
38755941Sbostic 	struct buf *bp;
38855941Sbostic 	dev_t dev;
38955941Sbostic 	int error;
39055941Sbostic 
39155941Sbostic 	ump = VFSTOUFS(mp);
39255941Sbostic 	dev = ump->um_dev;
39356191Smargo 	if ((*vpp = ufs_ihashget(dev, ino)) != NULL) {
39456191Smargo 		ip = VTOI(*vpp);
395*56369Smargo 		if (!(ip->i_flag & IMOD)) {
396*56369Smargo 			++ump->um_lfs->lfs_uinodes;
397*56369Smargo 			ip->i_flag |= IMOD;
398*56369Smargo 		}
39956191Smargo 		ip->i_flag |= IMOD;
40055941Sbostic 		return (0);
40156191Smargo 	}
40255941Sbostic 
40355941Sbostic 	/* Allocate new vnode/inode. */
40455941Sbostic 	if (error = lfs_vcreate(mp, ino, &vp)) {
40555941Sbostic 		*vpp = NULL;
40655941Sbostic 		return (error);
40755941Sbostic 	}
40855941Sbostic 
40955941Sbostic 	/*
41055941Sbostic 	 * Put it onto its hash chain and lock it so that other requests for
41155941Sbostic 	 * this inode will block if they arrive while we are sleeping waiting
41255941Sbostic 	 * for old data structures to be purged or for the contents of the
41355941Sbostic 	 * disk portion of this inode to be read.
41455941Sbostic 	 */
41555941Sbostic 	ip = VTOI(vp);
41655941Sbostic 	ufs_ihashins(ip);
41755941Sbostic 
41855941Sbostic 	/*
41955941Sbostic 	 * XXX
42055941Sbostic 	 * This may not need to be here, logically it should go down with
42155941Sbostic 	 * the i_devvp initialization.
42255941Sbostic 	 * Ask Kirk.
42355941Sbostic 	 */
42455941Sbostic 	ip->i_lfs = ump->um_lfs;
42555941Sbostic 
42655941Sbostic 	/* Read in the disk contents for the inode, copy into the inode. */
42755941Sbostic 	if (dinp)
42855941Sbostic 		if (error = copyin(dinp, &ip->i_din, sizeof(struct dinode)))
42955941Sbostic 			return (error);
43055941Sbostic 	else {
43155941Sbostic 		if (error = bread(ump->um_devvp, daddr,
43255941Sbostic 		    (int)ump->um_lfs->lfs_bsize, NOCRED, &bp)) {
43355941Sbostic 			/*
43455941Sbostic 			 * The inode does not contain anything useful, so it
43555941Sbostic 			 * would be misleading to leave it on its hash chain.
43655941Sbostic 			 * Iput() will return it to the free list.
43755941Sbostic 			 */
43855941Sbostic 			ufs_ihashrem(ip);
43955941Sbostic 
44055941Sbostic 			/* Unlock and discard unneeded inode. */
44155941Sbostic 			ufs_iput(ip);
44255941Sbostic 			brelse(bp);
44355941Sbostic 			*vpp = NULL;
44455941Sbostic 			return (error);
44555941Sbostic 		}
44655941Sbostic 		ip->i_din = *lfs_ifind(ump->um_lfs, ino, bp->b_un.b_dino);
44755941Sbostic 		brelse(bp);
44855941Sbostic 	}
44955941Sbostic 
45056054Sbostic 	/* Inode was just read from user space or disk, make sure it's locked */
45156054Sbostic 	ip->i_flag |= ILOCKED;
45256054Sbostic 
45355941Sbostic 	/*
45455941Sbostic 	 * Initialize the vnode from the inode, check for aliases.  In all
45555941Sbostic 	 * cases re-init ip, the underlying vnode/inode may have changed.
45655941Sbostic 	 */
45755941Sbostic 	if (error = ufs_vinit(mp, lfs_specop_p, LFS_FIFOOPS, &vp)) {
45855941Sbostic 		ufs_iput(ip);
45955941Sbostic 		*vpp = NULL;
46055941Sbostic 		return (error);
46155941Sbostic 	}
46255941Sbostic 	/*
46355941Sbostic 	 * Finish inode initialization now that aliasing has been resolved.
46455941Sbostic 	 */
46555941Sbostic 	ip->i_devvp = ump->um_devvp;
46655941Sbostic 	ip->i_flag |= IMOD;
46755941Sbostic 	++ump->um_lfs->lfs_uinodes;
46855941Sbostic 	VREF(ip->i_devvp);
46955941Sbostic 	*vpp = vp;
47055941Sbostic 	return (0);
47155941Sbostic }
47255941Sbostic struct buf *
47355941Sbostic lfs_fakebuf(vp, lbn, size, uaddr)
47455941Sbostic 	struct vnode *vp;
47555941Sbostic 	int lbn;
47655941Sbostic 	size_t size;
47755941Sbostic 	caddr_t uaddr;
47855941Sbostic {
47955941Sbostic 	struct buf *bp;
48055941Sbostic 
48155941Sbostic 	bp = lfs_newbuf(vp, lbn, 0);
48255941Sbostic 	bp->b_saveaddr = uaddr;
48355941Sbostic 	bp->b_bufsize = size;
48455941Sbostic 	bp->b_bcount = size;
48555941Sbostic 	bp->b_flags |= B_INVAL;
48655941Sbostic 	return(bp);
48755941Sbostic }
488