xref: /csrg-svn/sys/ufs/lfs/lfs_vfsops.c (revision 51501)
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*51501Sbostic  *	@(#)lfs_vfsops.c	7.63 (Berkeley) 11/01/91
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 
25*51501Sbostic #include <ufs/ufs/quota.h>
26*51501Sbostic #include <ufs/ufs/inode.h>
27*51501Sbostic #include <ufs/ufs/ufsmount.h>
28*51501Sbostic #include <ufs/ufs/ufs_extern.h>
2947571Skarels 
30*51501Sbostic #include <ufs/lfs/lfs.h>
31*51501Sbostic #include <ufs/lfs/lfs_extern.h>
3251155Sbostic 
3351483Sbostic 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,
3951483Sbostic 	ufs_root,
4041314Smckusick 	ufs_quotactl,
4151155Sbostic 	lfs_statfs,
4251155Sbostic 	lfs_sync,
4351483Sbostic 	ufs_fhtovp,
4439437Smckusick 	ufs_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;
69*51501Sbostic 	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 	/*
8040371Smckusick 	 * Process export requests.
8140371Smckusick 	 */
8241397Smckusick 	if ((args.exflags & MNT_EXPORTED) || (mp->mnt_flag & MNT_EXPORTED)) {
8341397Smckusick 		if (args.exflags & MNT_EXPORTED)
8441397Smckusick 			mp->mnt_flag |= MNT_EXPORTED;
8540371Smckusick 		else
8641397Smckusick 			mp->mnt_flag &= ~MNT_EXPORTED;
8741397Smckusick 		if (args.exflags & MNT_EXRDONLY)
8841397Smckusick 			mp->mnt_flag |= MNT_EXRDONLY;
8940371Smckusick 		else
9041397Smckusick 			mp->mnt_flag &= ~MNT_EXRDONLY;
9141397Smckusick 		mp->mnt_exroot = args.exroot;
9240371Smckusick 	}
9350264Skarels 	/*
9450264Skarels 	 * If updating, check whether changing from read-only to
9550264Skarels 	 * read/write; if there is no device name, that's all we do.
9650264Skarels 	 */
9750264Skarels 	if (mp->mnt_flag & MNT_UPDATE) {
9839336Smckusick 		ump = VFSTOUFS(mp);
9951155Sbostic #ifdef NOTLFS							/* LFS */
10039336Smckusick 		fs = ump->um_fs;
10141397Smckusick 		if (fs->fs_ronly && (mp->mnt_flag & MNT_RDONLY) == 0)
10239336Smckusick 			fs->fs_ronly = 0;
10351155Sbostic #else
10451155Sbostic 		fs = ump->um_lfs;
10551155Sbostic 		if (fs->lfs_ronly && (mp->mnt_flag & MNT_RDONLY) == 0)
10651155Sbostic 			fs->lfs_ronly = 0;
10751155Sbostic #endif
10840371Smckusick 		if (args.fspec == 0)
10940371Smckusick 			return (0);
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 	 */
11550264Skarels 	ndp->ni_nameiop = LOOKUP | FOLLOW;
11650264Skarels 	ndp->ni_segflg = UIO_USERSPACE;
11750264Skarels 	ndp->ni_dirp = args.fspec;
11850264Skarels 	if (error = namei(ndp, p))
11950264Skarels 		return (error);
12050264Skarels 	devvp = ndp->ni_vp;
12150264Skarels 	if (devvp->v_type != VBLK) {
12250264Skarels 		vrele(devvp);
12350264Skarels 		return (ENOTBLK);
12450264Skarels 	}
12550264Skarels 	if (major(devvp->v_rdev) >= nblkdev) {
12650264Skarels 		vrele(devvp);
12750264Skarels 		return (ENXIO);
12850264Skarels 	}
12950264Skarels 	if ((mp->mnt_flag & MNT_UPDATE) == 0)
13051155Sbostic 		error = lfs_mountfs(devvp, mp, p);		/* LFS */
13150264Skarels 	else {
13239336Smckusick 		if (devvp != ump->um_devvp)
13339336Smckusick 			error = EINVAL;	/* needs translation */
13442858Smckusick 		else
13542858Smckusick 			vrele(devvp);
13639336Smckusick 	}
13737737Smckusick 	if (error) {
13837737Smckusick 		vrele(devvp);
13937737Smckusick 		return (error);
14032721Smckusick 	}
14137737Smckusick 	ump = VFSTOUFS(mp);
14251155Sbostic 	fs = ump->um_lfs;					/* LFS */
14351155Sbostic #ifdef NOTLFS							/* LFS */
14437737Smckusick 	(void) copyinstr(path, fs->fs_fsmnt, sizeof(fs->fs_fsmnt) - 1, &size);
14537737Smckusick 	bzero(fs->fs_fsmnt + size, sizeof(fs->fs_fsmnt) - size);
14641397Smckusick 	bcopy((caddr_t)fs->fs_fsmnt, (caddr_t)mp->mnt_stat.f_mntonname,
14741397Smckusick 	    MNAMELEN);
14841397Smckusick 	(void) copyinstr(args.fspec, mp->mnt_stat.f_mntfromname, MNAMELEN - 1,
14941397Smckusick 	    &size);
15041397Smckusick 	bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
15148036Smckusick 	(void) ufs_statfs(mp, &mp->mnt_stat, p);
15251155Sbostic #else
15351155Sbostic 	(void)copyinstr(path, fs->lfs_fsmnt, sizeof(fs->lfs_fsmnt) - 1, &size);
15451155Sbostic 	bzero(fs->lfs_fsmnt + size, sizeof(fs->lfs_fsmnt) - size);
15551155Sbostic 	bcopy((caddr_t)fs->lfs_fsmnt, (caddr_t)mp->mnt_stat.f_mntonname,
15651155Sbostic 	    MNAMELEN);
15751155Sbostic 	(void) copyinstr(args.fspec, mp->mnt_stat.f_mntfromname, MNAMELEN - 1,
15851155Sbostic 	    &size);
15951155Sbostic 	bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
16051155Sbostic 	(void) lfs_statfs(mp, &mp->mnt_stat, p);
16151155Sbostic #endif
16237737Smckusick 	return (0);
16312795Ssam }
16412795Ssam 
16537737Smckusick /*
16637737Smckusick  * Common code for mount and mountroot
16751155Sbostic  * LFS specific
16837737Smckusick  */
16951155Sbostic static int
17051155Sbostic lfs_mountfs(devvp, mp, p)
17140376Smckusick 	register struct vnode *devvp;
17237737Smckusick 	struct mount *mp;
17348036Smckusick 	struct proc *p;
17412795Ssam {
17551155Sbostic 	extern struct vnode *rootvp;
176*51501Sbostic 	register struct lfs *fs;
17751155Sbostic 	register struct ufsmount *ump;
17851155Sbostic 	struct inode *ip;
17951155Sbostic 	struct vnode *vp;
18051155Sbostic 	struct buf *bp;
18130749Skarels 	struct partinfo dpart;
18251155Sbostic 	daddr_t seg_addr;
18351155Sbostic 	dev_t dev;
18451155Sbostic 	int error, i, ronly, size;
18512795Ssam 
18640376Smckusick 	/*
18740376Smckusick 	 * Disallow multiple mounts of the same device.
18845652Smckusick 	 * Disallow mounting of a device that is currently in use
18945652Smckusick 	 * (except for root, which might share swap device for miniroot).
19040376Smckusick 	 * Flush out any old buffers remaining from a previous use.
19140376Smckusick 	 */
19251483Sbostic 	if (error = ufs_mountedon(devvp))
19340376Smckusick 		return (error);
19445652Smckusick 	if (vcount(devvp) > 1 && devvp != rootvp)
19540376Smckusick 		return (EBUSY);
19640376Smckusick 	vinvalbuf(devvp, 1);
19751155Sbostic 
19851155Sbostic 	ronly = (mp->mnt_flag & MNT_RDONLY) != 0;
19948036Smckusick 	if (error = VOP_OPEN(devvp, ronly ? FREAD : FREAD|FWRITE, NOCRED, p))
20037737Smckusick 		return (error);
20151155Sbostic 
20248036Smckusick 	if (VOP_IOCTL(devvp, DIOCGPART, (caddr_t)&dpart, FREAD, NOCRED, p) != 0)
20337737Smckusick 		size = DEV_BSIZE;
20448036Smckusick 	else {
20530749Skarels 		size = dpart.disklab->d_secsize;
20651155Sbostic #ifdef NEVER_USED
20751155Sbostic 		dpart.part->p_fstype = FS_LFS;
20851155Sbostic 		dpart.part->p_fsize = fs->lfs_fsize;	/* frag size */
20951155Sbostic 		dpart.part->p_frag = fs->lfs_frag;	/* frags per block */
21051155Sbostic 		dpart.part->p_cpg = fs->lfs_segshift;	/* segment shift */
21151155Sbostic #endif
21237737Smckusick 	}
21351155Sbostic 
21451155Sbostic 	/* Don't free random space on error. */
21551155Sbostic 	bp = NULL;
21651155Sbostic 	ump = NULL;
21751155Sbostic 
21851155Sbostic 	/* Read in the superblock. */
21951155Sbostic 	if (error = bread(devvp, LFS_LABELPAD / size, LFS_SBPAD, NOCRED, &bp))
22012795Ssam 		goto out;
22151155Sbostic 	fs = bp->b_un.b_lfs;
22251155Sbostic 
22351155Sbostic 	/* Check the basics. */
22451155Sbostic 	if (fs->lfs_magic != LFS_MAGIC || fs->lfs_bsize > MAXBSIZE ||
225*51501Sbostic 	    fs->lfs_bsize < sizeof(struct lfs)) {
22641314Smckusick 		error = EINVAL;		/* XXX needs translation */
22716639Skarels 		goto out;
22816639Skarels 	}
22951155Sbostic #ifdef DEBUG
23051483Sbostic 	lfs_dump_super(fs);
23151155Sbostic #endif
23251155Sbostic 
23351155Sbostic 	/* Allocate the mount structure, copy the superblock into it. */
23441314Smckusick 	ump = (struct ufsmount *)malloc(sizeof *ump, M_UFSMNT, M_WAITOK);
235*51501Sbostic 	ump->um_lfs = malloc(sizeof(struct lfs), M_SUPERBLK, M_WAITOK);
236*51501Sbostic 	bcopy(bp->b_un.b_addr, ump->um_lfs, sizeof(struct lfs));
237*51501Sbostic 	if (sizeof(struct lfs) < LFS_SBPAD)			/* XXX why? */
23839675Smckusick 		bp->b_flags |= B_INVAL;
23934421Skarels 	brelse(bp);
24034421Skarels 	bp = NULL;
24151155Sbostic 
24251183Sbostic 	/* Set up the I/O information */
24351183Sbostic 	fs->lfs_iocount = 0;
24451183Sbostic 	fs->lfs_seglist = NULL;
24551183Sbostic 
24651155Sbostic 	/* Set the file system readonly/modify bits. */
24751155Sbostic 	fs = ump->um_lfs;
24851155Sbostic 	fs->lfs_ronly = ronly;
24912795Ssam 	if (ronly == 0)
25051155Sbostic 		fs->lfs_fmod = 1;
25151155Sbostic 
25251155Sbostic 	/* Initialize the mount structure. */
25351155Sbostic 	dev = devvp->v_rdev;
25441397Smckusick 	mp->mnt_data = (qaddr_t)ump;
25541397Smckusick 	mp->mnt_stat.f_fsid.val[0] = (long)dev;
25651155Sbostic 	mp->mnt_stat.f_fsid.val[1] = MOUNT_LFS;
25741397Smckusick 	mp->mnt_flag |= MNT_LOCAL;
25837737Smckusick 	ump->um_mountp = mp;
25937737Smckusick 	ump->um_dev = dev;
26037737Smckusick 	ump->um_devvp = devvp;
26141314Smckusick 	for (i = 0; i < MAXQUOTAS; i++)
26241314Smckusick 		ump->um_quotas[i] = NULLVP;
26351155Sbostic 
26451483Sbostic 	/* Initialize UFS glue. */
26551483Sbostic 	ump->um_blkatoff = lfs_blkatoff;
26651483Sbostic 	ump->um_write = lfs_write;
26751483Sbostic 	ump->um_iget = lfs_iget;
26851483Sbostic 	ump->um_ialloc = lfs_ialloc;
26951483Sbostic 	ump->um_ifree = lfs_ifree;
27051483Sbostic 	ump->um_itrunc = lfs_itrunc;
27151483Sbostic 	ump->um_iupdat = lfs_iupdat;
27251483Sbostic 	ump->um_bwrite = lfs_bwrite;
27351483Sbostic 	ump->um_bmap = lfs_bmap;
27451483Sbostic 
27551155Sbostic 	/* Read the ifile disk inode and store it in a vnode. */
27651155Sbostic 	error = bread(devvp, fs->lfs_idaddr, fs->lfs_bsize, NOCRED, &bp);
27751155Sbostic 	if (error)
27851155Sbostic 		goto out;
27951155Sbostic 	error = lfs_vcreate(mp, LFS_IFILE_INUM, &vp);
28051155Sbostic 	if (error)
28151155Sbostic 		goto out;
28251155Sbostic 	ip = VTOI(vp);
28351155Sbostic 
28451155Sbostic 	/* The ifile inode is stored in the superblock. */
28551155Sbostic 	fs->lfs_ivnode = vp;
28651155Sbostic 
28751155Sbostic 	/* Copy the on-disk inode into place. */
28851155Sbostic 	ip->i_din = *lfs_ifind(fs, LFS_IFILE_INUM, bp->b_un.b_dino);
28951155Sbostic 	brelse(bp);
29051155Sbostic 
29151155Sbostic 	/* Initialize the associated vnode */
29251155Sbostic 	vp->v_type = IFTOVT(ip->i_mode);
29351155Sbostic 
29451155Sbostic 	/*
29551155Sbostic 	 * Read in the segusage table.
29651155Sbostic 	 *
29751155Sbostic 	 * Since we always explicitly write the segusage table at a checkpoint,
29851155Sbostic 	 * we're assuming that it is continguous on disk.
29951155Sbostic 	 */
30051155Sbostic 	seg_addr = ip->i_din.di_db[0];
30151155Sbostic 	size = fs->lfs_segtabsz << fs->lfs_bshift;
30251155Sbostic 	fs->lfs_segtab = malloc(size, M_SUPERBLK, M_WAITOK);
30351155Sbostic 	error = bread(devvp, seg_addr, size, NOCRED, &bp);
30451155Sbostic 	if (error) {
30551155Sbostic 		free(fs->lfs_segtab, M_SUPERBLK);
30651155Sbostic 		goto out;
30751155Sbostic 	}
30851155Sbostic 	bcopy((caddr_t)bp->b_un.b_addr, fs->lfs_segtab, size);
30951155Sbostic 	brelse(bp);
31040653Smckusick 	devvp->v_specflags |= SI_MOUNTEDON;
31151155Sbostic 	VREF(ip->i_devvp);
31237737Smckusick 	return (0);
31312795Ssam out:
31440872Smckusick 	if (bp)
31540872Smckusick 		brelse(bp);
31651155Sbostic 	(void)VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE, NOCRED, p);
31741314Smckusick 	if (ump) {
318*51501Sbostic 		free(ump->um_lfs, M_SUPERBLK);
319*51501Sbostic 		free(ump, M_UFSMNT);
32041397Smckusick 		mp->mnt_data = (qaddr_t)0;
32132721Smckusick 	}
32237737Smckusick 	return (error);
32312795Ssam }
32412795Ssam 
32539043Smckusick /*
32637737Smckusick  * unmount system call
32737737Smckusick  */
32851155Sbostic lfs_unmount(mp, mntflags, p)
32937737Smckusick 	struct mount *mp;
33041314Smckusick 	int mntflags;
33148036Smckusick 	struct proc *p;
33212795Ssam {
333*51501Sbostic 	extern int doforce;
33437737Smckusick 	register struct ufsmount *ump;
335*51501Sbostic 	register struct lfs *fs;				/* LFS */
33641314Smckusick 	int i, error, ronly, flags = 0;
33751215Sbostic 	int ndirty;						/* LFS */
33812795Ssam 
33951155Sbostic printf("lfs_unmount\n");
34048065Smckusick 	if (mntflags & MNT_FORCE) {
34148359Smckusick 		if (!doforce || mp == rootfs)
34248065Smckusick 			return (EINVAL);
34341314Smckusick 		flags |= FORCECLOSE;
34448065Smckusick 	}
34551215Sbostic 	if (error = lfs_segwrite(mp, 1))
34651215Sbostic 		return(error);
34751215Sbostic 
34851215Sbostic ndirty = lfs_umountdebug(mp);
34951215Sbostic printf("lfs_umountdebug: returned %d dirty\n", ndirty);
35051215Sbostic return(0);
35139675Smckusick 	if (mntinvalbuf(mp))
35239675Smckusick 		return (EBUSY);
35337737Smckusick 	ump = VFSTOUFS(mp);
35412795Ssam #ifdef QUOTA
35541397Smckusick 	if (mp->mnt_flag & MNT_QUOTA) {
35641314Smckusick 		if (error = vflush(mp, NULLVP, SKIPSYSTEM|flags))
35739898Smckusick 			return (error);
35841314Smckusick 		for (i = 0; i < MAXQUOTAS; i++) {
35941314Smckusick 			if (ump->um_quotas[i] == NULLVP)
36041314Smckusick 				continue;
36150114Smckusick 			quotaoff(p, mp, i);
36241314Smckusick 		}
36339898Smckusick 		/*
36441314Smckusick 		 * Here we fall through to vflush again to ensure
36541314Smckusick 		 * that we have gotten rid of all the system vnodes.
36639898Smckusick 		 */
36741314Smckusick 	}
36812795Ssam #endif
36941314Smckusick 	if (error = vflush(mp, NULLVP, flags))
37039898Smckusick 		return (error);
37151155Sbostic #ifdef NOTLFS							/* LFS */
37237737Smckusick 	fs = ump->um_fs;
37337737Smckusick 	ronly = !fs->fs_ronly;
37451155Sbostic #else
37551155Sbostic 	fs = ump->um_lfs;
37651155Sbostic 	ronly = !fs->lfs_ronly;
37751155Sbostic #endif
37840653Smckusick 	ump->um_devvp->v_specflags &= ~SI_MOUNTEDON;
37948036Smckusick 	error = VOP_CLOSE(ump->um_devvp, ronly ? FREAD : FREAD|FWRITE,
38048036Smckusick 		NOCRED, p);
38137737Smckusick 	vrele(ump->um_devvp);
38251155Sbostic #ifdef NOTLFS							/* LFS */
38341314Smckusick 	free((caddr_t)fs->fs_csp[0], M_SUPERBLK);
38451155Sbostic #else
38551155Sbostic 	free(fs->lfs_segtab, M_SUPERBLK);
38651155Sbostic 	iput(VTOI(fs->lfs_ivnode));
38751155Sbostic #endif
388*51501Sbostic 	free(fs, M_SUPERBLK);
389*51501Sbostic 	free(ump, M_UFSMNT);
39041397Smckusick 	mp->mnt_data = (qaddr_t)0;
39141397Smckusick 	mp->mnt_flag &= ~MNT_LOCAL;
39230749Skarels 	return (error);
39312795Ssam }
39412795Ssam 
39537737Smckusick /*
39637737Smckusick  * Get file system statistics.
39737737Smckusick  */
39851155Sbostic lfs_statfs(mp, sbp, p)
39937737Smckusick 	struct mount *mp;
40037737Smckusick 	register struct statfs *sbp;
40148036Smckusick 	struct proc *p;
40237737Smckusick {
403*51501Sbostic 	register struct lfs *fs;
40437737Smckusick 	register struct ufsmount *ump;
40537737Smckusick 
40637737Smckusick 	ump = VFSTOUFS(mp);
40751155Sbostic #ifdef NOTLFS							/* LFS */
40837737Smckusick 	fs = ump->um_fs;
40937737Smckusick 	if (fs->fs_magic != FS_MAGIC)
41037737Smckusick 		panic("ufs_statfs");
41137737Smckusick 	sbp->f_type = MOUNT_UFS;
41237737Smckusick 	sbp->f_fsize = fs->fs_fsize;
41337737Smckusick 	sbp->f_bsize = fs->fs_bsize;
41437737Smckusick 	sbp->f_blocks = fs->fs_dsize;
41537737Smckusick 	sbp->f_bfree = fs->fs_cstotal.cs_nbfree * fs->fs_frag +
41637737Smckusick 		fs->fs_cstotal.cs_nffree;
41737737Smckusick 	sbp->f_bavail = (fs->fs_dsize * (100 - fs->fs_minfree) / 100) -
41837737Smckusick 		(fs->fs_dsize - sbp->f_bfree);
41939350Smckusick 	sbp->f_files =  fs->fs_ncg * fs->fs_ipg - ROOTINO;
42037737Smckusick 	sbp->f_ffree = fs->fs_cstotal.cs_nifree;
42151155Sbostic #else
42251155Sbostic 	fs = ump->um_lfs;
42351155Sbostic 	if (fs->lfs_magic != LFS_MAGIC)
42451155Sbostic 		panic("lfs_statfs: magic");
42551155Sbostic 	sbp->f_type = MOUNT_LFS;
42651155Sbostic 	sbp->f_fsize = fs->lfs_bsize;
42751155Sbostic 	sbp->f_bsize = fs->lfs_bsize;
42851155Sbostic 	sbp->f_blocks = fs->lfs_dsize;
42951155Sbostic 	sbp->f_bfree = fs->lfs_bfree;
43051155Sbostic 	sbp->f_bavail = (fs->lfs_dsize * (100 - fs->lfs_minfree) / 100) -
43151155Sbostic 		(fs->lfs_dsize - sbp->f_bfree);
43251155Sbostic 	sbp->f_files = fs->lfs_nfiles;
43351155Sbostic 	sbp->f_ffree = fs->lfs_bfree * INOPB(fs);
43451155Sbostic #endif
43541397Smckusick 	if (sbp != &mp->mnt_stat) {
43641397Smckusick 		bcopy((caddr_t)mp->mnt_stat.f_mntonname,
43740346Smckusick 			(caddr_t)&sbp->f_mntonname[0], MNAMELEN);
43841397Smckusick 		bcopy((caddr_t)mp->mnt_stat.f_mntfromname,
43940346Smckusick 			(caddr_t)&sbp->f_mntfromname[0], MNAMELEN);
44040346Smckusick 	}
44137737Smckusick 	return (0);
44237737Smckusick }
44337737Smckusick 
44437737Smckusick /*
44537737Smckusick  * Go through the disk queues to initiate sandbagged IO;
44637737Smckusick  * go through the inodes to write those that have been modified;
44737737Smckusick  * initiate the writing of the super block if it has been modified.
44841314Smckusick  *
44941314Smckusick  * Note: we are always called with the filesystem marked `MPBUSY'.
45037737Smckusick  */
45151155Sbostic lfs_sync(mp, waitfor)
45237737Smckusick 	struct mount *mp;
45337737Smckusick 	int waitfor;
45437737Smckusick {
45551483Sbostic 	extern int syncprt;
45651310Sbostic 	static int sync_lock, sync_want;
45751215Sbostic 	int error;
45837737Smckusick 
45951155Sbostic printf("lfs_sync\n");
46051215Sbostic 
46151215Sbostic 	/*
46251310Sbostic 	 * Meta data blocks are only marked dirty, not busy, so LFS syncs
46351310Sbostic 	 * must be single threaded.
46451215Sbostic 	 */
46551310Sbostic 	while (sync_lock) {
46651310Sbostic 		sync_want = 1;
46751310Sbostic 		if (error = tsleep(&sync_lock, PLOCK | PCATCH, "lfs sync", 0))
46851310Sbostic 			return (error);
46951310Sbostic 	}
47051310Sbostic 	sync_lock = 1;
47151215Sbostic 
47237737Smckusick 	if (syncprt)
47351483Sbostic 		ufs_bufstats();
47451310Sbostic 
47551310Sbostic 	/* All syncs must be checkpoints until roll-forward is implemented. */
47651215Sbostic 	error = lfs_segwrite(mp, 1);
47741314Smckusick #ifdef QUOTA
47841314Smckusick 	qsync(mp);
47941314Smckusick #endif
48051310Sbostic 	sync_lock = 0;
48151310Sbostic 	if (sync_want) {
48251310Sbostic 		sync_want = 0;
48351310Sbostic 		wakeup(&sync_lock);
48451310Sbostic 	}
48551215Sbostic 	return (error);
48637737Smckusick }
487