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