xref: /original-bsd/sys/ufs/ffs/ffs_vfsops.c (revision 9a35f7df)
1 /*
2  * Copyright (c) 1989, 1991, 1993, 1994
3  *	The Regents of the University of California.  All rights reserved.
4  *
5  * %sccs.include.redist.c%
6  *
7  *	@(#)ffs_vfsops.c	8.31 (Berkeley) 05/20/95
8  */
9 
10 #include <sys/param.h>
11 #include <sys/systm.h>
12 #include <sys/namei.h>
13 #include <sys/proc.h>
14 #include <sys/kernel.h>
15 #include <sys/vnode.h>
16 #include <sys/socket.h>
17 #include <sys/mount.h>
18 #include <sys/buf.h>
19 #include <sys/mbuf.h>
20 #include <sys/file.h>
21 #include <sys/disklabel.h>
22 #include <sys/ioctl.h>
23 #include <sys/errno.h>
24 #include <sys/malloc.h>
25 
26 #include <miscfs/specfs/specdev.h>
27 
28 #include <ufs/ufs/quota.h>
29 #include <ufs/ufs/ufsmount.h>
30 #include <ufs/ufs/inode.h>
31 #include <ufs/ufs/ufs_extern.h>
32 
33 #include <ufs/ffs/fs.h>
34 #include <ufs/ffs/ffs_extern.h>
35 
36 int ffs_sbupdate __P((struct ufsmount *, int));
37 
38 struct vfsops ufs_vfsops = {
39 	ffs_mount,
40 	ufs_start,
41 	ffs_unmount,
42 	ufs_root,
43 	ufs_quotactl,
44 	ffs_statfs,
45 	ffs_sync,
46 	ffs_vget,
47 	ffs_fhtovp,
48 	ffs_vptofh,
49 	ffs_init,
50 	ffs_sysctl,
51 };
52 
53 extern u_long nextgennumber;
54 
55 /*
56  * Called by main() when ufs is going to be mounted as root.
57  */
58 ffs_mountroot()
59 {
60 	extern struct vnode *rootvp;
61 	struct fs *fs;
62 	struct mount *mp;
63 	struct proc *p = curproc;	/* XXX */
64 	struct ufsmount *ump;
65 	u_int size;
66 	int error;
67 
68 	/*
69 	 * Get vnodes for swapdev and rootdev.
70 	 */
71 	if ((error = bdevvp(swapdev, &swapdev_vp)) ||
72 	    (error = bdevvp(rootdev, &rootvp))) {
73 		printf("ffs_mountroot: can't setup bdevvp's");
74 		return (error);
75 	}
76 	if (error = vfs_rootmountalloc("ufs", "root_device", &mp))
77 		return (error);
78 	if (error = ffs_mountfs(rootvp, mp, p)) {
79 		mp->mnt_vfc->vfc_refcount--;
80 		vfs_unbusy(mp, p);
81 		free(mp, M_MOUNT);
82 		return (error);
83 	}
84 	simple_lock(&mountlist_slock);
85 	CIRCLEQ_INSERT_TAIL(&mountlist, mp, mnt_list);
86 	simple_unlock(&mountlist_slock);
87 	ump = VFSTOUFS(mp);
88 	fs = ump->um_fs;
89 	(void) copystr(mp->mnt_stat.f_mntonname, fs->fs_fsmnt, MNAMELEN - 1, 0);
90 	(void)ffs_statfs(mp, &mp->mnt_stat, p);
91 	vfs_unbusy(mp, p);
92 	inittodr(fs->fs_time);
93 	return (0);
94 }
95 
96 /*
97  * VFS Operations.
98  *
99  * mount system call
100  */
101 int
102 ffs_mount(mp, path, data, ndp, p)
103 	register struct mount *mp;
104 	char *path;
105 	caddr_t data;
106 	struct nameidata *ndp;
107 	struct proc *p;
108 {
109 	struct vnode *devvp;
110 	struct ufs_args args;
111 	struct ufsmount *ump;
112 	register struct fs *fs;
113 	u_int size;
114 	int error, flags;
115 	mode_t accessmode;
116 
117 	if (error = copyin(data, (caddr_t)&args, sizeof (struct ufs_args)))
118 		return (error);
119 	/*
120 	 * If updating, check whether changing from read-only to
121 	 * read/write; if there is no device name, that's all we do.
122 	 */
123 	if (mp->mnt_flag & MNT_UPDATE) {
124 		ump = VFSTOUFS(mp);
125 		fs = ump->um_fs;
126 		if (fs->fs_ronly == 0 && (mp->mnt_flag & MNT_RDONLY)) {
127 			flags = WRITECLOSE;
128 			if (mp->mnt_flag & MNT_FORCE)
129 				flags |= FORCECLOSE;
130 			if (error = ffs_flushfiles(mp, flags, p))
131 				return (error);
132 			fs->fs_clean = 1;
133 			fs->fs_ronly = 1;
134 			if (error = ffs_sbupdate(ump, MNT_WAIT)) {
135 				fs->fs_clean = 0;
136 				fs->fs_ronly = 0;
137 				return (error);
138 			}
139 		}
140 		if ((mp->mnt_flag & MNT_RELOAD) &&
141 		    (error = ffs_reload(mp, ndp->ni_cnd.cn_cred, p)))
142 			return (error);
143 		if (fs->fs_ronly && (mp->mnt_flag & MNT_WANTRDWR)) {
144 			/*
145 			 * If upgrade to read-write by non-root, then verify
146 			 * that user has necessary permissions on the device.
147 			 */
148 			if (p->p_ucred->cr_uid != 0) {
149 				devvp = ump->um_devvp;
150 				vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p);
151 				if (error = VOP_ACCESS(devvp, VREAD | VWRITE,
152 				    p->p_ucred, p)) {
153 					VOP_UNLOCK(devvp, 0, p);
154 					return (error);
155 				}
156 				VOP_UNLOCK(devvp, 0, p);
157 			}
158 			fs->fs_ronly = 0;
159 			fs->fs_clean = 0;
160 			(void) ffs_sbupdate(ump, MNT_WAIT);
161 		}
162 		if (args.fspec == 0) {
163 			/*
164 			 * Process export requests.
165 			 */
166 			return (vfs_export(mp, &ump->um_export, &args.export));
167 		}
168 	}
169 	/*
170 	 * Not an update, or updating the name: look up the name
171 	 * and verify that it refers to a sensible block device.
172 	 */
173 	NDINIT(ndp, LOOKUP, FOLLOW, UIO_USERSPACE, args.fspec, p);
174 	if (error = namei(ndp))
175 		return (error);
176 	devvp = ndp->ni_vp;
177 
178 	if (devvp->v_type != VBLK) {
179 		vrele(devvp);
180 		return (ENOTBLK);
181 	}
182 	if (major(devvp->v_rdev) >= nblkdev) {
183 		vrele(devvp);
184 		return (ENXIO);
185 	}
186 	/*
187 	 * If mount by non-root, then verify that user has necessary
188 	 * permissions on the device.
189 	 */
190 	if (p->p_ucred->cr_uid != 0) {
191 		accessmode = VREAD;
192 		if ((mp->mnt_flag & MNT_RDONLY) == 0)
193 			accessmode |= VWRITE;
194 		vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p);
195 		if (error = VOP_ACCESS(devvp, accessmode, p->p_ucred, p)) {
196 			vput(devvp);
197 			return (error);
198 		}
199 		VOP_UNLOCK(devvp, 0, p);
200 	}
201 	if ((mp->mnt_flag & MNT_UPDATE) == 0)
202 		error = ffs_mountfs(devvp, mp, p);
203 	else {
204 		if (devvp != ump->um_devvp)
205 			error = EINVAL;	/* needs translation */
206 		else
207 			vrele(devvp);
208 	}
209 	if (error) {
210 		vrele(devvp);
211 		return (error);
212 	}
213 	ump = VFSTOUFS(mp);
214 	fs = ump->um_fs;
215 	(void) copyinstr(path, fs->fs_fsmnt, sizeof(fs->fs_fsmnt) - 1, &size);
216 	bzero(fs->fs_fsmnt + size, sizeof(fs->fs_fsmnt) - size);
217 	bcopy((caddr_t)fs->fs_fsmnt, (caddr_t)mp->mnt_stat.f_mntonname,
218 	    MNAMELEN);
219 	(void) copyinstr(args.fspec, mp->mnt_stat.f_mntfromname, MNAMELEN - 1,
220 	    &size);
221 	bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
222 	(void)ffs_statfs(mp, &mp->mnt_stat, p);
223 	return (0);
224 }
225 
226 /*
227  * Reload all incore data for a filesystem (used after running fsck on
228  * the root filesystem and finding things to fix). The filesystem must
229  * be mounted read-only.
230  *
231  * Things to do to update the mount:
232  *	1) invalidate all cached meta-data.
233  *	2) re-read superblock from disk.
234  *	3) re-read summary information from disk.
235  *	4) invalidate all inactive vnodes.
236  *	5) invalidate all cached file data.
237  *	6) re-read inode data for all active vnodes.
238  */
239 ffs_reload(mountp, cred, p)
240 	register struct mount *mountp;
241 	struct ucred *cred;
242 	struct proc *p;
243 {
244 	register struct vnode *vp, *nvp, *devvp;
245 	struct inode *ip;
246 	struct csum *space;
247 	struct buf *bp;
248 	struct fs *fs, *newfs;
249 	struct partinfo dpart;
250 	int i, blks, size, error;
251 	int32_t *lp;
252 
253 	if ((mountp->mnt_flag & MNT_RDONLY) == 0)
254 		return (EINVAL);
255 	/*
256 	 * Step 1: invalidate all cached meta-data.
257 	 */
258 	devvp = VFSTOUFS(mountp)->um_devvp;
259 	if (vinvalbuf(devvp, 0, cred, p, 0, 0))
260 		panic("ffs_reload: dirty1");
261 	/*
262 	 * Step 2: re-read superblock from disk.
263 	 */
264 	if (VOP_IOCTL(devvp, DIOCGPART, (caddr_t)&dpart, FREAD, NOCRED, p) != 0)
265 		size = DEV_BSIZE;
266 	else
267 		size = dpart.disklab->d_secsize;
268 	if (error = bread(devvp, (ufs_daddr_t)(SBOFF/size), SBSIZE, NOCRED,&bp))
269 		return (error);
270 	newfs = (struct fs *)bp->b_data;
271 	if (newfs->fs_magic != FS_MAGIC || newfs->fs_bsize > MAXBSIZE ||
272 	    newfs->fs_bsize < sizeof(struct fs)) {
273 		brelse(bp);
274 		return (EIO);		/* XXX needs translation */
275 	}
276 	fs = VFSTOUFS(mountp)->um_fs;
277 	/*
278 	 * Copy pointer fields back into superblock before copying in	XXX
279 	 * new superblock. These should really be in the ufsmount.	XXX
280 	 * Note that important parameters (eg fs_ncg) are unchanged.
281 	 */
282 	bcopy(&fs->fs_csp[0], &newfs->fs_csp[0], sizeof(fs->fs_csp));
283 	newfs->fs_maxcluster = fs->fs_maxcluster;
284 	bcopy(newfs, fs, (u_int)fs->fs_sbsize);
285 	if (fs->fs_sbsize < SBSIZE)
286 		bp->b_flags |= B_INVAL;
287 	brelse(bp);
288 	mountp->mnt_maxsymlinklen = fs->fs_maxsymlinklen;
289 	ffs_oldfscompat(fs);
290 	/*
291 	 * Step 3: re-read summary information from disk.
292 	 */
293 	blks = howmany(fs->fs_cssize, fs->fs_fsize);
294 	space = fs->fs_csp[0];
295 	for (i = 0; i < blks; i += fs->fs_frag) {
296 		size = fs->fs_bsize;
297 		if (i + fs->fs_frag > blks)
298 			size = (blks - i) * fs->fs_fsize;
299 		if (error = bread(devvp, fsbtodb(fs, fs->fs_csaddr + i), size,
300 		    NOCRED, &bp))
301 			return (error);
302 		bcopy(bp->b_data, fs->fs_csp[fragstoblks(fs, i)], (u_int)size);
303 		brelse(bp);
304 	}
305 	/*
306 	 * We no longer know anything about clusters per cylinder group.
307 	 */
308 	if (fs->fs_contigsumsize > 0) {
309 		lp = fs->fs_maxcluster;
310 		for (i = 0; i < fs->fs_ncg; i++)
311 			*lp++ = fs->fs_contigsumsize;
312 	}
313 
314 loop:
315 	simple_lock(&mntvnode_slock);
316 	for (vp = mountp->mnt_vnodelist.lh_first; vp != NULL; vp = nvp) {
317 		if (vp->v_mount != mountp) {
318 			simple_unlock(&mntvnode_slock);
319 			goto loop;
320 		}
321 		nvp = vp->v_mntvnodes.le_next;
322 		/*
323 		 * Step 4: invalidate all inactive vnodes.
324 		 */
325 		if (vrecycle(vp, &mntvnode_slock, p))
326 			goto loop;
327 		/*
328 		 * Step 5: invalidate all cached file data.
329 		 */
330 		simple_lock(&vp->v_interlock);
331 		simple_unlock(&mntvnode_slock);
332 		if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK, p)) {
333 			goto loop;
334 		}
335 		if (vinvalbuf(vp, 0, cred, p, 0, 0))
336 			panic("ffs_reload: dirty2");
337 		/*
338 		 * Step 6: re-read inode data for all active vnodes.
339 		 */
340 		ip = VTOI(vp);
341 		if (error =
342 		    bread(devvp, fsbtodb(fs, ino_to_fsba(fs, ip->i_number)),
343 		    (int)fs->fs_bsize, NOCRED, &bp)) {
344 			vput(vp);
345 			return (error);
346 		}
347 		ip->i_din = *((struct dinode *)bp->b_data +
348 		    ino_to_fsbo(fs, ip->i_number));
349 		brelse(bp);
350 		vput(vp);
351 		simple_lock(&mntvnode_slock);
352 	}
353 	simple_unlock(&mntvnode_slock);
354 	return (0);
355 }
356 
357 /*
358  * Common code for mount and mountroot
359  */
360 int
361 ffs_mountfs(devvp, mp, p)
362 	register struct vnode *devvp;
363 	struct mount *mp;
364 	struct proc *p;
365 {
366 	register struct ufsmount *ump;
367 	struct buf *bp;
368 	register struct fs *fs;
369 	dev_t dev;
370 	struct partinfo dpart;
371 	caddr_t base, space;
372 	int error, i, blks, size, ronly;
373 	int32_t *lp;
374 	struct ucred *cred;
375 	extern struct vnode *rootvp;
376 	u_int64_t maxfilesize;					/* XXX */
377 
378 	dev = devvp->v_rdev;
379 	cred = p ? p->p_ucred : NOCRED;
380 	/*
381 	 * Disallow multiple mounts of the same device.
382 	 * Disallow mounting of a device that is currently in use
383 	 * (except for root, which might share swap device for miniroot).
384 	 * Flush out any old buffers remaining from a previous use.
385 	 */
386 	if (error = vfs_mountedon(devvp))
387 		return (error);
388 	if (vcount(devvp) > 1 && devvp != rootvp)
389 		return (EBUSY);
390 	if (error = vinvalbuf(devvp, V_SAVE, cred, p, 0, 0))
391 		return (error);
392 
393 	ronly = (mp->mnt_flag & MNT_RDONLY) != 0;
394 	if (error = VOP_OPEN(devvp, ronly ? FREAD : FREAD|FWRITE, FSCRED, p))
395 		return (error);
396 	if (VOP_IOCTL(devvp, DIOCGPART, (caddr_t)&dpart, FREAD, cred, p) != 0)
397 		size = DEV_BSIZE;
398 	else
399 		size = dpart.disklab->d_secsize;
400 
401 	bp = NULL;
402 	ump = NULL;
403 	if (error = bread(devvp, (ufs_daddr_t)(SBOFF/size), SBSIZE, cred, &bp))
404 		goto out;
405 	fs = (struct fs *)bp->b_data;
406 	if (fs->fs_magic != FS_MAGIC || fs->fs_bsize > MAXBSIZE ||
407 	    fs->fs_bsize < sizeof(struct fs)) {
408 		error = EINVAL;		/* XXX needs translation */
409 		goto out;
410 	}
411 	/* XXX updating 4.2 FFS superblocks trashes rotational layout tables */
412 	if (fs->fs_postblformat == FS_42POSTBLFMT && !ronly) {
413 		error = EROFS;          /* needs translation */
414 		goto out;
415 	}
416 	ump = malloc(sizeof *ump, M_UFSMNT, M_WAITOK);
417 	bzero((caddr_t)ump, sizeof *ump);
418 	ump->um_fs = malloc((u_long)fs->fs_sbsize, M_UFSMNT,
419 	    M_WAITOK);
420 	bcopy(bp->b_data, ump->um_fs, (u_int)fs->fs_sbsize);
421 	if (fs->fs_sbsize < SBSIZE)
422 		bp->b_flags |= B_INVAL;
423 	brelse(bp);
424 	bp = NULL;
425 	fs = ump->um_fs;
426 	fs->fs_ronly = ronly;
427 	size = fs->fs_cssize;
428 	blks = howmany(size, fs->fs_fsize);
429 	if (fs->fs_contigsumsize > 0)
430 		size += fs->fs_ncg * sizeof(int32_t);
431 	base = space = malloc((u_long)size, M_UFSMNT, M_WAITOK);
432 	for (i = 0; i < blks; i += fs->fs_frag) {
433 		size = fs->fs_bsize;
434 		if (i + fs->fs_frag > blks)
435 			size = (blks - i) * fs->fs_fsize;
436 		if (error = bread(devvp, fsbtodb(fs, fs->fs_csaddr + i), size,
437 		    cred, &bp)) {
438 			free(base, M_UFSMNT);
439 			goto out;
440 		}
441 		bcopy(bp->b_data, space, (u_int)size);
442 		fs->fs_csp[fragstoblks(fs, i)] = (struct csum *)space;
443 		space += size;
444 		brelse(bp);
445 		bp = NULL;
446 	}
447 	if (fs->fs_contigsumsize > 0) {
448 		fs->fs_maxcluster = lp = (int32_t *)space;
449 		for (i = 0; i < fs->fs_ncg; i++)
450 			*lp++ = fs->fs_contigsumsize;
451 	}
452 	mp->mnt_data = (qaddr_t)ump;
453 	mp->mnt_stat.f_fsid.val[0] = (long)dev;
454 	mp->mnt_stat.f_fsid.val[1] = mp->mnt_vfc->vfc_typenum;
455 	mp->mnt_maxsymlinklen = fs->fs_maxsymlinklen;
456 	ump->um_mountp = mp;
457 	ump->um_dev = dev;
458 	ump->um_devvp = devvp;
459 	ump->um_nindir = fs->fs_nindir;
460 	ump->um_bptrtodb = fs->fs_fsbtodb;
461 	ump->um_seqinc = fs->fs_frag;
462 	for (i = 0; i < MAXQUOTAS; i++)
463 		ump->um_quotas[i] = NULLVP;
464 	devvp->v_specflags |= SI_MOUNTEDON;
465 	ffs_oldfscompat(fs);
466 	ump->um_savedmaxfilesize = fs->fs_maxfilesize;		/* XXX */
467 	maxfilesize = (u_int64_t)0x40000000 * fs->fs_bsize - 1;	/* XXX */
468 	if (fs->fs_maxfilesize > maxfilesize)			/* XXX */
469 		fs->fs_maxfilesize = maxfilesize;		/* XXX */
470 	if (ronly == 0) {
471 		fs->fs_clean = 0;
472 		(void) ffs_sbupdate(ump, MNT_WAIT);
473 	}
474 	return (0);
475 out:
476 	if (bp)
477 		brelse(bp);
478 	(void)VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE, cred, p);
479 	if (ump) {
480 		free(ump->um_fs, M_UFSMNT);
481 		free(ump, M_UFSMNT);
482 		mp->mnt_data = (qaddr_t)0;
483 	}
484 	return (error);
485 }
486 
487 /*
488  * Sanity checks for old file systems.
489  *
490  * XXX - goes away some day.
491  */
492 ffs_oldfscompat(fs)
493 	struct fs *fs;
494 {
495 	int i;
496 
497 	fs->fs_npsect = max(fs->fs_npsect, fs->fs_nsect);	/* XXX */
498 	fs->fs_interleave = max(fs->fs_interleave, 1);		/* XXX */
499 	if (fs->fs_postblformat == FS_42POSTBLFMT)		/* XXX */
500 		fs->fs_nrpos = 8;				/* XXX */
501 	if (fs->fs_inodefmt < FS_44INODEFMT) {			/* XXX */
502 		u_int64_t sizepb = fs->fs_bsize;		/* XXX */
503 								/* XXX */
504 		fs->fs_maxfilesize = fs->fs_bsize * NDADDR - 1;	/* XXX */
505 		for (i = 0; i < NIADDR; i++) {			/* XXX */
506 			sizepb *= NINDIR(fs);			/* XXX */
507 			fs->fs_maxfilesize += sizepb;		/* XXX */
508 		}						/* XXX */
509 		fs->fs_qbmask = ~fs->fs_bmask;			/* XXX */
510 		fs->fs_qfmask = ~fs->fs_fmask;			/* XXX */
511 	}							/* XXX */
512 	return (0);
513 }
514 
515 /*
516  * unmount system call
517  */
518 int
519 ffs_unmount(mp, mntflags, p)
520 	struct mount *mp;
521 	int mntflags;
522 	struct proc *p;
523 {
524 	register struct ufsmount *ump;
525 	register struct fs *fs;
526 	int error, flags;
527 
528 	flags = 0;
529 	if (mntflags & MNT_FORCE)
530 		flags |= FORCECLOSE;
531 	if (error = ffs_flushfiles(mp, flags, p))
532 		return (error);
533 	ump = VFSTOUFS(mp);
534 	fs = ump->um_fs;
535 	if (fs->fs_ronly == 0) {
536 		fs->fs_clean = 1;
537 		if (error = ffs_sbupdate(ump, MNT_WAIT)) {
538 			fs->fs_clean = 0;
539 			return (error);
540 		}
541 	}
542 	ump->um_devvp->v_specflags &= ~SI_MOUNTEDON;
543 	error = VOP_CLOSE(ump->um_devvp, fs->fs_ronly ? FREAD : FREAD|FWRITE,
544 		NOCRED, p);
545 	vrele(ump->um_devvp);
546 	free(fs->fs_csp[0], M_UFSMNT);
547 	free(fs, M_UFSMNT);
548 	free(ump, M_UFSMNT);
549 	mp->mnt_data = (qaddr_t)0;
550 	return (error);
551 }
552 
553 /*
554  * Flush out all the files in a filesystem.
555  */
556 ffs_flushfiles(mp, flags, p)
557 	register struct mount *mp;
558 	int flags;
559 	struct proc *p;
560 {
561 	register struct ufsmount *ump;
562 	int i, error;
563 
564 	ump = VFSTOUFS(mp);
565 #ifdef QUOTA
566 	if (mp->mnt_flag & MNT_QUOTA) {
567 		if (error = vflush(mp, NULLVP, SKIPSYSTEM|flags))
568 			return (error);
569 		for (i = 0; i < MAXQUOTAS; i++) {
570 			if (ump->um_quotas[i] == NULLVP)
571 				continue;
572 			quotaoff(p, mp, i);
573 		}
574 		/*
575 		 * Here we fall through to vflush again to ensure
576 		 * that we have gotten rid of all the system vnodes.
577 		 */
578 	}
579 #endif
580 	error = vflush(mp, NULLVP, flags);
581 	return (error);
582 }
583 
584 /*
585  * Get file system statistics.
586  */
587 int
588 ffs_statfs(mp, sbp, p)
589 	struct mount *mp;
590 	register struct statfs *sbp;
591 	struct proc *p;
592 {
593 	register struct ufsmount *ump;
594 	register struct fs *fs;
595 
596 	ump = VFSTOUFS(mp);
597 	fs = ump->um_fs;
598 	if (fs->fs_magic != FS_MAGIC)
599 		panic("ffs_statfs");
600 	sbp->f_bsize = fs->fs_fsize;
601 	sbp->f_iosize = fs->fs_bsize;
602 	sbp->f_blocks = fs->fs_dsize;
603 	sbp->f_bfree = fs->fs_cstotal.cs_nbfree * fs->fs_frag +
604 		fs->fs_cstotal.cs_nffree;
605 	sbp->f_bavail = (fs->fs_dsize * (100 - fs->fs_minfree) / 100) -
606 		(fs->fs_dsize - sbp->f_bfree);
607 	sbp->f_files =  fs->fs_ncg * fs->fs_ipg - ROOTINO;
608 	sbp->f_ffree = fs->fs_cstotal.cs_nifree;
609 	if (sbp != &mp->mnt_stat) {
610 		sbp->f_type = mp->mnt_vfc->vfc_typenum;
611 		bcopy((caddr_t)mp->mnt_stat.f_mntonname,
612 			(caddr_t)&sbp->f_mntonname[0], MNAMELEN);
613 		bcopy((caddr_t)mp->mnt_stat.f_mntfromname,
614 			(caddr_t)&sbp->f_mntfromname[0], MNAMELEN);
615 	}
616 	return (0);
617 }
618 
619 /*
620  * Go through the disk queues to initiate sandbagged IO;
621  * go through the inodes to write those that have been modified;
622  * initiate the writing of the super block if it has been modified.
623  *
624  * Note: we are always called with the filesystem marked `MPBUSY'.
625  */
626 int
627 ffs_sync(mp, waitfor, cred, p)
628 	struct mount *mp;
629 	int waitfor;
630 	struct ucred *cred;
631 	struct proc *p;
632 {
633 	struct vnode *nvp, *vp;
634 	struct inode *ip;
635 	struct ufsmount *ump = VFSTOUFS(mp);
636 	struct fs *fs;
637 	int error, allerror = 0;
638 
639 	fs = ump->um_fs;
640 	if (fs->fs_fmod != 0 && fs->fs_ronly != 0) {		/* XXX */
641 		printf("fs = %s\n", fs->fs_fsmnt);
642 		panic("update: rofs mod");
643 	}
644 	/*
645 	 * Write back each (modified) inode.
646 	 */
647 	simple_lock(&mntvnode_slock);
648 loop:
649 	for (vp = mp->mnt_vnodelist.lh_first;
650 	     vp != NULL;
651 	     vp = nvp) {
652 		/*
653 		 * If the vnode that we are about to sync is no longer
654 		 * associated with this mount point, start over.
655 		 */
656 		if (vp->v_mount != mp)
657 			goto loop;
658 		simple_lock(&vp->v_interlock);
659 		nvp = vp->v_mntvnodes.le_next;
660 		ip = VTOI(vp);
661 		if ((ip->i_flag &
662 		    (IN_ACCESS | IN_CHANGE | IN_MODIFIED | IN_UPDATE)) == 0 &&
663 		    vp->v_dirtyblkhd.lh_first == NULL) {
664 			simple_unlock(&vp->v_interlock);
665 			continue;
666 		}
667 		simple_unlock(&mntvnode_slock);
668 		error = vget(vp, LK_EXCLUSIVE | LK_NOWAIT | LK_INTERLOCK, p);
669 		if (error) {
670 			simple_lock(&mntvnode_slock);
671 			if (error == ENOENT)
672 				goto loop;
673 			continue;
674 		}
675 		if (error = VOP_FSYNC(vp, cred, waitfor, p))
676 			allerror = error;
677 		VOP_UNLOCK(vp, 0, p);
678 		vrele(vp);
679 		simple_lock(&mntvnode_slock);
680 	}
681 	simple_unlock(&mntvnode_slock);
682 	/*
683 	 * Force stale file system control information to be flushed.
684 	 */
685 	if (error = VOP_FSYNC(ump->um_devvp, cred, waitfor, p))
686 		allerror = error;
687 #ifdef QUOTA
688 	qsync(mp);
689 #endif
690 	/*
691 	 * Write back modified superblock.
692 	 */
693 	if (fs->fs_fmod != 0) {
694 		fs->fs_fmod = 0;
695 		fs->fs_time = time.tv_sec;
696 		if (error = ffs_sbupdate(ump, waitfor))
697 			allerror = error;
698 	}
699 	return (allerror);
700 }
701 
702 /*
703  * Look up a FFS dinode number to find its incore vnode, otherwise read it
704  * in from disk.  If it is in core, wait for the lock bit to clear, then
705  * return the inode locked.  Detection and handling of mount points must be
706  * done by the calling routine.
707  */
708 int
709 ffs_vget(mp, ino, vpp)
710 	struct mount *mp;
711 	ino_t ino;
712 	struct vnode **vpp;
713 {
714 	struct proc *p = curproc;		/* XXX */
715 	struct fs *fs;
716 	struct inode *ip;
717 	struct ufsmount *ump;
718 	struct buf *bp;
719 	struct vnode *vp;
720 	dev_t dev;
721 	int i, type, error;
722 
723 	ump = VFSTOUFS(mp);
724 	dev = ump->um_dev;
725 	if ((*vpp = ufs_ihashget(dev, ino)) != NULL)
726 		return (0);
727 
728 	/* Allocate a new vnode/inode. */
729 	if (error = getnewvnode(VT_UFS, mp, ffs_vnodeop_p, &vp)) {
730 		*vpp = NULL;
731 		return (error);
732 	}
733 	type = ump->um_devvp->v_tag == VT_MFS ? M_MFSNODE : M_FFSNODE; /* XXX */
734 	MALLOC(ip, struct inode *, sizeof(struct inode), type, M_WAITOK);
735 	bzero((caddr_t)ip, sizeof(struct inode));
736 	lockinit(&ip->i_lock, PINOD, "inode", 0, 0);
737 	vp->v_data = ip;
738 	ip->i_vnode = vp;
739 	ip->i_fs = fs = ump->um_fs;
740 	ip->i_dev = dev;
741 	ip->i_number = ino;
742 #ifdef QUOTA
743 	for (i = 0; i < MAXQUOTAS; i++)
744 		ip->i_dquot[i] = NODQUOT;
745 #endif
746 	/*
747 	 * Put it onto its hash chain and lock it so that other requests for
748 	 * this inode will block if they arrive while we are sleeping waiting
749 	 * for old data structures to be purged or for the contents of the
750 	 * disk portion of this inode to be read.
751 	 */
752 	ufs_ihashins(ip);
753 
754 	/* Read in the disk contents for the inode, copy into the inode. */
755 	if (error = bread(ump->um_devvp, fsbtodb(fs, ino_to_fsba(fs, ino)),
756 	    (int)fs->fs_bsize, NOCRED, &bp)) {
757 		/*
758 		 * The inode does not contain anything useful, so it would
759 		 * be misleading to leave it on its hash chain. With mode
760 		 * still zero, it will be unlinked and returned to the free
761 		 * list by vput().
762 		 */
763 		vput(vp);
764 		brelse(bp);
765 		*vpp = NULL;
766 		return (error);
767 	}
768 	ip->i_din = *((struct dinode *)bp->b_data + ino_to_fsbo(fs, ino));
769 	brelse(bp);
770 
771 	/*
772 	 * Initialize the vnode from the inode, check for aliases.
773 	 * Note that the underlying vnode may have changed.
774 	 */
775 	if (error = ufs_vinit(mp, ffs_specop_p, FFS_FIFOOPS, &vp)) {
776 		vput(vp);
777 		*vpp = NULL;
778 		return (error);
779 	}
780 	/*
781 	 * Finish inode initialization now that aliasing has been resolved.
782 	 */
783 	ip->i_devvp = ump->um_devvp;
784 	VREF(ip->i_devvp);
785 	/*
786 	 * Set up a generation number for this inode if it does not
787 	 * already have one. This should only happen on old filesystems.
788 	 */
789 	if (ip->i_gen == 0) {
790 		if (++nextgennumber < (u_long)time.tv_sec)
791 			nextgennumber = time.tv_sec;
792 		ip->i_gen = nextgennumber;
793 		if ((vp->v_mount->mnt_flag & MNT_RDONLY) == 0)
794 			ip->i_flag |= IN_MODIFIED;
795 	}
796 	/*
797 	 * Ensure that uid and gid are correct. This is a temporary
798 	 * fix until fsck has been changed to do the update.
799 	 */
800 	if (fs->fs_inodefmt < FS_44INODEFMT) {		/* XXX */
801 		ip->i_uid = ip->i_din.di_ouid;		/* XXX */
802 		ip->i_gid = ip->i_din.di_ogid;		/* XXX */
803 	}						/* XXX */
804 
805 	*vpp = vp;
806 	return (0);
807 }
808 
809 /*
810  * File handle to vnode
811  *
812  * Have to be really careful about stale file handles:
813  * - check that the inode number is valid
814  * - call ffs_vget() to get the locked inode
815  * - check for an unallocated inode (i_mode == 0)
816  * - check that the given client host has export rights and return
817  *   those rights via. exflagsp and credanonp
818  */
819 int
820 ffs_fhtovp(mp, fhp, nam, vpp, exflagsp, credanonp)
821 	register struct mount *mp;
822 	struct fid *fhp;
823 	struct mbuf *nam;
824 	struct vnode **vpp;
825 	int *exflagsp;
826 	struct ucred **credanonp;
827 {
828 	register struct ufid *ufhp;
829 	struct fs *fs;
830 
831 	ufhp = (struct ufid *)fhp;
832 	fs = VFSTOUFS(mp)->um_fs;
833 	if (ufhp->ufid_ino < ROOTINO ||
834 	    ufhp->ufid_ino >= fs->fs_ncg * fs->fs_ipg)
835 		return (ESTALE);
836 	return (ufs_check_export(mp, ufhp, nam, vpp, exflagsp, credanonp));
837 }
838 
839 /*
840  * Vnode pointer to File handle
841  */
842 /* ARGSUSED */
843 ffs_vptofh(vp, fhp)
844 	struct vnode *vp;
845 	struct fid *fhp;
846 {
847 	register struct inode *ip;
848 	register struct ufid *ufhp;
849 
850 	ip = VTOI(vp);
851 	ufhp = (struct ufid *)fhp;
852 	ufhp->ufid_len = sizeof(struct ufid);
853 	ufhp->ufid_ino = ip->i_number;
854 	ufhp->ufid_gen = ip->i_gen;
855 	return (0);
856 }
857 
858 /*
859  * Initialize the filesystem; just use ufs_init.
860  */
861 int
862 ffs_init(vfsp)
863 	struct vfsconf *vfsp;
864 {
865 
866 	return (ufs_init(vfsp));
867 }
868 
869 /*
870  * fast filesystem related variables.
871  */
872 ffs_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
873 	int *name;
874 	u_int namelen;
875 	void *oldp;
876 	size_t *oldlenp;
877 	void *newp;
878 	size_t newlen;
879 	struct proc *p;
880 {
881 	extern int doclusterread, doclusterwrite, doreallocblks, doasyncfree;
882 
883 	/* all sysctl names at this level are terminal */
884 	if (namelen != 1)
885 		return (ENOTDIR);		/* overloaded */
886 
887 	switch (name[0]) {
888 	case FFS_CLUSTERREAD:
889 		return (sysctl_int(oldp, oldlenp, newp, newlen,
890 		    &doclusterread));
891 	case FFS_CLUSTERWRITE:
892 		return (sysctl_int(oldp, oldlenp, newp, newlen,
893 		    &doclusterwrite));
894 	case FFS_REALLOCBLKS:
895 		return (sysctl_int(oldp, oldlenp, newp, newlen,
896 		    &doreallocblks));
897 	case FFS_ASYNCFREE:
898 		return (sysctl_int(oldp, oldlenp, newp, newlen, &doasyncfree));
899 	default:
900 		return (EOPNOTSUPP);
901 	}
902 	/* NOTREACHED */
903 }
904 
905 /*
906  * Write a superblock and associated information back to disk.
907  */
908 int
909 ffs_sbupdate(mp, waitfor)
910 	struct ufsmount *mp;
911 	int waitfor;
912 {
913 	register struct fs *dfs, *fs = mp->um_fs;
914 	register struct buf *bp;
915 	int blks;
916 	caddr_t space;
917 	int i, size, error, allerror = 0;
918 
919 	/*
920 	 * First write back the summary information.
921 	 */
922 	blks = howmany(fs->fs_cssize, fs->fs_fsize);
923 	space = (caddr_t)fs->fs_csp[0];
924 	for (i = 0; i < blks; i += fs->fs_frag) {
925 		size = fs->fs_bsize;
926 		if (i + fs->fs_frag > blks)
927 			size = (blks - i) * fs->fs_fsize;
928 		bp = getblk(mp->um_devvp, fsbtodb(fs, fs->fs_csaddr + i),
929 		    size, 0, 0);
930 		bcopy(space, bp->b_data, (u_int)size);
931 		space += size;
932 		if (waitfor != MNT_WAIT)
933 			bawrite(bp);
934 		else if (error = bwrite(bp))
935 			allerror = error;
936 	}
937 	/*
938 	 * Now write back the superblock itself. If any errors occurred
939 	 * up to this point, then fail so that the superblock avoids
940 	 * being written out as clean.
941 	 */
942 	if (allerror)
943 		return (allerror);
944 	bp = getblk(mp->um_devvp, SBLOCK, (int)fs->fs_sbsize, 0, 0);
945 	bcopy((caddr_t)fs, bp->b_data, (u_int)fs->fs_sbsize);
946 	/* Restore compatibility to old file systems.		   XXX */
947 	dfs = (struct fs *)bp->b_data;				/* XXX */
948 	if (fs->fs_postblformat == FS_42POSTBLFMT)		/* XXX */
949 		dfs->fs_nrpos = -1;				/* XXX */
950 	if (fs->fs_inodefmt < FS_44INODEFMT) {			/* XXX */
951 		int32_t *lp, tmp;				/* XXX */
952 								/* XXX */
953 		lp = (int32_t *)&dfs->fs_qbmask;		/* XXX */
954 		tmp = lp[4];					/* XXX */
955 		for (i = 4; i > 0; i--)				/* XXX */
956 			lp[i] = lp[i-1];			/* XXX */
957 		lp[0] = tmp;					/* XXX */
958 	}							/* XXX */
959 	dfs->fs_maxfilesize = mp->um_savedmaxfilesize;		/* XXX */
960 	if (waitfor != MNT_WAIT)
961 		bawrite(bp);
962 	else if (error = bwrite(bp))
963 		allerror = error;
964 	return (allerror);
965 }
966