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