xref: /netbsd-src/sys/fs/filecorefs/filecore_vfsops.c (revision 9120d4511b151fba58c7db8d56cfcf3560b22850)
1*9120d451Spgoyette /*	$NetBSD: filecore_vfsops.c,v 1.83 2020/03/16 21:20:10 pgoyette Exp $	*/
2aad01611Sagc 
3aad01611Sagc /*-
4aad01611Sagc  * Copyright (c) 1994 The Regents of the University of California.
5aad01611Sagc  * All rights reserved.
6aad01611Sagc  *
7aad01611Sagc  * Redistribution and use in source and binary forms, with or without
8aad01611Sagc  * modification, are permitted provided that the following conditions
9aad01611Sagc  * are met:
10aad01611Sagc  * 1. Redistributions of source code must retain the above copyright
11aad01611Sagc  *    notice, this list of conditions and the following disclaimer.
12aad01611Sagc  * 2. Redistributions in binary form must reproduce the above copyright
13aad01611Sagc  *    notice, this list of conditions and the following disclaimer in the
14aad01611Sagc  *    documentation and/or other materials provided with the distribution.
15aad01611Sagc  * 3. Neither the name of the University nor the names of its contributors
16aad01611Sagc  *    may be used to endorse or promote products derived from this software
17aad01611Sagc  *    without specific prior written permission.
18aad01611Sagc  *
19aad01611Sagc  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20aad01611Sagc  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21aad01611Sagc  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22aad01611Sagc  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23aad01611Sagc  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24aad01611Sagc  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25aad01611Sagc  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26aad01611Sagc  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27aad01611Sagc  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28aad01611Sagc  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29aad01611Sagc  * SUCH DAMAGE.
30aad01611Sagc  *
31aad01611Sagc  *	filecore_vfsops.c	1.1	1998/6/26
32aad01611Sagc  */
335356de15Sjdolecek 
345356de15Sjdolecek /*-
355356de15Sjdolecek  * Copyright (c) 1998 Andrew McMurry
365356de15Sjdolecek  *
375356de15Sjdolecek  * Redistribution and use in source and binary forms, with or without
385356de15Sjdolecek  * modification, are permitted provided that the following conditions
395356de15Sjdolecek  * are met:
405356de15Sjdolecek  * 1. Redistributions of source code must retain the above copyright
415356de15Sjdolecek  *    notice, this list of conditions and the following disclaimer.
425356de15Sjdolecek  * 2. Redistributions in binary form must reproduce the above copyright
435356de15Sjdolecek  *    notice, this list of conditions and the following disclaimer in the
445356de15Sjdolecek  *    documentation and/or other materials provided with the distribution.
455356de15Sjdolecek  * 3. All advertising materials mentioning features or use of this software
465356de15Sjdolecek  *    must display the following acknowledgement:
475356de15Sjdolecek  *	This product includes software developed by the University of
485356de15Sjdolecek  *	California, Berkeley and its contributors.
495356de15Sjdolecek  * 4. Neither the name of the University nor the names of its contributors
505356de15Sjdolecek  *    may be used to endorse or promote products derived from this software
515356de15Sjdolecek  *    without specific prior written permission.
525356de15Sjdolecek  *
535356de15Sjdolecek  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
545356de15Sjdolecek  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
555356de15Sjdolecek  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
565356de15Sjdolecek  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
575356de15Sjdolecek  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
585356de15Sjdolecek  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
595356de15Sjdolecek  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
605356de15Sjdolecek  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
615356de15Sjdolecek  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
625356de15Sjdolecek  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
635356de15Sjdolecek  * SUCH DAMAGE.
645356de15Sjdolecek  *
655356de15Sjdolecek  *	filecore_vfsops.c	1.1	1998/6/26
665356de15Sjdolecek  */
675356de15Sjdolecek 
685356de15Sjdolecek #include <sys/cdefs.h>
69*9120d451Spgoyette __KERNEL_RCSID(0, "$NetBSD: filecore_vfsops.c,v 1.83 2020/03/16 21:20:10 pgoyette Exp $");
705356de15Sjdolecek 
715356de15Sjdolecek #if defined(_KERNEL_OPT)
725356de15Sjdolecek #include "opt_compat_netbsd.h"
735356de15Sjdolecek #endif
745356de15Sjdolecek 
755356de15Sjdolecek #include <sys/param.h>
765356de15Sjdolecek #include <sys/systm.h>
775356de15Sjdolecek #include <sys/namei.h>
785356de15Sjdolecek #include <sys/proc.h>
795356de15Sjdolecek #include <sys/vnode.h>
80717e1785Sdholland #include <miscfs/genfs/genfs.h>
815356de15Sjdolecek #include <miscfs/specfs/specdev.h>
825356de15Sjdolecek #include <sys/mount.h>
835356de15Sjdolecek #include <sys/buf.h>
845356de15Sjdolecek #include <sys/file.h>
855356de15Sjdolecek #include <sys/device.h>
865356de15Sjdolecek #include <sys/errno.h>
875356de15Sjdolecek #include <sys/pool.h>
885356de15Sjdolecek #include <sys/conf.h>
89a42f9e30Sbjh21 #include <sys/sysctl.h>
90641b7ad8Schristos #include <sys/kauth.h>
91a1221b6dSrumble #include <sys/module.h>
925356de15Sjdolecek 
935356de15Sjdolecek #include <fs/filecorefs/filecore.h>
945356de15Sjdolecek #include <fs/filecorefs/filecore_extern.h>
955356de15Sjdolecek #include <fs/filecorefs/filecore_node.h>
965356de15Sjdolecek #include <fs/filecorefs/filecore_mount.h>
975356de15Sjdolecek 
98024c6fe9Spooka MODULE(MODULE_CLASS_VFS, filecore, NULL);
99a1221b6dSrumble 
1005356de15Sjdolecek extern const struct vnodeopv_desc filecore_vnodeop_opv_desc;
1015356de15Sjdolecek 
1025356de15Sjdolecek const struct vnodeopv_desc * const filecore_vnodeopv_descs[] = {
1035356de15Sjdolecek 	&filecore_vnodeop_opv_desc,
1045356de15Sjdolecek 	NULL,
1055356de15Sjdolecek };
1065356de15Sjdolecek 
1075356de15Sjdolecek struct vfsops filecore_vfsops = {
1086d285189Shannken 	.vfs_name = MOUNT_FILECORE,
1096d285189Shannken 	.vfs_min_mount_data = sizeof (struct filecore_args),
1106d285189Shannken 	.vfs_mount = filecore_mount,
1116d285189Shannken 	.vfs_start = filecore_start,
1126d285189Shannken 	.vfs_unmount = filecore_unmount,
1136d285189Shannken 	.vfs_root = filecore_root,
1146d285189Shannken 	.vfs_quotactl = (void *)eopnotsupp,
1156d285189Shannken 	.vfs_statvfs = filecore_statvfs,
1166d285189Shannken 	.vfs_sync = filecore_sync,
1176d285189Shannken 	.vfs_vget = filecore_vget,
118e716e7d8Shannken 	.vfs_loadvnode = filecore_loadvnode,
1196d285189Shannken 	.vfs_fhtovp = filecore_fhtovp,
1206d285189Shannken 	.vfs_vptofh = filecore_vptofh,
1216d285189Shannken 	.vfs_init = filecore_init,
1226d285189Shannken 	.vfs_reinit = filecore_reinit,
1236d285189Shannken 	.vfs_done = filecore_done,
1246d285189Shannken 	.vfs_snapshot = (void *)eopnotsupp,
1256d285189Shannken 	.vfs_extattrctl = vfs_stdextattrctl,
126326db3aaShannken 	.vfs_suspendctl = genfs_suspendctl,
1276d285189Shannken 	.vfs_renamelock_enter = genfs_renamelock_enter,
1286d285189Shannken 	.vfs_renamelock_exit = genfs_renamelock_exit,
1296d285189Shannken 	.vfs_fsync = (void *)eopnotsupp,
1306d285189Shannken 	.vfs_opv_descs = filecore_vnodeopv_descs
1315356de15Sjdolecek };
1325356de15Sjdolecek 
133*9120d451Spgoyette SYSCTL_SETUP(filecore_sysctl_setup, "filecore fs sysctl")
134a1221b6dSrumble {
135a1221b6dSrumble 
136*9120d451Spgoyette 	sysctl_createv(clog, 0, NULL, NULL,
13728f5ebd8Srumble 		       CTLFLAG_PERMANENT,
13828f5ebd8Srumble 		       CTLTYPE_NODE, "filecore",
13928f5ebd8Srumble 		       SYSCTL_DESCR("Acorn FILECORE file system"),
14028f5ebd8Srumble 		       NULL, 0, NULL, 0,
14128f5ebd8Srumble 		       CTL_VFS, 19, CTL_EOL);
14228f5ebd8Srumble 	/*
14328f5ebd8Srumble 	 * XXX the "19" above could be dynamic, thereby eliminating
14428f5ebd8Srumble 	 * one more instance of the "number to vfs" mapping problem,
14528f5ebd8Srumble 	 * but "19" is the order as taken from sys/mount.h
14628f5ebd8Srumble 	 */
147*9120d451Spgoyette }
148*9120d451Spgoyette 
149*9120d451Spgoyette static int
filecore_modcmd(modcmd_t cmd,void * arg)150*9120d451Spgoyette filecore_modcmd(modcmd_t cmd, void *arg)
151*9120d451Spgoyette {
152*9120d451Spgoyette 	int error;
153*9120d451Spgoyette 
154*9120d451Spgoyette 	switch (cmd) {
155*9120d451Spgoyette 	case MODULE_CMD_INIT:
156*9120d451Spgoyette 		error = vfs_attach(&filecore_vfsops);
157*9120d451Spgoyette 		if (error != 0)
158*9120d451Spgoyette 			break;
15928f5ebd8Srumble 		break;
160a1221b6dSrumble 	case MODULE_CMD_FINI:
16128f5ebd8Srumble 		error = vfs_detach(&filecore_vfsops);
16228f5ebd8Srumble 		if (error != 0)
16328f5ebd8Srumble 			break;
16428f5ebd8Srumble 		break;
165a1221b6dSrumble 	default:
16628f5ebd8Srumble 		error = ENOTTY;
16728f5ebd8Srumble 		break;
168a1221b6dSrumble 	}
16928f5ebd8Srumble 
17028f5ebd8Srumble 	return (error);
171a1221b6dSrumble }
172a1221b6dSrumble 
1735356de15Sjdolecek /*
1745356de15Sjdolecek  * Called by vfs_mountroot when iso is going to be mounted as root.
1755356de15Sjdolecek  *
1765356de15Sjdolecek  * Name is updated by mount(8) after booting.
1775356de15Sjdolecek  */
1785356de15Sjdolecek 
17902cdf4d2Sdsl static int filecore_mountfs(struct vnode *devvp, struct mount *mp,
18002cdf4d2Sdsl 		struct lwp *l, struct filecore_args *argp);
1815356de15Sjdolecek 
1825356de15Sjdolecek #if 0
1835356de15Sjdolecek int
184df7f595eScegger filecore_mountroot(void)
1855356de15Sjdolecek {
1865356de15Sjdolecek 	struct mount *mp;
1875356de15Sjdolecek 	extern struct vnode *rootvp;
1885356de15Sjdolecek 	struct proc *p = curproc;	/* XXX */
1895356de15Sjdolecek 	int error;
1905356de15Sjdolecek 	struct filecore_args args;
1915356de15Sjdolecek 
19258853410Sthorpej 	if (device_class(root_device) != DV_DISK)
1935356de15Sjdolecek 		return (ENODEV);
1945356de15Sjdolecek 
1955356de15Sjdolecek 	/*
1965356de15Sjdolecek 	 * Get vnodes for swapdev and rootdev.
1975356de15Sjdolecek 	 */
1985356de15Sjdolecek 	if (bdevvp(rootdev, &rootvp))
1995356de15Sjdolecek 		panic("filecore_mountroot: can't setup rootvp");
2005356de15Sjdolecek 
2015356de15Sjdolecek 	if ((error = vfs_rootmountalloc(MOUNT_FILECORE, "root_device", &mp)) != 0)
2025356de15Sjdolecek 		return (error);
2035356de15Sjdolecek 
2045356de15Sjdolecek 	args.flags = FILECOREMNT_ROOT;
2055356de15Sjdolecek 	if ((error = filecore_mountfs(rootvp, mp, p, &args)) != 0) {
20620bb034fShannken 		vfs_unbusy(mp);
207ebb8f73bShannken 		vfs_rele(mp);
2085356de15Sjdolecek 		return (error);
2095356de15Sjdolecek 	}
2100b725b63Schristos 	mountlist_append(mp);
2116bd1d6d4Schristos 	(void)filecore_statvfs(mp, &mp->mnt_stat, p);
21220bb034fShannken 	vfs_unbusy(mp);
2135356de15Sjdolecek 	return (0);
2145356de15Sjdolecek }
2155356de15Sjdolecek #endif
2165356de15Sjdolecek 
2175356de15Sjdolecek /*
2185356de15Sjdolecek  * VFS Operations.
2195356de15Sjdolecek  *
2205356de15Sjdolecek  * mount system call
2215356de15Sjdolecek  */
2225356de15Sjdolecek int
filecore_mount(struct mount * mp,const char * path,void * data,size_t * data_len)223454af1c0Sdsl filecore_mount(struct mount *mp, const char *path, void *data, size_t *data_len)
2245356de15Sjdolecek {
22561e8303eSpooka 	struct lwp *l = curlwp;
2265356de15Sjdolecek 	struct vnode *devvp;
2272721ab6cSdsl 	struct filecore_args *args = data;
2285356de15Sjdolecek 	int error;
2295356de15Sjdolecek 	struct filecore_mnt *fcmp = NULL;
2305356de15Sjdolecek 
23123f76b6dSmaxv 	if (args == NULL)
23223f76b6dSmaxv 		return EINVAL;
2332721ab6cSdsl 	if (*data_len < sizeof *args)
2342721ab6cSdsl 		return EINVAL;
2352721ab6cSdsl 
2365356de15Sjdolecek 	if (mp->mnt_flag & MNT_GETARGS) {
2375356de15Sjdolecek 		fcmp = VFSTOFILECORE(mp);
2385356de15Sjdolecek 		if (fcmp == NULL)
2395356de15Sjdolecek 			return EIO;
2402721ab6cSdsl 		args->flags = fcmp->fc_mntflags;
2412721ab6cSdsl 		args->uid = fcmp->fc_uid;
2422721ab6cSdsl 		args->gid = fcmp->fc_gid;
2432721ab6cSdsl 		args->fspec = NULL;
2442721ab6cSdsl 		*data_len = sizeof *args;
2452721ab6cSdsl 		return 0;
2465356de15Sjdolecek 	}
2475356de15Sjdolecek 
2485356de15Sjdolecek 	if ((mp->mnt_flag & MNT_RDONLY) == 0)
2495356de15Sjdolecek 		return (EROFS);
2505356de15Sjdolecek 
2512721ab6cSdsl 	if ((mp->mnt_flag & MNT_UPDATE) && args->fspec == NULL)
2522a3e5eebSjmmv 		return EINVAL;
2532a3e5eebSjmmv 
2545356de15Sjdolecek 	/*
2555356de15Sjdolecek 	 * Not an update, or updating the name: look up the name
2565356de15Sjdolecek 	 * and verify that it refers to a sensible block device.
2575356de15Sjdolecek 	 */
258effcf1afSdholland 	error = namei_simple_user(args->fspec,
259effcf1afSdholland 				NSM_FOLLOW_NOEMULROOT, &devvp);
260effcf1afSdholland 	if (error != 0)
2615356de15Sjdolecek 		return (error);
2625356de15Sjdolecek 
2635356de15Sjdolecek 	if (devvp->v_type != VBLK) {
2645356de15Sjdolecek 		vrele(devvp);
2655356de15Sjdolecek 		return ENOTBLK;
2665356de15Sjdolecek 	}
2675356de15Sjdolecek 	if (bdevsw_lookup(devvp->v_rdev) == NULL) {
2685356de15Sjdolecek 		vrele(devvp);
2695356de15Sjdolecek 		return ENXIO;
2705356de15Sjdolecek 	}
2715356de15Sjdolecek 	/*
2725356de15Sjdolecek 	 * If mount by non-root, then verify that user has necessary
2735356de15Sjdolecek 	 * permissions on the device.
2745356de15Sjdolecek 	 */
2755356de15Sjdolecek 	vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY);
2760c9d8d15Selad 	error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_MOUNT,
2770c9d8d15Selad 	    KAUTH_REQ_SYSTEM_MOUNT_DEVICE, mp, devvp, KAUTH_ARG(VREAD));
2781423e65bShannken 	VOP_UNLOCK(devvp);
2795356de15Sjdolecek 	if (error) {
2805356de15Sjdolecek 		vrele(devvp);
2815356de15Sjdolecek 		return (error);
2825356de15Sjdolecek 	}
2835356de15Sjdolecek 	if ((mp->mnt_flag & MNT_UPDATE) == 0)
2842721ab6cSdsl 		error = filecore_mountfs(devvp, mp, l, args);
2855356de15Sjdolecek 	else {
2868e1e9026Smlelstv 		fcmp = VFSTOFILECORE(mp);
2875356de15Sjdolecek 		if (devvp != fcmp->fc_devvp)
2885356de15Sjdolecek 			error = EINVAL;	/* needs translation */
2895356de15Sjdolecek 		else
2905356de15Sjdolecek 			vrele(devvp);
2915356de15Sjdolecek 	}
2925356de15Sjdolecek 	if (error) {
2935356de15Sjdolecek 		vrele(devvp);
2945356de15Sjdolecek 		return error;
2955356de15Sjdolecek 	}
2965356de15Sjdolecek 	fcmp = VFSTOFILECORE(mp);
2972721ab6cSdsl 	return set_statvfs_info(path, UIO_USERSPACE, args->fspec, UIO_USERSPACE,
298e24b0872Spooka 	    mp->mnt_op->vfs_name, mp, l);
2995356de15Sjdolecek }
3005356de15Sjdolecek 
3015356de15Sjdolecek /*
3025356de15Sjdolecek  * Common code for mount and mountroot
3035356de15Sjdolecek  */
3045356de15Sjdolecek static int
filecore_mountfs(struct vnode * devvp,struct mount * mp,struct lwp * l,struct filecore_args * argp)305454af1c0Sdsl filecore_mountfs(struct vnode *devvp, struct mount *mp, struct lwp *l, struct filecore_args *argp)
3065356de15Sjdolecek {
3075356de15Sjdolecek 	struct filecore_mnt *fcmp = (struct filecore_mnt *)0;
3085356de15Sjdolecek 	struct buf *bp = NULL;
3095356de15Sjdolecek 	dev_t dev = devvp->v_rdev;
3105356de15Sjdolecek 	int error = EINVAL;
3115356de15Sjdolecek 	int ronly = (mp->mnt_flag & MNT_RDONLY) != 0;
3125356de15Sjdolecek 	struct filecore_disc_record *fcdr;
3135356de15Sjdolecek 	unsigned map;
3145356de15Sjdolecek 	unsigned log2secsize;
3155356de15Sjdolecek 
3165356de15Sjdolecek 	if (!ronly)
3175356de15Sjdolecek 		return EROFS;
3185356de15Sjdolecek 
319703069c0Sad 	if ((error = vinvalbuf(devvp, V_SAVE, l->l_cred, l, 0, 0)) != 0)
3205356de15Sjdolecek 		return (error);
3215356de15Sjdolecek 
322d84a65ddShannken 	vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY);
32361e8303eSpooka 	error = VOP_OPEN(devvp, ronly ? FREAD : FREAD|FWRITE, FSCRED);
324d84a65ddShannken 	VOP_UNLOCK(devvp);
3255356de15Sjdolecek 	if (error)
3265356de15Sjdolecek 		return error;
3275356de15Sjdolecek 
3285356de15Sjdolecek 	/* Read the filecore boot block to check FS validity and to find the map */
3295356de15Sjdolecek 	error = bread(devvp, FILECORE_BOOTBLOCK_BLKN,
3306e392401Smaxv 			   FILECORE_BOOTBLOCK_SIZE, 0, &bp);
3315356de15Sjdolecek #ifdef FILECORE_DEBUG_BR
3325356de15Sjdolecek 		printf("bread(%p, %x, %d, CRED, %p)=%d\n", devvp,
3335356de15Sjdolecek 		       FILECORE_BOOTBLOCK_BLKN, FILECORE_BOOTBLOCK_SIZE,
3345356de15Sjdolecek 		       bp, error);
3355356de15Sjdolecek #endif
3365356de15Sjdolecek 	if (error != 0)
3375356de15Sjdolecek 		goto out;
338f89dbcf8Schristos 
339f89dbcf8Schristos 	KASSERT(bp != NULL);
3405356de15Sjdolecek 	if (filecore_bbchecksum(bp->b_data) != 0) {
3415356de15Sjdolecek 		error = EINVAL;
3425356de15Sjdolecek 		goto out;
3435356de15Sjdolecek 	}
3448b8caa1aSjnemeth 	fcdr = (struct filecore_disc_record *)((char *)(bp->b_data) +
3458b8caa1aSjnemeth 	    FILECORE_BB_DISCREC);
3465356de15Sjdolecek 	map = ((((8 << fcdr->log2secsize) - fcdr->zone_spare)
3475356de15Sjdolecek 	    * (fcdr->nzones / 2) - 8 * FILECORE_DISCREC_SIZE)
3485356de15Sjdolecek 	    << fcdr->log2bpmb) >> fcdr->log2secsize;
3495356de15Sjdolecek 	log2secsize = fcdr->log2secsize;
3505356de15Sjdolecek #ifdef FILECORE_DEBUG_BR
3515356de15Sjdolecek 	printf("brelse(%p) vf1\n", bp);
3525356de15Sjdolecek #endif
3539f56dfa5Sad 	brelse(bp, BC_AGE);
3545356de15Sjdolecek 	bp = NULL;
3555356de15Sjdolecek 
3565356de15Sjdolecek 	/* Read the bootblock in the map */
3576e392401Smaxv 	error = bread(devvp, map, 1 << log2secsize, 0, &bp);
3585356de15Sjdolecek #ifdef FILECORE_DEBUG_BR
3595356de15Sjdolecek 		printf("bread(%p, %x, %d, CRED, %p)=%d\n", devvp,
3605356de15Sjdolecek 		       map, 1 << log2secsize, bp, error);
3615356de15Sjdolecek #endif
3625356de15Sjdolecek 	if (error != 0)
3635356de15Sjdolecek 		goto out;
3648b8caa1aSjnemeth        	fcdr = (struct filecore_disc_record *)((char *)(bp->b_data) + 4);
3655cee5af5Srmind 	fcmp = kmem_zalloc(sizeof(*fcmp), KM_SLEEP);
3665356de15Sjdolecek 	if (fcdr->log2bpmb > fcdr->log2secsize)
3675356de15Sjdolecek 		fcmp->log2bsize = fcdr->log2bpmb;
3685356de15Sjdolecek 	else	fcmp->log2bsize = fcdr->log2secsize;
3695356de15Sjdolecek 	fcmp->blksize = 1 << fcmp->log2bsize;
370e3a43961Sjrf 	memcpy(&fcmp->drec, fcdr, sizeof(*fcdr));
3715356de15Sjdolecek 	fcmp->map = map;
3725356de15Sjdolecek 	fcmp->idspz = ((8 << fcdr->log2secsize) - fcdr->zone_spare)
3735356de15Sjdolecek 	    / (fcdr->idlen + 1);
3745356de15Sjdolecek 	fcmp->mask = (1 << fcdr->idlen) - 1;
3755356de15Sjdolecek 	if (fcdr->big_flag & 1) {
3765356de15Sjdolecek 		fcmp->nblks = ((((u_int64_t)fcdr->disc_size_2) << 32)
3775356de15Sjdolecek 		    + fcdr->disc_size) / fcmp->blksize;
3785356de15Sjdolecek 	} else {
3795356de15Sjdolecek 		fcmp->nblks=fcdr->disc_size / fcmp->blksize;
3805356de15Sjdolecek 	}
3815356de15Sjdolecek 
3825356de15Sjdolecek #ifdef FILECORE_DEBUG_BR
3835356de15Sjdolecek 	printf("brelse(%p) vf2\n", bp);
3845356de15Sjdolecek #endif
3859f56dfa5Sad 	brelse(bp, BC_AGE);
3865356de15Sjdolecek 	bp = NULL;
3875356de15Sjdolecek 
3885356de15Sjdolecek 	mp->mnt_data = fcmp;
3896bd1d6d4Schristos 	mp->mnt_stat.f_fsidx.__fsid_val[0] = (long)dev;
3906bd1d6d4Schristos 	mp->mnt_stat.f_fsidx.__fsid_val[1] = makefstype(MOUNT_FILECORE);
3916bd1d6d4Schristos 	mp->mnt_stat.f_fsid = mp->mnt_stat.f_fsidx.__fsid_val[0];
392caffd8efSjdolecek 	mp->mnt_stat.f_namemax = 10;
3935356de15Sjdolecek 	mp->mnt_flag |= MNT_LOCAL;
3945356de15Sjdolecek 	mp->mnt_dev_bshift = fcdr->log2secsize;
3955356de15Sjdolecek 	mp->mnt_fs_bshift = fcmp->log2bsize;
3965356de15Sjdolecek 
3975356de15Sjdolecek 	fcmp->fc_mountp = mp;
3985356de15Sjdolecek 	fcmp->fc_dev = dev;
3995356de15Sjdolecek 	fcmp->fc_devvp = devvp;
4005356de15Sjdolecek 	fcmp->fc_mntflags = argp->flags;
4015356de15Sjdolecek 	if (argp->flags & FILECOREMNT_USEUID) {
402f474dcebSad 		fcmp->fc_uid = kauth_cred_getuid(l->l_cred);
403f474dcebSad 		fcmp->fc_gid = kauth_cred_getgid(l->l_cred);
4045356de15Sjdolecek 	} else {
4055356de15Sjdolecek 		fcmp->fc_uid = argp->uid;
4065356de15Sjdolecek 		fcmp->fc_gid = argp->gid;
4075356de15Sjdolecek 	}
4085356de15Sjdolecek 
4095356de15Sjdolecek 	return 0;
4105356de15Sjdolecek out:
4115356de15Sjdolecek 	if (bp) {
4125356de15Sjdolecek #ifdef FILECORE_DEBUG_BR
4135356de15Sjdolecek 		printf("brelse(%p) vf3\n", bp);
4145356de15Sjdolecek #endif
4159f56dfa5Sad 		brelse(bp, 0);
4165356de15Sjdolecek 	}
4175356de15Sjdolecek 	vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY);
41861e8303eSpooka 	(void)VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE, NOCRED);
4191423e65bShannken 	VOP_UNLOCK(devvp);
4205356de15Sjdolecek 	return error;
4215356de15Sjdolecek }
4225356de15Sjdolecek 
4235356de15Sjdolecek /*
4245356de15Sjdolecek  * Make a filesystem operational.
4255356de15Sjdolecek  * Nothing to do at the moment.
4265356de15Sjdolecek  */
4275356de15Sjdolecek /* ARGSUSED */
4285356de15Sjdolecek int
filecore_start(struct mount * mp,int flags)429454af1c0Sdsl filecore_start(struct mount *mp, int flags)
4305356de15Sjdolecek {
4315356de15Sjdolecek 	return 0;
4325356de15Sjdolecek }
4335356de15Sjdolecek 
4345356de15Sjdolecek /*
4355356de15Sjdolecek  * unmount system call
4365356de15Sjdolecek  */
4375356de15Sjdolecek int
filecore_unmount(struct mount * mp,int mntflags)438454af1c0Sdsl filecore_unmount(struct mount *mp, int mntflags)
4395356de15Sjdolecek {
4405356de15Sjdolecek 	struct filecore_mnt *fcmp;
4415356de15Sjdolecek 	int error, flags = 0;
4425356de15Sjdolecek 
4435356de15Sjdolecek 	if (mntflags & MNT_FORCE)
4445356de15Sjdolecek 		flags |= FORCECLOSE;
4455356de15Sjdolecek 	if ((error = vflush(mp, NULLVP, flags)) != 0)
4465356de15Sjdolecek 		return (error);
4475356de15Sjdolecek 
4485356de15Sjdolecek 	fcmp = VFSTOFILECORE(mp);
4495356de15Sjdolecek 
4505356de15Sjdolecek 	if (fcmp->fc_devvp->v_type != VBAD)
4513881f4f3Shannken 		spec_node_setmountedfs(fcmp->fc_devvp, NULL);
4525356de15Sjdolecek 	vn_lock(fcmp->fc_devvp, LK_EXCLUSIVE | LK_RETRY);
45361e8303eSpooka 	error = VOP_CLOSE(fcmp->fc_devvp, FREAD, NOCRED);
4545356de15Sjdolecek 	vput(fcmp->fc_devvp);
4555cee5af5Srmind 	kmem_free(fcmp, sizeof(*fcmp));
4565356de15Sjdolecek 	mp->mnt_data = NULL;
4575356de15Sjdolecek 	mp->mnt_flag &= ~MNT_LOCAL;
4585356de15Sjdolecek 	return (error);
4595356de15Sjdolecek }
4605356de15Sjdolecek 
4615356de15Sjdolecek /*
4625356de15Sjdolecek  * Return root of a filesystem
4635356de15Sjdolecek  */
4645356de15Sjdolecek int
filecore_root(struct mount * mp,int lktype,struct vnode ** vpp)465c2e9cb94Sad filecore_root(struct mount *mp, int lktype, struct vnode **vpp)
4665356de15Sjdolecek {
4675356de15Sjdolecek 	struct vnode *nvp;
4685356de15Sjdolecek         int error;
4695356de15Sjdolecek 
470c2e9cb94Sad         if ((error = VFS_VGET(mp, FILECORE_ROOTINO, lktype, &nvp)) != 0)
4715356de15Sjdolecek                 return (error);
4725356de15Sjdolecek         *vpp = nvp;
4735356de15Sjdolecek         return (0);
4745356de15Sjdolecek }
4755356de15Sjdolecek 
4765356de15Sjdolecek /*
4775356de15Sjdolecek  * Get file system statistics.
4785356de15Sjdolecek  */
4795356de15Sjdolecek int
filecore_statvfs(struct mount * mp,struct statvfs * sbp)480454af1c0Sdsl filecore_statvfs(struct mount *mp, struct statvfs *sbp)
4815356de15Sjdolecek {
4825356de15Sjdolecek 	struct filecore_mnt *fcmp = VFSTOFILECORE(mp);
4835356de15Sjdolecek 
4845356de15Sjdolecek 	sbp->f_bsize = fcmp->blksize;
4856bd1d6d4Schristos 	sbp->f_frsize = sbp->f_bsize; /* XXX */
4865356de15Sjdolecek 	sbp->f_iosize = sbp->f_bsize;	/* XXX */
4875356de15Sjdolecek 	sbp->f_blocks = fcmp->nblks;
4885356de15Sjdolecek 	sbp->f_bfree = 0; /* total free blocks */
4895356de15Sjdolecek 	sbp->f_bavail = 0; /* blocks free for non superuser */
4906bd1d6d4Schristos 	sbp->f_bresvd = 0; /* reserved blocks */
4915356de15Sjdolecek 	sbp->f_files =  0; /* total files */
4926bd1d6d4Schristos 	sbp->f_ffree = 0; /* free file nodes for non superuser */
4936bd1d6d4Schristos 	sbp->f_favail = 0; /* free file nodes */
4946bd1d6d4Schristos 	sbp->f_fresvd = 0; /* reserved file nodes */
4956bd1d6d4Schristos 	copy_statvfs_info(sbp, mp);
4965356de15Sjdolecek 	return 0;
4975356de15Sjdolecek }
4985356de15Sjdolecek 
4995356de15Sjdolecek /* ARGSUSED */
5005356de15Sjdolecek int
filecore_sync(struct mount * mp,int waitfor,kauth_cred_t cred)501454af1c0Sdsl filecore_sync(struct mount *mp, int waitfor, kauth_cred_t cred)
5025356de15Sjdolecek {
5035356de15Sjdolecek 	return (0);
5045356de15Sjdolecek }
5055356de15Sjdolecek 
5065356de15Sjdolecek /*
5075356de15Sjdolecek  * File handle to vnode
5085356de15Sjdolecek  *
5095356de15Sjdolecek  * Have to be really careful about stale file handles:
5105356de15Sjdolecek  * - check that the inode number is in range
5115356de15Sjdolecek  * - call iget() to get the locked inode
5125356de15Sjdolecek  * - check for an unallocated inode (i_mode == 0)
5135356de15Sjdolecek  * - check that the generation number matches
5145356de15Sjdolecek  */
5155356de15Sjdolecek 
5165356de15Sjdolecek struct ifid {
5175356de15Sjdolecek 	ushort		ifid_len;
5185356de15Sjdolecek 	ushort		ifid_pad;
5195356de15Sjdolecek 	u_int32_t	ifid_ino;
5205356de15Sjdolecek };
5215356de15Sjdolecek 
5225356de15Sjdolecek /* ARGSUSED */
5235356de15Sjdolecek int
filecore_fhtovp(struct mount * mp,struct fid * fhp,int lktype,struct vnode ** vpp)524c2e9cb94Sad filecore_fhtovp(struct mount *mp, struct fid *fhp, int lktype,
525c2e9cb94Sad     struct vnode **vpp)
5265356de15Sjdolecek {
527a3b5baedSmartin 	struct ifid ifh;
5285356de15Sjdolecek 	struct vnode *nvp;
5295356de15Sjdolecek 	struct filecore_node *ip;
5305356de15Sjdolecek 	int error;
5315356de15Sjdolecek 
532a3b5baedSmartin 	if (fhp->fid_len != sizeof(struct ifid))
533a3b5baedSmartin 		return EINVAL;
534a3b5baedSmartin 
535a3b5baedSmartin 	memcpy(&ifh, fhp, sizeof(ifh));
536c2e9cb94Sad 	if ((error = VFS_VGET(mp, ifh.ifid_ino, lktype, &nvp)) != 0) {
5375356de15Sjdolecek 		*vpp = NULLVP;
5385356de15Sjdolecek 		return (error);
5395356de15Sjdolecek 	}
5405356de15Sjdolecek         ip = VTOI(nvp);
5415356de15Sjdolecek         if (filecore_staleinode(ip)) {
5425356de15Sjdolecek                 vput(nvp);
5435356de15Sjdolecek                 *vpp = NULLVP;
5445356de15Sjdolecek                 return (ESTALE);
5455356de15Sjdolecek         }
5465356de15Sjdolecek 	*vpp = nvp;
5475356de15Sjdolecek 	return (0);
5485356de15Sjdolecek }
5495356de15Sjdolecek 
5505356de15Sjdolecek /* This looks complicated. Look at other vgets as well as the iso9660 one.
5515356de15Sjdolecek  *
5525356de15Sjdolecek  * The filecore inode number is made up of 1 byte directory entry index and
5535356de15Sjdolecek  * 3 bytes of the internal disc address of the directory. On a read-only
5545356de15Sjdolecek  * filesystem this is unique. For a read-write version we may not be able to
5555356de15Sjdolecek  * do vget, see msdosfs.
5565356de15Sjdolecek  */
5575356de15Sjdolecek 
5585356de15Sjdolecek int
filecore_vget(struct mount * mp,ino_t ino,int lktype,struct vnode ** vpp)559c2e9cb94Sad filecore_vget(struct mount *mp, ino_t ino, int lktype, struct vnode **vpp)
5605356de15Sjdolecek {
5615356de15Sjdolecek 	int error;
5625356de15Sjdolecek 
563e716e7d8Shannken 	error = vcache_get(mp, &ino, sizeof(ino), vpp);
564e716e7d8Shannken 	if (error)
565e716e7d8Shannken 		return error;
566c2e9cb94Sad 	error = vn_lock(*vpp, lktype);
567e225b7bdSrmind 	if (error) {
568e716e7d8Shannken 		vrele(*vpp);
5695356de15Sjdolecek 		*vpp = NULL;
570e716e7d8Shannken 		return error;
5715356de15Sjdolecek 	}
572e716e7d8Shannken 	return 0;
5735356de15Sjdolecek }
5745356de15Sjdolecek 
5755356de15Sjdolecek /*
5765356de15Sjdolecek  * Vnode pointer to File handle
5775356de15Sjdolecek  */
5785356de15Sjdolecek /* ARGSUSED */
5795356de15Sjdolecek int
filecore_vptofh(struct vnode * vp,struct fid * fhp,size_t * fh_size)580454af1c0Sdsl filecore_vptofh(struct vnode *vp, struct fid *fhp, size_t *fh_size)
5815356de15Sjdolecek {
5825356de15Sjdolecek 	struct filecore_node *ip = VTOI(vp);
583a3b5baedSmartin 	struct ifid ifh;
5845356de15Sjdolecek 
585a3b5baedSmartin 	if (*fh_size < sizeof(struct ifid)) {
586a3b5baedSmartin 		*fh_size = sizeof(struct ifid);
587a3b5baedSmartin 		return E2BIG;
588a3b5baedSmartin 	}
589a3b5baedSmartin 	memset(&ifh, 0, sizeof(ifh));
590a3b5baedSmartin 	ifh.ifid_len = sizeof(struct ifid);
591a3b5baedSmartin 	ifh.ifid_ino = ip->i_number;
592a3b5baedSmartin 	memcpy(fhp, &ifh, sizeof(ifh));
5935356de15Sjdolecek        	return 0;
5945356de15Sjdolecek }
595