Home | History | Annotate | Line # | Download | only in ext2fs
ext2fs_vfsops.c revision 1.7
      1 /*	$NetBSD: ext2fs_vfsops.c,v 1.7 1998/02/18 07:05:49 thorpej Exp $	*/
      2 
      3 /*
      4  * Copyright (c) 1997 Manuel Bouyer.
      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  * Modified for ext2fs by Manuel Bouyer.
     38  */
     39 
     40 #include <sys/param.h>
     41 #include <sys/systm.h>
     42 #include <sys/namei.h>
     43 #include <sys/proc.h>
     44 #include <sys/kernel.h>
     45 #include <sys/vnode.h>
     46 #include <sys/socket.h>
     47 #include <sys/mount.h>
     48 #include <sys/buf.h>
     49 #include <sys/device.h>
     50 #include <sys/mbuf.h>
     51 #include <sys/file.h>
     52 #include <sys/disklabel.h>
     53 #include <sys/ioctl.h>
     54 #include <sys/errno.h>
     55 #include <sys/malloc.h>
     56 #include <sys/lock.h>
     57 
     58 #include <miscfs/specfs/specdev.h>
     59 
     60 #include <ufs/ufs/quota.h>
     61 #include <ufs/ufs/ufsmount.h>
     62 #include <ufs/ufs/inode.h>
     63 #include <ufs/ufs/dir.h>
     64 #include <ufs/ufs/ufs_extern.h>
     65 
     66 #include <ufs/ext2fs/ext2fs.h>
     67 #include <ufs/ext2fs/ext2fs_extern.h>
     68 
     69 extern struct lock ufs_hashlock;
     70 
     71 int ext2fs_sbupdate __P((struct ufsmount *, int));
     72 int ext2fs_check_export __P((struct mount *, struct ufid *, struct mbuf *,
     73 	struct vnode **, int *, struct ucred **));
     74 
     75 extern struct vnodeopv_desc ext2fs_vnodeop_opv_desc;
     76 extern struct vnodeopv_desc ext2fs_specop_opv_desc;
     77 #ifdef FIFO
     78 extern struct vnodeopv_desc ext2fs_fifoop_opv_desc;
     79 #endif
     80 
     81 struct vnodeopv_desc *ext2fs_vnodeopv_descs[] = {
     82 	&ext2fs_vnodeop_opv_desc,
     83 	&ext2fs_specop_opv_desc,
     84 #ifdef FIFO
     85 	&ext2fs_fifoop_opv_desc,
     86 #endif
     87 	NULL,
     88 };
     89 
     90 struct vfsops ext2fs_vfsops = {
     91 	MOUNT_EXT2FS,
     92 	ext2fs_mount,
     93 	ufs_start,
     94 	ext2fs_unmount,
     95 	ufs_root,
     96 	ufs_quotactl,
     97 	ext2fs_statfs,
     98 	ext2fs_sync,
     99 	ext2fs_vget,
    100 	ext2fs_fhtovp,
    101 	ext2fs_vptofh,
    102 	ext2fs_init,
    103 	ext2fs_mountroot,
    104 };
    105 
    106 extern u_long ext2gennumber;
    107 
    108 /*
    109  * This is the generic part of fhtovp called after the underlying
    110  * filesystem has validated the file handle.
    111  *
    112  * Verify that a host should have access to a filesystem, and if so
    113  * return a vnode for the presented file handle.
    114  */
    115 int
    116 ext2fs_check_export(mp, ufhp, nam, vpp, exflagsp, credanonp)
    117 	register struct mount *mp;
    118 	struct ufid *ufhp;
    119 	struct mbuf *nam;
    120 	struct vnode **vpp;
    121 	int *exflagsp;
    122 	struct ucred **credanonp;
    123 {
    124 	register struct inode *ip;
    125 	register struct netcred *np;
    126 	register struct ufsmount *ump = VFSTOUFS(mp);
    127 	struct vnode *nvp;
    128 	int error;
    129 
    130 	/*
    131 	 * Get the export permission structure for this <mp, client> tuple.
    132 	 */
    133 	np = vfs_export_lookup(mp, &ump->um_export, nam);
    134 	if (np == NULL)
    135 		return (EACCES);
    136 
    137 	if ((error = VFS_VGET(mp, ufhp->ufid_ino, &nvp)) != 0) {
    138 		*vpp = NULLVP;
    139 		return (error);
    140 	}
    141 	ip = VTOI(nvp);
    142 	if (ip->i_e2fs_mode == 0 || ip->i_e2fs_dtime != 0 ||
    143 		ip->i_e2fs_gen != ufhp->ufid_gen) {
    144 		vput(nvp);
    145 		*vpp = NULLVP;
    146 		return (ESTALE);
    147 	}
    148 	*vpp = nvp;
    149 	*exflagsp = np->netc_exflags;
    150 	*credanonp = &np->netc_anon;
    151 	return (0);
    152 }
    153 
    154 
    155 /*
    156  * Called by main() when ext2fs is going to be mounted as root.
    157  *
    158  * Name is updated by mount(8) after booting.
    159  */
    160 #define ROOTNAME	"root_device"
    161 
    162 int
    163 ext2fs_mountroot()
    164 {
    165 	extern struct vnode *rootvp;
    166 	register struct m_ext2fs *fs;
    167 	register struct mount *mp;
    168 	struct proc *p = curproc;	/* XXX */
    169 	struct ufsmount *ump;
    170 	size_t size;
    171 	int error;
    172 
    173 	if (root_device->dv_class != DV_DISK)
    174 		return (ENODEV);
    175 
    176 	/*
    177 	 * Get vnodes for rootdev.
    178 	 */
    179 	if (bdevvp(rootdev, &rootvp))
    180 		panic("ext2fs_mountroot: can't setup bdevvp's");
    181 
    182 	mp = malloc(sizeof(struct mount), M_MOUNT, M_WAITOK);
    183 	bzero((char *)mp, sizeof(struct mount));
    184 	mp->mnt_op = &ext2fs_vfsops;
    185 	mp->mnt_flag = MNT_RDONLY;
    186 	if ((error = ext2fs_mountfs(rootvp, mp, p)) != 0) {
    187 		free(mp, M_MOUNT);
    188 		return (error);
    189 	}
    190 	if ((error = vfs_lock(mp)) != 0) {
    191 		(void)ext2fs_unmount(mp, 0, p);
    192 		free(mp, M_MOUNT);
    193 		return (error);
    194 	}
    195 	CIRCLEQ_INSERT_TAIL(&mountlist, mp, mnt_list);
    196 	mp->mnt_vnodecovered = NULLVP;
    197 	ump = VFSTOUFS(mp);
    198 	fs = ump->um_e2fs;
    199 	bzero(fs->e2fs_fsmnt, sizeof(fs->e2fs_fsmnt));
    200 	fs->e2fs_fsmnt[0] = '/';
    201 	bcopy(fs->e2fs_fsmnt, mp->mnt_stat.f_mntonname, MNAMELEN);
    202 	(void) copystr(ROOTNAME, mp->mnt_stat.f_mntfromname, MNAMELEN - 1,
    203 		&size);
    204 	bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
    205 	(void)ext2fs_statfs(mp, &mp->mnt_stat, p);
    206 	vfs_unlock(mp);
    207 	inittodr(fs->e2fs.e2fs_wtime);
    208 	return (0);
    209 }
    210 
    211 /*
    212  * VFS Operations.
    213  *
    214  * mount system call
    215  */
    216 int
    217 ext2fs_mount(mp, path, data, ndp, p)
    218 	register struct mount *mp;
    219 	const char *path;
    220 	void * data;
    221 	struct nameidata *ndp;
    222 	struct proc *p;
    223 {
    224 	struct vnode *devvp;
    225 	struct ufs_args args;
    226 	struct ufsmount *ump = NULL;
    227 	register struct m_ext2fs *fs;
    228 	size_t size;
    229 	int error, flags;
    230 	mode_t accessmode;
    231 
    232 	error = copyin(data, (caddr_t)&args, sizeof (struct ufs_args));
    233 	if (error)
    234 		return (error);
    235 	/*
    236 	 * If updating, check whether changing from read-only to
    237 	 * read/write; if there is no device name, that's all we do.
    238 	 */
    239 	if (mp->mnt_flag & MNT_UPDATE) {
    240 		ump = VFSTOUFS(mp);
    241 		fs = ump->um_e2fs;
    242 		if (fs->e2fs_ronly == 0 && (mp->mnt_flag & MNT_RDONLY)) {
    243 			flags = WRITECLOSE;
    244 			if (mp->mnt_flag & MNT_FORCE)
    245 				flags |= FORCECLOSE;
    246 			if (vfs_busy(mp))
    247 				return (EBUSY);
    248 			error = ext2fs_flushfiles(mp, flags, p);
    249 			if (error == 0 &&
    250 				ext2fs_cgupdate(ump, MNT_WAIT) == 0 &&
    251 				(fs->e2fs.e2fs_state & E2FS_ERRORS) == 0) {
    252 				fs->e2fs.e2fs_state = E2FS_ISCLEAN;
    253 				(void) ext2fs_sbupdate(ump, MNT_WAIT);
    254 			}
    255 			vfs_unbusy(mp);
    256 			if (error)
    257 				return (error);
    258 			fs->e2fs_ronly = 1;
    259 		}
    260 		if (mp->mnt_flag & MNT_RELOAD) {
    261 			error = ext2fs_reload(mp, ndp->ni_cnd.cn_cred, p);
    262 			if (error)
    263 				return (error);
    264 		}
    265 		if (fs->e2fs_ronly && (mp->mnt_flag & MNT_WANTRDWR)) {
    266 			/*
    267 			 * If upgrade to read-write by non-root, then verify
    268 			 * that user has necessary permissions on the device.
    269 			 */
    270 			if (p->p_ucred->cr_uid != 0) {
    271 				devvp = ump->um_devvp;
    272 				VOP_LOCK(devvp);
    273 				error = VOP_ACCESS(devvp, VREAD | VWRITE,
    274 						   p->p_ucred, p);
    275 				if (error) {
    276 					VOP_UNLOCK(devvp);
    277 					return (error);
    278 				}
    279 				VOP_UNLOCK(devvp);
    280 			}
    281 			fs->e2fs_ronly = 0;
    282 			if (fs->e2fs.e2fs_state == E2FS_ISCLEAN)
    283 				fs->e2fs.e2fs_state = 0;
    284 			else
    285 				fs->e2fs.e2fs_state = E2FS_ERRORS;
    286 			fs->e2fs_fmod = 1;
    287 		}
    288 		if (args.fspec == 0) {
    289 			/*
    290 			 * Process export requests.
    291 			 */
    292 			return (vfs_export(mp, &ump->um_export, &args.export));
    293 		}
    294 	}
    295 	/*
    296 	 * Not an update, or updating the name: look up the name
    297 	 * and verify that it refers to a sensible block device.
    298 	 */
    299 	NDINIT(ndp, LOOKUP, FOLLOW, UIO_USERSPACE, args.fspec, p);
    300 	if ((error = namei(ndp)) != 0)
    301 		return (error);
    302 	devvp = ndp->ni_vp;
    303 
    304 	if (devvp->v_type != VBLK) {
    305 		vrele(devvp);
    306 		return (ENOTBLK);
    307 	}
    308 	if (major(devvp->v_rdev) >= nblkdev) {
    309 		vrele(devvp);
    310 		return (ENXIO);
    311 	}
    312 	/*
    313 	 * If mount by non-root, then verify that user has necessary
    314 	 * permissions on the device.
    315 	 */
    316 	if (p->p_ucred->cr_uid != 0) {
    317 		accessmode = VREAD;
    318 		if ((mp->mnt_flag & MNT_RDONLY) == 0)
    319 			accessmode |= VWRITE;
    320 		VOP_LOCK(devvp);
    321 		error = VOP_ACCESS(devvp, accessmode, p->p_ucred, p);
    322 		if (error) {
    323 			vput(devvp);
    324 			return (error);
    325 		}
    326 		VOP_UNLOCK(devvp);
    327 	}
    328 	if ((mp->mnt_flag & MNT_UPDATE) == 0)
    329 		error = ext2fs_mountfs(devvp, mp, p);
    330 	else {
    331 		if (devvp != ump->um_devvp)
    332 			error = EINVAL;	/* needs translation */
    333 		else
    334 			vrele(devvp);
    335 	}
    336 	if (error) {
    337 		vrele(devvp);
    338 		return (error);
    339 	}
    340 	ump = VFSTOUFS(mp);
    341 	fs = ump->um_e2fs;
    342 	(void) copyinstr(path, fs->e2fs_fsmnt, sizeof(fs->e2fs_fsmnt) - 1, &size);
    343 	bzero(fs->e2fs_fsmnt + size, sizeof(fs->e2fs_fsmnt) - size);
    344 	bcopy(fs->e2fs_fsmnt, mp->mnt_stat.f_mntonname, MNAMELEN);
    345 	(void) copyinstr(args.fspec, mp->mnt_stat.f_mntfromname, MNAMELEN - 1,
    346 		&size);
    347 	bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
    348 	if (fs->e2fs_fmod != 0) {	/* XXX */
    349 		fs->e2fs_fmod = 0;
    350 		if (fs->e2fs.e2fs_state == 0)
    351 			fs->e2fs.e2fs_wtime = time.tv_sec;
    352 		else
    353 			printf("%s: file system not clean; please fsck(8)\n",
    354 				mp->mnt_stat.f_mntfromname);
    355 		(void) ext2fs_cgupdate(ump, MNT_WAIT);
    356 	}
    357 	return (0);
    358 }
    359 
    360 /*
    361  * Reload all incore data for a filesystem (used after running fsck on
    362  * the root filesystem and finding things to fix). The filesystem must
    363  * be mounted read-only.
    364  *
    365  * Things to do to update the mount:
    366  *	1) invalidate all cached meta-data.
    367  *	2) re-read superblock from disk.
    368  *	3) re-read summary information from disk.
    369  *	4) invalidate all inactive vnodes.
    370  *	5) invalidate all cached file data.
    371  *	6) re-read inode data for all active vnodes.
    372  */
    373 int
    374 ext2fs_reload(mountp, cred, p)
    375 	register struct mount *mountp;
    376 	struct ucred *cred;
    377 	struct proc *p;
    378 {
    379 	register struct vnode *vp, *nvp, *devvp;
    380 	struct inode *ip;
    381 	struct buf *bp;
    382 	struct m_ext2fs *fs;
    383 	struct ext2fs *newfs;
    384 	struct partinfo dpart;
    385 	int i, size, error;
    386 
    387 	if ((mountp->mnt_flag & MNT_RDONLY) == 0)
    388 		return (EINVAL);
    389 	/*
    390 	 * Step 1: invalidate all cached meta-data.
    391 	 */
    392 	devvp = VFSTOUFS(mountp)->um_devvp;
    393 	if (vinvalbuf(devvp, 0, cred, p, 0, 0))
    394 		panic("ext2fs_reload: dirty1");
    395 	/*
    396 	 * Step 2: re-read superblock from disk.
    397 	 */
    398 	if (VOP_IOCTL(devvp, DIOCGPART, (caddr_t)&dpart, FREAD, NOCRED, p) != 0)
    399 		size = DEV_BSIZE;
    400 	else
    401 		size = dpart.disklab->d_secsize;
    402 	error = bread(devvp, (daddr_t)(SBOFF / size), SBSIZE, NOCRED, &bp);
    403 	if (error)
    404 		return (error);
    405 	newfs = (struct ext2fs *)bp->b_data;
    406 	if (fs2h16(newfs->e2fs_magic) != E2FS_MAGIC ||
    407 		fs2h32(newfs->e2fs_rev) != E2FS_REV) {
    408 #ifdef DIAGNOSTIC
    409 		printf("Wrong magic number: %x (expected %x for ext2 fs)",
    410 					fs2h16(newfs->e2fs_magic), E2FS_MAGIC);
    411 		printf("or wrong revision number: %x (expected %x for ext2 fs)",
    412 					fs2h32(newfs->e2fs_rev), E2FS_REV);
    413 #endif
    414 		brelse(bp);
    415 		return (EIO);		/* XXX needs translation */
    416 	}
    417 	if (fs2h32(newfs->e2fs_log_bsize) > 2) { /* block size = 1024|2048|4096 */
    418 #ifdef DIAGNOSTIC
    419 		printf("wrong block size: %d (expected <=2 for ext2 fs)\n",
    420 			fs2h32(newfs->e2fs_log_bsize));
    421 #endif
    422 		brelse(bp);
    423 		return (EIO);	   /* XXX needs translation */
    424 	}
    425 
    426 
    427 	fs = VFSTOUFS(mountp)->um_e2fs;
    428 	/*
    429 	 * copy in new superblock, and compute in-memory values
    430 	 */
    431 	e2fs_sbload(newfs, &fs->e2fs);
    432 	fs->e2fs_ncg = howmany(fs->e2fs.e2fs_bcount - fs->e2fs.e2fs_first_dblock,
    433 		fs->e2fs.e2fs_bpg);
    434 	/* XXX assume hw bsize = 512 */
    435 	fs->e2fs_fsbtodb = fs->e2fs.e2fs_log_bsize + 1;
    436 	fs->e2fs_bsize = 1024 << fs->e2fs.e2fs_log_bsize;
    437 	fs->e2fs_bshift = LOG_MINBSIZE + fs->e2fs.e2fs_log_bsize;
    438 	fs->e2fs_qbmask = fs->e2fs_bsize - 1;
    439 	fs->e2fs_bmask = ~fs->e2fs_qbmask;
    440 	fs->e2fs_ngdb = howmany(fs->e2fs_ncg,
    441 			fs->e2fs_bsize / sizeof(struct ext2_gd));
    442 	fs->e2fs_ipb = fs->e2fs_bsize / sizeof(struct ext2fs_dinode);
    443 	fs->e2fs_itpg = fs->e2fs.e2fs_ipg/fs->e2fs_ipb;
    444 
    445 	/*
    446 	 * Step 3: re-read summary information from disk.
    447 	 */
    448 
    449 	for (i=0; i < fs->e2fs_ngdb; i++) {
    450 		error = bread(devvp , fsbtodb(fs, ((fs->e2fs_bsize>1024)?0:1)+i+1),
    451 				fs->e2fs_bsize, NOCRED, &bp);
    452 		if (error)
    453 			return (error);
    454 		e2fs_cgload((struct ext2_gd*)bp->b_data,
    455 			&fs->e2fs_gd[i* fs->e2fs_bsize / sizeof(struct ext2_gd)],
    456 			fs->e2fs_bsize);
    457 		brelse(bp);
    458 	}
    459 
    460 loop:
    461 	for (vp = mountp->mnt_vnodelist.lh_first; vp != NULL; vp = nvp) {
    462 		nvp = vp->v_mntvnodes.le_next;
    463 		/*
    464 		 * Step 4: invalidate all inactive vnodes.
    465 		 */
    466 		if (vp->v_usecount == 0) {
    467 			vgone(vp);
    468 			continue;
    469 		}
    470 		/*
    471 		 * Step 5: invalidate all cached file data.
    472 		 */
    473 		if (vget(vp, 1))
    474 			goto loop;
    475 		if (vinvalbuf(vp, 0, cred, p, 0, 0))
    476 			panic("ext2fs_reload: dirty2");
    477 		/*
    478 		 * Step 6: re-read inode data for all active vnodes.
    479 		 */
    480 		ip = VTOI(vp);
    481 		error = bread(devvp, fsbtodb(fs, ino_to_fsba(fs, ip->i_number)),
    482 				  (int)fs->e2fs_bsize, NOCRED, &bp);
    483 		if (error) {
    484 			vput(vp);
    485 			return (error);
    486 		}
    487 		e2fs_iload((struct ext2fs_dinode *)bp->b_data +
    488 			ino_to_fsbo(fs, ip->i_number),
    489 					&ip->i_din.e2fs_din);
    490 		brelse(bp);
    491 		vput(vp);
    492 		if (vp->v_mount != mountp)
    493 			goto loop;
    494 	}
    495 	return (0);
    496 }
    497 
    498 /*
    499  * Common code for mount and mountroot
    500  */
    501 int
    502 ext2fs_mountfs(devvp, mp, p)
    503 	register struct vnode *devvp;
    504 	struct mount *mp;
    505 	struct proc *p;
    506 {
    507 	register struct ufsmount *ump;
    508 	struct buf *bp;
    509 	register struct ext2fs *fs;
    510 	register struct m_ext2fs *m_fs;
    511 	dev_t dev;
    512 	struct partinfo dpart;
    513 	int error, i, size, ronly;
    514 	struct ucred *cred;
    515 	extern struct vnode *rootvp;
    516 
    517 	dev = devvp->v_rdev;
    518 	cred = p ? p->p_ucred : NOCRED;
    519 	/*
    520 	 * Disallow multiple mounts of the same device.
    521 	 * Disallow mounting of a device that is currently in use
    522 	 * (except for root, which might share swap device for miniroot).
    523 	 * Flush out any old buffers remaining from a previous use.
    524 	 */
    525 	if ((error = vfs_mountedon(devvp)) != 0)
    526 		return (error);
    527 	if (vcount(devvp) > 1 && devvp != rootvp)
    528 		return (EBUSY);
    529 	if ((error = vinvalbuf(devvp, V_SAVE, cred, p, 0, 0)) != 0)
    530 		return (error);
    531 
    532 	ronly = (mp->mnt_flag & MNT_RDONLY) != 0;
    533 	error = VOP_OPEN(devvp, ronly ? FREAD : FREAD|FWRITE, FSCRED, p);
    534 	if (error)
    535 		return (error);
    536 	if (VOP_IOCTL(devvp, DIOCGPART, (caddr_t)&dpart, FREAD, cred, p) != 0)
    537 		size = DEV_BSIZE;
    538 	else
    539 		size = dpart.disklab->d_secsize;
    540 
    541 	bp = NULL;
    542 	ump = NULL;
    543 
    544 #ifdef DEBUG_EXT2
    545 	printf("sb size: %d ino size %d\n", sizeof(struct ext2fs),
    546 			sizeof(struct ext2fs_dinode));
    547 #endif
    548 	error = bread(devvp, (SBOFF / DEV_BSIZE), SBSIZE, cred, &bp);
    549 	if (error)
    550 		goto out;
    551 	fs = (struct ext2fs *)bp->b_data;
    552 	if (fs2h16(fs->e2fs_magic) != E2FS_MAGIC ||
    553 		fs2h32(fs->e2fs_rev) != E2FS_REV) {
    554 #ifdef DIAGNOSTIC
    555 		printf("Wrong magic number: %x (expected %x for ext2 fs)",
    556 			fs2h16(fs->e2fs_magic), E2FS_MAGIC);
    557 		printf(" or wrong revision number: %x (expected %x for ext2 fs)\n",
    558 			fs2h32(fs->e2fs_rev), E2FS_REV);
    559 #endif
    560 		error = EINVAL;		/* XXX needs translation */
    561 		goto out;
    562 	}
    563 
    564 	if (fs2h32(fs->e2fs_log_bsize) > 2) { /* block size = 1024|2048|4096 */
    565 #ifdef DIAGNOSTIC
    566 		printf("wrong block size: %d (expected <2 for ext2 fs)\n",
    567 			fs2h32(fs->e2fs_log_bsize));
    568 #endif
    569 		error = EINVAL;	 /* XXX needs translation */
    570 		goto out;
    571 	}
    572 
    573 	ump = malloc(sizeof *ump, M_UFSMNT, M_WAITOK);
    574 	bzero((caddr_t)ump, sizeof *ump);
    575 	ump->um_e2fs = malloc(sizeof(struct m_ext2fs), M_UFSMNT, M_WAITOK);
    576 	e2fs_sbload((struct ext2fs*)bp->b_data, &ump->um_e2fs->e2fs);
    577 	brelse(bp);
    578 	bp = NULL;
    579 	m_fs = ump->um_e2fs;
    580 	m_fs->e2fs_ronly = ronly;
    581 	if (ronly == 0) {
    582 		if (m_fs->e2fs.e2fs_state == E2FS_ISCLEAN)
    583 			m_fs->e2fs.e2fs_state = 0;
    584 		else
    585 			m_fs->e2fs.e2fs_state = E2FS_ERRORS;
    586 		m_fs->e2fs_fmod = 1;
    587 	}
    588 
    589 	/* compute dynamic sb infos */
    590 	m_fs->e2fs_ncg =
    591 		howmany(m_fs->e2fs.e2fs_bcount - m_fs->e2fs.e2fs_first_dblock,
    592 		m_fs->e2fs.e2fs_bpg);
    593 	/* XXX assume hw bsize = 512 */
    594 	m_fs->e2fs_fsbtodb = m_fs->e2fs.e2fs_log_bsize + 1;
    595 	m_fs->e2fs_bsize = 1024 << m_fs->e2fs.e2fs_log_bsize;
    596 	m_fs->e2fs_bshift = LOG_MINBSIZE + m_fs->e2fs.e2fs_log_bsize;
    597 	m_fs->e2fs_qbmask = m_fs->e2fs_bsize - 1;
    598 	m_fs->e2fs_bmask = ~m_fs->e2fs_qbmask;
    599 	m_fs->e2fs_ngdb = howmany(m_fs->e2fs_ncg,
    600 		m_fs->e2fs_bsize / sizeof(struct ext2_gd));
    601 	m_fs->e2fs_ipb = m_fs->e2fs_bsize / sizeof(struct ext2fs_dinode);
    602 	m_fs->e2fs_itpg = m_fs->e2fs.e2fs_ipg/m_fs->e2fs_ipb;
    603 
    604 	m_fs->e2fs_gd = malloc(m_fs->e2fs_ngdb * m_fs->e2fs_bsize,
    605 		M_UFSMNT, M_WAITOK);
    606 	for (i=0; i < m_fs->e2fs_ngdb; i++) {
    607 		error = bread(devvp , fsbtodb(m_fs, ((m_fs->e2fs_bsize>1024)?0:1)+i+1),
    608 			m_fs->e2fs_bsize, NOCRED, &bp);
    609 		if (error) {
    610 			free(m_fs->e2fs_gd, M_UFSMNT);
    611 			goto out;
    612 		}
    613 		e2fs_cgload((struct ext2_gd*)bp->b_data,
    614 			&m_fs->e2fs_gd[i* m_fs->e2fs_bsize / sizeof(struct ext2_gd)],
    615 			m_fs->e2fs_bsize);
    616 		brelse(bp);
    617 		bp = NULL;
    618 	}
    619 
    620 	mp->mnt_data = (qaddr_t)ump;
    621 	mp->mnt_stat.f_fsid.val[0] = (long)dev;
    622 	mp->mnt_stat.f_fsid.val[1] = makefstype(MOUNT_EXT2FS);
    623 	mp->mnt_maxsymlinklen = EXT2_MAXSYMLINKLEN;
    624 	mp->mnt_flag |= MNT_LOCAL;
    625 	ump->um_mountp = mp;
    626 	ump->um_dev = dev;
    627 	ump->um_devvp = devvp;
    628 	ump->um_nindir = NINDIR(m_fs);
    629 	ump->um_bptrtodb = m_fs->e2fs_fsbtodb;
    630 	ump->um_seqinc = 1; /* no frags */
    631 	devvp->v_specflags |= SI_MOUNTEDON;
    632 	return (0);
    633 out:
    634 	if (bp)
    635 		brelse(bp);
    636 	(void)VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE, cred, p);
    637 	if (ump) {
    638 		free(ump->um_e2fs, M_UFSMNT);
    639 		free(ump, M_UFSMNT);
    640 		mp->mnt_data = (qaddr_t)0;
    641 	}
    642 	return (error);
    643 }
    644 
    645 /*
    646  * unmount system call
    647  */
    648 int
    649 ext2fs_unmount(mp, mntflags, p)
    650 	struct mount *mp;
    651 	int mntflags;
    652 	struct proc *p;
    653 {
    654 	register struct ufsmount *ump;
    655 	register struct m_ext2fs *fs;
    656 	int error, flags;
    657 
    658 	flags = 0;
    659 	if (mntflags & MNT_FORCE)
    660 		flags |= FORCECLOSE;
    661 	if ((error = ext2fs_flushfiles(mp, flags, p)) != 0)
    662 		return (error);
    663 	ump = VFSTOUFS(mp);
    664 	fs = ump->um_e2fs;
    665 	if (fs->e2fs_ronly == 0 &&
    666 		ext2fs_cgupdate(ump, MNT_WAIT) == 0 &&
    667 		(fs->e2fs.e2fs_state & E2FS_ERRORS) == 0) {
    668 		fs->e2fs.e2fs_state = E2FS_ISCLEAN;
    669 		(void) ext2fs_sbupdate(ump, MNT_WAIT);
    670 	}
    671 	ump->um_devvp->v_specflags &= ~SI_MOUNTEDON;
    672 	error = VOP_CLOSE(ump->um_devvp, fs->e2fs_ronly ? FREAD : FREAD|FWRITE,
    673 		NOCRED, p);
    674 	vrele(ump->um_devvp);
    675 	free(fs->e2fs_gd, M_UFSMNT);
    676 	free(fs, M_UFSMNT);
    677 	free(ump, M_UFSMNT);
    678 	mp->mnt_data = (qaddr_t)0;
    679 	mp->mnt_flag &= ~MNT_LOCAL;
    680 	return (error);
    681 }
    682 
    683 /*
    684  * Flush out all the files in a filesystem.
    685  */
    686 int
    687 ext2fs_flushfiles(mp, flags, p)
    688 	register struct mount *mp;
    689 	int flags;
    690 	struct proc *p;
    691 {
    692 	extern int doforce;
    693 	register struct ufsmount *ump;
    694 	int error;
    695 
    696 	if (!doforce)
    697 		flags &= ~FORCECLOSE;
    698 	ump = VFSTOUFS(mp);
    699 	error = vflush(mp, NULLVP, flags);
    700 	return (error);
    701 }
    702 
    703 /*
    704  * Get file system statistics.
    705  */
    706 int
    707 ext2fs_statfs(mp, sbp, p)
    708 	struct mount *mp;
    709 	register struct statfs *sbp;
    710 	struct proc *p;
    711 {
    712 	register struct ufsmount *ump;
    713 	register struct m_ext2fs *fs;
    714 	u_int32_t overhead, overhead_per_group;
    715 
    716 	ump = VFSTOUFS(mp);
    717 	fs = ump->um_e2fs;
    718 	if (fs->e2fs.e2fs_magic != E2FS_MAGIC)
    719 		panic("ext2fs_statfs");
    720 #ifdef COMPAT_09
    721 	sbp->f_type = 1;
    722 #else
    723 	sbp->f_type = 0;
    724 #endif
    725 
    726 	/*
    727 	 * Compute the overhead (FS structures)
    728 	 */
    729 	overhead_per_group = 1 /* super block */ +
    730 						 fs->e2fs_ngdb +
    731 						 1 /* block bitmap */ +
    732 						 1 /* inode bitmap */ +
    733 						 fs->e2fs_itpg;
    734 	overhead = fs->e2fs.e2fs_first_dblock +
    735 		   fs->e2fs_ncg * overhead_per_group;
    736 
    737 
    738 	sbp->f_bsize = fs->e2fs_bsize;
    739 	sbp->f_iosize = fs->e2fs_bsize;
    740 	sbp->f_blocks = fs->e2fs.e2fs_bcount - overhead;
    741 	sbp->f_bfree = fs->e2fs.e2fs_fbcount;
    742 	sbp->f_bavail = sbp->f_bfree - fs->e2fs.e2fs_rbcount;
    743 	sbp->f_files =  fs->e2fs.e2fs_icount;
    744 	sbp->f_ffree = fs->e2fs.e2fs_ficount;
    745 	if (sbp != &mp->mnt_stat) {
    746 		bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN);
    747 		bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN);
    748 	}
    749 	strncpy(sbp->f_fstypename, mp->mnt_op->vfs_name, MFSNAMELEN);
    750 	return (0);
    751 }
    752 
    753 /*
    754  * Go through the disk queues to initiate sandbagged IO;
    755  * go through the inodes to write those that have been modified;
    756  * initiate the writing of the super block if it has been modified.
    757  *
    758  * Note: we are always called with the filesystem marked `MPBUSY'.
    759  */
    760 int
    761 ext2fs_sync(mp, waitfor, cred, p)
    762 	struct mount *mp;
    763 	int waitfor;
    764 	struct ucred *cred;
    765 	struct proc *p;
    766 {
    767 	register struct vnode *vp;
    768 	register struct inode *ip;
    769 	register struct ufsmount *ump = VFSTOUFS(mp);
    770 	register struct m_ext2fs *fs;
    771 	int error, allerror = 0;
    772 
    773 	fs = ump->um_e2fs;
    774 	/*
    775 	 * Write back modified superblock.
    776 	 * Consistency check that the superblock
    777 	 * is still in the buffer cache.
    778 	 */
    779 	if (fs->e2fs_fmod != 0) {
    780 		if (fs->e2fs_ronly != 0) {		/* XXX */
    781 			printf("fs = %s\n", fs->e2fs_fsmnt);
    782 			panic("update: rofs mod");
    783 		}
    784 		fs->e2fs_fmod = 0;
    785 		fs->e2fs.e2fs_wtime = time.tv_sec;
    786 		allerror = ext2fs_cgupdate(ump, waitfor);
    787 	}
    788 	/*
    789 	 * Write back each (modified) inode.
    790 	 */
    791 loop:
    792 	for (vp = mp->mnt_vnodelist.lh_first;
    793 		 vp != NULL;
    794 		 vp = vp->v_mntvnodes.le_next) {
    795 		/*
    796 		 * If the vnode that we are about to sync is no longer
    797 		 * associated with this mount point, start over.
    798 		 */
    799 		if (vp->v_mount != mp)
    800 			goto loop;
    801 		if (VOP_ISLOCKED(vp))
    802 			continue;
    803 		ip = VTOI(vp);
    804 		if ((ip->i_flag &
    805 			(IN_ACCESS | IN_CHANGE | IN_MODIFIED | IN_UPDATE)) == 0 &&
    806 			vp->v_dirtyblkhd.lh_first == NULL)
    807 			continue;
    808 		if (vget(vp, 1))
    809 			goto loop;
    810 		if ((error = VOP_FSYNC(vp, cred, waitfor, p)) != 0)
    811 			allerror = error;
    812 		vput(vp);
    813 	}
    814 	/*
    815 	 * Force stale file system control information to be flushed.
    816 	 */
    817 	if ((error = VOP_FSYNC(ump->um_devvp, cred, waitfor, p)) != 0)
    818 		allerror = error;
    819 	return (allerror);
    820 }
    821 
    822 /*
    823  * Look up a EXT2FS dinode number to find its incore vnode, otherwise read it
    824  * in from disk.  If it is in core, wait for the lock bit to clear, then
    825  * return the inode locked.  Detection and handling of mount points must be
    826  * done by the calling routine.
    827  */
    828 int
    829 ext2fs_vget(mp, ino, vpp)
    830 	struct mount *mp;
    831 	ino_t ino;
    832 	struct vnode **vpp;
    833 {
    834 	register struct m_ext2fs *fs;
    835 	register struct inode *ip;
    836 	struct ufsmount *ump;
    837 	struct buf *bp;
    838 	struct vnode *vp;
    839 	dev_t dev;
    840 	int error;
    841 
    842 	ump = VFSTOUFS(mp);
    843 	dev = ump->um_dev;
    844 	do {
    845 		if ((*vpp = ufs_ihashget(dev, ino)) != NULL)
    846 			return (0);
    847 	} while (lockmgr(&ufs_hashlock, LK_EXCLUSIVE|LK_SLEEPFAIL, 0, curproc));
    848 
    849 	/* Allocate a new vnode/inode. */
    850 	if ((error = getnewvnode(VT_EXT2FS, mp, ext2fs_vnodeop_p, &vp)) != 0) {
    851 		*vpp = NULL;
    852 		lockmgr(&ufs_hashlock, LK_RELEASE, 0, curproc);
    853 		return (error);
    854 	}
    855 	MALLOC(ip, struct inode *, sizeof(struct inode), M_EXT2FSNODE, M_WAITOK);
    856 	bzero((caddr_t)ip, sizeof(struct inode));
    857 	vp->v_data = ip;
    858 	ip->i_vnode = vp;
    859 	ip->i_e2fs = fs = ump->um_e2fs;
    860 	ip->i_dev = dev;
    861 	ip->i_number = ino;
    862 	ip->i_e2fs_last_lblk = 0;
    863 	ip->i_e2fs_last_blk = 0;
    864 
    865 	/*
    866 	 * Put it onto its hash chain and lock it so that other requests for
    867 	 * this inode will block if they arrive while we are sleeping waiting
    868 	 * for old data structures to be purged or for the contents of the
    869 	 * disk portion of this inode to be read.
    870 	 */
    871 	ufs_ihashins(ip);
    872 	lockmgr(&ufs_hashlock, LK_RELEASE, 0, curproc);
    873 
    874 	/* Read in the disk contents for the inode, copy into the inode. */
    875 	error = bread(ump->um_devvp, fsbtodb(fs, ino_to_fsba(fs, ino)),
    876 			  (int)fs->e2fs_bsize, NOCRED, &bp);
    877 	if (error) {
    878 		/*
    879 		 * The inode does not contain anything useful, so it would
    880 		 * be misleading to leave it on its hash chain. With mode
    881 		 * still zero, it will be unlinked and returned to the free
    882 		 * list by vput().
    883 		 */
    884 		vput(vp);
    885 		brelse(bp);
    886 		*vpp = NULL;
    887 		return (error);
    888 	}
    889 	e2fs_iload((struct ext2fs_dinode*)bp->b_data + ino_to_fsbo(fs, ino),
    890 				&ip->i_din.e2fs_din);
    891 	brelse(bp);
    892 
    893 	/* If the inode was deleted, reset all fields */
    894 	if (ip->i_e2fs_dtime != 0) {
    895 		ip->i_e2fs_mode = ip->i_e2fs_size = ip->i_e2fs_nblock = 0;
    896 		bzero(ip->i_e2fs_blocks, sizeof(ip->i_e2fs_blocks));
    897 	}
    898 
    899 	/*
    900 	 * Initialize the vnode from the inode, check for aliases.
    901 	 * Note that the underlying vnode may have changed.
    902 	 */
    903 	error = ext2fs_vinit(mp, ext2fs_specop_p, EXT2FS_FIFOOPS, &vp);
    904 	if (error) {
    905 		vput(vp);
    906 		*vpp = NULL;
    907 		return (error);
    908 	}
    909 	/*
    910 	 * Finish inode initialization now that aliasing has been resolved.
    911 	 */
    912 	ip->i_devvp = ump->um_devvp;
    913 	VREF(ip->i_devvp);
    914 	/*
    915 	 * Set up a generation number for this inode if it does not
    916 	 * already have one. This should only happen on old filesystems.
    917 	 */
    918 	if (ip->i_e2fs_gen == 0) {
    919 		if (++ext2gennumber < (u_long)time.tv_sec)
    920 			ext2gennumber = time.tv_sec;
    921 		ip->i_e2fs_gen = ext2gennumber;
    922 		if ((vp->v_mount->mnt_flag & MNT_RDONLY) == 0)
    923 			ip->i_flag |= IN_MODIFIED;
    924 	}
    925 
    926 	*vpp = vp;
    927 	return (0);
    928 }
    929 
    930 /*
    931  * File handle to vnode
    932  *
    933  * Have to be really careful about stale file handles:
    934  * - check that the inode number is valid
    935  * - call ext2fs_vget() to get the locked inode
    936  * - check for an unallocated inode (i_mode == 0)
    937  * - check that the given client host has export rights and return
    938  *   those rights via. exflagsp and credanonp
    939  */
    940 int
    941 ext2fs_fhtovp(mp, fhp, nam, vpp, exflagsp, credanonp)
    942 	register struct mount *mp;
    943 	struct fid *fhp;
    944 	struct mbuf *nam;
    945 	struct vnode **vpp;
    946 	int *exflagsp;
    947 	struct ucred **credanonp;
    948 {
    949 	register struct ufid *ufhp;
    950 	struct m_ext2fs *fs;
    951 
    952 	ufhp = (struct ufid *)fhp;
    953 	fs = VFSTOUFS(mp)->um_e2fs;
    954 	if ((ufhp->ufid_ino < EXT2_FIRSTINO && ufhp->ufid_ino != EXT2_ROOTINO) ||
    955 		ufhp->ufid_ino >= fs->e2fs_ncg * fs->e2fs.e2fs_ipg)
    956 		return (ESTALE);
    957 	return (ext2fs_check_export(mp, ufhp, nam, vpp, exflagsp, credanonp));
    958 }
    959 
    960 /*
    961  * Vnode pointer to File handle
    962  */
    963 /* ARGSUSED */
    964 int
    965 ext2fs_vptofh(vp, fhp)
    966 	struct vnode *vp;
    967 	struct fid *fhp;
    968 {
    969 	register struct inode *ip;
    970 	register struct ufid *ufhp;
    971 
    972 	ip = VTOI(vp);
    973 	ufhp = (struct ufid *)fhp;
    974 	ufhp->ufid_len = sizeof(struct ufid);
    975 	ufhp->ufid_ino = ip->i_number;
    976 	ufhp->ufid_gen = ip->i_e2fs_gen;
    977 	return (0);
    978 }
    979 
    980 /*
    981  * Write a superblock and associated information back to disk.
    982  */
    983 int
    984 ext2fs_sbupdate(mp, waitfor)
    985 	struct ufsmount *mp;
    986 	int waitfor;
    987 {
    988 	register struct m_ext2fs *fs = mp->um_e2fs;
    989 	register struct buf *bp;
    990 	int error = 0;
    991 
    992 	bp = getblk(mp->um_devvp, SBLOCK, SBSIZE, 0, 0);
    993 	e2fs_sbsave(&fs->e2fs, (struct ext2fs*)bp->b_data);
    994 	if (waitfor == MNT_WAIT)
    995 		error = bwrite(bp);
    996 	else
    997 		bawrite(bp);
    998 	return (error);
    999 }
   1000 
   1001 int
   1002 ext2fs_cgupdate(mp, waitfor)
   1003 	struct ufsmount *mp;
   1004 	int waitfor;
   1005 {
   1006 	register struct m_ext2fs *fs = mp->um_e2fs;
   1007 	register struct buf *bp;
   1008 	int i, error = 0, allerror = 0;
   1009 
   1010 	allerror = ext2fs_sbupdate(mp, waitfor);
   1011 	for (i = 0; i < fs->e2fs_ngdb; i++) {
   1012 		bp = getblk(mp->um_devvp, fsbtodb(fs, ((fs->e2fs_bsize>1024)?0:1)+i+1),
   1013 			fs->e2fs_bsize, 0, 0);
   1014 		e2fs_cgsave(&fs->e2fs_gd[i* fs->e2fs_bsize / sizeof(struct ext2_gd)],
   1015 				(struct ext2_gd*)bp->b_data, fs->e2fs_bsize);
   1016 		if (waitfor == MNT_WAIT)
   1017 			error = bwrite(bp);
   1018 		else
   1019 			bawrite(bp);
   1020 	}
   1021 
   1022 	if (!allerror && error)
   1023 		allerror = error;
   1024 	return (allerror);
   1025 }
   1026