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