xref: /csrg-svn/sys/ufs/lfs/lfs_vfsops.c (revision 51483)
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*51483Sbostic  *	@(#)lfs_vfsops.c	7.62 (Berkeley) 11/01/91
823400Smckusick  */
912795Ssam 
10*51483Sbostic #include <sys/param.h>
11*51483Sbostic #include <sys/systm.h>
12*51483Sbostic #include <sys/namei.h>
13*51483Sbostic #include <sys/proc.h>
14*51483Sbostic #include <sys/kernel.h>
15*51483Sbostic #include <sys/vnode.h>
16*51483Sbostic #include <sys/specdev.h>
17*51483Sbostic #include <sys/mount.h>
18*51483Sbostic #include <sys/buf.h>
19*51483Sbostic #include <sys/file.h>
20*51483Sbostic #include <sys/disklabel.h>
21*51483Sbostic #include <sys/ioctl.h>
22*51483Sbostic #include <sys/errno.h>
23*51483Sbostic #include <sys/malloc.h>
2412795Ssam 
25*51483Sbostic #include <ufs/quota.h>
26*51483Sbostic #include <ufs/inode.h>
27*51483Sbostic #include <ufs/ufsmount.h>
28*51483Sbostic #include <ufs/ufs_extern.h>
2947571Skarels 
30*51483Sbostic #include <lfs/lfs.h>
31*51483Sbostic #include <lfs/lfs_extern.h>
3251155Sbostic 
33*51483Sbostic static 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,
39*51483Sbostic 	ufs_root,
4041314Smckusick 	ufs_quotactl,
4151155Sbostic 	lfs_statfs,
4251155Sbostic 	lfs_sync,
43*51483Sbostic 	ufs_fhtovp,
4439437Smckusick 	ufs_vptofh,
45*51483Sbostic 	lfs_init,
4637737Smckusick };
4737737Smckusick 
4837737Smckusick /*
4948359Smckusick  * Flag to allow forcible unmounting.
5048359Smckusick  */
51*51483Sbostic extern int doforce;
5248359Smckusick 
53*51483Sbostic int
5451155Sbostic lfs_mountroot()
5512795Ssam {
56*51483Sbostic 	panic("lfs_mountroot");		/* XXX -- implement */
5737737Smckusick }
5837737Smckusick 
5937737Smckusick /*
6037737Smckusick  * VFS Operations.
6137737Smckusick  *
6237737Smckusick  * mount system call
6337737Smckusick  */
6451155Sbostic lfs_mount(mp, path, data, ndp, p)
6540346Smckusick 	register struct mount *mp;
6637737Smckusick 	char *path;
6737737Smckusick 	caddr_t data;
6837737Smckusick 	struct nameidata *ndp;
6948036Smckusick 	struct proc *p;
7037737Smckusick {
7137737Smckusick 	struct vnode *devvp;
7237737Smckusick 	struct ufs_args args;
7337737Smckusick 	struct ufsmount *ump;
7451155Sbostic 	register LFS *fs;					/* LFS */
7537737Smckusick 	u_int size;
7637737Smckusick 	int error;
7737737Smckusick 
7837737Smckusick 	if (error = copyin(data, (caddr_t)&args, sizeof (struct ufs_args)))
7937737Smckusick 		return (error);
80*51483Sbostic 
81*51483Sbostic 	/* Until LFS can do NFS right.		XXX */
82*51483Sbostic 	if (args.exflags & MNT_EXPORTED)
83*51483Sbostic 		return (EINVAL);
8440371Smckusick 	/*
8540371Smckusick 	 * Process export requests.
8640371Smckusick 	 */
8741397Smckusick 	if ((args.exflags & MNT_EXPORTED) || (mp->mnt_flag & MNT_EXPORTED)) {
8841397Smckusick 		if (args.exflags & MNT_EXPORTED)
8941397Smckusick 			mp->mnt_flag |= MNT_EXPORTED;
9040371Smckusick 		else
9141397Smckusick 			mp->mnt_flag &= ~MNT_EXPORTED;
9241397Smckusick 		if (args.exflags & MNT_EXRDONLY)
9341397Smckusick 			mp->mnt_flag |= MNT_EXRDONLY;
9440371Smckusick 		else
9541397Smckusick 			mp->mnt_flag &= ~MNT_EXRDONLY;
9641397Smckusick 		mp->mnt_exroot = args.exroot;
9740371Smckusick 	}
9850264Skarels 	/*
9950264Skarels 	 * If updating, check whether changing from read-only to
10050264Skarels 	 * read/write; if there is no device name, that's all we do.
10150264Skarels 	 */
10250264Skarels 	if (mp->mnt_flag & MNT_UPDATE) {
10339336Smckusick 		ump = VFSTOUFS(mp);
10451155Sbostic #ifdef NOTLFS							/* LFS */
10539336Smckusick 		fs = ump->um_fs;
10641397Smckusick 		if (fs->fs_ronly && (mp->mnt_flag & MNT_RDONLY) == 0)
10739336Smckusick 			fs->fs_ronly = 0;
10851155Sbostic #else
10951155Sbostic 		fs = ump->um_lfs;
11051155Sbostic 		if (fs->lfs_ronly && (mp->mnt_flag & MNT_RDONLY) == 0)
11151155Sbostic 			fs->lfs_ronly = 0;
11251155Sbostic #endif
11340371Smckusick 		if (args.fspec == 0)
11440371Smckusick 			return (0);
11550264Skarels 	}
11650264Skarels 	/*
11750264Skarels 	 * Not an update, or updating the name: look up the name
11850264Skarels 	 * and verify that it refers to a sensible block device.
11950264Skarels 	 */
12050264Skarels 	ndp->ni_nameiop = LOOKUP | FOLLOW;
12150264Skarels 	ndp->ni_segflg = UIO_USERSPACE;
12250264Skarels 	ndp->ni_dirp = args.fspec;
12350264Skarels 	if (error = namei(ndp, p))
12450264Skarels 		return (error);
12550264Skarels 	devvp = ndp->ni_vp;
12650264Skarels 	if (devvp->v_type != VBLK) {
12750264Skarels 		vrele(devvp);
12850264Skarels 		return (ENOTBLK);
12950264Skarels 	}
13050264Skarels 	if (major(devvp->v_rdev) >= nblkdev) {
13150264Skarels 		vrele(devvp);
13250264Skarels 		return (ENXIO);
13350264Skarels 	}
13450264Skarels 	if ((mp->mnt_flag & MNT_UPDATE) == 0)
13551155Sbostic 		error = lfs_mountfs(devvp, mp, p);		/* LFS */
13650264Skarels 	else {
13739336Smckusick 		if (devvp != ump->um_devvp)
13839336Smckusick 			error = EINVAL;	/* needs translation */
13942858Smckusick 		else
14042858Smckusick 			vrele(devvp);
14139336Smckusick 	}
14237737Smckusick 	if (error) {
14337737Smckusick 		vrele(devvp);
14437737Smckusick 		return (error);
14532721Smckusick 	}
14637737Smckusick 	ump = VFSTOUFS(mp);
14751155Sbostic 	fs = ump->um_lfs;					/* LFS */
14851155Sbostic #ifdef NOTLFS							/* LFS */
14937737Smckusick 	(void) copyinstr(path, fs->fs_fsmnt, sizeof(fs->fs_fsmnt) - 1, &size);
15037737Smckusick 	bzero(fs->fs_fsmnt + size, sizeof(fs->fs_fsmnt) - size);
15141397Smckusick 	bcopy((caddr_t)fs->fs_fsmnt, (caddr_t)mp->mnt_stat.f_mntonname,
15241397Smckusick 	    MNAMELEN);
15341397Smckusick 	(void) copyinstr(args.fspec, mp->mnt_stat.f_mntfromname, MNAMELEN - 1,
15441397Smckusick 	    &size);
15541397Smckusick 	bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
15648036Smckusick 	(void) ufs_statfs(mp, &mp->mnt_stat, p);
15751155Sbostic #else
15851155Sbostic 	(void)copyinstr(path, fs->lfs_fsmnt, sizeof(fs->lfs_fsmnt) - 1, &size);
15951155Sbostic 	bzero(fs->lfs_fsmnt + size, sizeof(fs->lfs_fsmnt) - size);
16051155Sbostic 	bcopy((caddr_t)fs->lfs_fsmnt, (caddr_t)mp->mnt_stat.f_mntonname,
16151155Sbostic 	    MNAMELEN);
16251155Sbostic 	(void) copyinstr(args.fspec, mp->mnt_stat.f_mntfromname, MNAMELEN - 1,
16351155Sbostic 	    &size);
16451155Sbostic 	bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
16551155Sbostic 	(void) lfs_statfs(mp, &mp->mnt_stat, p);
16651155Sbostic #endif
16737737Smckusick 	return (0);
16812795Ssam }
16912795Ssam 
17037737Smckusick /*
17137737Smckusick  * Common code for mount and mountroot
17251155Sbostic  * LFS specific
17337737Smckusick  */
17451155Sbostic static int
17551155Sbostic lfs_mountfs(devvp, mp, p)
17640376Smckusick 	register struct vnode *devvp;
17737737Smckusick 	struct mount *mp;
17848036Smckusick 	struct proc *p;
17912795Ssam {
18051155Sbostic 	extern struct vnode *rootvp;
18151155Sbostic 	register LFS *fs;
18251155Sbostic 	register struct ufsmount *ump;
18351155Sbostic 	struct inode *ip;
18451155Sbostic 	struct vnode *vp;
18551155Sbostic 	struct buf *bp;
18630749Skarels 	struct partinfo dpart;
18751155Sbostic 	daddr_t seg_addr;
18851155Sbostic 	dev_t dev;
18951155Sbostic 	int error, i, ronly, size;
19012795Ssam 
19140376Smckusick 	/*
19240376Smckusick 	 * Disallow multiple mounts of the same device.
19345652Smckusick 	 * Disallow mounting of a device that is currently in use
19445652Smckusick 	 * (except for root, which might share swap device for miniroot).
19540376Smckusick 	 * Flush out any old buffers remaining from a previous use.
19640376Smckusick 	 */
197*51483Sbostic 	if (error = ufs_mountedon(devvp))
19840376Smckusick 		return (error);
19945652Smckusick 	if (vcount(devvp) > 1 && devvp != rootvp)
20040376Smckusick 		return (EBUSY);
20140376Smckusick 	vinvalbuf(devvp, 1);
20251155Sbostic 
20351155Sbostic 	ronly = (mp->mnt_flag & MNT_RDONLY) != 0;
20448036Smckusick 	if (error = VOP_OPEN(devvp, ronly ? FREAD : FREAD|FWRITE, NOCRED, p))
20537737Smckusick 		return (error);
20651155Sbostic 
20748036Smckusick 	if (VOP_IOCTL(devvp, DIOCGPART, (caddr_t)&dpart, FREAD, NOCRED, p) != 0)
20837737Smckusick 		size = DEV_BSIZE;
20948036Smckusick 	else {
21030749Skarels 		size = dpart.disklab->d_secsize;
21151155Sbostic #ifdef NEVER_USED
21251155Sbostic 		dpart.part->p_fstype = FS_LFS;
21351155Sbostic 		dpart.part->p_fsize = fs->lfs_fsize;	/* frag size */
21451155Sbostic 		dpart.part->p_frag = fs->lfs_frag;	/* frags per block */
21551155Sbostic 		dpart.part->p_cpg = fs->lfs_segshift;	/* segment shift */
21651155Sbostic #endif
21737737Smckusick 	}
21851155Sbostic 
21951155Sbostic 	/* Don't free random space on error. */
22051155Sbostic 	bp = NULL;
22151155Sbostic 	ump = NULL;
22251155Sbostic 
22351155Sbostic 	/* Read in the superblock. */
22451155Sbostic 	if (error = bread(devvp, LFS_LABELPAD / size, LFS_SBPAD, NOCRED, &bp))
22512795Ssam 		goto out;
22651155Sbostic 	fs = bp->b_un.b_lfs;
22751155Sbostic 
22851155Sbostic 	/* Check the basics. */
22951155Sbostic 	if (fs->lfs_magic != LFS_MAGIC || fs->lfs_bsize > MAXBSIZE ||
23051155Sbostic 	    fs->lfs_bsize < sizeof(LFS)) {
23141314Smckusick 		error = EINVAL;		/* XXX needs translation */
23216639Skarels 		goto out;
23316639Skarels 	}
23451155Sbostic #ifdef DEBUG
235*51483Sbostic 	lfs_dump_super(fs);
23651155Sbostic #endif
23751155Sbostic 
23851155Sbostic 	/* Allocate the mount structure, copy the superblock into it. */
23941314Smckusick 	ump = (struct ufsmount *)malloc(sizeof *ump, M_UFSMNT, M_WAITOK);
24051155Sbostic 	ump->um_lfs = malloc(sizeof(LFS), M_SUPERBLK, M_WAITOK);
24151155Sbostic 	bcopy(bp->b_un.b_addr, ump->um_lfs, sizeof(LFS));
24251155Sbostic 	if (sizeof(LFS) < LFS_SBPAD)			/* XXX why? */
24339675Smckusick 		bp->b_flags |= B_INVAL;
24434421Skarels 	brelse(bp);
24534421Skarels 	bp = NULL;
24651155Sbostic 
24751183Sbostic 	/* Set up the I/O information */
24851183Sbostic 	fs->lfs_iocount = 0;
24951183Sbostic 	fs->lfs_seglist = NULL;
25051183Sbostic 
25151155Sbostic 	/* Set the file system readonly/modify bits. */
25251155Sbostic 	fs = ump->um_lfs;
25351155Sbostic 	fs->lfs_ronly = ronly;
25412795Ssam 	if (ronly == 0)
25551155Sbostic 		fs->lfs_fmod = 1;
25651155Sbostic 
25751155Sbostic 	/* Initialize the mount structure. */
25851155Sbostic 	dev = devvp->v_rdev;
25941397Smckusick 	mp->mnt_data = (qaddr_t)ump;
26041397Smckusick 	mp->mnt_stat.f_fsid.val[0] = (long)dev;
26151155Sbostic 	mp->mnt_stat.f_fsid.val[1] = MOUNT_LFS;
26241397Smckusick 	mp->mnt_flag |= MNT_LOCAL;
26337737Smckusick 	ump->um_mountp = mp;
26437737Smckusick 	ump->um_dev = dev;
26537737Smckusick 	ump->um_devvp = devvp;
26641314Smckusick 	for (i = 0; i < MAXQUOTAS; i++)
26741314Smckusick 		ump->um_quotas[i] = NULLVP;
26851155Sbostic 
269*51483Sbostic 	/* Initialize UFS glue. */
270*51483Sbostic 	ump->um_blkatoff = lfs_blkatoff;
271*51483Sbostic 	ump->um_write = lfs_write;
272*51483Sbostic 	ump->um_iget = lfs_iget;
273*51483Sbostic 	ump->um_ialloc = lfs_ialloc;
274*51483Sbostic 	ump->um_ifree = lfs_ifree;
275*51483Sbostic 	ump->um_itrunc = lfs_itrunc;
276*51483Sbostic 	ump->um_iupdat = lfs_iupdat;
277*51483Sbostic 	ump->um_bwrite = lfs_bwrite;
278*51483Sbostic 	ump->um_bmap = lfs_bmap;
279*51483Sbostic 
28051155Sbostic 	/* Read the ifile disk inode and store it in a vnode. */
28151155Sbostic 	error = bread(devvp, fs->lfs_idaddr, fs->lfs_bsize, NOCRED, &bp);
28251155Sbostic 	if (error)
28351155Sbostic 		goto out;
28451155Sbostic 	error = lfs_vcreate(mp, LFS_IFILE_INUM, &vp);
28551155Sbostic 	if (error)
28651155Sbostic 		goto out;
28751155Sbostic 	ip = VTOI(vp);
28851155Sbostic 
28951155Sbostic 	/* The ifile inode is stored in the superblock. */
29051155Sbostic 	fs->lfs_ivnode = vp;
29151155Sbostic 
29251155Sbostic 	/* Copy the on-disk inode into place. */
29351155Sbostic 	ip->i_din = *lfs_ifind(fs, LFS_IFILE_INUM, bp->b_un.b_dino);
29451155Sbostic 	brelse(bp);
29551155Sbostic 
29651155Sbostic 	/* Initialize the associated vnode */
29751155Sbostic 	vp->v_type = IFTOVT(ip->i_mode);
29851155Sbostic 
29951155Sbostic 	/*
30051155Sbostic 	 * Read in the segusage table.
30151155Sbostic 	 *
30251155Sbostic 	 * Since we always explicitly write the segusage table at a checkpoint,
30351155Sbostic 	 * we're assuming that it is continguous on disk.
30451155Sbostic 	 */
30551155Sbostic 	seg_addr = ip->i_din.di_db[0];
30651155Sbostic 	size = fs->lfs_segtabsz << fs->lfs_bshift;
30751155Sbostic 	fs->lfs_segtab = malloc(size, M_SUPERBLK, M_WAITOK);
30851155Sbostic 	error = bread(devvp, seg_addr, size, NOCRED, &bp);
30951155Sbostic 	if (error) {
31051155Sbostic 		free(fs->lfs_segtab, M_SUPERBLK);
31151155Sbostic 		goto out;
31251155Sbostic 	}
31351155Sbostic 	bcopy((caddr_t)bp->b_un.b_addr, fs->lfs_segtab, size);
31451155Sbostic 	brelse(bp);
31540653Smckusick 	devvp->v_specflags |= SI_MOUNTEDON;
31651155Sbostic 	VREF(ip->i_devvp);
31737737Smckusick 	return (0);
31812795Ssam out:
31940872Smckusick 	if (bp)
32040872Smckusick 		brelse(bp);
32151155Sbostic 	(void)VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE, NOCRED, p);
32241314Smckusick 	if (ump) {
32351155Sbostic 		free((caddr_t)ump->um_lfs, M_SUPERBLK);
32441314Smckusick 		free((caddr_t)ump, M_UFSMNT);
32541397Smckusick 		mp->mnt_data = (qaddr_t)0;
32632721Smckusick 	}
32737737Smckusick 	return (error);
32812795Ssam }
32912795Ssam 
33039043Smckusick /*
33137737Smckusick  * unmount system call
33237737Smckusick  */
33351155Sbostic lfs_unmount(mp, mntflags, p)
33437737Smckusick 	struct mount *mp;
33541314Smckusick 	int mntflags;
33648036Smckusick 	struct proc *p;
33712795Ssam {
33837737Smckusick 	register struct ufsmount *ump;
33951183Sbostic 	register LFS *fs;					/* LFS */
34041314Smckusick 	int i, error, ronly, flags = 0;
34151215Sbostic 	int ndirty;						/* LFS */
34212795Ssam 
34351155Sbostic printf("lfs_unmount\n");
34448065Smckusick 	if (mntflags & MNT_FORCE) {
34548359Smckusick 		if (!doforce || mp == rootfs)
34648065Smckusick 			return (EINVAL);
34741314Smckusick 		flags |= FORCECLOSE;
34848065Smckusick 	}
34951215Sbostic 	if (error = lfs_segwrite(mp, 1))
35051215Sbostic 		return(error);
35151215Sbostic 
35251215Sbostic ndirty = lfs_umountdebug(mp);
35351215Sbostic printf("lfs_umountdebug: returned %d dirty\n", ndirty);
35451215Sbostic return(0);
35539675Smckusick 	if (mntinvalbuf(mp))
35639675Smckusick 		return (EBUSY);
35737737Smckusick 	ump = VFSTOUFS(mp);
35812795Ssam #ifdef QUOTA
35941397Smckusick 	if (mp->mnt_flag & MNT_QUOTA) {
36041314Smckusick 		if (error = vflush(mp, NULLVP, SKIPSYSTEM|flags))
36139898Smckusick 			return (error);
36241314Smckusick 		for (i = 0; i < MAXQUOTAS; i++) {
36341314Smckusick 			if (ump->um_quotas[i] == NULLVP)
36441314Smckusick 				continue;
36550114Smckusick 			quotaoff(p, mp, i);
36641314Smckusick 		}
36739898Smckusick 		/*
36841314Smckusick 		 * Here we fall through to vflush again to ensure
36941314Smckusick 		 * that we have gotten rid of all the system vnodes.
37039898Smckusick 		 */
37141314Smckusick 	}
37212795Ssam #endif
37341314Smckusick 	if (error = vflush(mp, NULLVP, flags))
37439898Smckusick 		return (error);
37551155Sbostic #ifdef NOTLFS							/* LFS */
37637737Smckusick 	fs = ump->um_fs;
37737737Smckusick 	ronly = !fs->fs_ronly;
37851155Sbostic #else
37951155Sbostic 	fs = ump->um_lfs;
38051155Sbostic 	ronly = !fs->lfs_ronly;
38151155Sbostic #endif
38240653Smckusick 	ump->um_devvp->v_specflags &= ~SI_MOUNTEDON;
38348036Smckusick 	error = VOP_CLOSE(ump->um_devvp, ronly ? FREAD : FREAD|FWRITE,
38448036Smckusick 		NOCRED, p);
38537737Smckusick 	vrele(ump->um_devvp);
38651155Sbostic #ifdef NOTLFS							/* LFS */
38741314Smckusick 	free((caddr_t)fs->fs_csp[0], M_SUPERBLK);
38851155Sbostic #else
38951155Sbostic 	free(fs->lfs_segtab, M_SUPERBLK);
39051155Sbostic 	iput(VTOI(fs->lfs_ivnode));
39151155Sbostic #endif
39241314Smckusick 	free((caddr_t)fs, M_SUPERBLK);
39341314Smckusick 	free((caddr_t)ump, M_UFSMNT);
39441397Smckusick 	mp->mnt_data = (qaddr_t)0;
39541397Smckusick 	mp->mnt_flag &= ~MNT_LOCAL;
39630749Skarels 	return (error);
39712795Ssam }
39812795Ssam 
39937737Smckusick /*
40037737Smckusick  * Get file system statistics.
40137737Smckusick  */
40251155Sbostic lfs_statfs(mp, sbp, p)
40337737Smckusick 	struct mount *mp;
40437737Smckusick 	register struct statfs *sbp;
40548036Smckusick 	struct proc *p;
40637737Smckusick {
40751155Sbostic 	register LFS *fs;
40837737Smckusick 	register struct ufsmount *ump;
40937737Smckusick 
41037737Smckusick 	ump = VFSTOUFS(mp);
41151155Sbostic #ifdef NOTLFS							/* LFS */
41237737Smckusick 	fs = ump->um_fs;
41337737Smckusick 	if (fs->fs_magic != FS_MAGIC)
41437737Smckusick 		panic("ufs_statfs");
41537737Smckusick 	sbp->f_type = MOUNT_UFS;
41637737Smckusick 	sbp->f_fsize = fs->fs_fsize;
41737737Smckusick 	sbp->f_bsize = fs->fs_bsize;
41837737Smckusick 	sbp->f_blocks = fs->fs_dsize;
41937737Smckusick 	sbp->f_bfree = fs->fs_cstotal.cs_nbfree * fs->fs_frag +
42037737Smckusick 		fs->fs_cstotal.cs_nffree;
42137737Smckusick 	sbp->f_bavail = (fs->fs_dsize * (100 - fs->fs_minfree) / 100) -
42237737Smckusick 		(fs->fs_dsize - sbp->f_bfree);
42339350Smckusick 	sbp->f_files =  fs->fs_ncg * fs->fs_ipg - ROOTINO;
42437737Smckusick 	sbp->f_ffree = fs->fs_cstotal.cs_nifree;
42551155Sbostic #else
42651155Sbostic 	fs = ump->um_lfs;
42751155Sbostic 	if (fs->lfs_magic != LFS_MAGIC)
42851155Sbostic 		panic("lfs_statfs: magic");
42951155Sbostic 	sbp->f_type = MOUNT_LFS;
43051155Sbostic 	sbp->f_fsize = fs->lfs_bsize;
43151155Sbostic 	sbp->f_bsize = fs->lfs_bsize;
43251155Sbostic 	sbp->f_blocks = fs->lfs_dsize;
43351155Sbostic 	sbp->f_bfree = fs->lfs_bfree;
43451155Sbostic 	sbp->f_bavail = (fs->lfs_dsize * (100 - fs->lfs_minfree) / 100) -
43551155Sbostic 		(fs->lfs_dsize - sbp->f_bfree);
43651155Sbostic 	sbp->f_files = fs->lfs_nfiles;
43751155Sbostic 	sbp->f_ffree = fs->lfs_bfree * INOPB(fs);
43851155Sbostic #endif
43941397Smckusick 	if (sbp != &mp->mnt_stat) {
44041397Smckusick 		bcopy((caddr_t)mp->mnt_stat.f_mntonname,
44140346Smckusick 			(caddr_t)&sbp->f_mntonname[0], MNAMELEN);
44241397Smckusick 		bcopy((caddr_t)mp->mnt_stat.f_mntfromname,
44340346Smckusick 			(caddr_t)&sbp->f_mntfromname[0], MNAMELEN);
44440346Smckusick 	}
44537737Smckusick 	return (0);
44637737Smckusick }
44737737Smckusick 
44837737Smckusick /*
44937737Smckusick  * Go through the disk queues to initiate sandbagged IO;
45037737Smckusick  * go through the inodes to write those that have been modified;
45137737Smckusick  * initiate the writing of the super block if it has been modified.
45241314Smckusick  *
45341314Smckusick  * Note: we are always called with the filesystem marked `MPBUSY'.
45437737Smckusick  */
45551155Sbostic lfs_sync(mp, waitfor)
45637737Smckusick 	struct mount *mp;
45737737Smckusick 	int waitfor;
45837737Smckusick {
459*51483Sbostic 	extern int syncprt;
46051310Sbostic 	static int sync_lock, sync_want;
46151215Sbostic 	int error;
46237737Smckusick 
46351155Sbostic printf("lfs_sync\n");
46451215Sbostic 
46551215Sbostic 	/*
46651310Sbostic 	 * Meta data blocks are only marked dirty, not busy, so LFS syncs
46751310Sbostic 	 * must be single threaded.
46851215Sbostic 	 */
46951310Sbostic 	while (sync_lock) {
47051310Sbostic 		sync_want = 1;
47151310Sbostic 		if (error = tsleep(&sync_lock, PLOCK | PCATCH, "lfs sync", 0))
47251310Sbostic 			return (error);
47351310Sbostic 	}
47451310Sbostic 	sync_lock = 1;
47551215Sbostic 
47637737Smckusick 	if (syncprt)
477*51483Sbostic 		ufs_bufstats();
47851310Sbostic 
47951310Sbostic 	/* All syncs must be checkpoints until roll-forward is implemented. */
48051215Sbostic 	error = lfs_segwrite(mp, 1);
48141314Smckusick #ifdef QUOTA
48241314Smckusick 	qsync(mp);
48341314Smckusick #endif
48451310Sbostic 	sync_lock = 0;
48551310Sbostic 	if (sync_want) {
48651310Sbostic 		sync_want = 0;
48751310Sbostic 		wakeup(&sync_lock);
48851310Sbostic 	}
48951215Sbostic 	return (error);
49037737Smckusick }
491