xref: /csrg-svn/sys/ufs/lfs/lfs_vfsops.c (revision 65674)
123400Smckusick /*
263375Sbostic  * Copyright (c) 1989, 1991, 1993
363375Sbostic  *	The Regents of the University of California.  All rights reserved.
423400Smckusick  *
544539Sbostic  * %sccs.include.redist.c%
637737Smckusick  *
7*65674Shibler  *	@(#)lfs_vfsops.c	8.5 (Berkeley) 01/12/94
823400Smckusick  */
912795Ssam 
1051483Sbostic #include <sys/param.h>
1151483Sbostic #include <sys/systm.h>
1251483Sbostic #include <sys/namei.h>
1351483Sbostic #include <sys/proc.h>
1451483Sbostic #include <sys/kernel.h>
1551483Sbostic #include <sys/vnode.h>
1651483Sbostic #include <sys/mount.h>
1751483Sbostic #include <sys/buf.h>
1854734Smckusick #include <sys/mbuf.h>
1951483Sbostic #include <sys/file.h>
2051483Sbostic #include <sys/disklabel.h>
2151483Sbostic #include <sys/ioctl.h>
2251483Sbostic #include <sys/errno.h>
2351483Sbostic #include <sys/malloc.h>
2454734Smckusick #include <sys/socket.h>
2512795Ssam 
2655047Smckusick #include <miscfs/specfs/specdev.h>
2755047Smckusick 
2851501Sbostic #include <ufs/ufs/quota.h>
2951501Sbostic #include <ufs/ufs/inode.h>
3051501Sbostic #include <ufs/ufs/ufsmount.h>
3151501Sbostic #include <ufs/ufs/ufs_extern.h>
3247571Skarels 
3351501Sbostic #include <ufs/lfs/lfs.h>
3451501Sbostic #include <ufs/lfs/lfs_extern.h>
3551155Sbostic 
3651991Sbostic int lfs_mountfs __P((struct vnode *, struct mount *, struct proc *));
3751215Sbostic 
3851155Sbostic struct vfsops lfs_vfsops = {
3951155Sbostic 	lfs_mount,
4039043Smckusick 	ufs_start,
4151155Sbostic 	lfs_unmount,
4251559Smckusick 	lfs_root,
4341314Smckusick 	ufs_quotactl,
4451155Sbostic 	lfs_statfs,
4551155Sbostic 	lfs_sync,
4654693Sbostic 	lfs_vget,
4751559Smckusick 	lfs_fhtovp,
4851559Smckusick 	lfs_vptofh,
4951483Sbostic 	lfs_init,
5037737Smckusick };
5137737Smckusick 
5251483Sbostic int
5351155Sbostic lfs_mountroot()
5412795Ssam {
5551483Sbostic 	panic("lfs_mountroot");		/* XXX -- implement */
5637737Smckusick }
5737737Smckusick 
5837737Smckusick /*
5937737Smckusick  * VFS Operations.
6037737Smckusick  *
6137737Smckusick  * mount system call
6237737Smckusick  */
6351155Sbostic lfs_mount(mp, path, data, ndp, p)
6440346Smckusick 	register struct mount *mp;
6537737Smckusick 	char *path;
6637737Smckusick 	caddr_t data;
6737737Smckusick 	struct nameidata *ndp;
6848036Smckusick 	struct proc *p;
6937737Smckusick {
7037737Smckusick 	struct vnode *devvp;
7137737Smckusick 	struct ufs_args args;
7237737Smckusick 	struct ufsmount *ump;
7351501Sbostic 	register struct lfs *fs;				/* LFS */
7437737Smckusick 	u_int size;
7537737Smckusick 	int error;
7637737Smckusick 
7737737Smckusick 	if (error = copyin(data, (caddr_t)&args, sizeof (struct ufs_args)))
7837737Smckusick 		return (error);
7951483Sbostic 
8051483Sbostic 	/* Until LFS can do NFS right.		XXX */
81*65674Shibler 	if (args.export.ex_flags & MNT_EXPORTED)
8251483Sbostic 		return (EINVAL);
83*65674Shibler 
8440371Smckusick 	/*
8550264Skarels 	 * If updating, check whether changing from read-only to
8650264Skarels 	 * read/write; if there is no device name, that's all we do.
8750264Skarels 	 */
8850264Skarels 	if (mp->mnt_flag & MNT_UPDATE) {
8939336Smckusick 		ump = VFSTOUFS(mp);
9051155Sbostic #ifdef NOTLFS							/* LFS */
9139336Smckusick 		fs = ump->um_fs;
9241397Smckusick 		if (fs->fs_ronly && (mp->mnt_flag & MNT_RDONLY) == 0)
9339336Smckusick 			fs->fs_ronly = 0;
9451155Sbostic #else
9551155Sbostic 		fs = ump->um_lfs;
9651155Sbostic 		if (fs->lfs_ronly && (mp->mnt_flag & MNT_RDONLY) == 0)
9751155Sbostic 			fs->lfs_ronly = 0;
9851155Sbostic #endif
9952175Smckusick 		if (args.fspec == 0) {
10052175Smckusick 			/*
10152175Smckusick 			 * Process export requests.
10252175Smckusick 			 */
103*65674Shibler 			return (vfs_export(mp, &ump->um_export, &args.export));
10452175Smckusick 		}
10550264Skarels 	}
10650264Skarels 	/*
10750264Skarels 	 * Not an update, or updating the name: look up the name
10850264Skarels 	 * and verify that it refers to a sensible block device.
10950264Skarels 	 */
11052333Smckusick 	NDINIT(ndp, LOOKUP, FOLLOW, UIO_USERSPACE, args.fspec, p);
11152333Smckusick 	if (error = namei(ndp))
11250264Skarels 		return (error);
11350264Skarels 	devvp = ndp->ni_vp;
11450264Skarels 	if (devvp->v_type != VBLK) {
11550264Skarels 		vrele(devvp);
11650264Skarels 		return (ENOTBLK);
11750264Skarels 	}
11850264Skarels 	if (major(devvp->v_rdev) >= nblkdev) {
11950264Skarels 		vrele(devvp);
12050264Skarels 		return (ENXIO);
12150264Skarels 	}
12250264Skarels 	if ((mp->mnt_flag & MNT_UPDATE) == 0)
12351155Sbostic 		error = lfs_mountfs(devvp, mp, p);		/* LFS */
12450264Skarels 	else {
12539336Smckusick 		if (devvp != ump->um_devvp)
12639336Smckusick 			error = EINVAL;	/* needs translation */
12742858Smckusick 		else
12842858Smckusick 			vrele(devvp);
12939336Smckusick 	}
13037737Smckusick 	if (error) {
13137737Smckusick 		vrele(devvp);
13237737Smckusick 		return (error);
13332721Smckusick 	}
13437737Smckusick 	ump = VFSTOUFS(mp);
13551155Sbostic 	fs = ump->um_lfs;					/* LFS */
13651155Sbostic #ifdef NOTLFS							/* LFS */
13737737Smckusick 	(void) copyinstr(path, fs->fs_fsmnt, sizeof(fs->fs_fsmnt) - 1, &size);
13837737Smckusick 	bzero(fs->fs_fsmnt + size, sizeof(fs->fs_fsmnt) - size);
13941397Smckusick 	bcopy((caddr_t)fs->fs_fsmnt, (caddr_t)mp->mnt_stat.f_mntonname,
14041397Smckusick 	    MNAMELEN);
14151991Sbostic 	(void) copyinstr(args.fspec, mp->mnt_stat.f_mntfromname, MNAMELEN - 1,
14241397Smckusick 	    &size);
14341397Smckusick 	bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
14448036Smckusick 	(void) ufs_statfs(mp, &mp->mnt_stat, p);
14551155Sbostic #else
14651155Sbostic 	(void)copyinstr(path, fs->lfs_fsmnt, sizeof(fs->lfs_fsmnt) - 1, &size);
14751155Sbostic 	bzero(fs->lfs_fsmnt + size, sizeof(fs->lfs_fsmnt) - size);
14851155Sbostic 	bcopy((caddr_t)fs->lfs_fsmnt, (caddr_t)mp->mnt_stat.f_mntonname,
14951155Sbostic 	    MNAMELEN);
15051991Sbostic 	(void) copyinstr(args.fspec, mp->mnt_stat.f_mntfromname, MNAMELEN - 1,
15151155Sbostic 	    &size);
15251155Sbostic 	bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
15351155Sbostic 	(void) lfs_statfs(mp, &mp->mnt_stat, p);
15451155Sbostic #endif
15537737Smckusick 	return (0);
15612795Ssam }
15712795Ssam 
15837737Smckusick /*
15937737Smckusick  * Common code for mount and mountroot
16051155Sbostic  * LFS specific
16137737Smckusick  */
16251991Sbostic int
16351155Sbostic lfs_mountfs(devvp, mp, p)
16440376Smckusick 	register struct vnode *devvp;
16537737Smckusick 	struct mount *mp;
16648036Smckusick 	struct proc *p;
16712795Ssam {
16851155Sbostic 	extern struct vnode *rootvp;
16951501Sbostic 	register struct lfs *fs;
17051155Sbostic 	register struct ufsmount *ump;
17151155Sbostic 	struct vnode *vp;
17251155Sbostic 	struct buf *bp;
17330749Skarels 	struct partinfo dpart;
17451155Sbostic 	dev_t dev;
17551155Sbostic 	int error, i, ronly, size;
17612795Ssam 
17740376Smckusick 	/*
17840376Smckusick 	 * Disallow multiple mounts of the same device.
17945652Smckusick 	 * Disallow mounting of a device that is currently in use
18045652Smckusick 	 * (except for root, which might share swap device for miniroot).
18140376Smckusick 	 * Flush out any old buffers remaining from a previous use.
18240376Smckusick 	 */
183*65674Shibler 	if (error = vfs_mountedon(devvp))
18440376Smckusick 		return (error);
18545652Smckusick 	if (vcount(devvp) > 1 && devvp != rootvp)
18640376Smckusick 		return (EBUSY);
18757805Smckusick 	if (error = vinvalbuf(devvp, 1, p->p_ucred, p, 0, 0))
18854693Sbostic 		return (error);
18951155Sbostic 
19051155Sbostic 	ronly = (mp->mnt_flag & MNT_RDONLY) != 0;
19159473Smckusick 	if (error = VOP_OPEN(devvp, ronly ? FREAD : FREAD|FWRITE, FSCRED, p))
19237737Smckusick 		return (error);
19351155Sbostic 
19448036Smckusick 	if (VOP_IOCTL(devvp, DIOCGPART, (caddr_t)&dpart, FREAD, NOCRED, p) != 0)
19537737Smckusick 		size = DEV_BSIZE;
19648036Smckusick 	else {
19730749Skarels 		size = dpart.disklab->d_secsize;
19851155Sbostic #ifdef NEVER_USED
19951155Sbostic 		dpart.part->p_fstype = FS_LFS;
20051155Sbostic 		dpart.part->p_fsize = fs->lfs_fsize;	/* frag size */
20151155Sbostic 		dpart.part->p_frag = fs->lfs_frag;	/* frags per block */
20251155Sbostic 		dpart.part->p_cpg = fs->lfs_segshift;	/* segment shift */
20351155Sbostic #endif
20437737Smckusick 	}
20551155Sbostic 
20651155Sbostic 	/* Don't free random space on error. */
20751155Sbostic 	bp = NULL;
20851155Sbostic 	ump = NULL;
20951155Sbostic 
21051155Sbostic 	/* Read in the superblock. */
21151155Sbostic 	if (error = bread(devvp, LFS_LABELPAD / size, LFS_SBPAD, NOCRED, &bp))
21212795Ssam 		goto out;
21364523Sbostic 	fs = (struct lfs *)bp->b_data;
21451155Sbostic 
21551155Sbostic 	/* Check the basics. */
21651155Sbostic 	if (fs->lfs_magic != LFS_MAGIC || fs->lfs_bsize > MAXBSIZE ||
21751501Sbostic 	    fs->lfs_bsize < sizeof(struct lfs)) {
21841314Smckusick 		error = EINVAL;		/* XXX needs translation */
21916639Skarels 		goto out;
22016639Skarels 	}
22151155Sbostic 
22251155Sbostic 	/* Allocate the mount structure, copy the superblock into it. */
22341314Smckusick 	ump = (struct ufsmount *)malloc(sizeof *ump, M_UFSMNT, M_WAITOK);
22455548Sbostic 	fs = ump->um_lfs = malloc(sizeof(struct lfs), M_UFSMNT, M_WAITOK);
22564523Sbostic 	bcopy(bp->b_data, fs, sizeof(struct lfs));
22651501Sbostic 	if (sizeof(struct lfs) < LFS_SBPAD)			/* XXX why? */
22739675Smckusick 		bp->b_flags |= B_INVAL;
22834421Skarels 	brelse(bp);
22934421Skarels 	bp = NULL;
23051155Sbostic 
23151183Sbostic 	/* Set up the I/O information */
23251183Sbostic 	fs->lfs_iocount = 0;
23351183Sbostic 
23455548Sbostic 	/* Set up the ifile and lock aflags */
23554264Sbostic 	fs->lfs_doifile = 0;
23654264Sbostic 	fs->lfs_writer = 0;
23754264Sbostic 	fs->lfs_dirops = 0;
23855548Sbostic 	fs->lfs_seglock = 0;
23954264Sbostic 
24051155Sbostic 	/* Set the file system readonly/modify bits. */
24151155Sbostic 	fs->lfs_ronly = ronly;
24212795Ssam 	if (ronly == 0)
24351155Sbostic 		fs->lfs_fmod = 1;
24451155Sbostic 
24551155Sbostic 	/* Initialize the mount structure. */
24651155Sbostic 	dev = devvp->v_rdev;
24741397Smckusick 	mp->mnt_data = (qaddr_t)ump;
24841397Smckusick 	mp->mnt_stat.f_fsid.val[0] = (long)dev;
24951991Sbostic 	mp->mnt_stat.f_fsid.val[1] = MOUNT_LFS;
25041397Smckusick 	mp->mnt_flag |= MNT_LOCAL;
25137737Smckusick 	ump->um_mountp = mp;
25237737Smckusick 	ump->um_dev = dev;
25337737Smckusick 	ump->um_devvp = devvp;
25456475Smargo 	ump->um_bptrtodb = 0;
25556475Smargo 	ump->um_seqinc = 1 << fs->lfs_fsbtodb;
25656475Smargo 	ump->um_nindir = fs->lfs_nindir;
25741314Smckusick 	for (i = 0; i < MAXQUOTAS; i++)
25841314Smckusick 		ump->um_quotas[i] = NULLVP;
25952221Sbostic 	devvp->v_specflags |= SI_MOUNTEDON;
26051155Sbostic 
26152221Sbostic 	/*
26252221Sbostic 	 * We use the ifile vnode for almost every operation.  Instead of
26352221Sbostic 	 * retrieving it from the hash table each time we retrieve it here,
26452221Sbostic 	 * artificially increment the reference count and keep a pointer
26552221Sbostic 	 * to it in the incore copy of the superblock.
26652221Sbostic 	 */
26754693Sbostic 	if (error = VFS_VGET(mp, LFS_IFILE_INUM, &vp))
26851155Sbostic 		goto out;
26951155Sbostic 	fs->lfs_ivnode = vp;
27052221Sbostic 	VREF(vp);
27152221Sbostic 	vput(vp);
27251155Sbostic 
27337737Smckusick 	return (0);
27412795Ssam out:
27540872Smckusick 	if (bp)
27640872Smckusick 		brelse(bp);
27751155Sbostic 	(void)VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE, NOCRED, p);
27841314Smckusick 	if (ump) {
27951989Smckusick 		free(ump->um_lfs, M_UFSMNT);
28051501Sbostic 		free(ump, M_UFSMNT);
28141397Smckusick 		mp->mnt_data = (qaddr_t)0;
28232721Smckusick 	}
28337737Smckusick 	return (error);
28412795Ssam }
28512795Ssam 
28639043Smckusick /*
28737737Smckusick  * unmount system call
28837737Smckusick  */
28951155Sbostic lfs_unmount(mp, mntflags, p)
29037737Smckusick 	struct mount *mp;
29141314Smckusick 	int mntflags;
29248036Smckusick 	struct proc *p;
29312795Ssam {
29451501Sbostic 	extern int doforce;
29537737Smckusick 	register struct ufsmount *ump;
29655548Sbostic 	register struct lfs *fs;
29754693Sbostic 	int i, error, flags, ronly;
29812795Ssam 
29954693Sbostic 	flags = 0;
30048065Smckusick 	if (mntflags & MNT_FORCE) {
30165240Smckusick 		if (!doforce || (mp->mnt_flag & MNT_ROOTFS))
30248065Smckusick 			return (EINVAL);
30341314Smckusick 		flags |= FORCECLOSE;
30448065Smckusick 	}
30554264Sbostic 
30654264Sbostic 	ump = VFSTOUFS(mp);
30754264Sbostic 	fs = ump->um_lfs;
30812795Ssam #ifdef QUOTA
30941397Smckusick 	if (mp->mnt_flag & MNT_QUOTA) {
31054264Sbostic 		if (error = vflush(mp, fs->lfs_ivnode, SKIPSYSTEM|flags))
31139898Smckusick 			return (error);
31241314Smckusick 		for (i = 0; i < MAXQUOTAS; i++) {
31341314Smckusick 			if (ump->um_quotas[i] == NULLVP)
31441314Smckusick 				continue;
31550114Smckusick 			quotaoff(p, mp, i);
31641314Smckusick 		}
31739898Smckusick 		/*
31841314Smckusick 		 * Here we fall through to vflush again to ensure
31941314Smckusick 		 * that we have gotten rid of all the system vnodes.
32039898Smckusick 		 */
32141314Smckusick 	}
32212795Ssam #endif
32354693Sbostic 	if (error = vflush(mp, fs->lfs_ivnode, flags))
32439898Smckusick 		return (error);
32555548Sbostic 	fs->lfs_clean = 1;
32654693Sbostic 	if (error = VFS_SYNC(mp, 1, p->p_ucred, p))
32754693Sbostic 		return (error);
32865240Smckusick 	if (fs->lfs_ivnode->v_dirtyblkhd.lh_first)
32954693Sbostic 		panic("lfs_unmount: still dirty blocks on ifile vnode\n");
33055806Sbostic 	vrele(fs->lfs_ivnode);
33154693Sbostic 	vgone(fs->lfs_ivnode);
33254693Sbostic 
33351155Sbostic 	ronly = !fs->lfs_ronly;
33440653Smckusick 	ump->um_devvp->v_specflags &= ~SI_MOUNTEDON;
33554693Sbostic 	error = VOP_CLOSE(ump->um_devvp,
33654693Sbostic 	    ronly ? FREAD : FREAD|FWRITE, NOCRED, p);
33737737Smckusick 	vrele(ump->um_devvp);
33851989Smckusick 	free(fs, M_UFSMNT);
33951501Sbostic 	free(ump, M_UFSMNT);
34041397Smckusick 	mp->mnt_data = (qaddr_t)0;
34141397Smckusick 	mp->mnt_flag &= ~MNT_LOCAL;
34230749Skarels 	return (error);
34312795Ssam }
34412795Ssam 
34537737Smckusick /*
34651559Smckusick  * Return root of a filesystem
34751559Smckusick  */
34851559Smckusick int
34951559Smckusick lfs_root(mp, vpp)
35051559Smckusick 	struct mount *mp;
35151559Smckusick 	struct vnode **vpp;
35251559Smckusick {
35351559Smckusick 	struct vnode *nvp;
35451559Smckusick 	int error;
35551559Smckusick 
35654693Sbostic 	if (error = VFS_VGET(mp, (ino_t)ROOTINO, &nvp))
35751559Smckusick 		return (error);
35851559Smckusick 	*vpp = nvp;
35951559Smckusick 	return (0);
36051559Smckusick }
36151559Smckusick 
36251559Smckusick /*
36337737Smckusick  * Get file system statistics.
36437737Smckusick  */
36551155Sbostic lfs_statfs(mp, sbp, p)
36637737Smckusick 	struct mount *mp;
36737737Smckusick 	register struct statfs *sbp;
36848036Smckusick 	struct proc *p;
36937737Smckusick {
37051501Sbostic 	register struct lfs *fs;
37137737Smckusick 	register struct ufsmount *ump;
37237737Smckusick 
37337737Smckusick 	ump = VFSTOUFS(mp);
37451155Sbostic 	fs = ump->um_lfs;
37551155Sbostic 	if (fs->lfs_magic != LFS_MAGIC)
37651155Sbostic 		panic("lfs_statfs: magic");
37751155Sbostic 	sbp->f_type = MOUNT_LFS;
37851155Sbostic 	sbp->f_bsize = fs->lfs_bsize;
37951943Smckusick 	sbp->f_iosize = fs->lfs_bsize;
38056156Smargo 	sbp->f_blocks = dbtofsb(fs,fs->lfs_dsize);
38155588Sbostic 	sbp->f_bfree = dbtofsb(fs, fs->lfs_bfree);
38251155Sbostic 	sbp->f_bavail = (fs->lfs_dsize * (100 - fs->lfs_minfree) / 100) -
38356368Smargo 		(fs->lfs_dsize - fs->lfs_bfree);
38456156Smargo 	sbp->f_bavail = dbtofsb(fs, sbp->f_bavail);
38551155Sbostic 	sbp->f_files = fs->lfs_nfiles;
38655588Sbostic 	sbp->f_ffree = sbp->f_bfree * INOPB(fs);
38741397Smckusick 	if (sbp != &mp->mnt_stat) {
38841397Smckusick 		bcopy((caddr_t)mp->mnt_stat.f_mntonname,
38940346Smckusick 			(caddr_t)&sbp->f_mntonname[0], MNAMELEN);
39041397Smckusick 		bcopy((caddr_t)mp->mnt_stat.f_mntfromname,
39140346Smckusick 			(caddr_t)&sbp->f_mntfromname[0], MNAMELEN);
39240346Smckusick 	}
39337737Smckusick 	return (0);
39437737Smckusick }
39537737Smckusick 
39637737Smckusick /*
39737737Smckusick  * Go through the disk queues to initiate sandbagged IO;
39837737Smckusick  * go through the inodes to write those that have been modified;
39937737Smckusick  * initiate the writing of the super block if it has been modified.
40041314Smckusick  *
40141314Smckusick  * Note: we are always called with the filesystem marked `MPBUSY'.
40237737Smckusick  */
40354693Sbostic lfs_sync(mp, waitfor, cred, p)
40437737Smckusick 	struct mount *mp;
40537737Smckusick 	int waitfor;
40654693Sbostic 	struct ucred *cred;
40754693Sbostic 	struct proc *p;
40837737Smckusick {
40951215Sbostic 	int error;
41037737Smckusick 
41151310Sbostic 	/* All syncs must be checkpoints until roll-forward is implemented. */
41257068Smargo 	error = lfs_segwrite(mp, SEGM_CKP | (waitfor ? SEGM_SYNC : 0));
41341314Smckusick #ifdef QUOTA
41441314Smckusick 	qsync(mp);
41541314Smckusick #endif
41651215Sbostic 	return (error);
41737737Smckusick }
41851559Smckusick 
41951559Smckusick /*
42054693Sbostic  * Look up an LFS dinode number to find its incore vnode.  If not already
42154693Sbostic  * in core, read it in from the specified device.  Return the inode locked.
42254693Sbostic  * Detection and handling of mount points must be done by the calling routine.
42354693Sbostic  */
42454693Sbostic int
42554693Sbostic lfs_vget(mp, ino, vpp)
42654693Sbostic 	struct mount *mp;
42754693Sbostic 	ino_t ino;
42854693Sbostic 	struct vnode **vpp;
42954693Sbostic {
43054693Sbostic 	register struct lfs *fs;
43154693Sbostic 	register struct inode *ip;
43254693Sbostic 	struct buf *bp;
43354693Sbostic 	struct ifile *ifp;
43454693Sbostic 	struct vnode *vp;
43554693Sbostic 	struct ufsmount *ump;
43654693Sbostic 	daddr_t daddr;
43754693Sbostic 	dev_t dev;
43854693Sbostic 	int error;
43954693Sbostic 
44054693Sbostic 	ump = VFSTOUFS(mp);
44154693Sbostic 	dev = ump->um_dev;
44254693Sbostic 	if ((*vpp = ufs_ihashget(dev, ino)) != NULL)
44354693Sbostic 		return (0);
44454693Sbostic 
44554693Sbostic 	/* Translate the inode number to a disk address. */
44654693Sbostic 	fs = ump->um_lfs;
44754693Sbostic 	if (ino == LFS_IFILE_INUM)
44854693Sbostic 		daddr = fs->lfs_idaddr;
44954693Sbostic 	else {
45054693Sbostic 		LFS_IENTRY(ifp, fs, ino, bp);
45154693Sbostic 		daddr = ifp->if_daddr;
45254693Sbostic 		brelse(bp);
45354693Sbostic 		if (daddr == LFS_UNUSED_DADDR)
45454693Sbostic 			return (ENOENT);
45554693Sbostic 	}
45654693Sbostic 
45754693Sbostic 	/* Allocate new vnode/inode. */
45854693Sbostic 	if (error = lfs_vcreate(mp, ino, &vp)) {
45954693Sbostic 		*vpp = NULL;
46054693Sbostic 		return (error);
46154693Sbostic 	}
46254693Sbostic 
46354693Sbostic 	/*
46454693Sbostic 	 * Put it onto its hash chain and lock it so that other requests for
46554693Sbostic 	 * this inode will block if they arrive while we are sleeping waiting
46654693Sbostic 	 * for old data structures to be purged or for the contents of the
46754693Sbostic 	 * disk portion of this inode to be read.
46854693Sbostic 	 */
46954693Sbostic 	ip = VTOI(vp);
47054693Sbostic 	ufs_ihashins(ip);
47154693Sbostic 
47254693Sbostic 	/*
47354693Sbostic 	 * XXX
47454693Sbostic 	 * This may not need to be here, logically it should go down with
47554693Sbostic 	 * the i_devvp initialization.
47654693Sbostic 	 * Ask Kirk.
47754693Sbostic 	 */
47854693Sbostic 	ip->i_lfs = ump->um_lfs;
47954693Sbostic 
48054693Sbostic 	/* Read in the disk contents for the inode, copy into the inode. */
48154693Sbostic 	if (error =
48254693Sbostic 	    bread(ump->um_devvp, daddr, (int)fs->lfs_bsize, NOCRED, &bp)) {
48354693Sbostic 		/*
48459820Smckusick 		 * The inode does not contain anything useful, so it would
48559820Smckusick 		 * be misleading to leave it on its hash chain. With mode
48659820Smckusick 		 * still zero, it will be unlinked and returned to the free
48759820Smckusick 		 * list by vput().
48854693Sbostic 		 */
48956799Smckusick 		vput(vp);
49054693Sbostic 		brelse(bp);
49154693Sbostic 		*vpp = NULL;
49254693Sbostic 		return (error);
49354693Sbostic 	}
49464523Sbostic 	ip->i_din = *lfs_ifind(fs, ino, (struct dinode *)bp->b_data);
49554693Sbostic 	brelse(bp);
49654693Sbostic 
49754693Sbostic 	/*
49854693Sbostic 	 * Initialize the vnode from the inode, check for aliases.  In all
49954693Sbostic 	 * cases re-init ip, the underlying vnode/inode may have changed.
50054693Sbostic 	 */
50154693Sbostic 	if (error = ufs_vinit(mp, lfs_specop_p, LFS_FIFOOPS, &vp)) {
50256799Smckusick 		vput(vp);
50354693Sbostic 		*vpp = NULL;
50454693Sbostic 		return (error);
50554693Sbostic 	}
50654693Sbostic 	/*
50754693Sbostic 	 * Finish inode initialization now that aliasing has been resolved.
50854693Sbostic 	 */
50954693Sbostic 	ip->i_devvp = ump->um_devvp;
51054693Sbostic 	VREF(ip->i_devvp);
51154693Sbostic 	*vpp = vp;
51254693Sbostic 	return (0);
51354693Sbostic }
51454693Sbostic 
51554693Sbostic /*
51651559Smckusick  * File handle to vnode
51751559Smckusick  *
51851559Smckusick  * Have to be really careful about stale file handles:
51951559Smckusick  * - check that the inode number is valid
52051559Smckusick  * - call lfs_vget() to get the locked inode
52151559Smckusick  * - check for an unallocated inode (i_mode == 0)
52255891Smckusick  * - check that the given client host has export rights and return
52355891Smckusick  *   those rights via. exflagsp and credanonp
52451559Smckusick  *
52551559Smckusick  * XXX
52651559Smckusick  * use ifile to see if inode is allocated instead of reading off disk
52751559Smckusick  * what is the relationship between my generational number and the NFS
52851559Smckusick  * generational number.
52951559Smckusick  */
53051559Smckusick int
53154734Smckusick lfs_fhtovp(mp, fhp, nam, vpp, exflagsp, credanonp)
53251559Smckusick 	register struct mount *mp;
53351559Smckusick 	struct fid *fhp;
53454734Smckusick 	struct mbuf *nam;
53551559Smckusick 	struct vnode **vpp;
53654734Smckusick 	int *exflagsp;
53754734Smckusick 	struct ucred **credanonp;
53851559Smckusick {
53951559Smckusick 	register struct ufid *ufhp;
54051559Smckusick 
54151559Smckusick 	ufhp = (struct ufid *)fhp;
54251559Smckusick 	if (ufhp->ufid_ino < ROOTINO)
54354734Smckusick 		return (ESTALE);
54456246Smckusick 	return (ufs_check_export(mp, ufhp, nam, vpp, exflagsp, credanonp));
54551559Smckusick }
54651559Smckusick 
54751559Smckusick /*
54851559Smckusick  * Vnode pointer to File handle
54951559Smckusick  */
55051559Smckusick /* ARGSUSED */
55151559Smckusick lfs_vptofh(vp, fhp)
55251559Smckusick 	struct vnode *vp;
55351559Smckusick 	struct fid *fhp;
55451559Smckusick {
55551559Smckusick 	register struct inode *ip;
55651559Smckusick 	register struct ufid *ufhp;
55751559Smckusick 
55851559Smckusick 	ip = VTOI(vp);
55951559Smckusick 	ufhp = (struct ufid *)fhp;
56051559Smckusick 	ufhp->ufid_len = sizeof(struct ufid);
56151559Smckusick 	ufhp->ufid_ino = ip->i_number;
56251559Smckusick 	ufhp->ufid_gen = ip->i_gen;
56351559Smckusick 	return (0);
56451559Smckusick }
565