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