xref: /dragonfly/sys/vfs/ufs/ffs_vfsops.c (revision 984263bc)
1 /*
2  * Copyright (c) 1989, 1991, 1993, 1994
3  *	The Regents of the University of California.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. All advertising materials mentioning features or use of this software
14  *    must display the following acknowledgement:
15  *	This product includes software developed by the University of
16  *	California, Berkeley and its contributors.
17  * 4. Neither the name of the University nor the names of its contributors
18  *    may be used to endorse or promote products derived from this software
19  *    without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  *
33  *	@(#)ffs_vfsops.c	8.31 (Berkeley) 5/20/95
34  * $FreeBSD: src/sys/ufs/ffs/ffs_vfsops.c,v 1.117.2.10 2002/06/23 22:34:52 iedowse Exp $
35  */
36 
37 #include "opt_quota.h"
38 
39 #include <sys/param.h>
40 #include <sys/systm.h>
41 #include <sys/namei.h>
42 #include <sys/proc.h>
43 #include <sys/kernel.h>
44 #include <sys/vnode.h>
45 #include <sys/mount.h>
46 #include <sys/buf.h>
47 #include <sys/conf.h>
48 #include <sys/fcntl.h>
49 #include <sys/disklabel.h>
50 #include <sys/malloc.h>
51 
52 #include <ufs/ufs/quota.h>
53 #include <ufs/ufs/ufsmount.h>
54 #include <ufs/ufs/inode.h>
55 #include <ufs/ufs/ufs_extern.h>
56 
57 #include <ufs/ffs/fs.h>
58 #include <ufs/ffs/ffs_extern.h>
59 
60 #include <vm/vm.h>
61 #include <vm/vm_page.h>
62 #include <vm/vm_zone.h>
63 
64 static MALLOC_DEFINE(M_FFSNODE, "FFS node", "FFS vnode private part");
65 
66 static int	ffs_sbupdate __P((struct ufsmount *, int));
67 static int	ffs_reload __P((struct mount *,struct ucred *,struct proc *));
68 static int	ffs_oldfscompat __P((struct fs *));
69 static int	ffs_mount __P((struct mount *, char *, caddr_t,
70 				struct nameidata *, struct proc *));
71 static int	ffs_init __P((struct vfsconf *));
72 
73 static struct vfsops ufs_vfsops = {
74 	ffs_mount,
75 	ufs_start,
76 	ffs_unmount,
77 	ufs_root,
78 	ufs_quotactl,
79 	ffs_statfs,
80 	ffs_sync,
81 	ffs_vget,
82 	ffs_fhtovp,
83 	ufs_check_export,
84 	ffs_vptofh,
85 	ffs_init,
86 	vfs_stduninit,
87 	vfs_stdextattrctl,
88 };
89 
90 VFS_SET(ufs_vfsops, ufs, 0);
91 
92 /*
93  * ffs_mount
94  *
95  * Called when mounting local physical media
96  *
97  * PARAMETERS:
98  *		mountroot
99  *			mp	mount point structure
100  *			path	NULL (flag for root mount!!!)
101  *			data	<unused>
102  *			ndp	<unused>
103  *			p	process (user credentials check [statfs])
104  *
105  *		mount
106  *			mp	mount point structure
107  *			path	path to mount point
108  *			data	pointer to argument struct in user space
109  *			ndp	mount point namei() return (used for
110  *				credentials on reload), reused to look
111  *				up block device.
112  *			p	process (user credentials check)
113  *
114  * RETURNS:	0	Success
115  *		!0	error number (errno.h)
116  *
117  * LOCK STATE:
118  *
119  *		ENTRY
120  *			mount point is locked
121  *		EXIT
122  *			mount point is locked
123  *
124  * NOTES:
125  *		A NULL path can be used for a flag since the mount
126  *		system call will fail with EFAULT in copyinstr in
127  *		namei() if it is a genuine NULL from the user.
128  */
129 static int
130 ffs_mount( mp, path, data, ndp, p)
131         struct mount		*mp;	/* mount struct pointer*/
132         char			*path;	/* path to mount point*/
133         caddr_t			data;	/* arguments to FS specific mount*/
134         struct nameidata	*ndp;	/* mount point credentials*/
135         struct proc		*p;	/* process requesting mount*/
136 {
137 	size_t		size;
138 	int		err = 0;
139 	struct vnode	*devvp;
140 
141 	struct ufs_args args;
142 	struct ufsmount *ump = 0;
143 	register struct fs *fs;
144 	int error, flags, ronly = 0;
145 	mode_t accessmode;
146 
147 	/*
148 	 * Use NULL path to flag a root mount
149 	 */
150 	if( path == NULL) {
151 		/*
152 		 ***
153 		 * Mounting root file system
154 		 ***
155 		 */
156 
157 		if ((err = bdevvp(rootdev, &rootvp))) {
158 			printf("ffs_mountroot: can't find rootvp\n");
159 			return (err);
160 		}
161 
162 		if( ( err = ffs_mountfs(rootvp, mp, p, M_FFSNODE)) != 0) {
163 			/* fs specific cleanup (if any)*/
164 			goto error_1;
165 		}
166 
167 		goto dostatfs;		/* success*/
168 
169 	}
170 
171 	/*
172 	 ***
173 	 * Mounting non-root file system or updating a file system
174 	 ***
175 	 */
176 
177 	/* copy in user arguments*/
178 	err = copyin(data, (caddr_t)&args, sizeof (struct ufs_args));
179 	if (err)
180 		goto error_1;		/* can't get arguments*/
181 
182 	/*
183 	 * If updating, check whether changing from read-only to
184 	 * read/write; if there is no device name, that's all we do.
185 	 */
186 	if (mp->mnt_flag & MNT_UPDATE) {
187 		ump = VFSTOUFS(mp);
188 		fs = ump->um_fs;
189 		devvp = ump->um_devvp;
190 		err = 0;
191 		ronly = fs->fs_ronly;	/* MNT_RELOAD might change this */
192 		if (ronly == 0 && (mp->mnt_flag & MNT_RDONLY)) {
193 			/*
194 			 * Flush any dirty data.
195 			 */
196 			VFS_SYNC(mp, MNT_WAIT, p->p_ucred, p);
197 			/*
198 			 * Check for and optionally get rid of files open
199 			 * for writing.
200 			 */
201 			flags = WRITECLOSE;
202 			if (mp->mnt_flag & MNT_FORCE)
203 				flags |= FORCECLOSE;
204 			if (mp->mnt_flag & MNT_SOFTDEP) {
205 				err = softdep_flushfiles(mp, flags, p);
206 			} else {
207 				err = ffs_flushfiles(mp, flags, p);
208 			}
209 			ronly = 1;
210 		}
211 		if (!err && (mp->mnt_flag & MNT_RELOAD))
212 			err = ffs_reload(mp, ndp->ni_cnd.cn_cred, p);
213 		if (err) {
214 			goto error_1;
215 		}
216 		if (ronly && (mp->mnt_kern_flag & MNTK_WANTRDWR)) {
217 			/*
218 			 * If upgrade to read-write by non-root, then verify
219 			 * that user has necessary permissions on the device.
220 			 */
221 			if (p->p_ucred->cr_uid != 0) {
222 				vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p);
223 				if ((error = VOP_ACCESS(devvp, VREAD | VWRITE,
224 				    p->p_ucred, p)) != 0) {
225 					VOP_UNLOCK(devvp, 0, p);
226 					return (error);
227 				}
228 				VOP_UNLOCK(devvp, 0, p);
229 			}
230 
231 			fs->fs_flags &= ~FS_UNCLEAN;
232 			if (fs->fs_clean == 0) {
233 				fs->fs_flags |= FS_UNCLEAN;
234 				if (mp->mnt_flag & MNT_FORCE) {
235 					printf(
236 "WARNING: %s was not properly dismounted\n",
237 					    fs->fs_fsmnt);
238 				} else {
239 					printf(
240 "WARNING: R/W mount of %s denied.  Filesystem is not clean - run fsck\n",
241 					    fs->fs_fsmnt);
242 					err = EPERM;
243 					goto error_1;
244 				}
245 			}
246 
247 			/* check to see if we need to start softdep */
248 			if (fs->fs_flags & FS_DOSOFTDEP) {
249 				err = softdep_mount(devvp, mp, fs, p->p_ucred);
250 				if (err)
251 					goto error_1;
252 			}
253 
254 			ronly = 0;
255 		}
256 		/*
257 		 * Soft updates is incompatible with "async",
258 		 * so if we are doing softupdates stop the user
259 		 * from setting the async flag in an update.
260 		 * Softdep_mount() clears it in an initial mount
261 		 * or ro->rw remount.
262 		 */
263 		if (mp->mnt_flag & MNT_SOFTDEP) {
264 			mp->mnt_flag &= ~MNT_ASYNC;
265 		}
266 		/* if not updating name...*/
267 		if (args.fspec == 0) {
268 			/*
269 			 * Process export requests.  Jumping to "success"
270 			 * will return the vfs_export() error code.
271 			 */
272 			err = vfs_export(mp, &ump->um_export, &args.export);
273 			goto success;
274 		}
275 	}
276 
277 	/*
278 	 * Not an update, or updating the name: look up the name
279 	 * and verify that it refers to a sensible block device.
280 	 */
281 	NDINIT(ndp, LOOKUP, FOLLOW, UIO_USERSPACE, args.fspec, p);
282 	err = namei(ndp);
283 	if (err) {
284 		/* can't get devvp!*/
285 		goto error_1;
286 	}
287 
288 	NDFREE(ndp, NDF_ONLY_PNBUF);
289 	devvp = ndp->ni_vp;
290 
291 	if (!vn_isdisk(devvp, &err))
292 		goto error_2;
293 
294 	/*
295 	 * If mount by non-root, then verify that user has necessary
296 	 * permissions on the device.
297 	 */
298 	if (p->p_ucred->cr_uid != 0) {
299 		accessmode = VREAD;
300 		if ((mp->mnt_flag & MNT_RDONLY) == 0)
301 			accessmode |= VWRITE;
302 		vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p);
303 		if ((error = VOP_ACCESS(devvp, accessmode, p->p_ucred, p)) != 0) {
304 			vput(devvp);
305 			return (error);
306 		}
307 		VOP_UNLOCK(devvp, 0, p);
308 	}
309 
310 	if (mp->mnt_flag & MNT_UPDATE) {
311 		/*
312 		 ********************
313 		 * UPDATE
314 		 * If it's not the same vnode, or at least the same device
315 		 * then it's not correct.
316 		 ********************
317 		 */
318 
319 		if (devvp != ump->um_devvp) {
320 			if ( devvp->v_rdev == ump->um_devvp->v_rdev) {
321 				vrele(devvp);
322 			} else {
323 				err = EINVAL;	/* needs translation */
324 			}
325 		} else
326 			vrele(devvp);
327 		/*
328 		 * Update device name only on success
329 		 */
330 		if( !err) {
331 			/* Save "mounted from" info for mount point (NULL pad)*/
332 			copyinstr(	args.fspec,
333 					mp->mnt_stat.f_mntfromname,
334 					MNAMELEN - 1,
335 					&size);
336 			bzero( mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
337 		}
338 	} else {
339 		/*
340 		 ********************
341 		 * NEW MOUNT
342 		 ********************
343 		 */
344 
345 		/*
346 		 * Since this is a new mount, we want the names for
347 		 * the device and the mount point copied in.  If an
348 		 * error occurs,  the mountpoint is discarded by the
349 		 * upper level code.
350 		 */
351 		/* Save "last mounted on" info for mount point (NULL pad)*/
352 		copyinstr(	path,				/* mount point*/
353 				mp->mnt_stat.f_mntonname,	/* save area*/
354 				MNAMELEN - 1,			/* max size*/
355 				&size);				/* real size*/
356 		bzero( mp->mnt_stat.f_mntonname + size, MNAMELEN - size);
357 
358 		/* Save "mounted from" info for mount point (NULL pad)*/
359 		copyinstr(	args.fspec,			/* device name*/
360 				mp->mnt_stat.f_mntfromname,	/* save area*/
361 				MNAMELEN - 1,			/* max size*/
362 				&size);				/* real size*/
363 		bzero( mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
364 
365 		err = ffs_mountfs(devvp, mp, p, M_FFSNODE);
366 	}
367 	if (err) {
368 		goto error_2;
369 	}
370 
371 dostatfs:
372 	/*
373 	 * Initialize FS stat information in mount struct; uses both
374 	 * mp->mnt_stat.f_mntonname and mp->mnt_stat.f_mntfromname
375 	 *
376 	 * This code is common to root and non-root mounts
377 	 */
378 	(void)VFS_STATFS(mp, &mp->mnt_stat, p);
379 
380 	goto success;
381 
382 
383 error_2:	/* error with devvp held*/
384 
385 	/* release devvp before failing*/
386 	vrele(devvp);
387 
388 error_1:	/* no state to back out*/
389 
390 success:
391 	if (!err && path && (mp->mnt_flag & MNT_UPDATE)) {
392 		/* Update clean flag after changing read-onlyness. */
393 		fs = ump->um_fs;
394 		if (ronly != fs->fs_ronly) {
395 			fs->fs_ronly = ronly;
396 			fs->fs_clean = ronly &&
397 			    (fs->fs_flags & FS_UNCLEAN) == 0 ? 1 : 0;
398 			ffs_sbupdate(ump, MNT_WAIT);
399 		}
400 	}
401 	return (err);
402 }
403 
404 /*
405  * Reload all incore data for a filesystem (used after running fsck on
406  * the root filesystem and finding things to fix). The filesystem must
407  * be mounted read-only.
408  *
409  * Things to do to update the mount:
410  *	1) invalidate all cached meta-data.
411  *	2) re-read superblock from disk.
412  *	3) re-read summary information from disk.
413  *	4) invalidate all inactive vnodes.
414  *	5) invalidate all cached file data.
415  *	6) re-read inode data for all active vnodes.
416  */
417 static int
418 ffs_reload(mp, cred, p)
419 	register struct mount *mp;
420 	struct ucred *cred;
421 	struct proc *p;
422 {
423 	register struct vnode *vp, *nvp, *devvp;
424 	struct inode *ip;
425 	void *space;
426 	struct buf *bp;
427 	struct fs *fs, *newfs;
428 	struct partinfo dpart;
429 	dev_t dev;
430 	int i, blks, size, error;
431 	int32_t *lp;
432 
433 	if ((mp->mnt_flag & MNT_RDONLY) == 0)
434 		return (EINVAL);
435 	/*
436 	 * Step 1: invalidate all cached meta-data.
437 	 */
438 	devvp = VFSTOUFS(mp)->um_devvp;
439 	vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p);
440 	error = vinvalbuf(devvp, 0, cred, p, 0, 0);
441 	VOP_UNLOCK(devvp, 0, p);
442 	if (error)
443 		panic("ffs_reload: dirty1");
444 
445 	dev = devvp->v_rdev;
446 
447 	/*
448 	 * Only VMIO the backing device if the backing device is a real
449 	 * block device.  See ffs_mountmfs() for more details.
450 	 */
451 	if (devvp->v_tag != VT_MFS && vn_isdisk(devvp, NULL)) {
452 		vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p);
453 		vfs_object_create(devvp, p, p->p_ucred);
454 		simple_lock(&devvp->v_interlock);
455 		VOP_UNLOCK(devvp, LK_INTERLOCK, p);
456 	}
457 
458 	/*
459 	 * Step 2: re-read superblock from disk.
460 	 */
461 	if (VOP_IOCTL(devvp, DIOCGPART, (caddr_t)&dpart, FREAD, NOCRED, p) != 0)
462 		size = DEV_BSIZE;
463 	else
464 		size = dpart.disklab->d_secsize;
465 	if ((error = bread(devvp, (ufs_daddr_t)(SBOFF/size), SBSIZE, NOCRED,&bp)) != 0)
466 		return (error);
467 	newfs = (struct fs *)bp->b_data;
468 	if (newfs->fs_magic != FS_MAGIC || newfs->fs_bsize > MAXBSIZE ||
469 		newfs->fs_bsize < sizeof(struct fs)) {
470 			brelse(bp);
471 			return (EIO);		/* XXX needs translation */
472 	}
473 	fs = VFSTOUFS(mp)->um_fs;
474 	/*
475 	 * Copy pointer fields back into superblock before copying in	XXX
476 	 * new superblock. These should really be in the ufsmount.	XXX
477 	 * Note that important parameters (eg fs_ncg) are unchanged.
478 	 */
479 	newfs->fs_csp = fs->fs_csp;
480 	newfs->fs_maxcluster = fs->fs_maxcluster;
481 	newfs->fs_contigdirs = fs->fs_contigdirs;
482 	bcopy(newfs, fs, (u_int)fs->fs_sbsize);
483 	if (fs->fs_sbsize < SBSIZE)
484 		bp->b_flags |= B_INVAL;
485 	brelse(bp);
486 	mp->mnt_maxsymlinklen = fs->fs_maxsymlinklen;
487 	ffs_oldfscompat(fs);
488 	/* An old fsck may have zeroed these fields, so recheck them. */
489 	if (fs->fs_avgfilesize <= 0)		/* XXX */
490 		fs->fs_avgfilesize = AVFILESIZ;	/* XXX */
491 	if (fs->fs_avgfpdir <= 0)		/* XXX */
492 		fs->fs_avgfpdir = AFPDIR;	/* XXX */
493 
494 	/*
495 	 * Step 3: re-read summary information from disk.
496 	 */
497 	blks = howmany(fs->fs_cssize, fs->fs_fsize);
498 	space = fs->fs_csp;
499 	for (i = 0; i < blks; i += fs->fs_frag) {
500 		size = fs->fs_bsize;
501 		if (i + fs->fs_frag > blks)
502 			size = (blks - i) * fs->fs_fsize;
503 		error = bread(devvp, fsbtodb(fs, fs->fs_csaddr + i), size,
504 		    NOCRED, &bp);
505 		if (error)
506 			return (error);
507 		bcopy(bp->b_data, space, (u_int)size);
508 		space = (char *)space + size;
509 		brelse(bp);
510 	}
511 	/*
512 	 * We no longer know anything about clusters per cylinder group.
513 	 */
514 	if (fs->fs_contigsumsize > 0) {
515 		lp = fs->fs_maxcluster;
516 		for (i = 0; i < fs->fs_ncg; i++)
517 			*lp++ = fs->fs_contigsumsize;
518 	}
519 
520 loop:
521 	simple_lock(&mntvnode_slock);
522 	for (vp = TAILQ_FIRST(&mp->mnt_nvnodelist); vp != NULL; vp = nvp) {
523 		if (vp->v_mount != mp) {
524 			simple_unlock(&mntvnode_slock);
525 			goto loop;
526 		}
527 		nvp = TAILQ_NEXT(vp, v_nmntvnodes);
528 		/*
529 		 * Step 4: invalidate all inactive vnodes.
530 		 */
531 		if (vrecycle(vp, &mntvnode_slock, p))
532 			goto loop;
533 		/*
534 		 * Step 5: invalidate all cached file data.
535 		 */
536 		simple_lock(&vp->v_interlock);
537 		simple_unlock(&mntvnode_slock);
538 		if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK, p)) {
539 			goto loop;
540 		}
541 		if (vinvalbuf(vp, 0, cred, p, 0, 0))
542 			panic("ffs_reload: dirty2");
543 		/*
544 		 * Step 6: re-read inode data for all active vnodes.
545 		 */
546 		ip = VTOI(vp);
547 		error =
548 		    bread(devvp, fsbtodb(fs, ino_to_fsba(fs, ip->i_number)),
549 		    (int)fs->fs_bsize, NOCRED, &bp);
550 		if (error) {
551 			vput(vp);
552 			return (error);
553 		}
554 		ip->i_din = *((struct dinode *)bp->b_data +
555 		    ino_to_fsbo(fs, ip->i_number));
556 		ip->i_effnlink = ip->i_nlink;
557 		brelse(bp);
558 		vput(vp);
559 		simple_lock(&mntvnode_slock);
560 	}
561 	simple_unlock(&mntvnode_slock);
562 	return (0);
563 }
564 
565 /*
566  * Common code for mount and mountroot
567  */
568 int
569 ffs_mountfs(devvp, mp, p, malloctype)
570 	register struct vnode *devvp;
571 	struct mount *mp;
572 	struct proc *p;
573 	struct malloc_type *malloctype;
574 {
575 	register struct ufsmount *ump;
576 	struct buf *bp;
577 	register struct fs *fs;
578 	dev_t dev;
579 	struct partinfo dpart;
580 	void *space;
581 	int error, i, blks, size, ronly;
582 	int32_t *lp;
583 	struct ucred *cred;
584 	u_int64_t maxfilesize;					/* XXX */
585 	size_t strsize;
586 	int ncount;
587 
588 	dev = devvp->v_rdev;
589 	cred = p ? p->p_ucred : NOCRED;
590 	/*
591 	 * Disallow multiple mounts of the same device.
592 	 * Disallow mounting of a device that is currently in use
593 	 * (except for root, which might share swap device for miniroot).
594 	 * Flush out any old buffers remaining from a previous use.
595 	 */
596 	error = vfs_mountedon(devvp);
597 	if (error)
598 		return (error);
599 	ncount = vcount(devvp);
600 
601 	if (ncount > 1 && devvp != rootvp)
602 		return (EBUSY);
603 	vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p);
604 	error = vinvalbuf(devvp, V_SAVE, cred, p, 0, 0);
605 	VOP_UNLOCK(devvp, 0, p);
606 	if (error)
607 		return (error);
608 
609 	/*
610 	 * Only VMIO the backing device if the backing device is a real
611 	 * block device.  This excludes the original MFS implementation.
612 	 * Note that it is optional that the backing device be VMIOed.  This
613 	 * increases the opportunity for metadata caching.
614 	 */
615 	if (devvp->v_tag != VT_MFS && vn_isdisk(devvp, NULL)) {
616 		vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p);
617 		vfs_object_create(devvp, p, p->p_ucred);
618 		simple_lock(&devvp->v_interlock);
619 		VOP_UNLOCK(devvp, LK_INTERLOCK, p);
620 	}
621 
622 	ronly = (mp->mnt_flag & MNT_RDONLY) != 0;
623 	vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p);
624 	error = VOP_OPEN(devvp, ronly ? FREAD : FREAD|FWRITE, FSCRED, p);
625 	VOP_UNLOCK(devvp, 0, p);
626 	if (error)
627 		return (error);
628 	if (devvp->v_rdev->si_iosize_max != 0)
629 		mp->mnt_iosize_max = devvp->v_rdev->si_iosize_max;
630 	if (mp->mnt_iosize_max > MAXPHYS)
631 		mp->mnt_iosize_max = MAXPHYS;
632 
633 	if (VOP_IOCTL(devvp, DIOCGPART, (caddr_t)&dpart, FREAD, cred, p) != 0)
634 		size = DEV_BSIZE;
635 	else
636 		size = dpart.disklab->d_secsize;
637 
638 	bp = NULL;
639 	ump = NULL;
640 	if ((error = bread(devvp, SBLOCK, SBSIZE, cred, &bp)) != 0)
641 		goto out;
642 	fs = (struct fs *)bp->b_data;
643 	if (fs->fs_magic != FS_MAGIC || fs->fs_bsize > MAXBSIZE ||
644 	    fs->fs_bsize < sizeof(struct fs)) {
645 		error = EINVAL;		/* XXX needs translation */
646 		goto out;
647 	}
648 	fs->fs_fmod = 0;
649 	fs->fs_flags &= ~FS_UNCLEAN;
650 	if (fs->fs_clean == 0) {
651 		fs->fs_flags |= FS_UNCLEAN;
652 		if (ronly || (mp->mnt_flag & MNT_FORCE)) {
653 			printf(
654 "WARNING: %s was not properly dismounted\n",
655 			    fs->fs_fsmnt);
656 		} else {
657 			printf(
658 "WARNING: R/W mount of %s denied.  Filesystem is not clean - run fsck\n",
659 			    fs->fs_fsmnt);
660 			error = EPERM;
661 			goto out;
662 		}
663 	}
664 	/* XXX updating 4.2 FFS superblocks trashes rotational layout tables */
665 	if (fs->fs_postblformat == FS_42POSTBLFMT && !ronly) {
666 		error = EROFS;          /* needs translation */
667 		goto out;
668 	}
669 	ump = malloc(sizeof *ump, M_UFSMNT, M_WAITOK);
670 	bzero((caddr_t)ump, sizeof *ump);
671 	ump->um_malloctype = malloctype;
672 	ump->um_i_effnlink_valid = 1;
673 	ump->um_fs = malloc((u_long)fs->fs_sbsize, M_UFSMNT,
674 	    M_WAITOK);
675 	ump->um_blkatoff = ffs_blkatoff;
676 	ump->um_truncate = ffs_truncate;
677 	ump->um_update = ffs_update;
678 	ump->um_valloc = ffs_valloc;
679 	ump->um_vfree = ffs_vfree;
680 	bcopy(bp->b_data, ump->um_fs, (u_int)fs->fs_sbsize);
681 	if (fs->fs_sbsize < SBSIZE)
682 		bp->b_flags |= B_INVAL;
683 	brelse(bp);
684 	bp = NULL;
685 	fs = ump->um_fs;
686 	fs->fs_ronly = ronly;
687 	size = fs->fs_cssize;
688 	blks = howmany(size, fs->fs_fsize);
689 	if (fs->fs_contigsumsize > 0)
690 		size += fs->fs_ncg * sizeof(int32_t);
691 	size += fs->fs_ncg * sizeof(u_int8_t);
692 	space = malloc((u_long)size, M_UFSMNT, M_WAITOK);
693 	fs->fs_csp = space;
694 	for (i = 0; i < blks; i += fs->fs_frag) {
695 		size = fs->fs_bsize;
696 		if (i + fs->fs_frag > blks)
697 			size = (blks - i) * fs->fs_fsize;
698 		if ((error = bread(devvp, fsbtodb(fs, fs->fs_csaddr + i), size,
699 		    cred, &bp)) != 0) {
700 			free(fs->fs_csp, M_UFSMNT);
701 			goto out;
702 		}
703 		bcopy(bp->b_data, space, (u_int)size);
704 		space = (char *)space + size;
705 		brelse(bp);
706 		bp = NULL;
707 	}
708 	if (fs->fs_contigsumsize > 0) {
709 		fs->fs_maxcluster = lp = space;
710 		for (i = 0; i < fs->fs_ncg; i++)
711 			*lp++ = fs->fs_contigsumsize;
712 		space = lp;
713 	}
714 	size = fs->fs_ncg * sizeof(u_int8_t);
715 	fs->fs_contigdirs = (u_int8_t *)space;
716 	bzero(fs->fs_contigdirs, size);
717 	/* Compatibility for old filesystems 	   XXX */
718 	if (fs->fs_avgfilesize <= 0)		/* XXX */
719 		fs->fs_avgfilesize = AVFILESIZ;	/* XXX */
720 	if (fs->fs_avgfpdir <= 0)		/* XXX */
721 		fs->fs_avgfpdir = AFPDIR;	/* XXX */
722 	mp->mnt_data = (qaddr_t)ump;
723 	mp->mnt_stat.f_fsid.val[0] = fs->fs_id[0];
724 	mp->mnt_stat.f_fsid.val[1] = fs->fs_id[1];
725 	if (fs->fs_id[0] == 0 || fs->fs_id[1] == 0 ||
726 	    vfs_getvfs(&mp->mnt_stat.f_fsid))
727 		vfs_getnewfsid(mp);
728 	mp->mnt_maxsymlinklen = fs->fs_maxsymlinklen;
729 	mp->mnt_flag |= MNT_LOCAL;
730 	ump->um_mountp = mp;
731 	ump->um_dev = dev;
732 	ump->um_devvp = devvp;
733 	ump->um_nindir = fs->fs_nindir;
734 	ump->um_bptrtodb = fs->fs_fsbtodb;
735 	ump->um_seqinc = fs->fs_frag;
736 	for (i = 0; i < MAXQUOTAS; i++)
737 		ump->um_quotas[i] = NULLVP;
738 	devvp->v_specmountpoint = mp;
739 	ffs_oldfscompat(fs);
740 
741 	/*
742 	 * Set FS local "last mounted on" information (NULL pad)
743 	 */
744 	copystr(	mp->mnt_stat.f_mntonname,	/* mount point*/
745 			fs->fs_fsmnt,			/* copy area*/
746 			sizeof(fs->fs_fsmnt) - 1,	/* max size*/
747 			&strsize);			/* real size*/
748 	bzero( fs->fs_fsmnt + strsize, sizeof(fs->fs_fsmnt) - strsize);
749 
750 	if( mp->mnt_flag & MNT_ROOTFS) {
751 		/*
752 		 * Root mount; update timestamp in mount structure.
753 		 * this will be used by the common root mount code
754 		 * to update the system clock.
755 		 */
756 		mp->mnt_time = fs->fs_time;
757 	}
758 
759 	ump->um_savedmaxfilesize = fs->fs_maxfilesize;		/* XXX */
760 	maxfilesize = (u_int64_t)0x40000000 * fs->fs_bsize - 1;	/* XXX */
761 	/* Enforce limit caused by vm object backing (32 bits vm_pindex_t). */
762 	if (maxfilesize > (u_int64_t)0x80000000u * PAGE_SIZE - 1)
763 		maxfilesize = (u_int64_t)0x80000000u * PAGE_SIZE - 1;
764 	if (fs->fs_maxfilesize > maxfilesize)			/* XXX */
765 		fs->fs_maxfilesize = maxfilesize;		/* XXX */
766 	if (ronly == 0) {
767 		if ((fs->fs_flags & FS_DOSOFTDEP) &&
768 		    (error = softdep_mount(devvp, mp, fs, cred)) != 0) {
769 			free(fs->fs_csp, M_UFSMNT);
770 			goto out;
771 		}
772 		fs->fs_fmod = 1;
773 		fs->fs_clean = 0;
774 		(void) ffs_sbupdate(ump, MNT_WAIT);
775 	}
776 	return (0);
777 out:
778 	devvp->v_specmountpoint = NULL;
779 	if (bp)
780 		brelse(bp);
781 	(void)VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE, cred, p);
782 	if (ump) {
783 		free(ump->um_fs, M_UFSMNT);
784 		free(ump, M_UFSMNT);
785 		mp->mnt_data = (qaddr_t)0;
786 	}
787 	return (error);
788 }
789 
790 /*
791  * Sanity checks for old file systems.
792  *
793  * XXX - goes away some day.
794  */
795 static int
796 ffs_oldfscompat(fs)
797 	struct fs *fs;
798 {
799 
800 	fs->fs_npsect = max(fs->fs_npsect, fs->fs_nsect);	/* XXX */
801 	fs->fs_interleave = max(fs->fs_interleave, 1);		/* XXX */
802 	if (fs->fs_postblformat == FS_42POSTBLFMT)		/* XXX */
803 		fs->fs_nrpos = 8;				/* XXX */
804 	if (fs->fs_inodefmt < FS_44INODEFMT) {			/* XXX */
805 #if 0
806 		int i;						/* XXX */
807 		u_int64_t sizepb = fs->fs_bsize;		/* XXX */
808 								/* XXX */
809 		fs->fs_maxfilesize = fs->fs_bsize * NDADDR - 1;	/* XXX */
810 		for (i = 0; i < NIADDR; i++) {			/* XXX */
811 			sizepb *= NINDIR(fs);			/* XXX */
812 			fs->fs_maxfilesize += sizepb;		/* XXX */
813 		}						/* XXX */
814 #endif
815 		fs->fs_maxfilesize = (u_quad_t) 1LL << 39;
816 		fs->fs_qbmask = ~fs->fs_bmask;			/* XXX */
817 		fs->fs_qfmask = ~fs->fs_fmask;			/* XXX */
818 	}							/* XXX */
819 	return (0);
820 }
821 
822 /*
823  * unmount system call
824  */
825 int
826 ffs_unmount(mp, mntflags, p)
827 	struct mount *mp;
828 	int mntflags;
829 	struct proc *p;
830 {
831 	register struct ufsmount *ump;
832 	register struct fs *fs;
833 	int error, flags;
834 
835 	flags = 0;
836 	if (mntflags & MNT_FORCE) {
837 		flags |= FORCECLOSE;
838 	}
839 	if (mp->mnt_flag & MNT_SOFTDEP) {
840 		if ((error = softdep_flushfiles(mp, flags, p)) != 0)
841 			return (error);
842 	} else {
843 		if ((error = ffs_flushfiles(mp, flags, p)) != 0)
844 			return (error);
845 	}
846 	ump = VFSTOUFS(mp);
847 	fs = ump->um_fs;
848 	if (fs->fs_ronly == 0) {
849 		fs->fs_clean = fs->fs_flags & FS_UNCLEAN ? 0 : 1;
850 		error = ffs_sbupdate(ump, MNT_WAIT);
851 		if (error) {
852 			fs->fs_clean = 0;
853 			return (error);
854 		}
855 	}
856 	ump->um_devvp->v_specmountpoint = NULL;
857 
858 	vinvalbuf(ump->um_devvp, V_SAVE, NOCRED, p, 0, 0);
859 	error = VOP_CLOSE(ump->um_devvp, fs->fs_ronly ? FREAD : FREAD|FWRITE,
860 		NOCRED, p);
861 
862 	vrele(ump->um_devvp);
863 
864 	free(fs->fs_csp, M_UFSMNT);
865 	free(fs, M_UFSMNT);
866 	free(ump, M_UFSMNT);
867 	mp->mnt_data = (qaddr_t)0;
868 	mp->mnt_flag &= ~MNT_LOCAL;
869 	return (error);
870 }
871 
872 /*
873  * Flush out all the files in a filesystem.
874  */
875 int
876 ffs_flushfiles(mp, flags, p)
877 	register struct mount *mp;
878 	int flags;
879 	struct proc *p;
880 {
881 	register struct ufsmount *ump;
882 	int error;
883 
884 	ump = VFSTOUFS(mp);
885 #ifdef QUOTA
886 	if (mp->mnt_flag & MNT_QUOTA) {
887 		int i;
888 		error = vflush(mp, 0, SKIPSYSTEM|flags);
889 		if (error)
890 			return (error);
891 		for (i = 0; i < MAXQUOTAS; i++) {
892 			if (ump->um_quotas[i] == NULLVP)
893 				continue;
894 			quotaoff(p, mp, i);
895 		}
896 		/*
897 		 * Here we fall through to vflush again to ensure
898 		 * that we have gotten rid of all the system vnodes.
899 		 */
900 	}
901 #endif
902         /*
903 	 * Flush all the files.
904 	 */
905 	if ((error = vflush(mp, 0, flags)) != 0)
906 		return (error);
907 	/*
908 	 * Flush filesystem metadata.
909 	 */
910 	vn_lock(ump->um_devvp, LK_EXCLUSIVE | LK_RETRY, p);
911 	error = VOP_FSYNC(ump->um_devvp, p->p_ucred, MNT_WAIT, p);
912 	VOP_UNLOCK(ump->um_devvp, 0, p);
913 	return (error);
914 }
915 
916 /*
917  * Get file system statistics.
918  */
919 int
920 ffs_statfs(mp, sbp, p)
921 	struct mount *mp;
922 	register struct statfs *sbp;
923 	struct proc *p;
924 {
925 	register struct ufsmount *ump;
926 	register struct fs *fs;
927 
928 	ump = VFSTOUFS(mp);
929 	fs = ump->um_fs;
930 	if (fs->fs_magic != FS_MAGIC)
931 		panic("ffs_statfs");
932 	sbp->f_bsize = fs->fs_fsize;
933 	sbp->f_iosize = fs->fs_bsize;
934 	sbp->f_blocks = fs->fs_dsize;
935 	sbp->f_bfree = fs->fs_cstotal.cs_nbfree * fs->fs_frag +
936 		fs->fs_cstotal.cs_nffree;
937 	sbp->f_bavail = freespace(fs, fs->fs_minfree);
938 	sbp->f_files =  fs->fs_ncg * fs->fs_ipg - ROOTINO;
939 	sbp->f_ffree = fs->fs_cstotal.cs_nifree;
940 	if (sbp != &mp->mnt_stat) {
941 		sbp->f_type = mp->mnt_vfc->vfc_typenum;
942 		bcopy((caddr_t)mp->mnt_stat.f_mntonname,
943 			(caddr_t)&sbp->f_mntonname[0], MNAMELEN);
944 		bcopy((caddr_t)mp->mnt_stat.f_mntfromname,
945 			(caddr_t)&sbp->f_mntfromname[0], MNAMELEN);
946 	}
947 	return (0);
948 }
949 
950 /*
951  * Go through the disk queues to initiate sandbagged IO;
952  * go through the inodes to write those that have been modified;
953  * initiate the writing of the super block if it has been modified.
954  *
955  * Note: we are always called with the filesystem marked `MPBUSY'.
956  */
957 int
958 ffs_sync(mp, waitfor, cred, p)
959 	struct mount *mp;
960 	int waitfor;
961 	struct ucred *cred;
962 	struct proc *p;
963 {
964 	struct vnode *nvp, *vp;
965 	struct inode *ip;
966 	struct ufsmount *ump = VFSTOUFS(mp);
967 	struct fs *fs;
968 	int error, allerror = 0;
969 
970 	fs = ump->um_fs;
971 	if (fs->fs_fmod != 0 && fs->fs_ronly != 0) {		/* XXX */
972 		printf("fs = %s\n", fs->fs_fsmnt);
973 		panic("ffs_sync: rofs mod");
974 	}
975 	/*
976 	 * Write back each (modified) inode.
977 	 */
978 	simple_lock(&mntvnode_slock);
979 loop:
980 	for (vp = TAILQ_FIRST(&mp->mnt_nvnodelist); vp != NULL; vp = nvp) {
981 		/*
982 		 * If the vnode that we are about to sync is no longer
983 		 * associated with this mount point, start over.
984 		 */
985 		if (vp->v_mount != mp)
986 			goto loop;
987 
988 		/*
989 		 * Depend on the mntvnode_slock to keep things stable enough
990 		 * for a quick test.  Since there might be hundreds of
991 		 * thousands of vnodes, we cannot afford even a subroutine
992 		 * call unless there's a good chance that we have work to do.
993 		 */
994 		nvp = TAILQ_NEXT(vp, v_nmntvnodes);
995 		ip = VTOI(vp);
996 		if (vp->v_type == VNON || ((ip->i_flag &
997 		     (IN_ACCESS | IN_CHANGE | IN_MODIFIED | IN_UPDATE)) == 0 &&
998 		     TAILQ_EMPTY(&vp->v_dirtyblkhd))) {
999 			continue;
1000 		}
1001 		if (vp->v_type != VCHR) {
1002 			simple_unlock(&mntvnode_slock);
1003 			error = vget(vp, LK_EXCLUSIVE | LK_NOWAIT, p);
1004 			if (error) {
1005 				simple_lock(&mntvnode_slock);
1006 				if (error == ENOENT)
1007 					goto loop;
1008 			} else {
1009 				if ((error = VOP_FSYNC(vp, cred, waitfor, p)) != 0)
1010 					allerror = error;
1011 				VOP_UNLOCK(vp, 0, p);
1012 				vrele(vp);
1013 				simple_lock(&mntvnode_slock);
1014 			}
1015 		} else {
1016 			/*
1017 			 * We must reference the vp to prevent it from
1018 			 * getting ripped out from under UFS_UPDATE, since
1019 			 * we are not holding a vnode lock.  XXX why aren't
1020 			 * we holding a vnode lock?
1021 			 */
1022 			VREF(vp);
1023 			simple_unlock(&mntvnode_slock);
1024 			/* UFS_UPDATE(vp, waitfor == MNT_WAIT); */
1025 			UFS_UPDATE(vp, 0);
1026 			vrele(vp);
1027 			simple_lock(&mntvnode_slock);
1028 		}
1029 		if (TAILQ_NEXT(vp, v_nmntvnodes) != nvp)
1030 			goto loop;
1031 	}
1032 	simple_unlock(&mntvnode_slock);
1033 	/*
1034 	 * Force stale file system control information to be flushed.
1035 	 */
1036 	if (waitfor != MNT_LAZY) {
1037 		if (ump->um_mountp->mnt_flag & MNT_SOFTDEP)
1038 			waitfor = MNT_NOWAIT;
1039 		vn_lock(ump->um_devvp, LK_EXCLUSIVE | LK_RETRY, p);
1040 		if ((error = VOP_FSYNC(ump->um_devvp, cred, waitfor, p)) != 0)
1041 			allerror = error;
1042 		VOP_UNLOCK(ump->um_devvp, 0, p);
1043 	}
1044 #ifdef QUOTA
1045 	qsync(mp);
1046 #endif
1047 	/*
1048 	 * Write back modified superblock.
1049 	 */
1050 	if (fs->fs_fmod != 0 && (error = ffs_sbupdate(ump, waitfor)) != 0)
1051 		allerror = error;
1052 	return (allerror);
1053 }
1054 
1055 /*
1056  * Look up a FFS dinode number to find its incore vnode, otherwise read it
1057  * in from disk.  If it is in core, wait for the lock bit to clear, then
1058  * return the inode locked.  Detection and handling of mount points must be
1059  * done by the calling routine.
1060  */
1061 static int ffs_inode_hash_lock;
1062 
1063 int
1064 ffs_vget(mp, ino, vpp)
1065 	struct mount *mp;
1066 	ino_t ino;
1067 	struct vnode **vpp;
1068 {
1069 	struct fs *fs;
1070 	struct inode *ip;
1071 	struct ufsmount *ump;
1072 	struct buf *bp;
1073 	struct vnode *vp;
1074 	dev_t dev;
1075 	int error;
1076 
1077 	ump = VFSTOUFS(mp);
1078 	dev = ump->um_dev;
1079 restart:
1080 	if ((*vpp = ufs_ihashget(dev, ino)) != NULL) {
1081 		return (0);
1082 	}
1083 
1084 	/*
1085 	 * Lock out the creation of new entries in the FFS hash table in
1086 	 * case getnewvnode() or MALLOC() blocks, otherwise a duplicate
1087 	 * may occur!
1088 	 */
1089 	if (ffs_inode_hash_lock) {
1090 		while (ffs_inode_hash_lock) {
1091 			ffs_inode_hash_lock = -1;
1092 			tsleep(&ffs_inode_hash_lock, PVM, "ffsvgt", 0);
1093 		}
1094 		goto restart;
1095 	}
1096 	ffs_inode_hash_lock = 1;
1097 
1098 	/*
1099 	 * If this MALLOC() is performed after the getnewvnode()
1100 	 * it might block, leaving a vnode with a NULL v_data to be
1101 	 * found by ffs_sync() if a sync happens to fire right then,
1102 	 * which will cause a panic because ffs_sync() blindly
1103 	 * dereferences vp->v_data (as well it should).
1104 	 */
1105 	MALLOC(ip, struct inode *, sizeof(struct inode),
1106 	    ump->um_malloctype, M_WAITOK);
1107 
1108 	/* Allocate a new vnode/inode. */
1109 	error = getnewvnode(VT_UFS, mp, ffs_vnodeop_p, &vp);
1110 	if (error) {
1111 		if (ffs_inode_hash_lock < 0)
1112 			wakeup(&ffs_inode_hash_lock);
1113 		ffs_inode_hash_lock = 0;
1114 		*vpp = NULL;
1115 		FREE(ip, ump->um_malloctype);
1116 		return (error);
1117 	}
1118 	bzero((caddr_t)ip, sizeof(struct inode));
1119 	lockinit(&ip->i_lock, PINOD, "inode", VLKTIMEOUT, LK_CANRECURSE);
1120 	vp->v_data = ip;
1121 	/*
1122 	 * FFS supports lock sharing in the stack of vnodes
1123 	 */
1124 	vp->v_vnlock = &ip->i_lock;
1125 	ip->i_vnode = vp;
1126 	ip->i_fs = fs = ump->um_fs;
1127 	ip->i_dev = dev;
1128 	ip->i_number = ino;
1129 #ifdef QUOTA
1130 	{
1131 		int i;
1132 		for (i = 0; i < MAXQUOTAS; i++)
1133 			ip->i_dquot[i] = NODQUOT;
1134 	}
1135 #endif
1136 	/*
1137 	 * Put it onto its hash chain and lock it so that other requests for
1138 	 * this inode will block if they arrive while we are sleeping waiting
1139 	 * for old data structures to be purged or for the contents of the
1140 	 * disk portion of this inode to be read.
1141 	 */
1142 	ufs_ihashins(ip);
1143 
1144 	if (ffs_inode_hash_lock < 0)
1145 		wakeup(&ffs_inode_hash_lock);
1146 	ffs_inode_hash_lock = 0;
1147 
1148 	/* Read in the disk contents for the inode, copy into the inode. */
1149 	error = bread(ump->um_devvp, fsbtodb(fs, ino_to_fsba(fs, ino)),
1150 	    (int)fs->fs_bsize, NOCRED, &bp);
1151 	if (error) {
1152 		/*
1153 		 * The inode does not contain anything useful, so it would
1154 		 * be misleading to leave it on its hash chain. With mode
1155 		 * still zero, it will be unlinked and returned to the free
1156 		 * list by vput().
1157 		 */
1158 		brelse(bp);
1159 		vput(vp);
1160 		*vpp = NULL;
1161 		return (error);
1162 	}
1163 	ip->i_din = *((struct dinode *)bp->b_data + ino_to_fsbo(fs, ino));
1164 	if (DOINGSOFTDEP(vp))
1165 		softdep_load_inodeblock(ip);
1166 	else
1167 		ip->i_effnlink = ip->i_nlink;
1168 	bqrelse(bp);
1169 
1170 	/*
1171 	 * Initialize the vnode from the inode, check for aliases.
1172 	 * Note that the underlying vnode may have changed.
1173 	 */
1174 	error = ufs_vinit(mp, ffs_specop_p, ffs_fifoop_p, &vp);
1175 	if (error) {
1176 		vput(vp);
1177 		*vpp = NULL;
1178 		return (error);
1179 	}
1180 	/*
1181 	 * Finish inode initialization now that aliasing has been resolved.
1182 	 */
1183 	ip->i_devvp = ump->um_devvp;
1184 	VREF(ip->i_devvp);
1185 	/*
1186 	 * Set up a generation number for this inode if it does not
1187 	 * already have one. This should only happen on old filesystems.
1188 	 */
1189 	if (ip->i_gen == 0) {
1190 		ip->i_gen = random() / 2 + 1;
1191 		if ((vp->v_mount->mnt_flag & MNT_RDONLY) == 0)
1192 			ip->i_flag |= IN_MODIFIED;
1193 	}
1194 	/*
1195 	 * Ensure that uid and gid are correct. This is a temporary
1196 	 * fix until fsck has been changed to do the update.
1197 	 */
1198 	if (fs->fs_inodefmt < FS_44INODEFMT) {		/* XXX */
1199 		ip->i_uid = ip->i_din.di_ouid;		/* XXX */
1200 		ip->i_gid = ip->i_din.di_ogid;		/* XXX */
1201 	}						/* XXX */
1202 
1203 	*vpp = vp;
1204 	return (0);
1205 }
1206 
1207 /*
1208  * File handle to vnode
1209  *
1210  * Have to be really careful about stale file handles:
1211  * - check that the inode number is valid
1212  * - call ffs_vget() to get the locked inode
1213  * - check for an unallocated inode (i_mode == 0)
1214  * - check that the given client host has export rights and return
1215  *   those rights via. exflagsp and credanonp
1216  */
1217 int
1218 ffs_fhtovp(mp, fhp, vpp)
1219 	register struct mount *mp;
1220 	struct fid *fhp;
1221 	struct vnode **vpp;
1222 {
1223 	register struct ufid *ufhp;
1224 	struct fs *fs;
1225 
1226 	ufhp = (struct ufid *)fhp;
1227 	fs = VFSTOUFS(mp)->um_fs;
1228 	if (ufhp->ufid_ino < ROOTINO ||
1229 	    ufhp->ufid_ino >= fs->fs_ncg * fs->fs_ipg)
1230 		return (ESTALE);
1231 	return (ufs_fhtovp(mp, ufhp, vpp));
1232 }
1233 
1234 /*
1235  * Vnode pointer to File handle
1236  */
1237 /* ARGSUSED */
1238 int
1239 ffs_vptofh(vp, fhp)
1240 	struct vnode *vp;
1241 	struct fid *fhp;
1242 {
1243 	register struct inode *ip;
1244 	register struct ufid *ufhp;
1245 
1246 	ip = VTOI(vp);
1247 	ufhp = (struct ufid *)fhp;
1248 	ufhp->ufid_len = sizeof(struct ufid);
1249 	ufhp->ufid_ino = ip->i_number;
1250 	ufhp->ufid_gen = ip->i_gen;
1251 	return (0);
1252 }
1253 
1254 /*
1255  * Initialize the filesystem; just use ufs_init.
1256  */
1257 static int
1258 ffs_init(vfsp)
1259 	struct vfsconf *vfsp;
1260 {
1261 
1262 	softdep_initialize();
1263 	return (ufs_init(vfsp));
1264 }
1265 
1266 /*
1267  * Write a superblock and associated information back to disk.
1268  */
1269 static int
1270 ffs_sbupdate(mp, waitfor)
1271 	struct ufsmount *mp;
1272 	int waitfor;
1273 {
1274 	register struct fs *dfs, *fs = mp->um_fs;
1275 	register struct buf *bp;
1276 	int blks;
1277 	void *space;
1278 	int i, size, error, allerror = 0;
1279 
1280 	/*
1281 	 * First write back the summary information.
1282 	 */
1283 	blks = howmany(fs->fs_cssize, fs->fs_fsize);
1284 	space = fs->fs_csp;
1285 	for (i = 0; i < blks; i += fs->fs_frag) {
1286 		size = fs->fs_bsize;
1287 		if (i + fs->fs_frag > blks)
1288 			size = (blks - i) * fs->fs_fsize;
1289 		bp = getblk(mp->um_devvp, fsbtodb(fs, fs->fs_csaddr + i),
1290 		    size, 0, 0);
1291 		bcopy(space, bp->b_data, (u_int)size);
1292 		space = (char *)space + size;
1293 		if (waitfor != MNT_WAIT)
1294 			bawrite(bp);
1295 		else if ((error = bwrite(bp)) != 0)
1296 			allerror = error;
1297 	}
1298 	/*
1299 	 * Now write back the superblock itself. If any errors occurred
1300 	 * up to this point, then fail so that the superblock avoids
1301 	 * being written out as clean.
1302 	 */
1303 	if (allerror)
1304 		return (allerror);
1305 	bp = getblk(mp->um_devvp, SBLOCK, (int)fs->fs_sbsize, 0, 0);
1306 	fs->fs_fmod = 0;
1307 	fs->fs_time = time_second;
1308 	bcopy((caddr_t)fs, bp->b_data, (u_int)fs->fs_sbsize);
1309 	/* Restore compatibility to old file systems.		   XXX */
1310 	dfs = (struct fs *)bp->b_data;				/* XXX */
1311 	if (fs->fs_postblformat == FS_42POSTBLFMT)		/* XXX */
1312 		dfs->fs_nrpos = -1;				/* XXX */
1313 	if (fs->fs_inodefmt < FS_44INODEFMT) {			/* XXX */
1314 		int32_t *lp, tmp;				/* XXX */
1315 								/* XXX */
1316 		lp = (int32_t *)&dfs->fs_qbmask;		/* XXX */
1317 		tmp = lp[4];					/* XXX */
1318 		for (i = 4; i > 0; i--)				/* XXX */
1319 			lp[i] = lp[i-1];			/* XXX */
1320 		lp[0] = tmp;					/* XXX */
1321 	}							/* XXX */
1322 	dfs->fs_maxfilesize = mp->um_savedmaxfilesize;		/* XXX */
1323 	if (waitfor != MNT_WAIT)
1324 		bawrite(bp);
1325 	else if ((error = bwrite(bp)) != 0)
1326 		allerror = error;
1327 	return (allerror);
1328 }
1329