xref: /csrg-svn/sys/ufs/lfs/lfs_vfsops.c (revision 51215)
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*51215Sbostic  *	@(#)lfs_vfsops.c	7.59 (Berkeley) 10/02/91
823400Smckusick  */
912795Ssam 
10*51215Sbostic #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"
29*51215Sbostic #include "../vm/vm_param.h"
30*51215Sbostic #include "../vm/lock.h"
3151155Sbostic #include "lfs.h"
3251155Sbostic #include "lfs_extern.h"
3347571Skarels 
3451155Sbostic static int	lfs_mountfs
3551155Sbostic 		    __P((struct vnode *, struct mount *, struct proc *));
3651155Sbostic 
37*51215Sbostic static int 	lfs_umountdebug __P((struct mount *));
38*51215Sbostic static int 	lfs_vinvalbuf __P((register struct vnode *));
39*51215Sbostic 
4051155Sbostic struct vfsops lfs_vfsops = {
4151155Sbostic 	lfs_mount,
4239043Smckusick 	ufs_start,
4351155Sbostic 	lfs_unmount,
4451155Sbostic 	lfs_root,
4541314Smckusick 	ufs_quotactl,
4651155Sbostic 	lfs_statfs,
4751155Sbostic 	lfs_sync,
4851155Sbostic 	lfs_fhtovp,
4939437Smckusick 	ufs_vptofh,
5051155Sbostic 	lfs_init
5137737Smckusick };
5237737Smckusick 
5337737Smckusick /*
5448359Smckusick  * Flag to allow forcible unmounting.
5548359Smckusick  */
5651155Sbostic extern int doforce;						/* LFS */
5748359Smckusick 
5851155Sbostic lfs_mountroot()
5912795Ssam {
6051155Sbostic 	/* LFS IMPLEMENT -- lfs_mountroot */
6151155Sbostic 	panic("lfs_mountroot");
6237737Smckusick }
6337737Smckusick 
6437737Smckusick /*
6537737Smckusick  * VFS Operations.
6637737Smckusick  *
6737737Smckusick  * mount system call
6837737Smckusick  */
6951155Sbostic lfs_mount(mp, path, data, ndp, p)
7040346Smckusick 	register struct mount *mp;
7137737Smckusick 	char *path;
7237737Smckusick 	caddr_t data;
7337737Smckusick 	struct nameidata *ndp;
7448036Smckusick 	struct proc *p;
7537737Smckusick {
7637737Smckusick 	struct vnode *devvp;
7737737Smckusick 	struct ufs_args args;
7837737Smckusick 	struct ufsmount *ump;
7951155Sbostic 	register LFS *fs;					/* LFS */
8037737Smckusick 	u_int size;
8137737Smckusick 	int error;
8237737Smckusick 
8337737Smckusick 	if (error = copyin(data, (caddr_t)&args, sizeof (struct ufs_args)))
8437737Smckusick 		return (error);
8540371Smckusick 	/*
8640371Smckusick 	 * Process export requests.
8740371Smckusick 	 */
8841397Smckusick 	if ((args.exflags & MNT_EXPORTED) || (mp->mnt_flag & MNT_EXPORTED)) {
8941397Smckusick 		if (args.exflags & MNT_EXPORTED)
9041397Smckusick 			mp->mnt_flag |= MNT_EXPORTED;
9140371Smckusick 		else
9241397Smckusick 			mp->mnt_flag &= ~MNT_EXPORTED;
9341397Smckusick 		if (args.exflags & MNT_EXRDONLY)
9441397Smckusick 			mp->mnt_flag |= MNT_EXRDONLY;
9540371Smckusick 		else
9641397Smckusick 			mp->mnt_flag &= ~MNT_EXRDONLY;
9741397Smckusick 		mp->mnt_exroot = args.exroot;
9840371Smckusick 	}
9950264Skarels 	/*
10050264Skarels 	 * If updating, check whether changing from read-only to
10150264Skarels 	 * read/write; if there is no device name, that's all we do.
10250264Skarels 	 */
10350264Skarels 	if (mp->mnt_flag & MNT_UPDATE) {
10439336Smckusick 		ump = VFSTOUFS(mp);
10551155Sbostic #ifdef NOTLFS							/* LFS */
10639336Smckusick 		fs = ump->um_fs;
10741397Smckusick 		if (fs->fs_ronly && (mp->mnt_flag & MNT_RDONLY) == 0)
10839336Smckusick 			fs->fs_ronly = 0;
10951155Sbostic #else
11051155Sbostic 		fs = ump->um_lfs;
11151155Sbostic 		if (fs->lfs_ronly && (mp->mnt_flag & MNT_RDONLY) == 0)
11251155Sbostic 			fs->lfs_ronly = 0;
11351155Sbostic #endif
11440371Smckusick 		if (args.fspec == 0)
11540371Smckusick 			return (0);
11650264Skarels 	}
11750264Skarels 	/*
11850264Skarels 	 * Not an update, or updating the name: look up the name
11950264Skarels 	 * and verify that it refers to a sensible block device.
12050264Skarels 	 */
12150264Skarels 	ndp->ni_nameiop = LOOKUP | FOLLOW;
12250264Skarels 	ndp->ni_segflg = UIO_USERSPACE;
12350264Skarels 	ndp->ni_dirp = args.fspec;
12450264Skarels 	if (error = namei(ndp, p))
12550264Skarels 		return (error);
12650264Skarels 	devvp = ndp->ni_vp;
12750264Skarels 	if (devvp->v_type != VBLK) {
12850264Skarels 		vrele(devvp);
12950264Skarels 		return (ENOTBLK);
13050264Skarels 	}
13150264Skarels 	if (major(devvp->v_rdev) >= nblkdev) {
13250264Skarels 		vrele(devvp);
13350264Skarels 		return (ENXIO);
13450264Skarels 	}
13550264Skarels 	if ((mp->mnt_flag & MNT_UPDATE) == 0)
13651155Sbostic 		error = lfs_mountfs(devvp, mp, p);		/* LFS */
13750264Skarels 	else {
13839336Smckusick 		if (devvp != ump->um_devvp)
13939336Smckusick 			error = EINVAL;	/* needs translation */
14042858Smckusick 		else
14142858Smckusick 			vrele(devvp);
14239336Smckusick 	}
14337737Smckusick 	if (error) {
14437737Smckusick 		vrele(devvp);
14537737Smckusick 		return (error);
14632721Smckusick 	}
14737737Smckusick 	ump = VFSTOUFS(mp);
14851155Sbostic 	fs = ump->um_lfs;					/* LFS */
14951155Sbostic #ifdef NOTLFS							/* LFS */
15037737Smckusick 	(void) copyinstr(path, fs->fs_fsmnt, sizeof(fs->fs_fsmnt) - 1, &size);
15137737Smckusick 	bzero(fs->fs_fsmnt + size, sizeof(fs->fs_fsmnt) - size);
15241397Smckusick 	bcopy((caddr_t)fs->fs_fsmnt, (caddr_t)mp->mnt_stat.f_mntonname,
15341397Smckusick 	    MNAMELEN);
15441397Smckusick 	(void) copyinstr(args.fspec, mp->mnt_stat.f_mntfromname, MNAMELEN - 1,
15541397Smckusick 	    &size);
15641397Smckusick 	bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
15748036Smckusick 	(void) ufs_statfs(mp, &mp->mnt_stat, p);
15851155Sbostic #else
15951155Sbostic 	(void)copyinstr(path, fs->lfs_fsmnt, sizeof(fs->lfs_fsmnt) - 1, &size);
16051155Sbostic 	bzero(fs->lfs_fsmnt + size, sizeof(fs->lfs_fsmnt) - size);
16151155Sbostic 	bcopy((caddr_t)fs->lfs_fsmnt, (caddr_t)mp->mnt_stat.f_mntonname,
16251155Sbostic 	    MNAMELEN);
16351155Sbostic 	(void) copyinstr(args.fspec, mp->mnt_stat.f_mntfromname, MNAMELEN - 1,
16451155Sbostic 	    &size);
16551155Sbostic 	bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
16651155Sbostic 	(void) lfs_statfs(mp, &mp->mnt_stat, p);
16751155Sbostic #endif
16837737Smckusick 	return (0);
16912795Ssam }
17012795Ssam 
17137737Smckusick /*
17237737Smckusick  * Common code for mount and mountroot
17351155Sbostic  * LFS specific
17437737Smckusick  */
17551155Sbostic static int
17651155Sbostic lfs_mountfs(devvp, mp, p)
17740376Smckusick 	register struct vnode *devvp;
17837737Smckusick 	struct mount *mp;
17948036Smckusick 	struct proc *p;
18012795Ssam {
18151155Sbostic 	extern struct vnode *rootvp;
18251155Sbostic 	register LFS *fs;
18351155Sbostic 	register struct ufsmount *ump;
18451155Sbostic 	struct inode *ip;
18551155Sbostic 	struct vnode *vp;
18651155Sbostic 	struct buf *bp;
18730749Skarels 	struct partinfo dpart;
18851155Sbostic 	daddr_t seg_addr;
18951155Sbostic 	dev_t dev;
19051155Sbostic 	int error, i, ronly, size;
19112795Ssam 
19240376Smckusick 	/*
19340376Smckusick 	 * Disallow multiple mounts of the same device.
19445652Smckusick 	 * Disallow mounting of a device that is currently in use
19545652Smckusick 	 * (except for root, which might share swap device for miniroot).
19640376Smckusick 	 * Flush out any old buffers remaining from a previous use.
19740376Smckusick 	 */
19840376Smckusick 	if (error = mountedon(devvp))
19940376Smckusick 		return (error);
20045652Smckusick 	if (vcount(devvp) > 1 && devvp != rootvp)
20140376Smckusick 		return (EBUSY);
20240376Smckusick 	vinvalbuf(devvp, 1);
20351155Sbostic 
20451155Sbostic 	ronly = (mp->mnt_flag & MNT_RDONLY) != 0;
20548036Smckusick 	if (error = VOP_OPEN(devvp, ronly ? FREAD : FREAD|FWRITE, NOCRED, p))
20637737Smckusick 		return (error);
20751155Sbostic 
20848036Smckusick 	if (VOP_IOCTL(devvp, DIOCGPART, (caddr_t)&dpart, FREAD, NOCRED, p) != 0)
20937737Smckusick 		size = DEV_BSIZE;
21048036Smckusick 	else {
21130749Skarels 		size = dpart.disklab->d_secsize;
21251155Sbostic #ifdef NEVER_USED
21351155Sbostic 		dpart.part->p_fstype = FS_LFS;
21451155Sbostic 		dpart.part->p_fsize = fs->lfs_fsize;	/* frag size */
21551155Sbostic 		dpart.part->p_frag = fs->lfs_frag;	/* frags per block */
21651155Sbostic 		dpart.part->p_cpg = fs->lfs_segshift;	/* segment shift */
21751155Sbostic #endif
21837737Smckusick 	}
21951155Sbostic 
22051155Sbostic 	/* Don't free random space on error. */
22151155Sbostic 	bp = NULL;
22251155Sbostic 	ump = NULL;
22351155Sbostic 
22451155Sbostic 	/* Read in the superblock. */
22551155Sbostic 	if (error = bread(devvp, LFS_LABELPAD / size, LFS_SBPAD, NOCRED, &bp))
22612795Ssam 		goto out;
22751155Sbostic 	fs = bp->b_un.b_lfs;
22851155Sbostic 
22951155Sbostic 	/* Check the basics. */
23051155Sbostic 	if (fs->lfs_magic != LFS_MAGIC || fs->lfs_bsize > MAXBSIZE ||
23151155Sbostic 	    fs->lfs_bsize < sizeof(LFS)) {
23241314Smckusick 		error = EINVAL;		/* XXX needs translation */
23316639Skarels 		goto out;
23416639Skarels 	}
23551155Sbostic #ifdef DEBUG
23651155Sbostic 	dump_super(fs);
23751155Sbostic #endif
23851155Sbostic 
23951155Sbostic 	/* Allocate the mount structure, copy the superblock into it. */
24041314Smckusick 	ump = (struct ufsmount *)malloc(sizeof *ump, M_UFSMNT, M_WAITOK);
24151155Sbostic 	ump->um_lfs = malloc(sizeof(LFS), M_SUPERBLK, M_WAITOK);
24251155Sbostic 	bcopy(bp->b_un.b_addr, ump->um_lfs, sizeof(LFS));
24351155Sbostic 	if (sizeof(LFS) < LFS_SBPAD)			/* XXX why? */
24439675Smckusick 		bp->b_flags |= B_INVAL;
24534421Skarels 	brelse(bp);
24634421Skarels 	bp = NULL;
24751155Sbostic 
24851183Sbostic 	/* Set up the I/O information */
24951183Sbostic 	fs->lfs_iocount = 0;
25051183Sbostic 	fs->lfs_seglist = NULL;
25151183Sbostic 
25251155Sbostic 	/* Set the file system readonly/modify bits. */
25351155Sbostic 	fs = ump->um_lfs;
25451155Sbostic 	fs->lfs_ronly = ronly;
25512795Ssam 	if (ronly == 0)
25651155Sbostic 		fs->lfs_fmod = 1;
25751155Sbostic 
25851155Sbostic 	/* Initialize the mount structure. */
25951155Sbostic 	dev = devvp->v_rdev;
26041397Smckusick 	mp->mnt_data = (qaddr_t)ump;
26141397Smckusick 	mp->mnt_stat.f_fsid.val[0] = (long)dev;
26251155Sbostic 	mp->mnt_stat.f_fsid.val[1] = MOUNT_LFS;
26341397Smckusick 	mp->mnt_flag |= MNT_LOCAL;
26437737Smckusick 	ump->um_mountp = mp;
26537737Smckusick 	ump->um_dev = dev;
26637737Smckusick 	ump->um_devvp = devvp;
26741314Smckusick 	for (i = 0; i < MAXQUOTAS; i++)
26841314Smckusick 		ump->um_quotas[i] = NULLVP;
26951155Sbostic 
27051155Sbostic 	/* Read the ifile disk inode and store it in a vnode. */
27151155Sbostic 	error = bread(devvp, fs->lfs_idaddr, fs->lfs_bsize, NOCRED, &bp);
27251155Sbostic 	if (error)
27351155Sbostic 		goto out;
27451155Sbostic 	error = lfs_vcreate(mp, LFS_IFILE_INUM, &vp);
27551155Sbostic 	if (error)
27651155Sbostic 		goto out;
27751155Sbostic 	ip = VTOI(vp);
27851155Sbostic 
27951155Sbostic 	/* The ifile inode is stored in the superblock. */
28051155Sbostic 	fs->lfs_ivnode = vp;
28151155Sbostic 
28251155Sbostic 	/* Copy the on-disk inode into place. */
28351155Sbostic 	ip->i_din = *lfs_ifind(fs, LFS_IFILE_INUM, bp->b_un.b_dino);
28451155Sbostic 	brelse(bp);
28551155Sbostic 
28651155Sbostic 	/* Initialize the associated vnode */
28751155Sbostic 	vp->v_type = IFTOVT(ip->i_mode);
28851155Sbostic 
28951155Sbostic 	/*
29051155Sbostic 	 * Read in the segusage table.
29151155Sbostic 	 *
29251155Sbostic 	 * Since we always explicitly write the segusage table at a checkpoint,
29351155Sbostic 	 * we're assuming that it is continguous on disk.
29451155Sbostic 	 */
29551155Sbostic 	seg_addr = ip->i_din.di_db[0];
29651155Sbostic 	size = fs->lfs_segtabsz << fs->lfs_bshift;
29751155Sbostic 	fs->lfs_segtab = malloc(size, M_SUPERBLK, M_WAITOK);
29851155Sbostic 	error = bread(devvp, seg_addr, size, NOCRED, &bp);
29951155Sbostic 	if (error) {
30051155Sbostic 		free(fs->lfs_segtab, M_SUPERBLK);
30151155Sbostic 		goto out;
30251155Sbostic 	}
30351155Sbostic 	bcopy((caddr_t)bp->b_un.b_addr, fs->lfs_segtab, size);
30451155Sbostic 	brelse(bp);
30540653Smckusick 	devvp->v_specflags |= SI_MOUNTEDON;
30651155Sbostic 	VREF(ip->i_devvp);
30737737Smckusick 	return (0);
30812795Ssam out:
30940872Smckusick 	if (bp)
31040872Smckusick 		brelse(bp);
31151155Sbostic 	(void)VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE, NOCRED, p);
31241314Smckusick 	if (ump) {
31351155Sbostic 		free((caddr_t)ump->um_lfs, M_SUPERBLK);
31441314Smckusick 		free((caddr_t)ump, M_UFSMNT);
31541397Smckusick 		mp->mnt_data = (qaddr_t)0;
31632721Smckusick 	}
31737737Smckusick 	return (error);
31812795Ssam }
31912795Ssam 
32039043Smckusick /*
32137737Smckusick  * unmount system call
32237737Smckusick  */
32351155Sbostic lfs_unmount(mp, mntflags, p)
32437737Smckusick 	struct mount *mp;
32541314Smckusick 	int mntflags;
32648036Smckusick 	struct proc *p;
32712795Ssam {
32837737Smckusick 	register struct ufsmount *ump;
32951183Sbostic 	register LFS *fs;					/* LFS */
33041314Smckusick 	int i, error, ronly, flags = 0;
331*51215Sbostic 	int ndirty;						/* LFS */
33212795Ssam 
33351155Sbostic printf("lfs_unmount\n");
33448065Smckusick 	if (mntflags & MNT_FORCE) {
33548359Smckusick 		if (!doforce || mp == rootfs)
33648065Smckusick 			return (EINVAL);
33741314Smckusick 		flags |= FORCECLOSE;
33848065Smckusick 	}
339*51215Sbostic 	if (error = lfs_segwrite(mp, 1))
340*51215Sbostic 		return(error);
341*51215Sbostic 
342*51215Sbostic ndirty = lfs_umountdebug(mp);
343*51215Sbostic printf("lfs_umountdebug: returned %d dirty\n", ndirty);
344*51215Sbostic return(0);
34539675Smckusick 	if (mntinvalbuf(mp))
34639675Smckusick 		return (EBUSY);
34737737Smckusick 	ump = VFSTOUFS(mp);
34812795Ssam #ifdef QUOTA
34941397Smckusick 	if (mp->mnt_flag & MNT_QUOTA) {
35041314Smckusick 		if (error = vflush(mp, NULLVP, SKIPSYSTEM|flags))
35139898Smckusick 			return (error);
35241314Smckusick 		for (i = 0; i < MAXQUOTAS; i++) {
35341314Smckusick 			if (ump->um_quotas[i] == NULLVP)
35441314Smckusick 				continue;
35550114Smckusick 			quotaoff(p, mp, i);
35641314Smckusick 		}
35739898Smckusick 		/*
35841314Smckusick 		 * Here we fall through to vflush again to ensure
35941314Smckusick 		 * that we have gotten rid of all the system vnodes.
36039898Smckusick 		 */
36141314Smckusick 	}
36212795Ssam #endif
36341314Smckusick 	if (error = vflush(mp, NULLVP, flags))
36439898Smckusick 		return (error);
36551155Sbostic #ifdef NOTLFS							/* LFS */
36637737Smckusick 	fs = ump->um_fs;
36737737Smckusick 	ronly = !fs->fs_ronly;
36851155Sbostic #else
36951155Sbostic 	fs = ump->um_lfs;
37051155Sbostic 	ronly = !fs->lfs_ronly;
37151155Sbostic #endif
37240653Smckusick 	ump->um_devvp->v_specflags &= ~SI_MOUNTEDON;
37348036Smckusick 	error = VOP_CLOSE(ump->um_devvp, ronly ? FREAD : FREAD|FWRITE,
37448036Smckusick 		NOCRED, p);
37537737Smckusick 	vrele(ump->um_devvp);
37651155Sbostic #ifdef NOTLFS							/* LFS */
37741314Smckusick 	free((caddr_t)fs->fs_csp[0], M_SUPERBLK);
37851155Sbostic #else
37951155Sbostic 	free(fs->lfs_segtab, M_SUPERBLK);
38051155Sbostic 	iput(VTOI(fs->lfs_ivnode));
38151155Sbostic #endif
38241314Smckusick 	free((caddr_t)fs, M_SUPERBLK);
38341314Smckusick 	free((caddr_t)ump, M_UFSMNT);
38441397Smckusick 	mp->mnt_data = (qaddr_t)0;
38541397Smckusick 	mp->mnt_flag &= ~MNT_LOCAL;
38630749Skarels 	return (error);
38712795Ssam }
38812795Ssam 
38937737Smckusick /*
39037737Smckusick  * Return root of a filesystem
39137737Smckusick  */
39251155Sbostic lfs_root(mp, vpp)
39312795Ssam 	struct mount *mp;
39437737Smckusick 	struct vnode **vpp;
39512795Ssam {
39639390Smckusick 	register struct inode *ip;
39739390Smckusick 	struct inode *nip;
39839390Smckusick 	struct vnode tvp;
39937737Smckusick 	int error;
40037737Smckusick 
40139390Smckusick 	tvp.v_mount = mp;
40239390Smckusick 	ip = VTOI(&tvp);
40339390Smckusick 	ip->i_vnode = &tvp;
40439390Smckusick 	ip->i_dev = VFSTOUFS(mp)->um_dev;
40551155Sbostic 	error = lfs_iget(ip, (ino_t)ROOTINO, &nip);		/* LFS */
40637737Smckusick 	if (error)
40737737Smckusick 		return (error);
40839390Smckusick 	*vpp = ITOV(nip);
40937737Smckusick 	return (0);
41037737Smckusick }
41137737Smckusick 
41237737Smckusick /*
41337737Smckusick  * Get file system statistics.
41437737Smckusick  */
41551155Sbostic lfs_statfs(mp, sbp, p)
41637737Smckusick 	struct mount *mp;
41737737Smckusick 	register struct statfs *sbp;
41848036Smckusick 	struct proc *p;
41937737Smckusick {
42051155Sbostic 	register LFS *fs;
42137737Smckusick 	register struct ufsmount *ump;
42237737Smckusick 
42337737Smckusick 	ump = VFSTOUFS(mp);
42451155Sbostic #ifdef NOTLFS							/* LFS */
42537737Smckusick 	fs = ump->um_fs;
42637737Smckusick 	if (fs->fs_magic != FS_MAGIC)
42737737Smckusick 		panic("ufs_statfs");
42837737Smckusick 	sbp->f_type = MOUNT_UFS;
42937737Smckusick 	sbp->f_fsize = fs->fs_fsize;
43037737Smckusick 	sbp->f_bsize = fs->fs_bsize;
43137737Smckusick 	sbp->f_blocks = fs->fs_dsize;
43237737Smckusick 	sbp->f_bfree = fs->fs_cstotal.cs_nbfree * fs->fs_frag +
43337737Smckusick 		fs->fs_cstotal.cs_nffree;
43437737Smckusick 	sbp->f_bavail = (fs->fs_dsize * (100 - fs->fs_minfree) / 100) -
43537737Smckusick 		(fs->fs_dsize - sbp->f_bfree);
43639350Smckusick 	sbp->f_files =  fs->fs_ncg * fs->fs_ipg - ROOTINO;
43737737Smckusick 	sbp->f_ffree = fs->fs_cstotal.cs_nifree;
43851155Sbostic #else
43951155Sbostic 	fs = ump->um_lfs;
44051155Sbostic 	if (fs->lfs_magic != LFS_MAGIC)
44151155Sbostic 		panic("lfs_statfs: magic");
44251155Sbostic 	sbp->f_type = MOUNT_LFS;
44351155Sbostic 	sbp->f_fsize = fs->lfs_bsize;
44451155Sbostic 	sbp->f_bsize = fs->lfs_bsize;
44551155Sbostic 	sbp->f_blocks = fs->lfs_dsize;
44651155Sbostic 	sbp->f_bfree = fs->lfs_bfree;
44751155Sbostic 	sbp->f_bavail = (fs->lfs_dsize * (100 - fs->lfs_minfree) / 100) -
44851155Sbostic 		(fs->lfs_dsize - sbp->f_bfree);
44951155Sbostic 	sbp->f_files = fs->lfs_nfiles;
45051155Sbostic 	sbp->f_ffree = fs->lfs_bfree * INOPB(fs);
45151155Sbostic #endif
45241397Smckusick 	if (sbp != &mp->mnt_stat) {
45341397Smckusick 		bcopy((caddr_t)mp->mnt_stat.f_mntonname,
45440346Smckusick 			(caddr_t)&sbp->f_mntonname[0], MNAMELEN);
45541397Smckusick 		bcopy((caddr_t)mp->mnt_stat.f_mntfromname,
45640346Smckusick 			(caddr_t)&sbp->f_mntfromname[0], MNAMELEN);
45740346Smckusick 	}
45837737Smckusick 	return (0);
45937737Smckusick }
46037737Smckusick 
46151155Sbostic extern int	syncprt;					/* LFS */
462*51215Sbostic extern lock_data_t lfs_sync_lock;
46337737Smckusick 
46437737Smckusick /*
46537737Smckusick  * Go through the disk queues to initiate sandbagged IO;
46637737Smckusick  * go through the inodes to write those that have been modified;
46737737Smckusick  * initiate the writing of the super block if it has been modified.
46841314Smckusick  *
46941314Smckusick  * Note: we are always called with the filesystem marked `MPBUSY'.
47037737Smckusick  */
471*51215Sbostic int STOPNOW;
47251155Sbostic lfs_sync(mp, waitfor)
47337737Smckusick 	struct mount *mp;
47437737Smckusick 	int waitfor;
47537737Smckusick {
476*51215Sbostic 	int error;
47737737Smckusick 
47851155Sbostic printf("lfs_sync\n");
479*51215Sbostic 
480*51215Sbostic 	/*
481*51215Sbostic 	 * Concurrent syncs aren't possible because the meta data blocks are
482*51215Sbostic 	 * only marked dirty, not busy!
483*51215Sbostic 	 */
484*51215Sbostic 	lock_write(&lfs_sync_lock);
485*51215Sbostic 
48637737Smckusick 	if (syncprt)
48737737Smckusick 		bufstats();
488*51215Sbostic 	/*
489*51215Sbostic 	 * If we do roll forward, then all syncs do not have to be checkpoints.
490*51215Sbostic 	 * Until then, make sure they are.
49137737Smckusick 	 */
492*51215Sbostic STOPNOW=1;
493*51215Sbostic 	error = lfs_segwrite(mp, 1);
494*51215Sbostic 	lock_done(&lfs_sync_lock);
49541314Smckusick #ifdef QUOTA
49641314Smckusick 	qsync(mp);
49741314Smckusick #endif
498*51215Sbostic 	return (error);
49937737Smckusick }
50037737Smckusick 
50112795Ssam /*
50237737Smckusick  * File handle to vnode
50338453Smckusick  *
50438453Smckusick  * Have to be really careful about stale file handles:
50538453Smckusick  * - check that the inode number is in range
50638453Smckusick  * - call iget() to get the locked inode
50738453Smckusick  * - check for an unallocated inode (i_mode == 0)
50838453Smckusick  * - check that the generation number matches
50937737Smckusick  */
51051155Sbostic lfs_fhtovp(mp, fhp, vpp)
51138453Smckusick 	register struct mount *mp;
51237737Smckusick 	struct fid *fhp;
51337737Smckusick 	struct vnode **vpp;
51437737Smckusick {
51537737Smckusick 	register struct ufid *ufhp;
51651183Sbostic 	register LFS *fs;					/* LFS */
51739390Smckusick 	register struct inode *ip;
51851155Sbostic 	IFILE *ifp;
51951155Sbostic 	struct buf *bp;
52039390Smckusick 	struct inode *nip;
52139390Smckusick 	struct vnode tvp;
52237737Smckusick 	int error;
52337737Smckusick 
52437737Smckusick 	ufhp = (struct ufid *)fhp;
52551155Sbostic #ifdef NOTLFS							/* LFS */
52638453Smckusick 	fs = VFSTOUFS(mp)->um_fs;
52738453Smckusick 	if (ufhp->ufid_ino < ROOTINO ||
52838453Smckusick 	    ufhp->ufid_ino >= fs->fs_ncg * fs->fs_ipg) {
52941397Smckusick 		*vpp = NULLVP;
53038453Smckusick 		return (EINVAL);
53138453Smckusick 	}
53251155Sbostic #else
53351155Sbostic 	fs = VFSTOUFS(mp)->um_lfs;
53451155Sbostic 	if (ufhp->ufid_ino < ROOTINO) {
53551155Sbostic 		*vpp = NULLVP;
53651155Sbostic 		return (EINVAL);
53751155Sbostic 	}
53851155Sbostic #endif
53939390Smckusick 	tvp.v_mount = mp;
54039390Smckusick 	ip = VTOI(&tvp);
54139390Smckusick 	ip->i_vnode = &tvp;
54239390Smckusick 	ip->i_dev = VFSTOUFS(mp)->um_dev;
54351155Sbostic 	if (error = lfs_iget(ip, ufhp->ufid_ino, &nip)) {	/* LFS */
54441397Smckusick 		*vpp = NULLVP;
54537737Smckusick 		return (error);
54637737Smckusick 	}
54739390Smckusick 	ip = nip;
54838453Smckusick 	if (ip->i_mode == 0) {
54938453Smckusick 		iput(ip);
55041397Smckusick 		*vpp = NULLVP;
55138453Smckusick 		return (EINVAL);
55238453Smckusick 	}
55337737Smckusick 	if (ip->i_gen != ufhp->ufid_gen) {
55437737Smckusick 		iput(ip);
55541397Smckusick 		*vpp = NULLVP;
55637737Smckusick 		return (EINVAL);
55737737Smckusick 	}
55837737Smckusick 	*vpp = ITOV(ip);
55937737Smckusick 	return (0);
56037737Smckusick }
561*51215Sbostic 
562*51215Sbostic static int
563*51215Sbostic lfs_umountdebug(mp)
564*51215Sbostic 	struct mount *mp;
565*51215Sbostic {
566*51215Sbostic 	struct vnode *vp;
567*51215Sbostic 	int dirty;
568*51215Sbostic 
569*51215Sbostic 	dirty = 0;
570*51215Sbostic 	if ((mp->mnt_flag & MNT_MPBUSY) == 0)
571*51215Sbostic 		panic("umountdebug: not busy");
572*51215Sbostic loop:
573*51215Sbostic 	for (vp = mp->mnt_mounth; vp; vp = vp->v_mountf) {
574*51215Sbostic 		if (vget(vp))
575*51215Sbostic 			goto loop;
576*51215Sbostic 		dirty += lfs_vinvalbuf(vp);
577*51215Sbostic 		vput(vp);
578*51215Sbostic 		if (vp->v_mount != mp)
579*51215Sbostic 			goto loop;
580*51215Sbostic 	}
581*51215Sbostic 	return (dirty);
582*51215Sbostic }
583*51215Sbostic static int
584*51215Sbostic lfs_vinvalbuf(vp)
585*51215Sbostic 	register struct vnode *vp;
586*51215Sbostic {
587*51215Sbostic 	register struct buf *bp;
588*51215Sbostic 	struct buf *nbp, *blist;
589*51215Sbostic 	int s, dirty = 0;
590*51215Sbostic 
591*51215Sbostic 	for (;;) {
592*51215Sbostic 		if (blist = vp->v_dirtyblkhd)
593*51215Sbostic 			/* void */;
594*51215Sbostic 		else if (blist = vp->v_cleanblkhd)
595*51215Sbostic 			/* void */;
596*51215Sbostic 		else
597*51215Sbostic 			break;
598*51215Sbostic 		for (bp = blist; bp; bp = nbp) {
599*51215Sbostic printf("lfs_vinvalbuf: ino %d, lblkno %d, blkno %lx flags %xl\n",
600*51215Sbostic VTOI(vp)->i_number, bp->b_lblkno, bp->b_blkno, bp->b_flags);
601*51215Sbostic 			nbp = bp->b_blockf;
602*51215Sbostic 			s = splbio();
603*51215Sbostic 			if (bp->b_flags & B_BUSY) {
604*51215Sbostic printf("lfs_vinvalbuf: buffer busy, would normally sleep\n");
605*51215Sbostic /*
606*51215Sbostic 				bp->b_flags |= B_WANTED;
607*51215Sbostic 				sleep((caddr_t)bp, PRIBIO + 1);
608*51215Sbostic */
609*51215Sbostic 				splx(s);
610*51215Sbostic 				break;
611*51215Sbostic 			}
612*51215Sbostic 			bremfree(bp);
613*51215Sbostic 			bp->b_flags |= B_BUSY;
614*51215Sbostic 			splx(s);
615*51215Sbostic 			if (bp->b_flags & B_DELWRI) {
616*51215Sbostic 				dirty++;			/* XXX */
617*51215Sbostic printf("lfs_vinvalbuf: buffer dirty (DELWRI). would normally write\n");
618*51215Sbostic 				break;
619*51215Sbostic 			}
620*51215Sbostic 			if (bp->b_vp != vp)
621*51215Sbostic 				reassignbuf(bp, bp->b_vp);
622*51215Sbostic 			else
623*51215Sbostic 				bp->b_flags |= B_INVAL;
624*51215Sbostic 			brelse(bp);
625*51215Sbostic 		}
626*51215Sbostic 	}
627*51215Sbostic 	if (vp->v_dirtyblkhd || vp->v_cleanblkhd)
628*51215Sbostic 		panic("lfs_vinvalbuf: flush failed");
629*51215Sbostic 	return (dirty);
630*51215Sbostic }
631*51215Sbostic #endif /* LOGFS */
632