xref: /csrg-svn/sys/ufs/lfs/lfs_vfsops.c (revision 37737)
123400Smckusick /*
2*37737Smckusick  * Copyright (c) 1989 The Regents of the University of California.
3*37737Smckusick  * All rights reserved.
423400Smckusick  *
5*37737Smckusick  * Redistribution and use in source and binary forms are permitted
6*37737Smckusick  * provided that the above copyright notice and this paragraph are
7*37737Smckusick  * duplicated in all such forms and that any documentation,
8*37737Smckusick  * advertising materials, and other materials related to such
9*37737Smckusick  * distribution and use acknowledge that the software was developed
10*37737Smckusick  * by the University of California, Berkeley.  The name of the
11*37737Smckusick  * University may not be used to endorse or promote products derived
12*37737Smckusick  * from this software without specific prior written permission.
13*37737Smckusick  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14*37737Smckusick  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15*37737Smckusick  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
16*37737Smckusick  *
17*37737Smckusick  *	@(#)lfs_vfsops.c	7.13 (Berkeley) 05/09/89
1823400Smckusick  */
1912795Ssam 
20*37737Smckusick 
2117100Sbloom #include "param.h"
2217100Sbloom #include "systm.h"
23*37737Smckusick #include "time.h"
24*37737Smckusick #include "kernel.h"
25*37737Smckusick #include "namei.h"
26*37737Smckusick #include "vnode.h"
27*37737Smckusick #include "mount.h"
2817100Sbloom #include "buf.h"
2917100Sbloom #include "file.h"
30*37737Smckusick #include "disklabel.h"
3130749Skarels #include "ioctl.h"
32*37737Smckusick #include "errno.h"
3331660Smckusick #include "malloc.h"
34*37737Smckusick #include "../ufs/fs.h"
35*37737Smckusick #include "../ufs/ufsmount.h"
36*37737Smckusick #include "../ufs/inode.h"
3712795Ssam 
38*37737Smckusick /*
39*37737Smckusick  * ufs vfs operations.
40*37737Smckusick  */
41*37737Smckusick int ufs_mount();
42*37737Smckusick int ufs_unmount();
43*37737Smckusick int ufs_root();
44*37737Smckusick int ufs_statfs();
45*37737Smckusick int ufs_sync();
46*37737Smckusick int ufs_fhtovp();
47*37737Smckusick int ufs_vptofh();
48*37737Smckusick 
49*37737Smckusick struct vfsops ufs_vfsops = {
50*37737Smckusick 	ufs_mount,
51*37737Smckusick 	ufs_unmount,
52*37737Smckusick 	ufs_root,
53*37737Smckusick 	ufs_statfs,
54*37737Smckusick 	ufs_sync,
55*37737Smckusick 	ufs_fhtovp,
56*37737Smckusick 	ufs_vptofh
57*37737Smckusick };
58*37737Smckusick 
59*37737Smckusick /*
60*37737Smckusick  * ufs mount table.
61*37737Smckusick  */
62*37737Smckusick struct ufsmount mounttab[NMOUNT];
63*37737Smckusick 
64*37737Smckusick /*
65*37737Smckusick  * Called by vfs_mountroot when ufs is going to be mounted as root
66*37737Smckusick  *
67*37737Smckusick  * XXX - Need to have a way of figuring the name of the root device
68*37737Smckusick  */
69*37737Smckusick #define ROOTNAME	"root device"
70*37737Smckusick 
71*37737Smckusick ufs_mountroot()
7212795Ssam {
73*37737Smckusick 	register struct mount *mp;
74*37737Smckusick 	extern struct vnode *rootvp;
75*37737Smckusick 	struct ufsmount *ump;
7612795Ssam 	register struct fs *fs;
77*37737Smckusick 	u_int size;
78*37737Smckusick 	int error;
7912795Ssam 
80*37737Smckusick 	mp = (struct mount *)malloc((u_long)sizeof(struct mount),
81*37737Smckusick 		M_MOUNT, M_WAITOK);
82*37737Smckusick 	mp->m_op = &ufs_vfsops;
83*37737Smckusick 	mp->m_flag = 0;
84*37737Smckusick 	mp->m_exroot = 0;
85*37737Smckusick 	error = mountfs(rootvp, mp);
86*37737Smckusick 	if (error) {
87*37737Smckusick 		free((caddr_t)mp, M_MOUNT);
88*37737Smckusick 		return (error);
8912795Ssam 	}
90*37737Smckusick 	error = vfs_add((struct vnode *)0, mp, 0);
91*37737Smckusick 	if (error) {
92*37737Smckusick 		(void)ufs_unmount(mp, 0);
93*37737Smckusick 		free((caddr_t)mp, M_MOUNT);
94*37737Smckusick 		return (error);
9521013Smckusick 	}
96*37737Smckusick 	ump = VFSTOUFS(mp);
97*37737Smckusick 	fs = ump->um_fs;
98*37737Smckusick 	fs->fs_fsmnt[0] = '/';
99*37737Smckusick 	bzero(fs->fs_fsmnt + 1, sizeof(fs->fs_fsmnt) - 1);
100*37737Smckusick 	(void) copystr(ROOTNAME, ump->um_mntname, MNAMELEN - 1, &size);
101*37737Smckusick 	bzero(ump->um_mntname + size, MNAMELEN - size);
102*37737Smckusick 	vfs_unlock(mp);
103*37737Smckusick 	inittodr(fs->fs_time);
104*37737Smckusick 	return (0);
105*37737Smckusick }
106*37737Smckusick 
107*37737Smckusick /*
108*37737Smckusick  * VFS Operations.
109*37737Smckusick  *
110*37737Smckusick  * mount system call
111*37737Smckusick  */
112*37737Smckusick ufs_mount(mp, path, data, ndp)
113*37737Smckusick 	struct mount *mp;
114*37737Smckusick 	char *path;
115*37737Smckusick 	caddr_t data;
116*37737Smckusick 	struct nameidata *ndp;
117*37737Smckusick {
118*37737Smckusick 	struct vnode *devvp;
119*37737Smckusick 	struct ufs_args args;
120*37737Smckusick 	struct ufsmount *ump;
121*37737Smckusick 	register struct fs *fs;
122*37737Smckusick 	u_int size;
123*37737Smckusick 	int error;
124*37737Smckusick 
125*37737Smckusick 	if (error = copyin(data, (caddr_t)&args, sizeof (struct ufs_args)))
126*37737Smckusick 		return (error);
127*37737Smckusick 	if ((error = getmdev(&devvp, args.fspec, ndp)) != 0)
128*37737Smckusick 		return (error);
129*37737Smckusick 	error = mountfs(devvp, mp);
130*37737Smckusick 	if (error) {
131*37737Smckusick 		vrele(devvp);
132*37737Smckusick 		return (error);
13332721Smckusick 	}
134*37737Smckusick 	ump = VFSTOUFS(mp);
135*37737Smckusick 	fs = ump->um_fs;
136*37737Smckusick 	(void) copyinstr(path, fs->fs_fsmnt, sizeof(fs->fs_fsmnt) - 1, &size);
137*37737Smckusick 	bzero(fs->fs_fsmnt + size, sizeof(fs->fs_fsmnt) - size);
138*37737Smckusick 	(void) copyinstr(args.fspec, ump->um_mntname, MNAMELEN - 1, &size);
139*37737Smckusick 	bzero(ump->um_mntname + size, MNAMELEN - size);
140*37737Smckusick 	return (0);
14112795Ssam }
14212795Ssam 
143*37737Smckusick /*
144*37737Smckusick  * Common code for mount and mountroot
145*37737Smckusick  */
146*37737Smckusick mountfs(devvp, mp)
147*37737Smckusick 	struct vnode *devvp;
148*37737Smckusick 	struct mount *mp;
14912795Ssam {
150*37737Smckusick 	register struct ufsmount *ump;
151*37737Smckusick 	struct ufsmount *fmp = NULL;
152*37737Smckusick 	struct buf *bp = NULL;
15312795Ssam 	register struct fs *fs;
154*37737Smckusick 	dev_t dev = devvp->v_rdev;
15530749Skarels 	struct partinfo dpart;
156*37737Smckusick 	caddr_t base, space;
15730749Skarels 	int havepart = 0, blks;
158*37737Smckusick 	int error, i, size;
15921013Smckusick 	int needclose = 0;
160*37737Smckusick 	int ronly = (mp->m_flag & M_RDONLY) != 0;
16112795Ssam 
162*37737Smckusick 	for (ump = &mounttab[0]; ump < &mounttab[NMOUNT]; ump++) {
163*37737Smckusick 		if (ump->um_fs == NULL) {
16432721Smckusick 			if (fmp == NULL)
165*37737Smckusick 				fmp = ump;
166*37737Smckusick 		} else if (dev == ump->um_dev) {
167*37737Smckusick 			return (EBUSY);		/* needs translation */
16832721Smckusick 		}
16932721Smckusick 	}
170*37737Smckusick 	if ((ump = fmp) == NULL)
171*37737Smckusick 		return (EMFILE);		/* needs translation */
172*37737Smckusick 	ump->um_fs = (struct fs *)1;		/* just to reserve this slot */
173*37737Smckusick 	error = VOP_OPEN(devvp, ronly ? FREAD : FREAD|FWRITE,
174*37737Smckusick 		(struct ucred *)0);
17532721Smckusick 	if (error) {
176*37737Smckusick 		ump->um_fs = NULL;
177*37737Smckusick 		return (error);
17832721Smckusick 	}
17921013Smckusick 	needclose = 1;
180*37737Smckusick 	if (VOP_IOCTL(devvp, DIOCGPART, (caddr_t)&dpart, FREAD,
181*37737Smckusick 	    (struct ucred *)0) != 0)
182*37737Smckusick 		size = DEV_BSIZE;
183*37737Smckusick 	else {
18430749Skarels 		havepart = 1;
18530749Skarels 		size = dpart.disklab->d_secsize;
186*37737Smckusick 	}
187*37737Smckusick 	if (error = bread(devvp, SBLOCK, SBSIZE, &bp)) {
188*37737Smckusick 		ump->um_fs = NULL;
18912795Ssam 		goto out;
19032721Smckusick 	}
19134421Skarels 	fs = bp->b_un.b_fs;
19230749Skarels 	if (fs->fs_magic != FS_MAGIC || fs->fs_bsize > MAXBSIZE ||
19330749Skarels 	    fs->fs_bsize < sizeof(struct fs)) {
194*37737Smckusick 		ump->um_fs = NULL;
195*37737Smckusick 		error = EINVAL;		/* XXX also needs translation */
19616639Skarels 		goto out;
19716639Skarels 	}
198*37737Smckusick 	ump->um_fs = (struct fs *)malloc((u_long)fs->fs_sbsize, M_SUPERBLK,
19934473Smckusick 	    M_WAITOK);
200*37737Smckusick 	bcopy((caddr_t)bp->b_un.b_addr, (caddr_t)ump->um_fs,
20112795Ssam 	   (u_int)fs->fs_sbsize);
20234421Skarels 	brelse(bp);
20334421Skarels 	bp = NULL;
204*37737Smckusick 	fs = ump->um_fs;
205*37737Smckusick 	fs->fs_ronly = ronly;
20612795Ssam 	if (ronly == 0)
20712795Ssam 		fs->fs_fmod = 1;
20830749Skarels 	if (havepart) {
20930749Skarels 		dpart.part->p_fstype = FS_BSDFFS;
21030749Skarels 		dpart.part->p_fsize = fs->fs_fsize;
21130749Skarels 		dpart.part->p_frag = fs->fs_frag;
21231385Skarels 		dpart.part->p_cpg = fs->fs_cpg;
21330749Skarels 	}
21412795Ssam 	blks = howmany(fs->fs_cssize, fs->fs_fsize);
21534473Smckusick 	base = space = (caddr_t)malloc((u_long)fs->fs_cssize, M_SUPERBLK,
21634473Smckusick 	    M_WAITOK);
21712795Ssam 	for (i = 0; i < blks; i += fs->fs_frag) {
21812795Ssam 		size = fs->fs_bsize;
21912795Ssam 		if (i + fs->fs_frag > blks)
22012795Ssam 			size = (blks - i) * fs->fs_fsize;
221*37737Smckusick 		error = bread(devvp, fsbtodb(fs, fs->fs_csaddr + i), size, &bp);
222*37737Smckusick 		if (error) {
22334473Smckusick 			free((caddr_t)base, M_SUPERBLK);
22412795Ssam 			goto out;
22512795Ssam 		}
22634421Skarels 		bcopy((caddr_t)bp->b_un.b_addr, space, (u_int)size);
22717225Smckusick 		fs->fs_csp[fragstoblks(fs, i)] = (struct csum *)space;
22812795Ssam 		space += size;
22934421Skarels 		brelse(bp);
23034421Skarels 		bp = NULL;
23112795Ssam 	}
232*37737Smckusick 	mp->m_data = (qaddr_t)ump;
233*37737Smckusick 	mp->m_bsize = fs->fs_bsize;
234*37737Smckusick 	mp->m_fsize = fs->fs_fsize;
235*37737Smckusick 	mp->m_fsid.val[0] = (long)dev;
236*37737Smckusick 	mp->m_fsid.val[1] = MOUNT_UFS;
237*37737Smckusick 	ump->um_mountp = mp;
238*37737Smckusick 	ump->um_dev = dev;
239*37737Smckusick 	ump->um_devvp = devvp;
240*37737Smckusick 	ump->um_qinod = NULL;
241*37737Smckusick 
24230383Smckusick 	/* Sanity checks for old file systems.			   XXX */
24330383Smckusick 	fs->fs_npsect = MAX(fs->fs_npsect, fs->fs_nsect);	/* XXX */
24430383Smckusick 	fs->fs_interleave = MAX(fs->fs_interleave, 1);		/* XXX */
24534145Smckusick 	if (fs->fs_postblformat == FS_42POSTBLFMT)		/* XXX */
24634145Smckusick 		fs->fs_nrpos = 8;				/* XXX */
247*37737Smckusick 	return (0);
24812795Ssam out:
24932721Smckusick 	if (needclose)
250*37737Smckusick 		(void) VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE,
251*37737Smckusick 			(struct ucred *)0);
252*37737Smckusick 	if (ump->um_fs) {
253*37737Smckusick 		free((caddr_t)ump->um_fs, M_SUPERBLK);
254*37737Smckusick 		ump->um_fs = NULL;
25532721Smckusick 	}
25634421Skarels 	if (bp)
25734421Skarels 		brelse(bp);
258*37737Smckusick 	return (error);
25912795Ssam }
26012795Ssam 
26112795Ssam 
262*37737Smckusick /*
263*37737Smckusick  * unmount system call
264*37737Smckusick  */
265*37737Smckusick ufs_unmount(mp, flags)
266*37737Smckusick 	struct mount *mp;
267*37737Smckusick 	int flags;
26812795Ssam {
269*37737Smckusick 	register struct ufsmount *ump;
270*37737Smckusick 	register struct fs *fs;
27112795Ssam 	dev_t dev;
272*37737Smckusick 	int error, ronly;
27312795Ssam 
274*37737Smckusick 	if (flags & MNT_FORCE)
275*37737Smckusick 		return (EINVAL);
276*37737Smckusick 	ump = VFSTOUFS(mp);
277*37737Smckusick 	dev = ump->um_dev;
27812795Ssam #ifdef QUOTA
279*37737Smckusick 	if (error = iflush(dev, ump->um_qinod))
28012795Ssam #else
281*37737Smckusick 	if (error = iflush(dev))
28212795Ssam #endif
28330749Skarels 		return (error);
28412795Ssam #ifdef QUOTA
285*37737Smckusick 	(void)closedq(ump);
28612795Ssam 	/*
28712795Ssam 	 * Here we have to iflush again to get rid of the quota inode.
288*37737Smckusick 	 * A drag, but it would be ugly to cheat, & this doesn't happen often
28912795Ssam 	 */
29012795Ssam 	(void)iflush(dev, (struct inode *)NULL);
29112795Ssam #endif
292*37737Smckusick 	fs = ump->um_fs;
293*37737Smckusick 	ronly = !fs->fs_ronly;
29431660Smckusick 	free((caddr_t)fs->fs_csp[0], M_SUPERBLK);
295*37737Smckusick 	free((caddr_t)fs, M_SUPERBLK);
296*37737Smckusick 	ump->um_fs = NULL;
297*37737Smckusick 	ump->um_dev = NODEV;
298*37737Smckusick 	error = VOP_CLOSE(ump->um_devvp, ronly ? FREAD : FREAD|FWRITE,
299*37737Smckusick 		(struct ucred *)0);
300*37737Smckusick 	vrele(ump->um_devvp);
301*37737Smckusick 	ump->um_devvp = (struct vnode *)0;
30230749Skarels 	return (error);
30312795Ssam }
30412795Ssam 
305*37737Smckusick /*
306*37737Smckusick  * Return root of a filesystem
307*37737Smckusick  */
308*37737Smckusick ufs_root(mp, vpp)
30912795Ssam 	struct mount *mp;
310*37737Smckusick 	struct vnode **vpp;
31112795Ssam {
312*37737Smckusick 	struct inode tip, *ip;
313*37737Smckusick 	int error;
314*37737Smckusick 
315*37737Smckusick 	tip.i_dev = VFSTOUFS(mp)->um_dev;
316*37737Smckusick 	tip.i_vnode.v_mount = mp;
317*37737Smckusick 	error = iget(&tip, (ino_t)ROOTINO, &ip);
318*37737Smckusick 	if (error)
319*37737Smckusick 		return (error);
320*37737Smckusick 	*vpp = ITOV(ip);
321*37737Smckusick 	return (0);
322*37737Smckusick }
323*37737Smckusick 
324*37737Smckusick /*
325*37737Smckusick  * Get file system statistics.
326*37737Smckusick  */
327*37737Smckusick ufs_statfs(mp, sbp)
328*37737Smckusick 	struct mount *mp;
329*37737Smckusick 	register struct statfs *sbp;
330*37737Smckusick {
331*37737Smckusick 	register struct ufsmount *ump;
332*37737Smckusick 	register struct fs *fs;
333*37737Smckusick 
334*37737Smckusick 	ump = VFSTOUFS(mp);
335*37737Smckusick 	fs = ump->um_fs;
336*37737Smckusick 	if (fs->fs_magic != FS_MAGIC)
337*37737Smckusick 		panic("ufs_statfs");
338*37737Smckusick 	sbp->f_type = MOUNT_UFS;
339*37737Smckusick 	sbp->f_flags = mp->m_flag &~ (M_MLOCK|M_MWAIT);
340*37737Smckusick 	sbp->f_fsize = fs->fs_fsize;
341*37737Smckusick 	sbp->f_bsize = fs->fs_bsize;
342*37737Smckusick 	sbp->f_blocks = fs->fs_dsize;
343*37737Smckusick 	sbp->f_bfree = fs->fs_cstotal.cs_nbfree * fs->fs_frag +
344*37737Smckusick 		fs->fs_cstotal.cs_nffree;
345*37737Smckusick 	sbp->f_bavail = (fs->fs_dsize * (100 - fs->fs_minfree) / 100) -
346*37737Smckusick 		(fs->fs_dsize - sbp->f_bfree);
347*37737Smckusick 	if (sbp->f_bavail < 0)
348*37737Smckusick 		sbp->f_bavail = 0;
349*37737Smckusick 	sbp->f_files =  fs->fs_ncg * fs->fs_ipg;
350*37737Smckusick 	sbp->f_ffree = fs->fs_cstotal.cs_nifree;
351*37737Smckusick 	sbp->f_fsid = mp->m_fsid;
352*37737Smckusick 	bcopy((caddr_t)fs->fs_fsmnt, (caddr_t)&sbp->f_mntonname[0], MNAMELEN);
353*37737Smckusick 	bcopy((caddr_t)ump->um_mntname, (caddr_t)&sbp->f_mntfromname[0],
354*37737Smckusick 		MNAMELEN);
355*37737Smckusick 	return (0);
356*37737Smckusick }
357*37737Smckusick 
358*37737Smckusick int	syncprt = 0;
359*37737Smckusick 
360*37737Smckusick /*
361*37737Smckusick  * Go through the disk queues to initiate sandbagged IO;
362*37737Smckusick  * go through the inodes to write those that have been modified;
363*37737Smckusick  * initiate the writing of the super block if it has been modified.
364*37737Smckusick  */
365*37737Smckusick ufs_sync(mp, waitfor)
366*37737Smckusick 	struct mount *mp;
367*37737Smckusick 	int waitfor;
368*37737Smckusick {
369*37737Smckusick 	register struct inode *ip;
370*37737Smckusick 	register struct ufsmount *ump = VFSTOUFS(mp);
371*37737Smckusick 	register struct fs *fs;
372*37737Smckusick 	int error = 0;
373*37737Smckusick 	static int updlock = 0;
374*37737Smckusick 
375*37737Smckusick 	if (syncprt)
376*37737Smckusick 		bufstats();
377*37737Smckusick 	if (updlock)
378*37737Smckusick 		return (EBUSY);
379*37737Smckusick 	fs = ump->um_fs;
380*37737Smckusick 	if (fs == (struct fs *)1)
381*37737Smckusick 		return (0);
382*37737Smckusick 	updlock++;
383*37737Smckusick 	/*
384*37737Smckusick 	 * Write back modified superblock.
385*37737Smckusick 	 * Consistency check that the superblock
386*37737Smckusick 	 * is still in the buffer cache.
387*37737Smckusick 	 */
388*37737Smckusick 	if (fs->fs_fmod != 0) {
389*37737Smckusick 		if (fs->fs_ronly != 0) {		/* XXX */
390*37737Smckusick 			printf("fs = %s\n", fs->fs_fsmnt);
391*37737Smckusick 			panic("update: rofs mod");
392*37737Smckusick 		}
393*37737Smckusick 		fs->fs_fmod = 0;
394*37737Smckusick 		fs->fs_time = time.tv_sec;
395*37737Smckusick 		error = sbupdate(ump, waitfor);
396*37737Smckusick 	}
397*37737Smckusick 	/*
398*37737Smckusick 	 * Write back each (modified) inode.
399*37737Smckusick 	 */
400*37737Smckusick 	for (ip = inode; ip < inodeNINODE; ip++) {
401*37737Smckusick 		if (ip->i_devvp != ump->um_devvp ||
402*37737Smckusick 		    (ip->i_flag & ILOCKED) != 0 || ITOV(ip)->v_count == 0 ||
403*37737Smckusick 		    (ip->i_flag & (IMOD|IACC|IUPD|ICHG)) == 0)
404*37737Smckusick 			continue;
405*37737Smckusick 		ip->i_flag |= ILOCKED;
406*37737Smckusick 		ITOV(ip)->v_count++;
407*37737Smckusick 		error = iupdat(ip, &time, &time, waitfor == MNT_WAIT);
408*37737Smckusick 		iput(ip);
409*37737Smckusick 	}
410*37737Smckusick 	updlock = 0;
411*37737Smckusick 	/*
412*37737Smckusick 	 * Force stale buffer cache information to be flushed.
413*37737Smckusick 	 */
414*37737Smckusick 	bflush(ump->um_devvp->v_rdev);
415*37737Smckusick 	return (error);
416*37737Smckusick }
417*37737Smckusick 
418*37737Smckusick /*
419*37737Smckusick  * Write a superblock and associated information back to disk.
420*37737Smckusick  */
421*37737Smckusick sbupdate(mp, waitfor)
422*37737Smckusick 	struct ufsmount *mp;
423*37737Smckusick 	int waitfor;
424*37737Smckusick {
425*37737Smckusick 	register struct fs *fs = mp->um_fs;
42612795Ssam 	register struct buf *bp;
42712795Ssam 	int blks;
42812795Ssam 	caddr_t space;
429*37737Smckusick 	int i, size, error = 0;
43012795Ssam 
431*37737Smckusick 	bp = getblk(mp->um_devvp, SBLOCK, (int)fs->fs_sbsize);
43212795Ssam 	bcopy((caddr_t)fs, bp->b_un.b_addr, (u_int)fs->fs_sbsize);
43334145Smckusick 	/* Restore compatibility to old file systems.		   XXX */
43434145Smckusick 	if (fs->fs_postblformat == FS_42POSTBLFMT)		/* XXX */
43534145Smckusick 		bp->b_un.b_fs->fs_nrpos = -1;			/* XXX */
436*37737Smckusick 	if (waitfor == MNT_WAIT)
437*37737Smckusick 		error = bwrite(bp);
438*37737Smckusick 	else
439*37737Smckusick 		bawrite(bp);
44012795Ssam 	blks = howmany(fs->fs_cssize, fs->fs_fsize);
44112795Ssam 	space = (caddr_t)fs->fs_csp[0];
44212795Ssam 	for (i = 0; i < blks; i += fs->fs_frag) {
44312795Ssam 		size = fs->fs_bsize;
44412795Ssam 		if (i + fs->fs_frag > blks)
44512795Ssam 			size = (blks - i) * fs->fs_fsize;
446*37737Smckusick 		bp = getblk(mp->um_devvp, fsbtodb(fs, fs->fs_csaddr + i), size);
44712795Ssam 		bcopy(space, bp->b_un.b_addr, (u_int)size);
44812795Ssam 		space += size;
449*37737Smckusick 		if (waitfor == MNT_WAIT)
450*37737Smckusick 			error = bwrite(bp);
451*37737Smckusick 		else
452*37737Smckusick 			bawrite(bp);
45312795Ssam 	}
454*37737Smckusick 	return (error);
45512795Ssam }
45612795Ssam 
45712795Ssam /*
458*37737Smckusick  * Print out statistics on the current allocation of the buffer pool.
459*37737Smckusick  * Can be enabled to print out on every ``sync'' by setting "syncprt"
460*37737Smckusick  * above.
461*37737Smckusick  */
462*37737Smckusick bufstats()
463*37737Smckusick {
464*37737Smckusick 	int s, i, j, count;
465*37737Smckusick 	register struct buf *bp, *dp;
466*37737Smckusick 	int counts[MAXBSIZE/CLBYTES+1];
467*37737Smckusick 	static char *bname[BQUEUES] = { "LOCKED", "LRU", "AGE", "EMPTY" };
468*37737Smckusick 
469*37737Smckusick 	for (bp = bfreelist, i = 0; bp < &bfreelist[BQUEUES]; bp++, i++) {
470*37737Smckusick 		count = 0;
471*37737Smckusick 		for (j = 0; j <= MAXBSIZE/CLBYTES; j++)
472*37737Smckusick 			counts[j] = 0;
473*37737Smckusick 		s = splbio();
474*37737Smckusick 		for (dp = bp->av_forw; dp != bp; dp = dp->av_forw) {
475*37737Smckusick 			counts[dp->b_bufsize/CLBYTES]++;
476*37737Smckusick 			count++;
477*37737Smckusick 		}
478*37737Smckusick 		splx(s);
479*37737Smckusick 		printf("%s: total-%d", bname[i], count);
480*37737Smckusick 		for (j = 0; j <= MAXBSIZE/CLBYTES; j++)
481*37737Smckusick 			if (counts[j] != 0)
482*37737Smckusick 				printf(", %d-%d", j * CLBYTES, counts[j]);
483*37737Smckusick 		printf("\n");
484*37737Smckusick 	}
485*37737Smckusick }
486*37737Smckusick 
487*37737Smckusick /*
488*37737Smckusick  * File handle to vnode
489*37737Smckusick  */
490*37737Smckusick ufs_fhtovp(mp, fhp, vpp)
491*37737Smckusick 	struct mount *mp;
492*37737Smckusick 	struct fid *fhp;
493*37737Smckusick 	struct vnode **vpp;
494*37737Smckusick {
495*37737Smckusick 	register struct ufid *ufhp;
496*37737Smckusick 	struct inode tip, *ip;
497*37737Smckusick 	int error;
498*37737Smckusick 
499*37737Smckusick 	ufhp = (struct ufid *)fhp;
500*37737Smckusick 	tip.i_dev = VFSTOUFS(mp)->um_dev;
501*37737Smckusick 	tip.i_vnode.v_mount = mp;
502*37737Smckusick 	if (error = iget(&tip, ufhp->ufid_ino, &ip)) {
503*37737Smckusick 		*vpp = NULL;
504*37737Smckusick 		return (error);
505*37737Smckusick 	}
506*37737Smckusick 	if (ip->i_gen != ufhp->ufid_gen) {
507*37737Smckusick 		iput(ip);
508*37737Smckusick 		*vpp = NULL;
509*37737Smckusick 		return (EINVAL);
510*37737Smckusick 	}
511*37737Smckusick 	*vpp = ITOV(ip);
512*37737Smckusick 	return (0);
513*37737Smckusick }
514*37737Smckusick 
515*37737Smckusick /*
516*37737Smckusick  * Vnode pointer to File handle, should never happen.
517*37737Smckusick  */
518*37737Smckusick /* ARGSUSED */
519*37737Smckusick ufs_vptofh(mp, fhp, vpp)
520*37737Smckusick 	struct mount *mp;
521*37737Smckusick 	struct fid *fhp;
522*37737Smckusick 	struct vnode **vpp;
523*37737Smckusick {
524*37737Smckusick 
525*37737Smckusick 	return (EINVAL);
526*37737Smckusick }
527*37737Smckusick 
528*37737Smckusick /*
529*37737Smckusick  * Common code for mount and quota.
53012795Ssam  * Check that the user's argument is a reasonable
53112795Ssam  * thing on which to mount, and return the device number if so.
53212795Ssam  */
533*37737Smckusick getmdev(devvpp, fname, ndp)
534*37737Smckusick 	struct vnode **devvpp;
53516697Smckusick 	caddr_t fname;
536*37737Smckusick 	register struct nameidata *ndp;
53712795Ssam {
538*37737Smckusick 	register struct vnode *vp;
539*37737Smckusick 	int error;
54012795Ssam 
541*37737Smckusick 	ndp->ni_nameiop = LOOKUP | LOCKLEAF | FOLLOW;
54216697Smckusick 	ndp->ni_segflg = UIO_USERSPACE;
54316697Smckusick 	ndp->ni_dirp = fname;
544*37737Smckusick 	if (error = namei(ndp)) {
545*37737Smckusick 		if (error == ENOENT)
546*37737Smckusick 			return (ENODEV);	/* needs translation */
547*37737Smckusick 		return (error);
54821013Smckusick 	}
549*37737Smckusick 	vp = ndp->ni_vp;
550*37737Smckusick 	if (vp->v_type != VBLK) {
551*37737Smckusick 		vput(vp);
55212795Ssam 		return (ENOTBLK);
55315956Skarels 	}
554*37737Smckusick 	if (major(vp->v_rdev) >= nblkdev)
55512795Ssam 		return (ENXIO);
556*37737Smckusick 	iunlock(VTOI(vp));
557*37737Smckusick 	*devvpp = vp;
55812795Ssam 	return (0);
55912795Ssam }
560