xref: /csrg-svn/sys/ufs/lfs/lfs_vfsops.c (revision 69421)
123400Smckusick /*
266805Sbostic  * Copyright (c) 1989, 1991, 1993, 1994
363375Sbostic  *	The Regents of the University of California.  All rights reserved.
423400Smckusick  *
544539Sbostic  * %sccs.include.redist.c%
637737Smckusick  *
7*69421Smckusick  *	@(#)lfs_vfsops.c	8.18 (Berkeley) 05/14/95
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,
4266805Sbostic 	ufs_root,
4341314Smckusick 	ufs_quotactl,
4451155Sbostic 	lfs_statfs,
4551155Sbostic 	lfs_sync,
4654693Sbostic 	lfs_vget,
4751559Smckusick 	lfs_fhtovp,
4851559Smckusick 	lfs_vptofh,
4951483Sbostic 	lfs_init,
5068676Smckusick 	lfs_sysctl,
5137737Smckusick };
5237737Smckusick 
5369369Smckusick /*
5469369Smckusick  * Called by main() when ufs is going to be mounted as root.
5569369Smckusick  */
5651155Sbostic lfs_mountroot()
5712795Ssam {
5869369Smckusick 	extern struct vnode *rootvp;
5969369Smckusick 	struct fs *fs;
6069369Smckusick 	struct mount *mp;
6169369Smckusick 	struct proc *p = curproc;	/* XXX */
6269369Smckusick 	int error;
6369369Smckusick 
6469369Smckusick 	/*
6569369Smckusick 	 * Get vnodes for swapdev and rootdev.
6669369Smckusick 	 */
6769373Smckusick 	if ((error = bdevvp(swapdev, &swapdev_vp)) ||
6869373Smckusick 	    (error = bdevvp(rootdev, &rootvp))) {
6969373Smckusick 		printf("lfs_mountroot: can't setup bdevvp's");
7069373Smckusick 		return (error);
7169373Smckusick 	}
7269369Smckusick 	if (error = vfs_rootmountalloc("lfs", "root_device", &mp))
7369369Smckusick 		return (error);
7469369Smckusick 	if (error = lfs_mountfs(rootvp, mp, p)) {
7569369Smckusick 		mp->mnt_vfc->vfc_refcount--;
7669369Smckusick 		free(mp, M_MOUNT);
7769369Smckusick 		return (error);
7869369Smckusick 	}
7969369Smckusick 	if (error = vfs_lock(mp)) {
8069369Smckusick 		(void)lfs_unmount(mp, 0, p);
8169369Smckusick 		mp->mnt_vfc->vfc_refcount--;
8269369Smckusick 		free(mp, M_MOUNT);
8369369Smckusick 		return (error);
8469369Smckusick 	}
8569369Smckusick 	CIRCLEQ_INSERT_TAIL(&mountlist, mp, mnt_list);
8669369Smckusick 	(void)lfs_statfs(mp, &mp->mnt_stat, p);
8769369Smckusick 	vfs_unlock(mp);
8869369Smckusick 	return (0);
8937737Smckusick }
9037737Smckusick 
9137737Smckusick /*
9237737Smckusick  * VFS Operations.
9337737Smckusick  *
9437737Smckusick  * mount system call
9537737Smckusick  */
9651155Sbostic lfs_mount(mp, path, data, ndp, p)
9740346Smckusick 	register struct mount *mp;
9837737Smckusick 	char *path;
9937737Smckusick 	caddr_t data;
10037737Smckusick 	struct nameidata *ndp;
10148036Smckusick 	struct proc *p;
10237737Smckusick {
10337737Smckusick 	struct vnode *devvp;
10437737Smckusick 	struct ufs_args args;
10537737Smckusick 	struct ufsmount *ump;
10651501Sbostic 	register struct lfs *fs;				/* LFS */
10737737Smckusick 	u_int size;
10837737Smckusick 	int error;
10967533Smckusick 	mode_t accessmode;
11037737Smckusick 
11137737Smckusick 	if (error = copyin(data, (caddr_t)&args, sizeof (struct ufs_args)))
11237737Smckusick 		return (error);
11351483Sbostic 
11451483Sbostic 	/* Until LFS can do NFS right.		XXX */
11565674Shibler 	if (args.export.ex_flags & MNT_EXPORTED)
11651483Sbostic 		return (EINVAL);
11765674Shibler 
11840371Smckusick 	/*
11950264Skarels 	 * If updating, check whether changing from read-only to
12050264Skarels 	 * read/write; if there is no device name, that's all we do.
12150264Skarels 	 */
12250264Skarels 	if (mp->mnt_flag & MNT_UPDATE) {
12339336Smckusick 		ump = VFSTOUFS(mp);
12467533Smckusick 		if (fs->lfs_ronly && (mp->mnt_flag & MNT_WANTRDWR)) {
12567533Smckusick 			/*
12667533Smckusick 			 * If upgrade to read-write by non-root, then verify
12767533Smckusick 			 * that user has necessary permissions on the device.
12867533Smckusick 			 */
12967533Smckusick 			if (p->p_ucred->cr_uid != 0) {
130*69421Smckusick 				vn_lock(ump->um_devvp, LK_EXCLUSIVE | LK_RETRY,
131*69421Smckusick 				    p);
13267533Smckusick 				if (error = VOP_ACCESS(ump->um_devvp,
13367533Smckusick 				    VREAD | VWRITE, p->p_ucred, p)) {
134*69421Smckusick 					VOP_UNLOCK(ump->um_devvp, 0, p);
13567533Smckusick 					return (error);
13667533Smckusick 				}
137*69421Smckusick 				VOP_UNLOCK(ump->um_devvp, 0, p);
13867533Smckusick 			}
13951155Sbostic 			fs->lfs_ronly = 0;
14067533Smckusick 		}
14152175Smckusick 		if (args.fspec == 0) {
14252175Smckusick 			/*
14352175Smckusick 			 * Process export requests.
14452175Smckusick 			 */
14565674Shibler 			return (vfs_export(mp, &ump->um_export, &args.export));
14652175Smckusick 		}
14750264Skarels 	}
14850264Skarels 	/*
14950264Skarels 	 * Not an update, or updating the name: look up the name
15050264Skarels 	 * and verify that it refers to a sensible block device.
15150264Skarels 	 */
15252333Smckusick 	NDINIT(ndp, LOOKUP, FOLLOW, UIO_USERSPACE, args.fspec, p);
15352333Smckusick 	if (error = namei(ndp))
15450264Skarels 		return (error);
15550264Skarels 	devvp = ndp->ni_vp;
15650264Skarels 	if (devvp->v_type != VBLK) {
15750264Skarels 		vrele(devvp);
15850264Skarels 		return (ENOTBLK);
15950264Skarels 	}
16050264Skarels 	if (major(devvp->v_rdev) >= nblkdev) {
16150264Skarels 		vrele(devvp);
16250264Skarels 		return (ENXIO);
16350264Skarels 	}
16467533Smckusick 	/*
16567533Smckusick 	 * If mount by non-root, then verify that user has necessary
16667533Smckusick 	 * permissions on the device.
16767533Smckusick 	 */
16867533Smckusick 	if (p->p_ucred->cr_uid != 0) {
16967533Smckusick 		accessmode = VREAD;
17067533Smckusick 		if ((mp->mnt_flag & MNT_RDONLY) == 0)
17167533Smckusick 			accessmode |= VWRITE;
172*69421Smckusick 		vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p);
17367533Smckusick 		if (error = VOP_ACCESS(devvp, accessmode, p->p_ucred, p)) {
17467533Smckusick 			vput(devvp);
17567533Smckusick 			return (error);
17667533Smckusick 		}
177*69421Smckusick 		VOP_UNLOCK(devvp, 0, p);
17867533Smckusick 	}
17950264Skarels 	if ((mp->mnt_flag & MNT_UPDATE) == 0)
18051155Sbostic 		error = lfs_mountfs(devvp, mp, p);		/* LFS */
18150264Skarels 	else {
18239336Smckusick 		if (devvp != ump->um_devvp)
18339336Smckusick 			error = EINVAL;	/* needs translation */
18442858Smckusick 		else
18542858Smckusick 			vrele(devvp);
18639336Smckusick 	}
18737737Smckusick 	if (error) {
18837737Smckusick 		vrele(devvp);
18937737Smckusick 		return (error);
19032721Smckusick 	}
19137737Smckusick 	ump = VFSTOUFS(mp);
19251155Sbostic 	fs = ump->um_lfs;					/* LFS */
19351155Sbostic #ifdef NOTLFS							/* LFS */
19437737Smckusick 	(void) copyinstr(path, fs->fs_fsmnt, sizeof(fs->fs_fsmnt) - 1, &size);
19537737Smckusick 	bzero(fs->fs_fsmnt + size, sizeof(fs->fs_fsmnt) - size);
19641397Smckusick 	bcopy((caddr_t)fs->fs_fsmnt, (caddr_t)mp->mnt_stat.f_mntonname,
19741397Smckusick 	    MNAMELEN);
19851991Sbostic 	(void) copyinstr(args.fspec, mp->mnt_stat.f_mntfromname, MNAMELEN - 1,
19941397Smckusick 	    &size);
20041397Smckusick 	bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
20148036Smckusick 	(void) ufs_statfs(mp, &mp->mnt_stat, p);
20251155Sbostic #else
20351155Sbostic 	(void)copyinstr(path, fs->lfs_fsmnt, sizeof(fs->lfs_fsmnt) - 1, &size);
20451155Sbostic 	bzero(fs->lfs_fsmnt + size, sizeof(fs->lfs_fsmnt) - size);
20551155Sbostic 	bcopy((caddr_t)fs->lfs_fsmnt, (caddr_t)mp->mnt_stat.f_mntonname,
20651155Sbostic 	    MNAMELEN);
20751991Sbostic 	(void) copyinstr(args.fspec, mp->mnt_stat.f_mntfromname, MNAMELEN - 1,
20851155Sbostic 	    &size);
20951155Sbostic 	bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
21051155Sbostic 	(void) lfs_statfs(mp, &mp->mnt_stat, p);
21151155Sbostic #endif
21237737Smckusick 	return (0);
21312795Ssam }
21412795Ssam 
21537737Smckusick /*
21637737Smckusick  * Common code for mount and mountroot
21751155Sbostic  * LFS specific
21837737Smckusick  */
21951991Sbostic int
22051155Sbostic lfs_mountfs(devvp, mp, p)
22140376Smckusick 	register struct vnode *devvp;
22237737Smckusick 	struct mount *mp;
22348036Smckusick 	struct proc *p;
22412795Ssam {
22551155Sbostic 	extern struct vnode *rootvp;
22651501Sbostic 	register struct lfs *fs;
22751155Sbostic 	register struct ufsmount *ump;
22851155Sbostic 	struct vnode *vp;
22951155Sbostic 	struct buf *bp;
23030749Skarels 	struct partinfo dpart;
23151155Sbostic 	dev_t dev;
23251155Sbostic 	int error, i, ronly, size;
23367949Smckusick 	struct ucred *cred;
23412795Ssam 
23567949Smckusick 	cred = p ? p->p_ucred : NOCRED;
23640376Smckusick 	/*
23740376Smckusick 	 * Disallow multiple mounts of the same device.
23845652Smckusick 	 * Disallow mounting of a device that is currently in use
23945652Smckusick 	 * (except for root, which might share swap device for miniroot).
24040376Smckusick 	 * Flush out any old buffers remaining from a previous use.
24140376Smckusick 	 */
24265674Shibler 	if (error = vfs_mountedon(devvp))
24340376Smckusick 		return (error);
24445652Smckusick 	if (vcount(devvp) > 1 && devvp != rootvp)
24540376Smckusick 		return (EBUSY);
24667949Smckusick 	if (error = vinvalbuf(devvp, V_SAVE, cred, p, 0, 0))
24754693Sbostic 		return (error);
24851155Sbostic 
24951155Sbostic 	ronly = (mp->mnt_flag & MNT_RDONLY) != 0;
25059473Smckusick 	if (error = VOP_OPEN(devvp, ronly ? FREAD : FREAD|FWRITE, FSCRED, p))
25137737Smckusick 		return (error);
25251155Sbostic 
25367949Smckusick 	if (VOP_IOCTL(devvp, DIOCGPART, (caddr_t)&dpart, FREAD, cred, p) != 0)
25437737Smckusick 		size = DEV_BSIZE;
25548036Smckusick 	else {
25630749Skarels 		size = dpart.disklab->d_secsize;
25751155Sbostic #ifdef NEVER_USED
25851155Sbostic 		dpart.part->p_fstype = FS_LFS;
25951155Sbostic 		dpart.part->p_fsize = fs->lfs_fsize;	/* frag size */
26051155Sbostic 		dpart.part->p_frag = fs->lfs_frag;	/* frags per block */
26151155Sbostic 		dpart.part->p_cpg = fs->lfs_segshift;	/* segment shift */
26251155Sbostic #endif
26337737Smckusick 	}
26451155Sbostic 
26551155Sbostic 	/* Don't free random space on error. */
26651155Sbostic 	bp = NULL;
26751155Sbostic 	ump = NULL;
26851155Sbostic 
26951155Sbostic 	/* Read in the superblock. */
27067949Smckusick 	if (error = bread(devvp, LFS_LABELPAD / size, LFS_SBPAD, cred, &bp))
27112795Ssam 		goto out;
27264523Sbostic 	fs = (struct lfs *)bp->b_data;
27351155Sbostic 
27451155Sbostic 	/* Check the basics. */
27551155Sbostic 	if (fs->lfs_magic != LFS_MAGIC || fs->lfs_bsize > MAXBSIZE ||
27651501Sbostic 	    fs->lfs_bsize < sizeof(struct lfs)) {
27741314Smckusick 		error = EINVAL;		/* XXX needs translation */
27816639Skarels 		goto out;
27916639Skarels 	}
28051155Sbostic 
28151155Sbostic 	/* Allocate the mount structure, copy the superblock into it. */
28241314Smckusick 	ump = (struct ufsmount *)malloc(sizeof *ump, M_UFSMNT, M_WAITOK);
28355548Sbostic 	fs = ump->um_lfs = malloc(sizeof(struct lfs), M_UFSMNT, M_WAITOK);
28464523Sbostic 	bcopy(bp->b_data, fs, sizeof(struct lfs));
28551501Sbostic 	if (sizeof(struct lfs) < LFS_SBPAD)			/* XXX why? */
28639675Smckusick 		bp->b_flags |= B_INVAL;
28734421Skarels 	brelse(bp);
28834421Skarels 	bp = NULL;
28951155Sbostic 
29051183Sbostic 	/* Set up the I/O information */
29151183Sbostic 	fs->lfs_iocount = 0;
29251183Sbostic 
29355548Sbostic 	/* Set up the ifile and lock aflags */
29454264Sbostic 	fs->lfs_doifile = 0;
29554264Sbostic 	fs->lfs_writer = 0;
29654264Sbostic 	fs->lfs_dirops = 0;
29755548Sbostic 	fs->lfs_seglock = 0;
29854264Sbostic 
29951155Sbostic 	/* Set the file system readonly/modify bits. */
30051155Sbostic 	fs->lfs_ronly = ronly;
30112795Ssam 	if (ronly == 0)
30251155Sbostic 		fs->lfs_fmod = 1;
30351155Sbostic 
30451155Sbostic 	/* Initialize the mount structure. */
30551155Sbostic 	dev = devvp->v_rdev;
30641397Smckusick 	mp->mnt_data = (qaddr_t)ump;
30741397Smckusick 	mp->mnt_stat.f_fsid.val[0] = (long)dev;
30868676Smckusick 	mp->mnt_stat.f_fsid.val[1] = lfs_mount_type;
30967395Smkm 	mp->mnt_maxsymlinklen = fs->lfs_maxsymlinklen;
31041397Smckusick 	mp->mnt_flag |= MNT_LOCAL;
31137737Smckusick 	ump->um_mountp = mp;
31237737Smckusick 	ump->um_dev = dev;
31337737Smckusick 	ump->um_devvp = devvp;
31456475Smargo 	ump->um_bptrtodb = 0;
31556475Smargo 	ump->um_seqinc = 1 << fs->lfs_fsbtodb;
31656475Smargo 	ump->um_nindir = fs->lfs_nindir;
31741314Smckusick 	for (i = 0; i < MAXQUOTAS; i++)
31841314Smckusick 		ump->um_quotas[i] = NULLVP;
31952221Sbostic 	devvp->v_specflags |= SI_MOUNTEDON;
32051155Sbostic 
32152221Sbostic 	/*
32252221Sbostic 	 * We use the ifile vnode for almost every operation.  Instead of
32352221Sbostic 	 * retrieving it from the hash table each time we retrieve it here,
32452221Sbostic 	 * artificially increment the reference count and keep a pointer
32552221Sbostic 	 * to it in the incore copy of the superblock.
32652221Sbostic 	 */
32754693Sbostic 	if (error = VFS_VGET(mp, LFS_IFILE_INUM, &vp))
32851155Sbostic 		goto out;
32951155Sbostic 	fs->lfs_ivnode = vp;
33052221Sbostic 	VREF(vp);
33152221Sbostic 	vput(vp);
33251155Sbostic 
33337737Smckusick 	return (0);
33412795Ssam out:
33540872Smckusick 	if (bp)
33640872Smckusick 		brelse(bp);
33767949Smckusick 	(void)VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE, cred, p);
33841314Smckusick 	if (ump) {
33951989Smckusick 		free(ump->um_lfs, M_UFSMNT);
34051501Sbostic 		free(ump, M_UFSMNT);
34141397Smckusick 		mp->mnt_data = (qaddr_t)0;
34232721Smckusick 	}
34337737Smckusick 	return (error);
34412795Ssam }
34512795Ssam 
34639043Smckusick /*
34737737Smckusick  * unmount system call
34837737Smckusick  */
34951155Sbostic lfs_unmount(mp, mntflags, p)
35037737Smckusick 	struct mount *mp;
35141314Smckusick 	int mntflags;
35248036Smckusick 	struct proc *p;
35312795Ssam {
35451501Sbostic 	extern int doforce;
35537737Smckusick 	register struct ufsmount *ump;
35655548Sbostic 	register struct lfs *fs;
35754693Sbostic 	int i, error, flags, ronly;
35812795Ssam 
35954693Sbostic 	flags = 0;
36069344Smckusick 	if (mntflags & MNT_FORCE)
36141314Smckusick 		flags |= FORCECLOSE;
36254264Sbostic 
36354264Sbostic 	ump = VFSTOUFS(mp);
36454264Sbostic 	fs = ump->um_lfs;
36512795Ssam #ifdef QUOTA
36641397Smckusick 	if (mp->mnt_flag & MNT_QUOTA) {
36754264Sbostic 		if (error = vflush(mp, fs->lfs_ivnode, SKIPSYSTEM|flags))
36839898Smckusick 			return (error);
36941314Smckusick 		for (i = 0; i < MAXQUOTAS; i++) {
37041314Smckusick 			if (ump->um_quotas[i] == NULLVP)
37141314Smckusick 				continue;
37250114Smckusick 			quotaoff(p, mp, i);
37341314Smckusick 		}
37439898Smckusick 		/*
37541314Smckusick 		 * Here we fall through to vflush again to ensure
37641314Smckusick 		 * that we have gotten rid of all the system vnodes.
37739898Smckusick 		 */
37841314Smckusick 	}
37912795Ssam #endif
38054693Sbostic 	if (error = vflush(mp, fs->lfs_ivnode, flags))
38139898Smckusick 		return (error);
38255548Sbostic 	fs->lfs_clean = 1;
38354693Sbostic 	if (error = VFS_SYNC(mp, 1, p->p_ucred, p))
38454693Sbostic 		return (error);
38565240Smckusick 	if (fs->lfs_ivnode->v_dirtyblkhd.lh_first)
38654693Sbostic 		panic("lfs_unmount: still dirty blocks on ifile vnode\n");
38755806Sbostic 	vrele(fs->lfs_ivnode);
38854693Sbostic 	vgone(fs->lfs_ivnode);
38954693Sbostic 
39051155Sbostic 	ronly = !fs->lfs_ronly;
39140653Smckusick 	ump->um_devvp->v_specflags &= ~SI_MOUNTEDON;
39254693Sbostic 	error = VOP_CLOSE(ump->um_devvp,
39354693Sbostic 	    ronly ? FREAD : FREAD|FWRITE, NOCRED, p);
39437737Smckusick 	vrele(ump->um_devvp);
39551989Smckusick 	free(fs, M_UFSMNT);
39651501Sbostic 	free(ump, M_UFSMNT);
39741397Smckusick 	mp->mnt_data = (qaddr_t)0;
39841397Smckusick 	mp->mnt_flag &= ~MNT_LOCAL;
39930749Skarels 	return (error);
40012795Ssam }
40112795Ssam 
40237737Smckusick /*
40337737Smckusick  * Get file system statistics.
40437737Smckusick  */
40551155Sbostic lfs_statfs(mp, sbp, p)
40637737Smckusick 	struct mount *mp;
40737737Smckusick 	register struct statfs *sbp;
40848036Smckusick 	struct proc *p;
40937737Smckusick {
41051501Sbostic 	register struct lfs *fs;
41137737Smckusick 	register struct ufsmount *ump;
41237737Smckusick 
41337737Smckusick 	ump = VFSTOUFS(mp);
41451155Sbostic 	fs = ump->um_lfs;
41551155Sbostic 	if (fs->lfs_magic != LFS_MAGIC)
41651155Sbostic 		panic("lfs_statfs: magic");
41751155Sbostic 	sbp->f_bsize = fs->lfs_bsize;
41851943Smckusick 	sbp->f_iosize = fs->lfs_bsize;
41956156Smargo 	sbp->f_blocks = dbtofsb(fs,fs->lfs_dsize);
42055588Sbostic 	sbp->f_bfree = dbtofsb(fs, fs->lfs_bfree);
42169293Smckusick 	/*
42269293Smckusick 	 * To compute the available space.  Subtract the minimum free
42369293Smckusick 	 * from the total number of blocks in the file system.  Set avail
42469293Smckusick 	 * to the smaller of this number and fs->lfs_bfree.
42569293Smckusick 	 */
42669293Smckusick 	sbp->f_bavail = fs->lfs_dsize * (100 - fs->lfs_minfree) / 100;
42769293Smckusick 	sbp->f_bavail =
42869293Smckusick 	    sbp->f_bavail > fs->lfs_bfree ? fs->lfs_bfree : sbp->f_bavail;
42956156Smargo 	sbp->f_bavail = dbtofsb(fs, sbp->f_bavail);
43051155Sbostic 	sbp->f_files = fs->lfs_nfiles;
43155588Sbostic 	sbp->f_ffree = sbp->f_bfree * INOPB(fs);
43241397Smckusick 	if (sbp != &mp->mnt_stat) {
43368676Smckusick 		sbp->f_type = mp->mnt_vfc->vfc_typenum;
43441397Smckusick 		bcopy((caddr_t)mp->mnt_stat.f_mntonname,
43540346Smckusick 			(caddr_t)&sbp->f_mntonname[0], MNAMELEN);
43641397Smckusick 		bcopy((caddr_t)mp->mnt_stat.f_mntfromname,
43740346Smckusick 			(caddr_t)&sbp->f_mntfromname[0], MNAMELEN);
43840346Smckusick 	}
43937737Smckusick 	return (0);
44037737Smckusick }
44137737Smckusick 
44237737Smckusick /*
44337737Smckusick  * Go through the disk queues to initiate sandbagged IO;
44437737Smckusick  * go through the inodes to write those that have been modified;
44537737Smckusick  * initiate the writing of the super block if it has been modified.
44641314Smckusick  *
44741314Smckusick  * Note: we are always called with the filesystem marked `MPBUSY'.
44837737Smckusick  */
44954693Sbostic lfs_sync(mp, waitfor, cred, p)
45037737Smckusick 	struct mount *mp;
45137737Smckusick 	int waitfor;
45254693Sbostic 	struct ucred *cred;
45354693Sbostic 	struct proc *p;
45437737Smckusick {
45551215Sbostic 	int error;
45637737Smckusick 
45751310Sbostic 	/* All syncs must be checkpoints until roll-forward is implemented. */
45857068Smargo 	error = lfs_segwrite(mp, SEGM_CKP | (waitfor ? SEGM_SYNC : 0));
45941314Smckusick #ifdef QUOTA
46041314Smckusick 	qsync(mp);
46141314Smckusick #endif
46251215Sbostic 	return (error);
46337737Smckusick }
46451559Smckusick 
46551559Smckusick /*
46654693Sbostic  * Look up an LFS dinode number to find its incore vnode.  If not already
46754693Sbostic  * in core, read it in from the specified device.  Return the inode locked.
46854693Sbostic  * Detection and handling of mount points must be done by the calling routine.
46954693Sbostic  */
47054693Sbostic int
47154693Sbostic lfs_vget(mp, ino, vpp)
47254693Sbostic 	struct mount *mp;
47354693Sbostic 	ino_t ino;
47454693Sbostic 	struct vnode **vpp;
47554693Sbostic {
47654693Sbostic 	register struct lfs *fs;
47754693Sbostic 	register struct inode *ip;
47854693Sbostic 	struct buf *bp;
47954693Sbostic 	struct ifile *ifp;
48054693Sbostic 	struct vnode *vp;
48154693Sbostic 	struct ufsmount *ump;
48268550Smckusick 	ufs_daddr_t daddr;
48354693Sbostic 	dev_t dev;
48454693Sbostic 	int error;
48554693Sbostic 
48654693Sbostic 	ump = VFSTOUFS(mp);
48754693Sbostic 	dev = ump->um_dev;
48854693Sbostic 	if ((*vpp = ufs_ihashget(dev, ino)) != NULL)
48954693Sbostic 		return (0);
49054693Sbostic 
49154693Sbostic 	/* Translate the inode number to a disk address. */
49254693Sbostic 	fs = ump->um_lfs;
49354693Sbostic 	if (ino == LFS_IFILE_INUM)
49454693Sbostic 		daddr = fs->lfs_idaddr;
49554693Sbostic 	else {
49654693Sbostic 		LFS_IENTRY(ifp, fs, ino, bp);
49754693Sbostic 		daddr = ifp->if_daddr;
49854693Sbostic 		brelse(bp);
49954693Sbostic 		if (daddr == LFS_UNUSED_DADDR)
50054693Sbostic 			return (ENOENT);
50154693Sbostic 	}
50254693Sbostic 
50354693Sbostic 	/* Allocate new vnode/inode. */
50454693Sbostic 	if (error = lfs_vcreate(mp, ino, &vp)) {
50554693Sbostic 		*vpp = NULL;
50654693Sbostic 		return (error);
50754693Sbostic 	}
50854693Sbostic 
50954693Sbostic 	/*
51054693Sbostic 	 * Put it onto its hash chain and lock it so that other requests for
51154693Sbostic 	 * this inode will block if they arrive while we are sleeping waiting
51254693Sbostic 	 * for old data structures to be purged or for the contents of the
51354693Sbostic 	 * disk portion of this inode to be read.
51454693Sbostic 	 */
51554693Sbostic 	ip = VTOI(vp);
51654693Sbostic 	ufs_ihashins(ip);
51754693Sbostic 
51854693Sbostic 	/*
51954693Sbostic 	 * XXX
52054693Sbostic 	 * This may not need to be here, logically it should go down with
52154693Sbostic 	 * the i_devvp initialization.
52254693Sbostic 	 * Ask Kirk.
52354693Sbostic 	 */
52454693Sbostic 	ip->i_lfs = ump->um_lfs;
52554693Sbostic 
52654693Sbostic 	/* Read in the disk contents for the inode, copy into the inode. */
52754693Sbostic 	if (error =
52854693Sbostic 	    bread(ump->um_devvp, daddr, (int)fs->lfs_bsize, NOCRED, &bp)) {
52954693Sbostic 		/*
53059820Smckusick 		 * The inode does not contain anything useful, so it would
53159820Smckusick 		 * be misleading to leave it on its hash chain. With mode
53259820Smckusick 		 * still zero, it will be unlinked and returned to the free
53359820Smckusick 		 * list by vput().
53454693Sbostic 		 */
53556799Smckusick 		vput(vp);
53654693Sbostic 		brelse(bp);
53754693Sbostic 		*vpp = NULL;
53854693Sbostic 		return (error);
53954693Sbostic 	}
54064523Sbostic 	ip->i_din = *lfs_ifind(fs, ino, (struct dinode *)bp->b_data);
54154693Sbostic 	brelse(bp);
54254693Sbostic 
54354693Sbostic 	/*
54454693Sbostic 	 * Initialize the vnode from the inode, check for aliases.  In all
54554693Sbostic 	 * cases re-init ip, the underlying vnode/inode may have changed.
54654693Sbostic 	 */
54754693Sbostic 	if (error = ufs_vinit(mp, lfs_specop_p, LFS_FIFOOPS, &vp)) {
54856799Smckusick 		vput(vp);
54954693Sbostic 		*vpp = NULL;
55054693Sbostic 		return (error);
55154693Sbostic 	}
55254693Sbostic 	/*
55354693Sbostic 	 * Finish inode initialization now that aliasing has been resolved.
55454693Sbostic 	 */
55554693Sbostic 	ip->i_devvp = ump->um_devvp;
55654693Sbostic 	VREF(ip->i_devvp);
55754693Sbostic 	*vpp = vp;
55854693Sbostic 	return (0);
55954693Sbostic }
56054693Sbostic 
56154693Sbostic /*
56251559Smckusick  * File handle to vnode
56351559Smckusick  *
56451559Smckusick  * Have to be really careful about stale file handles:
56551559Smckusick  * - check that the inode number is valid
56651559Smckusick  * - call lfs_vget() to get the locked inode
56751559Smckusick  * - check for an unallocated inode (i_mode == 0)
56855891Smckusick  * - check that the given client host has export rights and return
56955891Smckusick  *   those rights via. exflagsp and credanonp
57051559Smckusick  *
57151559Smckusick  * XXX
57251559Smckusick  * use ifile to see if inode is allocated instead of reading off disk
57351559Smckusick  * what is the relationship between my generational number and the NFS
57451559Smckusick  * generational number.
57551559Smckusick  */
57651559Smckusick int
57754734Smckusick lfs_fhtovp(mp, fhp, nam, vpp, exflagsp, credanonp)
57851559Smckusick 	register struct mount *mp;
57951559Smckusick 	struct fid *fhp;
58054734Smckusick 	struct mbuf *nam;
58151559Smckusick 	struct vnode **vpp;
58254734Smckusick 	int *exflagsp;
58354734Smckusick 	struct ucred **credanonp;
58451559Smckusick {
58551559Smckusick 	register struct ufid *ufhp;
58651559Smckusick 
58751559Smckusick 	ufhp = (struct ufid *)fhp;
58851559Smckusick 	if (ufhp->ufid_ino < ROOTINO)
58954734Smckusick 		return (ESTALE);
59056246Smckusick 	return (ufs_check_export(mp, ufhp, nam, vpp, exflagsp, credanonp));
59151559Smckusick }
59251559Smckusick 
59351559Smckusick /*
59451559Smckusick  * Vnode pointer to File handle
59551559Smckusick  */
59651559Smckusick /* ARGSUSED */
59751559Smckusick lfs_vptofh(vp, fhp)
59851559Smckusick 	struct vnode *vp;
59951559Smckusick 	struct fid *fhp;
60051559Smckusick {
60151559Smckusick 	register struct inode *ip;
60251559Smckusick 	register struct ufid *ufhp;
60351559Smckusick 
60451559Smckusick 	ip = VTOI(vp);
60551559Smckusick 	ufhp = (struct ufid *)fhp;
60651559Smckusick 	ufhp->ufid_len = sizeof(struct ufid);
60751559Smckusick 	ufhp->ufid_ino = ip->i_number;
60851559Smckusick 	ufhp->ufid_gen = ip->i_gen;
60951559Smckusick 	return (0);
61051559Smckusick }
61168676Smckusick 
61268676Smckusick /*
61368676Smckusick  * Initialize the filesystem, most work done by ufs_init.
61468676Smckusick  */
61568676Smckusick int lfs_mount_type;
61668676Smckusick 
61768676Smckusick int
61868676Smckusick lfs_init(vfsp)
61968676Smckusick 	struct vfsconf *vfsp;
62068676Smckusick {
62168676Smckusick 
62268676Smckusick 	lfs_mount_type = vfsp->vfc_typenum;
62368676Smckusick 	return (ufs_init(vfsp));
62468676Smckusick }
625