xref: /csrg-svn/sys/ufs/lfs/lfs_vfsops.c (revision 51310)
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*51310Sbostic  *	@(#)lfs_vfsops.c	7.60 (Berkeley) 10/03/91
823400Smckusick  */
912795Ssam 
1051215Sbostic #ifdef LOGFS
1117100Sbloom #include "param.h"
1217100Sbloom #include "systm.h"
1347571Skarels #include "namei.h"
1441314Smckusick #include "proc.h"
1537737Smckusick #include "kernel.h"
1637737Smckusick #include "vnode.h"
1740653Smckusick #include "specdev.h"
1837737Smckusick #include "mount.h"
1917100Sbloom #include "buf.h"
2017100Sbloom #include "file.h"
2137737Smckusick #include "disklabel.h"
2230749Skarels #include "ioctl.h"
2337737Smckusick #include "errno.h"
2431660Smckusick #include "malloc.h"
2512795Ssam 
2651155Sbostic #include "../ufs/quota.h"
2751155Sbostic #include "../ufs/inode.h"
2851155Sbostic #include "../ufs/ufsmount.h"
2951155Sbostic #include "lfs.h"
3051155Sbostic #include "lfs_extern.h"
3147571Skarels 
3251155Sbostic static int	lfs_mountfs
3351155Sbostic 		    __P((struct vnode *, struct mount *, struct proc *));
3451155Sbostic 
3551215Sbostic static int 	lfs_umountdebug __P((struct mount *));
3651215Sbostic static int 	lfs_vinvalbuf __P((register struct vnode *));
3751215Sbostic 
3851155Sbostic struct vfsops lfs_vfsops = {
3951155Sbostic 	lfs_mount,
4039043Smckusick 	ufs_start,
4151155Sbostic 	lfs_unmount,
4251155Sbostic 	lfs_root,
4341314Smckusick 	ufs_quotactl,
4451155Sbostic 	lfs_statfs,
4551155Sbostic 	lfs_sync,
4651155Sbostic 	lfs_fhtovp,
4739437Smckusick 	ufs_vptofh,
4851155Sbostic 	lfs_init
4937737Smckusick };
5037737Smckusick 
5137737Smckusick /*
5248359Smckusick  * Flag to allow forcible unmounting.
5348359Smckusick  */
5451155Sbostic extern int doforce;						/* LFS */
5548359Smckusick 
5651155Sbostic lfs_mountroot()
5712795Ssam {
5851155Sbostic 	/* LFS IMPLEMENT -- lfs_mountroot */
5951155Sbostic 	panic("lfs_mountroot");
6037737Smckusick }
6137737Smckusick 
6237737Smckusick /*
6337737Smckusick  * VFS Operations.
6437737Smckusick  *
6537737Smckusick  * mount system call
6637737Smckusick  */
6751155Sbostic lfs_mount(mp, path, data, ndp, p)
6840346Smckusick 	register struct mount *mp;
6937737Smckusick 	char *path;
7037737Smckusick 	caddr_t data;
7137737Smckusick 	struct nameidata *ndp;
7248036Smckusick 	struct proc *p;
7337737Smckusick {
7437737Smckusick 	struct vnode *devvp;
7537737Smckusick 	struct ufs_args args;
7637737Smckusick 	struct ufsmount *ump;
7751155Sbostic 	register LFS *fs;					/* LFS */
7837737Smckusick 	u_int size;
7937737Smckusick 	int error;
8037737Smckusick 
8137737Smckusick 	if (error = copyin(data, (caddr_t)&args, sizeof (struct ufs_args)))
8237737Smckusick 		return (error);
8340371Smckusick 	/*
8440371Smckusick 	 * Process export requests.
8540371Smckusick 	 */
8641397Smckusick 	if ((args.exflags & MNT_EXPORTED) || (mp->mnt_flag & MNT_EXPORTED)) {
8741397Smckusick 		if (args.exflags & MNT_EXPORTED)
8841397Smckusick 			mp->mnt_flag |= MNT_EXPORTED;
8940371Smckusick 		else
9041397Smckusick 			mp->mnt_flag &= ~MNT_EXPORTED;
9141397Smckusick 		if (args.exflags & MNT_EXRDONLY)
9241397Smckusick 			mp->mnt_flag |= MNT_EXRDONLY;
9340371Smckusick 		else
9441397Smckusick 			mp->mnt_flag &= ~MNT_EXRDONLY;
9541397Smckusick 		mp->mnt_exroot = args.exroot;
9640371Smckusick 	}
9750264Skarels 	/*
9850264Skarels 	 * If updating, check whether changing from read-only to
9950264Skarels 	 * read/write; if there is no device name, that's all we do.
10050264Skarels 	 */
10150264Skarels 	if (mp->mnt_flag & MNT_UPDATE) {
10239336Smckusick 		ump = VFSTOUFS(mp);
10351155Sbostic #ifdef NOTLFS							/* LFS */
10439336Smckusick 		fs = ump->um_fs;
10541397Smckusick 		if (fs->fs_ronly && (mp->mnt_flag & MNT_RDONLY) == 0)
10639336Smckusick 			fs->fs_ronly = 0;
10751155Sbostic #else
10851155Sbostic 		fs = ump->um_lfs;
10951155Sbostic 		if (fs->lfs_ronly && (mp->mnt_flag & MNT_RDONLY) == 0)
11051155Sbostic 			fs->lfs_ronly = 0;
11151155Sbostic #endif
11240371Smckusick 		if (args.fspec == 0)
11340371Smckusick 			return (0);
11450264Skarels 	}
11550264Skarels 	/*
11650264Skarels 	 * Not an update, or updating the name: look up the name
11750264Skarels 	 * and verify that it refers to a sensible block device.
11850264Skarels 	 */
11950264Skarels 	ndp->ni_nameiop = LOOKUP | FOLLOW;
12050264Skarels 	ndp->ni_segflg = UIO_USERSPACE;
12150264Skarels 	ndp->ni_dirp = args.fspec;
12250264Skarels 	if (error = namei(ndp, p))
12350264Skarels 		return (error);
12450264Skarels 	devvp = ndp->ni_vp;
12550264Skarels 	if (devvp->v_type != VBLK) {
12650264Skarels 		vrele(devvp);
12750264Skarels 		return (ENOTBLK);
12850264Skarels 	}
12950264Skarels 	if (major(devvp->v_rdev) >= nblkdev) {
13050264Skarels 		vrele(devvp);
13150264Skarels 		return (ENXIO);
13250264Skarels 	}
13350264Skarels 	if ((mp->mnt_flag & MNT_UPDATE) == 0)
13451155Sbostic 		error = lfs_mountfs(devvp, mp, p);		/* LFS */
13550264Skarels 	else {
13639336Smckusick 		if (devvp != ump->um_devvp)
13739336Smckusick 			error = EINVAL;	/* needs translation */
13842858Smckusick 		else
13942858Smckusick 			vrele(devvp);
14039336Smckusick 	}
14137737Smckusick 	if (error) {
14237737Smckusick 		vrele(devvp);
14337737Smckusick 		return (error);
14432721Smckusick 	}
14537737Smckusick 	ump = VFSTOUFS(mp);
14651155Sbostic 	fs = ump->um_lfs;					/* LFS */
14751155Sbostic #ifdef NOTLFS							/* LFS */
14837737Smckusick 	(void) copyinstr(path, fs->fs_fsmnt, sizeof(fs->fs_fsmnt) - 1, &size);
14937737Smckusick 	bzero(fs->fs_fsmnt + size, sizeof(fs->fs_fsmnt) - size);
15041397Smckusick 	bcopy((caddr_t)fs->fs_fsmnt, (caddr_t)mp->mnt_stat.f_mntonname,
15141397Smckusick 	    MNAMELEN);
15241397Smckusick 	(void) copyinstr(args.fspec, mp->mnt_stat.f_mntfromname, MNAMELEN - 1,
15341397Smckusick 	    &size);
15441397Smckusick 	bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
15548036Smckusick 	(void) ufs_statfs(mp, &mp->mnt_stat, p);
15651155Sbostic #else
15751155Sbostic 	(void)copyinstr(path, fs->lfs_fsmnt, sizeof(fs->lfs_fsmnt) - 1, &size);
15851155Sbostic 	bzero(fs->lfs_fsmnt + size, sizeof(fs->lfs_fsmnt) - size);
15951155Sbostic 	bcopy((caddr_t)fs->lfs_fsmnt, (caddr_t)mp->mnt_stat.f_mntonname,
16051155Sbostic 	    MNAMELEN);
16151155Sbostic 	(void) copyinstr(args.fspec, mp->mnt_stat.f_mntfromname, MNAMELEN - 1,
16251155Sbostic 	    &size);
16351155Sbostic 	bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
16451155Sbostic 	(void) lfs_statfs(mp, &mp->mnt_stat, p);
16551155Sbostic #endif
16637737Smckusick 	return (0);
16712795Ssam }
16812795Ssam 
16937737Smckusick /*
17037737Smckusick  * Common code for mount and mountroot
17151155Sbostic  * LFS specific
17237737Smckusick  */
17351155Sbostic static int
17451155Sbostic lfs_mountfs(devvp, mp, p)
17540376Smckusick 	register struct vnode *devvp;
17637737Smckusick 	struct mount *mp;
17748036Smckusick 	struct proc *p;
17812795Ssam {
17951155Sbostic 	extern struct vnode *rootvp;
18051155Sbostic 	register LFS *fs;
18151155Sbostic 	register struct ufsmount *ump;
18251155Sbostic 	struct inode *ip;
18351155Sbostic 	struct vnode *vp;
18451155Sbostic 	struct buf *bp;
18530749Skarels 	struct partinfo dpart;
18651155Sbostic 	daddr_t seg_addr;
18751155Sbostic 	dev_t dev;
18851155Sbostic 	int error, i, ronly, size;
18912795Ssam 
19040376Smckusick 	/*
19140376Smckusick 	 * Disallow multiple mounts of the same device.
19245652Smckusick 	 * Disallow mounting of a device that is currently in use
19345652Smckusick 	 * (except for root, which might share swap device for miniroot).
19440376Smckusick 	 * Flush out any old buffers remaining from a previous use.
19540376Smckusick 	 */
19640376Smckusick 	if (error = mountedon(devvp))
19740376Smckusick 		return (error);
19845652Smckusick 	if (vcount(devvp) > 1 && devvp != rootvp)
19940376Smckusick 		return (EBUSY);
20040376Smckusick 	vinvalbuf(devvp, 1);
20151155Sbostic 
20251155Sbostic 	ronly = (mp->mnt_flag & MNT_RDONLY) != 0;
20348036Smckusick 	if (error = VOP_OPEN(devvp, ronly ? FREAD : FREAD|FWRITE, NOCRED, p))
20437737Smckusick 		return (error);
20551155Sbostic 
20648036Smckusick 	if (VOP_IOCTL(devvp, DIOCGPART, (caddr_t)&dpart, FREAD, NOCRED, p) != 0)
20737737Smckusick 		size = DEV_BSIZE;
20848036Smckusick 	else {
20930749Skarels 		size = dpart.disklab->d_secsize;
21051155Sbostic #ifdef NEVER_USED
21151155Sbostic 		dpart.part->p_fstype = FS_LFS;
21251155Sbostic 		dpart.part->p_fsize = fs->lfs_fsize;	/* frag size */
21351155Sbostic 		dpart.part->p_frag = fs->lfs_frag;	/* frags per block */
21451155Sbostic 		dpart.part->p_cpg = fs->lfs_segshift;	/* segment shift */
21551155Sbostic #endif
21637737Smckusick 	}
21751155Sbostic 
21851155Sbostic 	/* Don't free random space on error. */
21951155Sbostic 	bp = NULL;
22051155Sbostic 	ump = NULL;
22151155Sbostic 
22251155Sbostic 	/* Read in the superblock. */
22351155Sbostic 	if (error = bread(devvp, LFS_LABELPAD / size, LFS_SBPAD, NOCRED, &bp))
22412795Ssam 		goto out;
22551155Sbostic 	fs = bp->b_un.b_lfs;
22651155Sbostic 
22751155Sbostic 	/* Check the basics. */
22851155Sbostic 	if (fs->lfs_magic != LFS_MAGIC || fs->lfs_bsize > MAXBSIZE ||
22951155Sbostic 	    fs->lfs_bsize < sizeof(LFS)) {
23041314Smckusick 		error = EINVAL;		/* XXX needs translation */
23116639Skarels 		goto out;
23216639Skarels 	}
23351155Sbostic #ifdef DEBUG
23451155Sbostic 	dump_super(fs);
23551155Sbostic #endif
23651155Sbostic 
23751155Sbostic 	/* Allocate the mount structure, copy the superblock into it. */
23841314Smckusick 	ump = (struct ufsmount *)malloc(sizeof *ump, M_UFSMNT, M_WAITOK);
23951155Sbostic 	ump->um_lfs = malloc(sizeof(LFS), M_SUPERBLK, M_WAITOK);
24051155Sbostic 	bcopy(bp->b_un.b_addr, ump->um_lfs, sizeof(LFS));
24151155Sbostic 	if (sizeof(LFS) < LFS_SBPAD)			/* XXX why? */
24239675Smckusick 		bp->b_flags |= B_INVAL;
24334421Skarels 	brelse(bp);
24434421Skarels 	bp = NULL;
24551155Sbostic 
24651183Sbostic 	/* Set up the I/O information */
24751183Sbostic 	fs->lfs_iocount = 0;
24851183Sbostic 	fs->lfs_seglist = NULL;
24951183Sbostic 
25051155Sbostic 	/* Set the file system readonly/modify bits. */
25151155Sbostic 	fs = ump->um_lfs;
25251155Sbostic 	fs->lfs_ronly = ronly;
25312795Ssam 	if (ronly == 0)
25451155Sbostic 		fs->lfs_fmod = 1;
25551155Sbostic 
25651155Sbostic 	/* Initialize the mount structure. */
25751155Sbostic 	dev = devvp->v_rdev;
25841397Smckusick 	mp->mnt_data = (qaddr_t)ump;
25941397Smckusick 	mp->mnt_stat.f_fsid.val[0] = (long)dev;
26051155Sbostic 	mp->mnt_stat.f_fsid.val[1] = MOUNT_LFS;
26141397Smckusick 	mp->mnt_flag |= MNT_LOCAL;
26237737Smckusick 	ump->um_mountp = mp;
26337737Smckusick 	ump->um_dev = dev;
26437737Smckusick 	ump->um_devvp = devvp;
26541314Smckusick 	for (i = 0; i < MAXQUOTAS; i++)
26641314Smckusick 		ump->um_quotas[i] = NULLVP;
26751155Sbostic 
26851155Sbostic 	/* Read the ifile disk inode and store it in a vnode. */
26951155Sbostic 	error = bread(devvp, fs->lfs_idaddr, fs->lfs_bsize, NOCRED, &bp);
27051155Sbostic 	if (error)
27151155Sbostic 		goto out;
27251155Sbostic 	error = lfs_vcreate(mp, LFS_IFILE_INUM, &vp);
27351155Sbostic 	if (error)
27451155Sbostic 		goto out;
27551155Sbostic 	ip = VTOI(vp);
27651155Sbostic 
27751155Sbostic 	/* The ifile inode is stored in the superblock. */
27851155Sbostic 	fs->lfs_ivnode = vp;
27951155Sbostic 
28051155Sbostic 	/* Copy the on-disk inode into place. */
28151155Sbostic 	ip->i_din = *lfs_ifind(fs, LFS_IFILE_INUM, bp->b_un.b_dino);
28251155Sbostic 	brelse(bp);
28351155Sbostic 
28451155Sbostic 	/* Initialize the associated vnode */
28551155Sbostic 	vp->v_type = IFTOVT(ip->i_mode);
28651155Sbostic 
28751155Sbostic 	/*
28851155Sbostic 	 * Read in the segusage table.
28951155Sbostic 	 *
29051155Sbostic 	 * Since we always explicitly write the segusage table at a checkpoint,
29151155Sbostic 	 * we're assuming that it is continguous on disk.
29251155Sbostic 	 */
29351155Sbostic 	seg_addr = ip->i_din.di_db[0];
29451155Sbostic 	size = fs->lfs_segtabsz << fs->lfs_bshift;
29551155Sbostic 	fs->lfs_segtab = malloc(size, M_SUPERBLK, M_WAITOK);
29651155Sbostic 	error = bread(devvp, seg_addr, size, NOCRED, &bp);
29751155Sbostic 	if (error) {
29851155Sbostic 		free(fs->lfs_segtab, M_SUPERBLK);
29951155Sbostic 		goto out;
30051155Sbostic 	}
30151155Sbostic 	bcopy((caddr_t)bp->b_un.b_addr, fs->lfs_segtab, size);
30251155Sbostic 	brelse(bp);
30340653Smckusick 	devvp->v_specflags |= SI_MOUNTEDON;
30451155Sbostic 	VREF(ip->i_devvp);
30537737Smckusick 	return (0);
30612795Ssam out:
30740872Smckusick 	if (bp)
30840872Smckusick 		brelse(bp);
30951155Sbostic 	(void)VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE, NOCRED, p);
31041314Smckusick 	if (ump) {
31151155Sbostic 		free((caddr_t)ump->um_lfs, M_SUPERBLK);
31241314Smckusick 		free((caddr_t)ump, M_UFSMNT);
31341397Smckusick 		mp->mnt_data = (qaddr_t)0;
31432721Smckusick 	}
31537737Smckusick 	return (error);
31612795Ssam }
31712795Ssam 
31839043Smckusick /*
31937737Smckusick  * unmount system call
32037737Smckusick  */
32151155Sbostic lfs_unmount(mp, mntflags, p)
32237737Smckusick 	struct mount *mp;
32341314Smckusick 	int mntflags;
32448036Smckusick 	struct proc *p;
32512795Ssam {
32637737Smckusick 	register struct ufsmount *ump;
32751183Sbostic 	register LFS *fs;					/* LFS */
32841314Smckusick 	int i, error, ronly, flags = 0;
32951215Sbostic 	int ndirty;						/* LFS */
33012795Ssam 
33151155Sbostic printf("lfs_unmount\n");
33248065Smckusick 	if (mntflags & MNT_FORCE) {
33348359Smckusick 		if (!doforce || mp == rootfs)
33448065Smckusick 			return (EINVAL);
33541314Smckusick 		flags |= FORCECLOSE;
33648065Smckusick 	}
33751215Sbostic 	if (error = lfs_segwrite(mp, 1))
33851215Sbostic 		return(error);
33951215Sbostic 
34051215Sbostic ndirty = lfs_umountdebug(mp);
34151215Sbostic printf("lfs_umountdebug: returned %d dirty\n", ndirty);
34251215Sbostic return(0);
34339675Smckusick 	if (mntinvalbuf(mp))
34439675Smckusick 		return (EBUSY);
34537737Smckusick 	ump = VFSTOUFS(mp);
34612795Ssam #ifdef QUOTA
34741397Smckusick 	if (mp->mnt_flag & MNT_QUOTA) {
34841314Smckusick 		if (error = vflush(mp, NULLVP, SKIPSYSTEM|flags))
34939898Smckusick 			return (error);
35041314Smckusick 		for (i = 0; i < MAXQUOTAS; i++) {
35141314Smckusick 			if (ump->um_quotas[i] == NULLVP)
35241314Smckusick 				continue;
35350114Smckusick 			quotaoff(p, mp, i);
35441314Smckusick 		}
35539898Smckusick 		/*
35641314Smckusick 		 * Here we fall through to vflush again to ensure
35741314Smckusick 		 * that we have gotten rid of all the system vnodes.
35839898Smckusick 		 */
35941314Smckusick 	}
36012795Ssam #endif
36141314Smckusick 	if (error = vflush(mp, NULLVP, flags))
36239898Smckusick 		return (error);
36351155Sbostic #ifdef NOTLFS							/* LFS */
36437737Smckusick 	fs = ump->um_fs;
36537737Smckusick 	ronly = !fs->fs_ronly;
36651155Sbostic #else
36751155Sbostic 	fs = ump->um_lfs;
36851155Sbostic 	ronly = !fs->lfs_ronly;
36951155Sbostic #endif
37040653Smckusick 	ump->um_devvp->v_specflags &= ~SI_MOUNTEDON;
37148036Smckusick 	error = VOP_CLOSE(ump->um_devvp, ronly ? FREAD : FREAD|FWRITE,
37248036Smckusick 		NOCRED, p);
37337737Smckusick 	vrele(ump->um_devvp);
37451155Sbostic #ifdef NOTLFS							/* LFS */
37541314Smckusick 	free((caddr_t)fs->fs_csp[0], M_SUPERBLK);
37651155Sbostic #else
37751155Sbostic 	free(fs->lfs_segtab, M_SUPERBLK);
37851155Sbostic 	iput(VTOI(fs->lfs_ivnode));
37951155Sbostic #endif
38041314Smckusick 	free((caddr_t)fs, M_SUPERBLK);
38141314Smckusick 	free((caddr_t)ump, M_UFSMNT);
38241397Smckusick 	mp->mnt_data = (qaddr_t)0;
38341397Smckusick 	mp->mnt_flag &= ~MNT_LOCAL;
38430749Skarels 	return (error);
38512795Ssam }
38612795Ssam 
38737737Smckusick /*
38837737Smckusick  * Return root of a filesystem
38937737Smckusick  */
39051155Sbostic lfs_root(mp, vpp)
39112795Ssam 	struct mount *mp;
39237737Smckusick 	struct vnode **vpp;
39312795Ssam {
39439390Smckusick 	register struct inode *ip;
39539390Smckusick 	struct inode *nip;
39639390Smckusick 	struct vnode tvp;
39737737Smckusick 	int error;
39837737Smckusick 
39939390Smckusick 	tvp.v_mount = mp;
40039390Smckusick 	ip = VTOI(&tvp);
40139390Smckusick 	ip->i_vnode = &tvp;
40239390Smckusick 	ip->i_dev = VFSTOUFS(mp)->um_dev;
40351155Sbostic 	error = lfs_iget(ip, (ino_t)ROOTINO, &nip);		/* LFS */
40437737Smckusick 	if (error)
40537737Smckusick 		return (error);
40639390Smckusick 	*vpp = ITOV(nip);
40737737Smckusick 	return (0);
40837737Smckusick }
40937737Smckusick 
41037737Smckusick /*
41137737Smckusick  * Get file system statistics.
41237737Smckusick  */
41351155Sbostic lfs_statfs(mp, sbp, p)
41437737Smckusick 	struct mount *mp;
41537737Smckusick 	register struct statfs *sbp;
41648036Smckusick 	struct proc *p;
41737737Smckusick {
41851155Sbostic 	register LFS *fs;
41937737Smckusick 	register struct ufsmount *ump;
42037737Smckusick 
42137737Smckusick 	ump = VFSTOUFS(mp);
42251155Sbostic #ifdef NOTLFS							/* LFS */
42337737Smckusick 	fs = ump->um_fs;
42437737Smckusick 	if (fs->fs_magic != FS_MAGIC)
42537737Smckusick 		panic("ufs_statfs");
42637737Smckusick 	sbp->f_type = MOUNT_UFS;
42737737Smckusick 	sbp->f_fsize = fs->fs_fsize;
42837737Smckusick 	sbp->f_bsize = fs->fs_bsize;
42937737Smckusick 	sbp->f_blocks = fs->fs_dsize;
43037737Smckusick 	sbp->f_bfree = fs->fs_cstotal.cs_nbfree * fs->fs_frag +
43137737Smckusick 		fs->fs_cstotal.cs_nffree;
43237737Smckusick 	sbp->f_bavail = (fs->fs_dsize * (100 - fs->fs_minfree) / 100) -
43337737Smckusick 		(fs->fs_dsize - sbp->f_bfree);
43439350Smckusick 	sbp->f_files =  fs->fs_ncg * fs->fs_ipg - ROOTINO;
43537737Smckusick 	sbp->f_ffree = fs->fs_cstotal.cs_nifree;
43651155Sbostic #else
43751155Sbostic 	fs = ump->um_lfs;
43851155Sbostic 	if (fs->lfs_magic != LFS_MAGIC)
43951155Sbostic 		panic("lfs_statfs: magic");
44051155Sbostic 	sbp->f_type = MOUNT_LFS;
44151155Sbostic 	sbp->f_fsize = fs->lfs_bsize;
44251155Sbostic 	sbp->f_bsize = fs->lfs_bsize;
44351155Sbostic 	sbp->f_blocks = fs->lfs_dsize;
44451155Sbostic 	sbp->f_bfree = fs->lfs_bfree;
44551155Sbostic 	sbp->f_bavail = (fs->lfs_dsize * (100 - fs->lfs_minfree) / 100) -
44651155Sbostic 		(fs->lfs_dsize - sbp->f_bfree);
44751155Sbostic 	sbp->f_files = fs->lfs_nfiles;
44851155Sbostic 	sbp->f_ffree = fs->lfs_bfree * INOPB(fs);
44951155Sbostic #endif
45041397Smckusick 	if (sbp != &mp->mnt_stat) {
45141397Smckusick 		bcopy((caddr_t)mp->mnt_stat.f_mntonname,
45240346Smckusick 			(caddr_t)&sbp->f_mntonname[0], MNAMELEN);
45341397Smckusick 		bcopy((caddr_t)mp->mnt_stat.f_mntfromname,
45440346Smckusick 			(caddr_t)&sbp->f_mntfromname[0], MNAMELEN);
45540346Smckusick 	}
45637737Smckusick 	return (0);
45737737Smckusick }
45837737Smckusick 
45951155Sbostic extern int	syncprt;					/* LFS */
46037737Smckusick 
46137737Smckusick /*
46237737Smckusick  * Go through the disk queues to initiate sandbagged IO;
46337737Smckusick  * go through the inodes to write those that have been modified;
46437737Smckusick  * initiate the writing of the super block if it has been modified.
46541314Smckusick  *
46641314Smckusick  * Note: we are always called with the filesystem marked `MPBUSY'.
46737737Smckusick  */
46851215Sbostic int STOPNOW;
46951155Sbostic lfs_sync(mp, waitfor)
47037737Smckusick 	struct mount *mp;
47137737Smckusick 	int waitfor;
47237737Smckusick {
473*51310Sbostic 	static int sync_lock, sync_want;
47451215Sbostic 	int error;
47537737Smckusick 
47651155Sbostic printf("lfs_sync\n");
47751215Sbostic 
47851215Sbostic 	/*
479*51310Sbostic 	 * Meta data blocks are only marked dirty, not busy, so LFS syncs
480*51310Sbostic 	 * must be single threaded.
48151215Sbostic 	 */
482*51310Sbostic 	while (sync_lock) {
483*51310Sbostic 		sync_want = 1;
484*51310Sbostic 		if (error = tsleep(&sync_lock, PLOCK | PCATCH, "lfs sync", 0))
485*51310Sbostic 			return (error);
486*51310Sbostic 	}
487*51310Sbostic 	sync_lock = 1;
48851215Sbostic 
48937737Smckusick 	if (syncprt)
49037737Smckusick 		bufstats();
491*51310Sbostic 
492*51310Sbostic 	/* All syncs must be checkpoints until roll-forward is implemented. */
493*51310Sbostic STOPNOW = 1;
49451215Sbostic 	error = lfs_segwrite(mp, 1);
49541314Smckusick #ifdef QUOTA
49641314Smckusick 	qsync(mp);
49741314Smckusick #endif
498*51310Sbostic 	sync_lock = 0;
499*51310Sbostic 	if (sync_want) {
500*51310Sbostic 		sync_want = 0;
501*51310Sbostic 		wakeup(&sync_lock);
502*51310Sbostic 	}
50351215Sbostic 	return (error);
50437737Smckusick }
50537737Smckusick 
50612795Ssam /*
50737737Smckusick  * File handle to vnode
50838453Smckusick  *
50938453Smckusick  * Have to be really careful about stale file handles:
51038453Smckusick  * - check that the inode number is in range
51138453Smckusick  * - call iget() to get the locked inode
51238453Smckusick  * - check for an unallocated inode (i_mode == 0)
51338453Smckusick  * - check that the generation number matches
51437737Smckusick  */
51551155Sbostic lfs_fhtovp(mp, fhp, vpp)
51638453Smckusick 	register struct mount *mp;
51737737Smckusick 	struct fid *fhp;
51837737Smckusick 	struct vnode **vpp;
51937737Smckusick {
52037737Smckusick 	register struct ufid *ufhp;
52151183Sbostic 	register LFS *fs;					/* LFS */
52239390Smckusick 	register struct inode *ip;
52351155Sbostic 	IFILE *ifp;
52451155Sbostic 	struct buf *bp;
52539390Smckusick 	struct inode *nip;
52639390Smckusick 	struct vnode tvp;
52737737Smckusick 	int error;
52837737Smckusick 
52937737Smckusick 	ufhp = (struct ufid *)fhp;
53051155Sbostic #ifdef NOTLFS							/* LFS */
53138453Smckusick 	fs = VFSTOUFS(mp)->um_fs;
53238453Smckusick 	if (ufhp->ufid_ino < ROOTINO ||
53338453Smckusick 	    ufhp->ufid_ino >= fs->fs_ncg * fs->fs_ipg) {
53441397Smckusick 		*vpp = NULLVP;
53538453Smckusick 		return (EINVAL);
53638453Smckusick 	}
53751155Sbostic #else
53851155Sbostic 	fs = VFSTOUFS(mp)->um_lfs;
53951155Sbostic 	if (ufhp->ufid_ino < ROOTINO) {
54051155Sbostic 		*vpp = NULLVP;
54151155Sbostic 		return (EINVAL);
54251155Sbostic 	}
54351155Sbostic #endif
54439390Smckusick 	tvp.v_mount = mp;
54539390Smckusick 	ip = VTOI(&tvp);
54639390Smckusick 	ip->i_vnode = &tvp;
54739390Smckusick 	ip->i_dev = VFSTOUFS(mp)->um_dev;
54851155Sbostic 	if (error = lfs_iget(ip, ufhp->ufid_ino, &nip)) {	/* LFS */
54941397Smckusick 		*vpp = NULLVP;
55037737Smckusick 		return (error);
55137737Smckusick 	}
55239390Smckusick 	ip = nip;
55338453Smckusick 	if (ip->i_mode == 0) {
55438453Smckusick 		iput(ip);
55541397Smckusick 		*vpp = NULLVP;
55638453Smckusick 		return (EINVAL);
55738453Smckusick 	}
55837737Smckusick 	if (ip->i_gen != ufhp->ufid_gen) {
55937737Smckusick 		iput(ip);
56041397Smckusick 		*vpp = NULLVP;
56137737Smckusick 		return (EINVAL);
56237737Smckusick 	}
56337737Smckusick 	*vpp = ITOV(ip);
56437737Smckusick 	return (0);
56537737Smckusick }
56651215Sbostic 
56751215Sbostic static int
56851215Sbostic lfs_umountdebug(mp)
56951215Sbostic 	struct mount *mp;
57051215Sbostic {
57151215Sbostic 	struct vnode *vp;
57251215Sbostic 	int dirty;
57351215Sbostic 
57451215Sbostic 	dirty = 0;
57551215Sbostic 	if ((mp->mnt_flag & MNT_MPBUSY) == 0)
57651215Sbostic 		panic("umountdebug: not busy");
57751215Sbostic loop:
57851215Sbostic 	for (vp = mp->mnt_mounth; vp; vp = vp->v_mountf) {
57951215Sbostic 		if (vget(vp))
58051215Sbostic 			goto loop;
58151215Sbostic 		dirty += lfs_vinvalbuf(vp);
58251215Sbostic 		vput(vp);
58351215Sbostic 		if (vp->v_mount != mp)
58451215Sbostic 			goto loop;
58551215Sbostic 	}
58651215Sbostic 	return (dirty);
58751215Sbostic }
58851215Sbostic static int
58951215Sbostic lfs_vinvalbuf(vp)
59051215Sbostic 	register struct vnode *vp;
59151215Sbostic {
59251215Sbostic 	register struct buf *bp;
59351215Sbostic 	struct buf *nbp, *blist;
59451215Sbostic 	int s, dirty = 0;
59551215Sbostic 
59651215Sbostic 	for (;;) {
59751215Sbostic 		if (blist = vp->v_dirtyblkhd)
59851215Sbostic 			/* void */;
59951215Sbostic 		else if (blist = vp->v_cleanblkhd)
60051215Sbostic 			/* void */;
60151215Sbostic 		else
60251215Sbostic 			break;
60351215Sbostic 		for (bp = blist; bp; bp = nbp) {
60451215Sbostic printf("lfs_vinvalbuf: ino %d, lblkno %d, blkno %lx flags %xl\n",
60551215Sbostic VTOI(vp)->i_number, bp->b_lblkno, bp->b_blkno, bp->b_flags);
60651215Sbostic 			nbp = bp->b_blockf;
60751215Sbostic 			s = splbio();
60851215Sbostic 			if (bp->b_flags & B_BUSY) {
60951215Sbostic printf("lfs_vinvalbuf: buffer busy, would normally sleep\n");
61051215Sbostic /*
61151215Sbostic 				bp->b_flags |= B_WANTED;
61251215Sbostic 				sleep((caddr_t)bp, PRIBIO + 1);
61351215Sbostic */
61451215Sbostic 				splx(s);
61551215Sbostic 				break;
61651215Sbostic 			}
61751215Sbostic 			bremfree(bp);
61851215Sbostic 			bp->b_flags |= B_BUSY;
61951215Sbostic 			splx(s);
62051215Sbostic 			if (bp->b_flags & B_DELWRI) {
62151215Sbostic 				dirty++;			/* XXX */
62251215Sbostic printf("lfs_vinvalbuf: buffer dirty (DELWRI). would normally write\n");
62351215Sbostic 				break;
62451215Sbostic 			}
62551215Sbostic 			if (bp->b_vp != vp)
62651215Sbostic 				reassignbuf(bp, bp->b_vp);
62751215Sbostic 			else
62851215Sbostic 				bp->b_flags |= B_INVAL;
62951215Sbostic 			brelse(bp);
63051215Sbostic 		}
63151215Sbostic 	}
63251215Sbostic 	if (vp->v_dirtyblkhd || vp->v_cleanblkhd)
63351215Sbostic 		panic("lfs_vinvalbuf: flush failed");
63451215Sbostic 	return (dirty);
63551215Sbostic }
63651215Sbostic #endif /* LOGFS */
637