xref: /csrg-svn/sys/ufs/lfs/lfs_vfsops.c (revision 52333)
123400Smckusick /*
250264Skarels  * Copyright (c) 1989, 1991 The Regents of the University of California.
337737Smckusick  * All rights reserved.
423400Smckusick  *
544539Sbostic  * %sccs.include.redist.c%
637737Smckusick  *
7*52333Smckusick  *	@(#)lfs_vfsops.c	7.73 (Berkeley) 02/04/92
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/specdev.h>
1751483Sbostic #include <sys/mount.h>
1851483Sbostic #include <sys/buf.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>
2412795Ssam 
2551501Sbostic #include <ufs/ufs/quota.h>
2651501Sbostic #include <ufs/ufs/inode.h>
2751501Sbostic #include <ufs/ufs/ufsmount.h>
2851501Sbostic #include <ufs/ufs/ufs_extern.h>
2947571Skarels 
3051501Sbostic #include <ufs/lfs/lfs.h>
3151501Sbostic #include <ufs/lfs/lfs_extern.h>
3251155Sbostic 
3351991Sbostic int lfs_mountfs __P((struct vnode *, struct mount *, struct proc *));
3451215Sbostic 
3551155Sbostic struct vfsops lfs_vfsops = {
3651155Sbostic 	lfs_mount,
3739043Smckusick 	ufs_start,
3851155Sbostic 	lfs_unmount,
3951559Smckusick 	lfs_root,
4041314Smckusick 	ufs_quotactl,
4151155Sbostic 	lfs_statfs,
4251155Sbostic 	lfs_sync,
4351559Smckusick 	lfs_fhtovp,
4451559Smckusick 	lfs_vptofh,
4551483Sbostic 	lfs_init,
4637737Smckusick };
4737737Smckusick 
4851483Sbostic int
4951155Sbostic lfs_mountroot()
5012795Ssam {
5151483Sbostic 	panic("lfs_mountroot");		/* XXX -- implement */
5237737Smckusick }
5337737Smckusick 
5437737Smckusick /*
5537737Smckusick  * VFS Operations.
5637737Smckusick  *
5737737Smckusick  * mount system call
5837737Smckusick  */
5951155Sbostic lfs_mount(mp, path, data, ndp, p)
6040346Smckusick 	register struct mount *mp;
6137737Smckusick 	char *path;
6237737Smckusick 	caddr_t data;
6337737Smckusick 	struct nameidata *ndp;
6448036Smckusick 	struct proc *p;
6537737Smckusick {
6637737Smckusick 	struct vnode *devvp;
6737737Smckusick 	struct ufs_args args;
6837737Smckusick 	struct ufsmount *ump;
6951501Sbostic 	register struct lfs *fs;				/* LFS */
7037737Smckusick 	u_int size;
7137737Smckusick 	int error;
7237737Smckusick 
7337737Smckusick 	if (error = copyin(data, (caddr_t)&args, sizeof (struct ufs_args)))
7437737Smckusick 		return (error);
7551483Sbostic 
7651483Sbostic 	/* Until LFS can do NFS right.		XXX */
7751483Sbostic 	if (args.exflags & MNT_EXPORTED)
7851483Sbostic 		return (EINVAL);
7940371Smckusick 	/*
8050264Skarels 	 * If updating, check whether changing from read-only to
8150264Skarels 	 * read/write; if there is no device name, that's all we do.
8250264Skarels 	 */
8350264Skarels 	if (mp->mnt_flag & MNT_UPDATE) {
8439336Smckusick 		ump = VFSTOUFS(mp);
8551155Sbostic #ifdef NOTLFS							/* LFS */
8639336Smckusick 		fs = ump->um_fs;
8741397Smckusick 		if (fs->fs_ronly && (mp->mnt_flag & MNT_RDONLY) == 0)
8839336Smckusick 			fs->fs_ronly = 0;
8951155Sbostic #else
9051155Sbostic 		fs = ump->um_lfs;
9151155Sbostic 		if (fs->lfs_ronly && (mp->mnt_flag & MNT_RDONLY) == 0)
9251155Sbostic 			fs->lfs_ronly = 0;
9351155Sbostic #endif
9452175Smckusick 		if (args.fspec == 0) {
9552175Smckusick 			/*
9652175Smckusick 			 * Process export requests.
9752175Smckusick 			 */
9852175Smckusick 			if (args.exflags & MNT_EXPORTED) {
9952175Smckusick 				if (error = hang_addrlist(mp, &args))
10052175Smckusick 					return (error);
10152175Smckusick 				mp->mnt_flag |= MNT_EXPORTED;
10252175Smckusick 			}
10352175Smckusick 			if (args.exflags & MNT_DELEXPORT) {
10452175Smckusick 				free_addrlist(ump);
10552175Smckusick 				mp->mnt_flag &=
10652175Smckusick 				    ~(MNT_EXPORTED | MNT_DEFEXPORTED);
10752175Smckusick 			}
10840371Smckusick 			return (0);
10952175Smckusick 		}
11050264Skarels 	}
11150264Skarels 	/*
11250264Skarels 	 * Not an update, or updating the name: look up the name
11350264Skarels 	 * and verify that it refers to a sensible block device.
11450264Skarels 	 */
115*52333Smckusick 	NDINIT(ndp, LOOKUP, FOLLOW, UIO_USERSPACE, args.fspec, p);
116*52333Smckusick 	if (error = namei(ndp))
11750264Skarels 		return (error);
11850264Skarels 	devvp = ndp->ni_vp;
11950264Skarels 	if (devvp->v_type != VBLK) {
12050264Skarels 		vrele(devvp);
12150264Skarels 		return (ENOTBLK);
12250264Skarels 	}
12350264Skarels 	if (major(devvp->v_rdev) >= nblkdev) {
12450264Skarels 		vrele(devvp);
12550264Skarels 		return (ENXIO);
12650264Skarels 	}
12750264Skarels 	if ((mp->mnt_flag & MNT_UPDATE) == 0)
12851155Sbostic 		error = lfs_mountfs(devvp, mp, p);		/* LFS */
12950264Skarels 	else {
13039336Smckusick 		if (devvp != ump->um_devvp)
13139336Smckusick 			error = EINVAL;	/* needs translation */
13242858Smckusick 		else
13342858Smckusick 			vrele(devvp);
13439336Smckusick 	}
13537737Smckusick 	if (error) {
13637737Smckusick 		vrele(devvp);
13737737Smckusick 		return (error);
13832721Smckusick 	}
13937737Smckusick 	ump = VFSTOUFS(mp);
14051155Sbostic 	fs = ump->um_lfs;					/* LFS */
14151155Sbostic #ifdef NOTLFS							/* LFS */
14237737Smckusick 	(void) copyinstr(path, fs->fs_fsmnt, sizeof(fs->fs_fsmnt) - 1, &size);
14337737Smckusick 	bzero(fs->fs_fsmnt + size, sizeof(fs->fs_fsmnt) - size);
14441397Smckusick 	bcopy((caddr_t)fs->fs_fsmnt, (caddr_t)mp->mnt_stat.f_mntonname,
14541397Smckusick 	    MNAMELEN);
14651991Sbostic 	(void) copyinstr(args.fspec, mp->mnt_stat.f_mntfromname, MNAMELEN - 1,
14741397Smckusick 	    &size);
14841397Smckusick 	bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
14948036Smckusick 	(void) ufs_statfs(mp, &mp->mnt_stat, p);
15051155Sbostic #else
15151155Sbostic 	(void)copyinstr(path, fs->lfs_fsmnt, sizeof(fs->lfs_fsmnt) - 1, &size);
15251155Sbostic 	bzero(fs->lfs_fsmnt + size, sizeof(fs->lfs_fsmnt) - size);
15351155Sbostic 	bcopy((caddr_t)fs->lfs_fsmnt, (caddr_t)mp->mnt_stat.f_mntonname,
15451155Sbostic 	    MNAMELEN);
15551991Sbostic 	(void) copyinstr(args.fspec, mp->mnt_stat.f_mntfromname, MNAMELEN - 1,
15651155Sbostic 	    &size);
15751155Sbostic 	bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
15851155Sbostic 	(void) lfs_statfs(mp, &mp->mnt_stat, p);
15951155Sbostic #endif
16037737Smckusick 	return (0);
16112795Ssam }
16212795Ssam 
16337737Smckusick /*
16437737Smckusick  * Common code for mount and mountroot
16551155Sbostic  * LFS specific
16637737Smckusick  */
16751991Sbostic int
16851155Sbostic lfs_mountfs(devvp, mp, p)
16940376Smckusick 	register struct vnode *devvp;
17037737Smckusick 	struct mount *mp;
17148036Smckusick 	struct proc *p;
17212795Ssam {
17351155Sbostic 	extern struct vnode *rootvp;
17451501Sbostic 	register struct lfs *fs;
17551155Sbostic 	register struct ufsmount *ump;
17651155Sbostic 	struct vnode *vp;
17751155Sbostic 	struct buf *bp;
17830749Skarels 	struct partinfo dpart;
17951155Sbostic 	dev_t dev;
18051155Sbostic 	int error, i, ronly, size;
18112795Ssam 
18240376Smckusick 	/*
18340376Smckusick 	 * Disallow multiple mounts of the same device.
18445652Smckusick 	 * Disallow mounting of a device that is currently in use
18545652Smckusick 	 * (except for root, which might share swap device for miniroot).
18640376Smckusick 	 * Flush out any old buffers remaining from a previous use.
18740376Smckusick 	 */
18851483Sbostic 	if (error = ufs_mountedon(devvp))
18940376Smckusick 		return (error);
19045652Smckusick 	if (vcount(devvp) > 1 && devvp != rootvp)
19140376Smckusick 		return (EBUSY);
19240376Smckusick 	vinvalbuf(devvp, 1);
19351155Sbostic 
19451155Sbostic 	ronly = (mp->mnt_flag & MNT_RDONLY) != 0;
19548036Smckusick 	if (error = VOP_OPEN(devvp, ronly ? FREAD : FREAD|FWRITE, NOCRED, p))
19637737Smckusick 		return (error);
19751155Sbostic 
19848036Smckusick 	if (VOP_IOCTL(devvp, DIOCGPART, (caddr_t)&dpart, FREAD, NOCRED, p) != 0)
19937737Smckusick 		size = DEV_BSIZE;
20048036Smckusick 	else {
20130749Skarels 		size = dpart.disklab->d_secsize;
20251155Sbostic #ifdef NEVER_USED
20351155Sbostic 		dpart.part->p_fstype = FS_LFS;
20451155Sbostic 		dpart.part->p_fsize = fs->lfs_fsize;	/* frag size */
20551155Sbostic 		dpart.part->p_frag = fs->lfs_frag;	/* frags per block */
20651155Sbostic 		dpart.part->p_cpg = fs->lfs_segshift;	/* segment shift */
20751155Sbostic #endif
20837737Smckusick 	}
20951155Sbostic 
21051155Sbostic 	/* Don't free random space on error. */
21151155Sbostic 	bp = NULL;
21251155Sbostic 	ump = NULL;
21351155Sbostic 
21451155Sbostic 	/* Read in the superblock. */
21551155Sbostic 	if (error = bread(devvp, LFS_LABELPAD / size, LFS_SBPAD, NOCRED, &bp))
21612795Ssam 		goto out;
21751155Sbostic 	fs = bp->b_un.b_lfs;
21851155Sbostic 
21951155Sbostic 	/* Check the basics. */
22051155Sbostic 	if (fs->lfs_magic != LFS_MAGIC || fs->lfs_bsize > MAXBSIZE ||
22151501Sbostic 	    fs->lfs_bsize < sizeof(struct lfs)) {
22241314Smckusick 		error = EINVAL;		/* XXX needs translation */
22316639Skarels 		goto out;
22416639Skarels 	}
22551155Sbostic #ifdef DEBUG
22651483Sbostic 	lfs_dump_super(fs);
22751155Sbostic #endif
22851155Sbostic 
22951155Sbostic 	/* Allocate the mount structure, copy the superblock into it. */
23041314Smckusick 	ump = (struct ufsmount *)malloc(sizeof *ump, M_UFSMNT, M_WAITOK);
23151989Smckusick 	ump->um_lfs = malloc(sizeof(struct lfs), M_UFSMNT, M_WAITOK);
23251501Sbostic 	bcopy(bp->b_un.b_addr, ump->um_lfs, sizeof(struct lfs));
23351501Sbostic 	if (sizeof(struct lfs) < LFS_SBPAD)			/* XXX why? */
23439675Smckusick 		bp->b_flags |= B_INVAL;
23534421Skarels 	brelse(bp);
23634421Skarels 	bp = NULL;
23751155Sbostic 
23851183Sbostic 	/* Set up the I/O information */
23951183Sbostic 	fs->lfs_iocount = 0;
24051183Sbostic 
24151155Sbostic 	/* Set the file system readonly/modify bits. */
24251155Sbostic 	fs = ump->um_lfs;
24351155Sbostic 	fs->lfs_ronly = ronly;
24412795Ssam 	if (ronly == 0)
24551155Sbostic 		fs->lfs_fmod = 1;
24651155Sbostic 
24751155Sbostic 	/* Initialize the mount structure. */
24851155Sbostic 	dev = devvp->v_rdev;
24941397Smckusick 	mp->mnt_data = (qaddr_t)ump;
25041397Smckusick 	mp->mnt_stat.f_fsid.val[0] = (long)dev;
25151991Sbostic 	mp->mnt_stat.f_fsid.val[1] = MOUNT_LFS;
25241397Smckusick 	mp->mnt_flag |= MNT_LOCAL;
25337737Smckusick 	ump->um_mountp = mp;
25437737Smckusick 	ump->um_dev = dev;
25537737Smckusick 	ump->um_devvp = devvp;
25641314Smckusick 	for (i = 0; i < MAXQUOTAS; i++)
25741314Smckusick 		ump->um_quotas[i] = NULLVP;
25852221Sbostic 	devvp->v_specflags |= SI_MOUNTEDON;
25951155Sbostic 
26052221Sbostic 	/*
26152221Sbostic 	 * We use the ifile vnode for almost every operation.  Instead of
26252221Sbostic 	 * retrieving it from the hash table each time we retrieve it here,
26352221Sbostic 	 * artificially increment the reference count and keep a pointer
26452221Sbostic 	 * to it in the incore copy of the superblock.
26552221Sbostic 	 */
26652221Sbostic 	if (error = lfs_vget(mp, LFS_IFILE_INUM, &vp))
26751155Sbostic 		goto out;
26851155Sbostic 	fs->lfs_ivnode = vp;
26952221Sbostic 	VREF(vp);
27052221Sbostic 	vput(vp);
27151155Sbostic 
27237737Smckusick 	return (0);
27312795Ssam out:
27440872Smckusick 	if (bp)
27540872Smckusick 		brelse(bp);
27651155Sbostic 	(void)VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE, NOCRED, p);
27741314Smckusick 	if (ump) {
27851989Smckusick 		free(ump->um_lfs, M_UFSMNT);
27951501Sbostic 		free(ump, M_UFSMNT);
28041397Smckusick 		mp->mnt_data = (qaddr_t)0;
28132721Smckusick 	}
28237737Smckusick 	return (error);
28312795Ssam }
28412795Ssam 
28539043Smckusick /*
28637737Smckusick  * unmount system call
28737737Smckusick  */
28851155Sbostic lfs_unmount(mp, mntflags, p)
28937737Smckusick 	struct mount *mp;
29041314Smckusick 	int mntflags;
29148036Smckusick 	struct proc *p;
29212795Ssam {
29351501Sbostic 	extern int doforce;
29437737Smckusick 	register struct ufsmount *ump;
29551501Sbostic 	register struct lfs *fs;				/* LFS */
29641314Smckusick 	int i, error, ronly, flags = 0;
29751215Sbostic 	int ndirty;						/* LFS */
29812795Ssam 
29951853Sbostic #ifdef VERBOSE
30051853Sbostic 	printf("lfs_unmount\n");
30151853Sbostic #endif
30248065Smckusick 	if (mntflags & MNT_FORCE) {
30348359Smckusick 		if (!doforce || mp == rootfs)
30448065Smckusick 			return (EINVAL);
30541314Smckusick 		flags |= FORCECLOSE;
30648065Smckusick 	}
30751215Sbostic 	if (error = lfs_segwrite(mp, 1))
30851215Sbostic 		return(error);
30951215Sbostic 
31051215Sbostic ndirty = lfs_umountdebug(mp);
31151215Sbostic printf("lfs_umountdebug: returned %d dirty\n", ndirty);
31251215Sbostic return(0);
31339675Smckusick 	if (mntinvalbuf(mp))
31439675Smckusick 		return (EBUSY);
31537737Smckusick 	ump = VFSTOUFS(mp);
31612795Ssam #ifdef QUOTA
31741397Smckusick 	if (mp->mnt_flag & MNT_QUOTA) {
31841314Smckusick 		if (error = vflush(mp, NULLVP, SKIPSYSTEM|flags))
31939898Smckusick 			return (error);
32041314Smckusick 		for (i = 0; i < MAXQUOTAS; i++) {
32141314Smckusick 			if (ump->um_quotas[i] == NULLVP)
32241314Smckusick 				continue;
32350114Smckusick 			quotaoff(p, mp, i);
32441314Smckusick 		}
32539898Smckusick 		/*
32641314Smckusick 		 * Here we fall through to vflush again to ensure
32741314Smckusick 		 * that we have gotten rid of all the system vnodes.
32839898Smckusick 		 */
32941314Smckusick 	}
33012795Ssam #endif
33141314Smckusick 	if (error = vflush(mp, NULLVP, flags))
33239898Smckusick 		return (error);
33351155Sbostic 	fs = ump->um_lfs;
33451155Sbostic 	ronly = !fs->lfs_ronly;
33552221Sbostic 	vrele(fs->lfs_ivnode);
33640653Smckusick 	ump->um_devvp->v_specflags &= ~SI_MOUNTEDON;
33748036Smckusick 	error = VOP_CLOSE(ump->um_devvp, ronly ? FREAD : FREAD|FWRITE,
33848036Smckusick 		NOCRED, p);
33937737Smckusick 	vrele(ump->um_devvp);
34051989Smckusick 	free(fs, M_UFSMNT);
34151501Sbostic 	free(ump, M_UFSMNT);
34241397Smckusick 	mp->mnt_data = (qaddr_t)0;
34341397Smckusick 	mp->mnt_flag &= ~MNT_LOCAL;
34430749Skarels 	return (error);
34512795Ssam }
34612795Ssam 
34737737Smckusick /*
34851559Smckusick  * Return root of a filesystem
34951559Smckusick  */
35051559Smckusick int
35151559Smckusick lfs_root(mp, vpp)
35251559Smckusick 	struct mount *mp;
35351559Smckusick 	struct vnode **vpp;
35451559Smckusick {
35551559Smckusick 	struct vnode *nvp;
35651559Smckusick 	int error;
35751559Smckusick 
35851853Sbostic #ifdef VERBOSE
35951853Sbostic 	printf("lfs_root\n");
36051853Sbostic #endif
36151559Smckusick 	if (error = lfs_vget(mp, (ino_t)ROOTINO, &nvp))
36251559Smckusick 		return (error);
36351559Smckusick 	*vpp = nvp;
36451559Smckusick 	return (0);
36551559Smckusick }
36651559Smckusick 
36751559Smckusick /*
36837737Smckusick  * Get file system statistics.
36937737Smckusick  */
37051155Sbostic lfs_statfs(mp, sbp, p)
37137737Smckusick 	struct mount *mp;
37237737Smckusick 	register struct statfs *sbp;
37348036Smckusick 	struct proc *p;
37437737Smckusick {
37551501Sbostic 	register struct lfs *fs;
37637737Smckusick 	register struct ufsmount *ump;
37737737Smckusick 
37837737Smckusick 	ump = VFSTOUFS(mp);
37951155Sbostic 	fs = ump->um_lfs;
38051155Sbostic 	if (fs->lfs_magic != LFS_MAGIC)
38151155Sbostic 		panic("lfs_statfs: magic");
38251155Sbostic 	sbp->f_type = MOUNT_LFS;
38351155Sbostic 	sbp->f_bsize = fs->lfs_bsize;
38451943Smckusick 	sbp->f_iosize = fs->lfs_bsize;
38551155Sbostic 	sbp->f_blocks = fs->lfs_dsize;
38651155Sbostic 	sbp->f_bfree = fs->lfs_bfree;
38751155Sbostic 	sbp->f_bavail = (fs->lfs_dsize * (100 - fs->lfs_minfree) / 100) -
38851155Sbostic 		(fs->lfs_dsize - sbp->f_bfree);
38951155Sbostic 	sbp->f_files = fs->lfs_nfiles;
39051155Sbostic 	sbp->f_ffree = fs->lfs_bfree * INOPB(fs);
39141397Smckusick 	if (sbp != &mp->mnt_stat) {
39241397Smckusick 		bcopy((caddr_t)mp->mnt_stat.f_mntonname,
39340346Smckusick 			(caddr_t)&sbp->f_mntonname[0], MNAMELEN);
39441397Smckusick 		bcopy((caddr_t)mp->mnt_stat.f_mntfromname,
39540346Smckusick 			(caddr_t)&sbp->f_mntfromname[0], MNAMELEN);
39640346Smckusick 	}
39737737Smckusick 	return (0);
39837737Smckusick }
39937737Smckusick 
40037737Smckusick /*
40137737Smckusick  * Go through the disk queues to initiate sandbagged IO;
40237737Smckusick  * go through the inodes to write those that have been modified;
40337737Smckusick  * initiate the writing of the super block if it has been modified.
40441314Smckusick  *
40541314Smckusick  * Note: we are always called with the filesystem marked `MPBUSY'.
40637737Smckusick  */
40751155Sbostic lfs_sync(mp, waitfor)
40837737Smckusick 	struct mount *mp;
40937737Smckusick 	int waitfor;
41037737Smckusick {
41151914Sbostic 	extern int crashandburn, syncprt;
41251215Sbostic 	int error;
41337737Smckusick 
41451853Sbostic #ifdef VERBOSE
41551853Sbostic 	printf("lfs_sync\n");
41651853Sbostic #endif
41751215Sbostic 
41851914Sbostic #ifdef DIAGNOSTIC
41951914Sbostic 	if (crashandburn)
42051914Sbostic 		return (0);
42151914Sbostic #endif
42237737Smckusick 	if (syncprt)
42351483Sbostic 		ufs_bufstats();
42451310Sbostic 
42551310Sbostic 	/* All syncs must be checkpoints until roll-forward is implemented. */
42651991Sbostic 	error = lfs_segwrite(mp, 1);
42741314Smckusick #ifdef QUOTA
42841314Smckusick 	qsync(mp);
42941314Smckusick #endif
43051215Sbostic 	return (error);
43137737Smckusick }
43251559Smckusick 
43351559Smckusick /*
43451559Smckusick  * File handle to vnode
43551559Smckusick  *
43651559Smckusick  * Have to be really careful about stale file handles:
43751559Smckusick  * - check that the inode number is valid
43851559Smckusick  * - call lfs_vget() to get the locked inode
43951559Smckusick  * - check for an unallocated inode (i_mode == 0)
44051559Smckusick  * - check that the generation number matches
44151559Smckusick  *
44251559Smckusick  * XXX
44351559Smckusick  * use ifile to see if inode is allocated instead of reading off disk
44451559Smckusick  * what is the relationship between my generational number and the NFS
44551559Smckusick  * generational number.
44651559Smckusick  */
44751559Smckusick int
44852175Smckusick lfs_fhtovp(mp, fhp, setgen, vpp)
44951559Smckusick 	register struct mount *mp;
45051559Smckusick 	struct fid *fhp;
45152175Smckusick 	int setgen;
45251559Smckusick 	struct vnode **vpp;
45351559Smckusick {
45451559Smckusick 	register struct inode *ip;
45551559Smckusick 	register struct ufid *ufhp;
45651559Smckusick 	struct vnode *nvp;
45751559Smckusick 	int error;
45851559Smckusick 
45951559Smckusick 	ufhp = (struct ufid *)fhp;
46051559Smckusick 	if (ufhp->ufid_ino < ROOTINO)
46151559Smckusick 		return (EINVAL);
46251559Smckusick 	if (error = lfs_vget(mp, ufhp->ufid_ino, &nvp)) {
46351559Smckusick 		*vpp = NULLVP;
46451559Smckusick 		return (error);
46551559Smckusick 	}
46651559Smckusick 	ip = VTOI(nvp);
46751559Smckusick 	if (ip->i_mode == 0) {
46851559Smckusick 		ufs_iput(ip);
46951559Smckusick 		*vpp = NULLVP;
47051559Smckusick 		return (EINVAL);
47151559Smckusick 	}
47251559Smckusick 	if (ip->i_gen != ufhp->ufid_gen) {
47352175Smckusick 		if (setgen)
47452175Smckusick 			ufhp->ufid_gen = ip->i_gen;
47552175Smckusick 		else {
47652175Smckusick 			ufs_iput(ip);
47752175Smckusick 			*vpp = NULLVP;
47852175Smckusick 			return (EINVAL);
47952175Smckusick 		}
48051559Smckusick 	}
48151559Smckusick 	*vpp = nvp;
48251559Smckusick 	return (0);
48351559Smckusick }
48451559Smckusick 
48551559Smckusick /*
48651559Smckusick  * Vnode pointer to File handle
48751559Smckusick  */
48851559Smckusick /* ARGSUSED */
48951559Smckusick lfs_vptofh(vp, fhp)
49051559Smckusick 	struct vnode *vp;
49151559Smckusick 	struct fid *fhp;
49251559Smckusick {
49351559Smckusick 	register struct inode *ip;
49451559Smckusick 	register struct ufid *ufhp;
49551559Smckusick 
49651559Smckusick 	ip = VTOI(vp);
49751559Smckusick 	ufhp = (struct ufid *)fhp;
49851559Smckusick 	ufhp->ufid_len = sizeof(struct ufid);
49951559Smckusick 	ufhp->ufid_ino = ip->i_number;
50051559Smckusick 	ufhp->ufid_gen = ip->i_gen;
50151559Smckusick 	return (0);
50251559Smckusick }
503