xref: /minix3/sys/fs/udf/udf_vfsops.c (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
1*0a6a1f1dSLionel Sambuc /* $NetBSD: udf_vfsops.c,v 1.71 2015/08/24 08:31:56 hannken Exp $ */
29f988b79SJean-Baptiste Boric 
39f988b79SJean-Baptiste Boric /*
49f988b79SJean-Baptiste Boric  * Copyright (c) 2006, 2008 Reinoud Zandijk
59f988b79SJean-Baptiste Boric  * All rights reserved.
69f988b79SJean-Baptiste Boric  *
79f988b79SJean-Baptiste Boric  * Redistribution and use in source and binary forms, with or without
89f988b79SJean-Baptiste Boric  * modification, are permitted provided that the following conditions
99f988b79SJean-Baptiste Boric  * are met:
109f988b79SJean-Baptiste Boric  * 1. Redistributions of source code must retain the above copyright
119f988b79SJean-Baptiste Boric  *    notice, this list of conditions and the following disclaimer.
129f988b79SJean-Baptiste Boric  * 2. Redistributions in binary form must reproduce the above copyright
139f988b79SJean-Baptiste Boric  *    notice, this list of conditions and the following disclaimer in the
149f988b79SJean-Baptiste Boric  *    documentation and/or other materials provided with the distribution.
159f988b79SJean-Baptiste Boric  *
169f988b79SJean-Baptiste Boric  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
179f988b79SJean-Baptiste Boric  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
189f988b79SJean-Baptiste Boric  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
199f988b79SJean-Baptiste Boric  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
209f988b79SJean-Baptiste Boric  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
219f988b79SJean-Baptiste Boric  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
229f988b79SJean-Baptiste Boric  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
239f988b79SJean-Baptiste Boric  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
249f988b79SJean-Baptiste Boric  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
259f988b79SJean-Baptiste Boric  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
269f988b79SJean-Baptiste Boric  *
279f988b79SJean-Baptiste Boric  */
289f988b79SJean-Baptiste Boric 
299f988b79SJean-Baptiste Boric #include <sys/cdefs.h>
309f988b79SJean-Baptiste Boric #ifndef lint
31*0a6a1f1dSLionel Sambuc __KERNEL_RCSID(0, "$NetBSD: udf_vfsops.c,v 1.71 2015/08/24 08:31:56 hannken Exp $");
329f988b79SJean-Baptiste Boric #endif /* not lint */
339f988b79SJean-Baptiste Boric 
349f988b79SJean-Baptiste Boric 
359f988b79SJean-Baptiste Boric #if defined(_KERNEL_OPT)
369f988b79SJean-Baptiste Boric #include "opt_compat_netbsd.h"
379f988b79SJean-Baptiste Boric #endif
389f988b79SJean-Baptiste Boric 
399f988b79SJean-Baptiste Boric #include <sys/param.h>
409f988b79SJean-Baptiste Boric #include <sys/systm.h>
419f988b79SJean-Baptiste Boric #include <sys/sysctl.h>
429f988b79SJean-Baptiste Boric #include <sys/namei.h>
439f988b79SJean-Baptiste Boric #include <sys/proc.h>
449f988b79SJean-Baptiste Boric #include <sys/kernel.h>
459f988b79SJean-Baptiste Boric #include <sys/vnode.h>
469f988b79SJean-Baptiste Boric #include <miscfs/genfs/genfs.h>
479f988b79SJean-Baptiste Boric #include <miscfs/specfs/specdev.h>
489f988b79SJean-Baptiste Boric #include <sys/mount.h>
499f988b79SJean-Baptiste Boric #include <sys/buf.h>
509f988b79SJean-Baptiste Boric #include <sys/file.h>
519f988b79SJean-Baptiste Boric #include <sys/device.h>
529f988b79SJean-Baptiste Boric #include <sys/disklabel.h>
539f988b79SJean-Baptiste Boric #include <sys/ioctl.h>
549f988b79SJean-Baptiste Boric #include <sys/malloc.h>
559f988b79SJean-Baptiste Boric #include <sys/dirent.h>
569f988b79SJean-Baptiste Boric #include <sys/stat.h>
579f988b79SJean-Baptiste Boric #include <sys/conf.h>
589f988b79SJean-Baptiste Boric #include <sys/kauth.h>
599f988b79SJean-Baptiste Boric #include <sys/module.h>
609f988b79SJean-Baptiste Boric 
619f988b79SJean-Baptiste Boric #include <fs/udf/ecma167-udf.h>
629f988b79SJean-Baptiste Boric #include <fs/udf/udf_mount.h>
639f988b79SJean-Baptiste Boric #include <sys/dirhash.h>
649f988b79SJean-Baptiste Boric 
659f988b79SJean-Baptiste Boric #include "udf.h"
669f988b79SJean-Baptiste Boric #include "udf_subr.h"
679f988b79SJean-Baptiste Boric #include "udf_bswap.h"
689f988b79SJean-Baptiste Boric 
699f988b79SJean-Baptiste Boric MODULE(MODULE_CLASS_VFS, udf, NULL);
709f988b79SJean-Baptiste Boric 
719f988b79SJean-Baptiste Boric #define VTOI(vnode) ((struct udf_node *) vnode->v_data)
729f988b79SJean-Baptiste Boric 
739f988b79SJean-Baptiste Boric /* verbose levels of the udf filingsystem */
749f988b79SJean-Baptiste Boric int udf_verbose = UDF_DEBUGGING;
759f988b79SJean-Baptiste Boric 
769f988b79SJean-Baptiste Boric /* malloc regions */
779f988b79SJean-Baptiste Boric MALLOC_JUSTDEFINE(M_UDFMNT,   "UDF mount",	"UDF mount structures");
789f988b79SJean-Baptiste Boric MALLOC_JUSTDEFINE(M_UDFVOLD,  "UDF volspace",	"UDF volume space descriptors");
799f988b79SJean-Baptiste Boric MALLOC_JUSTDEFINE(M_UDFTEMP,  "UDF temp",	"UDF scrap space");
809f988b79SJean-Baptiste Boric struct pool udf_node_pool;
819f988b79SJean-Baptiste Boric 
829f988b79SJean-Baptiste Boric static struct sysctllog *udf_sysctl_log;
839f988b79SJean-Baptiste Boric 
849f988b79SJean-Baptiste Boric /* internal functions */
859f988b79SJean-Baptiste Boric static int udf_mountfs(struct vnode *, struct mount *, struct lwp *, struct udf_args *);
869f988b79SJean-Baptiste Boric 
879f988b79SJean-Baptiste Boric 
889f988b79SJean-Baptiste Boric /* --------------------------------------------------------------------- */
899f988b79SJean-Baptiste Boric 
909f988b79SJean-Baptiste Boric /* predefine vnode-op list descriptor */
919f988b79SJean-Baptiste Boric extern const struct vnodeopv_desc udf_vnodeop_opv_desc;
929f988b79SJean-Baptiste Boric 
939f988b79SJean-Baptiste Boric const struct vnodeopv_desc * const udf_vnodeopv_descs[] = {
949f988b79SJean-Baptiste Boric 	&udf_vnodeop_opv_desc,
959f988b79SJean-Baptiste Boric 	NULL,
969f988b79SJean-Baptiste Boric };
979f988b79SJean-Baptiste Boric 
989f988b79SJean-Baptiste Boric 
999f988b79SJean-Baptiste Boric /* vfsops descriptor linked in as anchor point for the filingsystem */
1009f988b79SJean-Baptiste Boric struct vfsops udf_vfsops = {
101*0a6a1f1dSLionel Sambuc 	.vfs_name = MOUNT_UDF,
102*0a6a1f1dSLionel Sambuc 	.vfs_min_mount_data = sizeof (struct udf_args),
103*0a6a1f1dSLionel Sambuc 	.vfs_mount = udf_mount,
104*0a6a1f1dSLionel Sambuc 	.vfs_start = udf_start,
105*0a6a1f1dSLionel Sambuc 	.vfs_unmount = udf_unmount,
106*0a6a1f1dSLionel Sambuc 	.vfs_root = udf_root,
107*0a6a1f1dSLionel Sambuc 	.vfs_quotactl = (void *)eopnotsupp,
108*0a6a1f1dSLionel Sambuc 	.vfs_statvfs = udf_statvfs,
109*0a6a1f1dSLionel Sambuc 	.vfs_sync = udf_sync,
110*0a6a1f1dSLionel Sambuc 	.vfs_vget = udf_vget,
111*0a6a1f1dSLionel Sambuc 	.vfs_loadvnode = udf_loadvnode,
112*0a6a1f1dSLionel Sambuc 	.vfs_newvnode = udf_newvnode,
113*0a6a1f1dSLionel Sambuc 	.vfs_fhtovp = udf_fhtovp,
114*0a6a1f1dSLionel Sambuc 	.vfs_vptofh = udf_vptofh,
115*0a6a1f1dSLionel Sambuc 	.vfs_init = udf_init,
116*0a6a1f1dSLionel Sambuc 	.vfs_reinit = udf_reinit,
117*0a6a1f1dSLionel Sambuc 	.vfs_done = udf_done,
118*0a6a1f1dSLionel Sambuc 	.vfs_mountroot = udf_mountroot,
119*0a6a1f1dSLionel Sambuc 	.vfs_snapshot = udf_snapshot,
120*0a6a1f1dSLionel Sambuc 	.vfs_extattrctl = vfs_stdextattrctl,
121*0a6a1f1dSLionel Sambuc 	.vfs_suspendctl = (void *)eopnotsupp,
122*0a6a1f1dSLionel Sambuc 	.vfs_renamelock_enter = genfs_renamelock_enter,
123*0a6a1f1dSLionel Sambuc 	.vfs_renamelock_exit = genfs_renamelock_exit,
124*0a6a1f1dSLionel Sambuc 	.vfs_fsync = (void *)eopnotsupp,
125*0a6a1f1dSLionel Sambuc 	.vfs_opv_descs = udf_vnodeopv_descs
1269f988b79SJean-Baptiste Boric };
1279f988b79SJean-Baptiste Boric 
1289f988b79SJean-Baptiste Boric /* --------------------------------------------------------------------- */
1299f988b79SJean-Baptiste Boric 
1309f988b79SJean-Baptiste Boric /* file system starts here */
1319f988b79SJean-Baptiste Boric void
udf_init(void)1329f988b79SJean-Baptiste Boric udf_init(void)
1339f988b79SJean-Baptiste Boric {
1349f988b79SJean-Baptiste Boric 	size_t size;
1359f988b79SJean-Baptiste Boric 
1369f988b79SJean-Baptiste Boric 	/* setup memory types */
1379f988b79SJean-Baptiste Boric 	malloc_type_attach(M_UDFMNT);
1389f988b79SJean-Baptiste Boric 	malloc_type_attach(M_UDFVOLD);
1399f988b79SJean-Baptiste Boric 	malloc_type_attach(M_UDFTEMP);
1409f988b79SJean-Baptiste Boric 
1419f988b79SJean-Baptiste Boric 	/* init node pools */
1429f988b79SJean-Baptiste Boric 	size = sizeof(struct udf_node);
1439f988b79SJean-Baptiste Boric 	pool_init(&udf_node_pool, size, 0, 0, 0,
1449f988b79SJean-Baptiste Boric 		"udf_node_pool", NULL, IPL_NONE);
1459f988b79SJean-Baptiste Boric }
1469f988b79SJean-Baptiste Boric 
1479f988b79SJean-Baptiste Boric 
1489f988b79SJean-Baptiste Boric void
udf_reinit(void)1499f988b79SJean-Baptiste Boric udf_reinit(void)
1509f988b79SJean-Baptiste Boric {
1519f988b79SJean-Baptiste Boric 	/* nothing to do */
1529f988b79SJean-Baptiste Boric }
1539f988b79SJean-Baptiste Boric 
1549f988b79SJean-Baptiste Boric 
1559f988b79SJean-Baptiste Boric void
udf_done(void)1569f988b79SJean-Baptiste Boric udf_done(void)
1579f988b79SJean-Baptiste Boric {
1589f988b79SJean-Baptiste Boric 	/* remove pools */
1599f988b79SJean-Baptiste Boric 	pool_destroy(&udf_node_pool);
1609f988b79SJean-Baptiste Boric 
1619f988b79SJean-Baptiste Boric 	malloc_type_detach(M_UDFMNT);
1629f988b79SJean-Baptiste Boric 	malloc_type_detach(M_UDFVOLD);
1639f988b79SJean-Baptiste Boric 	malloc_type_detach(M_UDFTEMP);
1649f988b79SJean-Baptiste Boric }
1659f988b79SJean-Baptiste Boric 
1669f988b79SJean-Baptiste Boric /*
1679f988b79SJean-Baptiste Boric  * If running a DEBUG kernel, provide an easy way to set the debug flags when
1689f988b79SJean-Baptiste Boric  * running into a problem.
1699f988b79SJean-Baptiste Boric  */
1709f988b79SJean-Baptiste Boric #define UDF_VERBOSE_SYSCTLOPT        1
1719f988b79SJean-Baptiste Boric 
1729f988b79SJean-Baptiste Boric static int
udf_modcmd(modcmd_t cmd,void * arg)1739f988b79SJean-Baptiste Boric udf_modcmd(modcmd_t cmd, void *arg)
1749f988b79SJean-Baptiste Boric {
1759f988b79SJean-Baptiste Boric 	const struct sysctlnode *node;
1769f988b79SJean-Baptiste Boric 	int error;
1779f988b79SJean-Baptiste Boric 
1789f988b79SJean-Baptiste Boric 	switch (cmd) {
1799f988b79SJean-Baptiste Boric 	case MODULE_CMD_INIT:
1809f988b79SJean-Baptiste Boric 		error = vfs_attach(&udf_vfsops);
1819f988b79SJean-Baptiste Boric 		if (error != 0)
1829f988b79SJean-Baptiste Boric 			break;
1839f988b79SJean-Baptiste Boric 		/*
1849f988b79SJean-Baptiste Boric 		 * XXX the "24" below could be dynamic, thereby eliminating one
1859f988b79SJean-Baptiste Boric 		 * more instance of the "number to vfs" mapping problem, but
1869f988b79SJean-Baptiste Boric 		 * "24" is the order as taken from sys/mount.h
1879f988b79SJean-Baptiste Boric 		 */
1889f988b79SJean-Baptiste Boric 		sysctl_createv(&udf_sysctl_log, 0, NULL, &node,
1899f988b79SJean-Baptiste Boric 			       CTLFLAG_PERMANENT,
1909f988b79SJean-Baptiste Boric 			       CTLTYPE_NODE, "udf",
1919f988b79SJean-Baptiste Boric 			       SYSCTL_DESCR("OSTA Universal File System"),
1929f988b79SJean-Baptiste Boric 			       NULL, 0, NULL, 0,
1939f988b79SJean-Baptiste Boric 			       CTL_VFS, 24, CTL_EOL);
1949f988b79SJean-Baptiste Boric #ifdef DEBUG
1959f988b79SJean-Baptiste Boric 		sysctl_createv(&udf_sysctl_log, 0, NULL, &node,
1969f988b79SJean-Baptiste Boric 			       CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
1979f988b79SJean-Baptiste Boric 			       CTLTYPE_INT, "verbose",
1989f988b79SJean-Baptiste Boric 			       SYSCTL_DESCR("Bitmask for filesystem debugging"),
1999f988b79SJean-Baptiste Boric 			       NULL, 0, &udf_verbose, 0,
2009f988b79SJean-Baptiste Boric 			       CTL_VFS, 24, UDF_VERBOSE_SYSCTLOPT, CTL_EOL);
2019f988b79SJean-Baptiste Boric #endif
2029f988b79SJean-Baptiste Boric 		break;
2039f988b79SJean-Baptiste Boric 	case MODULE_CMD_FINI:
2049f988b79SJean-Baptiste Boric 		error = vfs_detach(&udf_vfsops);
2059f988b79SJean-Baptiste Boric 		if (error != 0)
2069f988b79SJean-Baptiste Boric 			break;
2079f988b79SJean-Baptiste Boric 		sysctl_teardown(&udf_sysctl_log);
2089f988b79SJean-Baptiste Boric 		break;
2099f988b79SJean-Baptiste Boric 	default:
2109f988b79SJean-Baptiste Boric 		error = ENOTTY;
2119f988b79SJean-Baptiste Boric 		break;
2129f988b79SJean-Baptiste Boric 	}
2139f988b79SJean-Baptiste Boric 
2149f988b79SJean-Baptiste Boric 	return (error);
2159f988b79SJean-Baptiste Boric }
2169f988b79SJean-Baptiste Boric 
2179f988b79SJean-Baptiste Boric /* --------------------------------------------------------------------- */
2189f988b79SJean-Baptiste Boric 
2199f988b79SJean-Baptiste Boric int
udf_mountroot(void)2209f988b79SJean-Baptiste Boric udf_mountroot(void)
2219f988b79SJean-Baptiste Boric {
2229f988b79SJean-Baptiste Boric 	return EOPNOTSUPP;
2239f988b79SJean-Baptiste Boric }
2249f988b79SJean-Baptiste Boric 
2259f988b79SJean-Baptiste Boric /* --------------------------------------------------------------------- */
2269f988b79SJean-Baptiste Boric 
2279f988b79SJean-Baptiste Boric #define MPFREE(a, lst) \
2289f988b79SJean-Baptiste Boric 	if ((a)) free((a), lst);
2299f988b79SJean-Baptiste Boric static void
free_udf_mountinfo(struct mount * mp)2309f988b79SJean-Baptiste Boric free_udf_mountinfo(struct mount *mp)
2319f988b79SJean-Baptiste Boric {
2329f988b79SJean-Baptiste Boric 	struct udf_mount *ump;
2339f988b79SJean-Baptiste Boric 	int i;
2349f988b79SJean-Baptiste Boric 
2359f988b79SJean-Baptiste Boric 	if (!mp)
2369f988b79SJean-Baptiste Boric 		return;
2379f988b79SJean-Baptiste Boric 
2389f988b79SJean-Baptiste Boric 	ump = VFSTOUDF(mp);
2399f988b79SJean-Baptiste Boric 	if (ump) {
2409f988b79SJean-Baptiste Boric 		/* clear our data */
2419f988b79SJean-Baptiste Boric 		for (i = 0; i < UDF_ANCHORS; i++)
2429f988b79SJean-Baptiste Boric 			MPFREE(ump->anchors[i], M_UDFVOLD);
2439f988b79SJean-Baptiste Boric 		MPFREE(ump->primary_vol,      M_UDFVOLD);
2449f988b79SJean-Baptiste Boric 		MPFREE(ump->logical_vol,      M_UDFVOLD);
2459f988b79SJean-Baptiste Boric 		MPFREE(ump->unallocated,      M_UDFVOLD);
2469f988b79SJean-Baptiste Boric 		MPFREE(ump->implementation,   M_UDFVOLD);
2479f988b79SJean-Baptiste Boric 		MPFREE(ump->logvol_integrity, M_UDFVOLD);
2489f988b79SJean-Baptiste Boric 		for (i = 0; i < UDF_PARTITIONS; i++) {
2499f988b79SJean-Baptiste Boric 			MPFREE(ump->partitions[i],        M_UDFVOLD);
2509f988b79SJean-Baptiste Boric 			MPFREE(ump->part_unalloc_dscr[i], M_UDFVOLD);
2519f988b79SJean-Baptiste Boric 			MPFREE(ump->part_freed_dscr[i],   M_UDFVOLD);
2529f988b79SJean-Baptiste Boric 		}
2539f988b79SJean-Baptiste Boric 		MPFREE(ump->metadata_unalloc_dscr, M_UDFVOLD);
2549f988b79SJean-Baptiste Boric 
2559f988b79SJean-Baptiste Boric 		MPFREE(ump->fileset_desc,   M_UDFVOLD);
2569f988b79SJean-Baptiste Boric 		MPFREE(ump->sparing_table,  M_UDFVOLD);
2579f988b79SJean-Baptiste Boric 
2589f988b79SJean-Baptiste Boric 		MPFREE(ump->la_node_ad_cpy, M_UDFMNT);
2599f988b79SJean-Baptiste Boric 		MPFREE(ump->la_pmapping,    M_TEMP);
2609f988b79SJean-Baptiste Boric 		MPFREE(ump->la_lmapping,    M_TEMP);
2619f988b79SJean-Baptiste Boric 
2629f988b79SJean-Baptiste Boric 		mutex_destroy(&ump->logvol_mutex);
2639f988b79SJean-Baptiste Boric 		mutex_destroy(&ump->allocate_mutex);
264*0a6a1f1dSLionel Sambuc 		mutex_destroy(&ump->sync_lock);
2659f988b79SJean-Baptiste Boric 
2669f988b79SJean-Baptiste Boric 		MPFREE(ump->vat_table, M_UDFVOLD);
2679f988b79SJean-Baptiste Boric 
2689f988b79SJean-Baptiste Boric 		free(ump, M_UDFMNT);
2699f988b79SJean-Baptiste Boric 	}
2709f988b79SJean-Baptiste Boric }
2719f988b79SJean-Baptiste Boric #undef MPFREE
2729f988b79SJean-Baptiste Boric 
2739f988b79SJean-Baptiste Boric /* --------------------------------------------------------------------- */
2749f988b79SJean-Baptiste Boric 
2759f988b79SJean-Baptiste Boric /* if the system nodes exist, release them */
2769f988b79SJean-Baptiste Boric static void
udf_release_system_nodes(struct mount * mp)2779f988b79SJean-Baptiste Boric udf_release_system_nodes(struct mount *mp)
2789f988b79SJean-Baptiste Boric {
2799f988b79SJean-Baptiste Boric 	struct udf_mount *ump = VFSTOUDF(mp);
2809f988b79SJean-Baptiste Boric 	int error;
2819f988b79SJean-Baptiste Boric 
2829f988b79SJean-Baptiste Boric 	/* if we haven't even got an ump, dont bother */
2839f988b79SJean-Baptiste Boric 	if (!ump)
2849f988b79SJean-Baptiste Boric 		return;
2859f988b79SJean-Baptiste Boric 
2869f988b79SJean-Baptiste Boric 	/* VAT partition support */
2879f988b79SJean-Baptiste Boric 	if (ump->vat_node)
2889f988b79SJean-Baptiste Boric 		vrele(ump->vat_node->vnode);
2899f988b79SJean-Baptiste Boric 
2909f988b79SJean-Baptiste Boric 	/* Metadata partition support */
2919f988b79SJean-Baptiste Boric 	if (ump->metadata_node)
2929f988b79SJean-Baptiste Boric 		vrele(ump->metadata_node->vnode);
2939f988b79SJean-Baptiste Boric 	if (ump->metadatamirror_node)
2949f988b79SJean-Baptiste Boric 		vrele(ump->metadatamirror_node->vnode);
2959f988b79SJean-Baptiste Boric 	if (ump->metadatabitmap_node)
2969f988b79SJean-Baptiste Boric 		vrele(ump->metadatabitmap_node->vnode);
2979f988b79SJean-Baptiste Boric 
2989f988b79SJean-Baptiste Boric 	/* This flush should NOT write anything nor allow any node to remain */
2999f988b79SJean-Baptiste Boric 	if ((error = vflush(ump->vfs_mountp, NULLVP, 0)) != 0)
3009f988b79SJean-Baptiste Boric 		panic("Failure to flush UDF system vnodes\n");
3019f988b79SJean-Baptiste Boric }
3029f988b79SJean-Baptiste Boric 
3039f988b79SJean-Baptiste Boric 
3049f988b79SJean-Baptiste Boric int
udf_mount(struct mount * mp,const char * path,void * data,size_t * data_len)3059f988b79SJean-Baptiste Boric udf_mount(struct mount *mp, const char *path,
3069f988b79SJean-Baptiste Boric 	  void *data, size_t *data_len)
3079f988b79SJean-Baptiste Boric {
3089f988b79SJean-Baptiste Boric 	struct lwp *l = curlwp;
3099f988b79SJean-Baptiste Boric 	struct udf_args *args = data;
3109f988b79SJean-Baptiste Boric 	struct udf_mount *ump;
3119f988b79SJean-Baptiste Boric 	struct vnode *devvp;
3129f988b79SJean-Baptiste Boric 	int openflags, accessmode, error;
3139f988b79SJean-Baptiste Boric 
3149f988b79SJean-Baptiste Boric 	DPRINTF(CALL, ("udf_mount called\n"));
3159f988b79SJean-Baptiste Boric 
316*0a6a1f1dSLionel Sambuc 	if (args == NULL)
317*0a6a1f1dSLionel Sambuc 		return EINVAL;
3189f988b79SJean-Baptiste Boric 	if (*data_len < sizeof *args)
3199f988b79SJean-Baptiste Boric 		return EINVAL;
3209f988b79SJean-Baptiste Boric 
3219f988b79SJean-Baptiste Boric 	if (mp->mnt_flag & MNT_GETARGS) {
3229f988b79SJean-Baptiste Boric 		/* request for the mount arguments */
3239f988b79SJean-Baptiste Boric 		ump = VFSTOUDF(mp);
3249f988b79SJean-Baptiste Boric 		if (ump == NULL)
3259f988b79SJean-Baptiste Boric 			return EINVAL;
3269f988b79SJean-Baptiste Boric 		*args = ump->mount_args;
3279f988b79SJean-Baptiste Boric 		*data_len = sizeof *args;
3289f988b79SJean-Baptiste Boric 		return 0;
3299f988b79SJean-Baptiste Boric 	}
3309f988b79SJean-Baptiste Boric 
3319f988b79SJean-Baptiste Boric 	/* handle request for updating mount parameters */
3329f988b79SJean-Baptiste Boric 	/* TODO can't update my mountpoint yet */
3339f988b79SJean-Baptiste Boric 	if (mp->mnt_flag & MNT_UPDATE) {
3349f988b79SJean-Baptiste Boric 		return EOPNOTSUPP;
3359f988b79SJean-Baptiste Boric 	}
3369f988b79SJean-Baptiste Boric 
3379f988b79SJean-Baptiste Boric 	/* OK, so we are asked to mount the device */
3389f988b79SJean-Baptiste Boric 
3399f988b79SJean-Baptiste Boric 	/* check/translate struct version */
3409f988b79SJean-Baptiste Boric 	/* TODO sanity checking other mount arguments */
3419f988b79SJean-Baptiste Boric 	if (args->version != 1) {
3429f988b79SJean-Baptiste Boric 		printf("mount_udf: unrecognized argument structure version\n");
3439f988b79SJean-Baptiste Boric 		return EINVAL;
3449f988b79SJean-Baptiste Boric 	}
3459f988b79SJean-Baptiste Boric 
3469f988b79SJean-Baptiste Boric 	/* lookup name to get its vnode */
3479f988b79SJean-Baptiste Boric 	error = namei_simple_user(args->fspec,
3489f988b79SJean-Baptiste Boric 				NSM_FOLLOW_NOEMULROOT, &devvp);
3499f988b79SJean-Baptiste Boric 	if (error)
3509f988b79SJean-Baptiste Boric 		return error;
3519f988b79SJean-Baptiste Boric 
3529f988b79SJean-Baptiste Boric #ifdef DEBUG
3539f988b79SJean-Baptiste Boric 	if (udf_verbose & UDF_DEBUG_VOLUMES)
3549f988b79SJean-Baptiste Boric 		vprint("UDF mount, trying to mount \n", devvp);
3559f988b79SJean-Baptiste Boric #endif
3569f988b79SJean-Baptiste Boric 
3579f988b79SJean-Baptiste Boric 	/* check if its a block device specified */
3589f988b79SJean-Baptiste Boric 	if (devvp->v_type != VBLK) {
3599f988b79SJean-Baptiste Boric 		vrele(devvp);
3609f988b79SJean-Baptiste Boric 		return ENOTBLK;
3619f988b79SJean-Baptiste Boric 	}
3629f988b79SJean-Baptiste Boric 	if (bdevsw_lookup(devvp->v_rdev) == NULL) {
3639f988b79SJean-Baptiste Boric 		vrele(devvp);
3649f988b79SJean-Baptiste Boric 		return ENXIO;
3659f988b79SJean-Baptiste Boric 	}
3669f988b79SJean-Baptiste Boric 
3679f988b79SJean-Baptiste Boric 	/*
3689f988b79SJean-Baptiste Boric 	 * If mount by non-root, then verify that user has necessary
3699f988b79SJean-Baptiste Boric 	 * permissions on the device.
3709f988b79SJean-Baptiste Boric 	 */
3719f988b79SJean-Baptiste Boric 	accessmode = VREAD;
3729f988b79SJean-Baptiste Boric 	if ((mp->mnt_flag & MNT_RDONLY) == 0)
3739f988b79SJean-Baptiste Boric 		accessmode |= VWRITE;
3749f988b79SJean-Baptiste Boric 	vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY);
3759f988b79SJean-Baptiste Boric 	error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_MOUNT,
3769f988b79SJean-Baptiste Boric 	    KAUTH_REQ_SYSTEM_MOUNT_DEVICE, mp, devvp, KAUTH_ARG(accessmode));
3779f988b79SJean-Baptiste Boric 	VOP_UNLOCK(devvp);
3789f988b79SJean-Baptiste Boric 	if (error) {
3799f988b79SJean-Baptiste Boric 		vrele(devvp);
3809f988b79SJean-Baptiste Boric 		return error;
3819f988b79SJean-Baptiste Boric 	}
3829f988b79SJean-Baptiste Boric 
3839f988b79SJean-Baptiste Boric 	/*
3849f988b79SJean-Baptiste Boric 	 * Open device and try to mount it!
3859f988b79SJean-Baptiste Boric 	 */
3869f988b79SJean-Baptiste Boric 	if (mp->mnt_flag & MNT_RDONLY) {
3879f988b79SJean-Baptiste Boric 		openflags = FREAD;
3889f988b79SJean-Baptiste Boric 	} else {
3899f988b79SJean-Baptiste Boric 		openflags = FREAD | FWRITE;
3909f988b79SJean-Baptiste Boric 	}
3919f988b79SJean-Baptiste Boric 	vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY);
3929f988b79SJean-Baptiste Boric 	error = VOP_OPEN(devvp, openflags, FSCRED);
3939f988b79SJean-Baptiste Boric 	VOP_UNLOCK(devvp);
3949f988b79SJean-Baptiste Boric 	if (error == 0) {
3959f988b79SJean-Baptiste Boric 		/* opened ok, try mounting */
3969f988b79SJean-Baptiste Boric 		error = udf_mountfs(devvp, mp, l, args);
3979f988b79SJean-Baptiste Boric 		if (error) {
3989f988b79SJean-Baptiste Boric 			udf_release_system_nodes(mp);
3999f988b79SJean-Baptiste Boric 			/* cleanup */
4009f988b79SJean-Baptiste Boric 			udf_discstrat_finish(VFSTOUDF(mp));
4019f988b79SJean-Baptiste Boric 			free_udf_mountinfo(mp);
4029f988b79SJean-Baptiste Boric 			vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY);
4039f988b79SJean-Baptiste Boric 			(void) VOP_CLOSE(devvp, openflags, NOCRED);
4049f988b79SJean-Baptiste Boric 			VOP_UNLOCK(devvp);
4059f988b79SJean-Baptiste Boric 		}
4069f988b79SJean-Baptiste Boric 	}
4079f988b79SJean-Baptiste Boric 	if (error) {
4089f988b79SJean-Baptiste Boric 		/* devvp is still locked */
4099f988b79SJean-Baptiste Boric 		vrele(devvp);
4109f988b79SJean-Baptiste Boric 		return error;
4119f988b79SJean-Baptiste Boric 	}
4129f988b79SJean-Baptiste Boric 
4139f988b79SJean-Baptiste Boric 	/* register our mountpoint being on this device */
4149f988b79SJean-Baptiste Boric 	spec_node_setmountedfs(devvp, mp);
4159f988b79SJean-Baptiste Boric 
4169f988b79SJean-Baptiste Boric 	/* successfully mounted */
4179f988b79SJean-Baptiste Boric 	DPRINTF(VOLUMES, ("udf_mount() successfull\n"));
4189f988b79SJean-Baptiste Boric 
4199f988b79SJean-Baptiste Boric 	error = set_statvfs_info(path, UIO_USERSPACE, args->fspec, UIO_USERSPACE,
4209f988b79SJean-Baptiste Boric 			mp->mnt_op->vfs_name, mp, l);
4219f988b79SJean-Baptiste Boric 	if (error)
4229f988b79SJean-Baptiste Boric 		return error;
4239f988b79SJean-Baptiste Boric 
4249f988b79SJean-Baptiste Boric 	/* If we're not opened read-only, open its logical volume */
4259f988b79SJean-Baptiste Boric 	if ((mp->mnt_flag & MNT_RDONLY) == 0) {
4269f988b79SJean-Baptiste Boric 		if ((error = udf_open_logvol(VFSTOUDF(mp))) != 0) {
4279f988b79SJean-Baptiste Boric 			printf( "mount_udf: can't open logical volume for "
4289f988b79SJean-Baptiste Boric 				"writing, downgrading access to read-only\n");
4299f988b79SJean-Baptiste Boric 			mp->mnt_flag |= MNT_RDONLY;
4309f988b79SJean-Baptiste Boric 			/* FIXME we can't return error now on open failure */
4319f988b79SJean-Baptiste Boric 			return 0;
4329f988b79SJean-Baptiste Boric 		}
4339f988b79SJean-Baptiste Boric 	}
4349f988b79SJean-Baptiste Boric 
4359f988b79SJean-Baptiste Boric 	return 0;
4369f988b79SJean-Baptiste Boric }
4379f988b79SJean-Baptiste Boric 
4389f988b79SJean-Baptiste Boric /* --------------------------------------------------------------------- */
4399f988b79SJean-Baptiste Boric 
4409f988b79SJean-Baptiste Boric #ifdef DEBUG
441*0a6a1f1dSLionel Sambuc static bool
udf_sanity_selector(void * cl,struct vnode * vp)442*0a6a1f1dSLionel Sambuc udf_sanity_selector(void *cl, struct vnode *vp)
4439f988b79SJean-Baptiste Boric {
4449f988b79SJean-Baptiste Boric 
4459f988b79SJean-Baptiste Boric 	vprint("", vp);
4469f988b79SJean-Baptiste Boric 	if (VOP_ISLOCKED(vp) == LK_EXCLUSIVE) {
4479f988b79SJean-Baptiste Boric 		printf("  is locked\n");
4489f988b79SJean-Baptiste Boric 	}
4499f988b79SJean-Baptiste Boric 	if (vp->v_usecount > 1)
4509f988b79SJean-Baptiste Boric 		printf("  more than one usecount %d\n", vp->v_usecount);
451*0a6a1f1dSLionel Sambuc 	return false;
4529f988b79SJean-Baptiste Boric }
453*0a6a1f1dSLionel Sambuc 
454*0a6a1f1dSLionel Sambuc static void
udf_unmount_sanity_check(struct mount * mp)455*0a6a1f1dSLionel Sambuc udf_unmount_sanity_check(struct mount *mp)
456*0a6a1f1dSLionel Sambuc {
457*0a6a1f1dSLionel Sambuc 	struct vnode_iterator *marker;
458*0a6a1f1dSLionel Sambuc 
459*0a6a1f1dSLionel Sambuc 	printf("On unmount, i found the following nodes:\n");
460*0a6a1f1dSLionel Sambuc 	vfs_vnode_iterator_init(mp, &marker);
461*0a6a1f1dSLionel Sambuc 	vfs_vnode_iterator_next(marker, udf_sanity_selector, NULL);
462*0a6a1f1dSLionel Sambuc 	vfs_vnode_iterator_destroy(marker);
4639f988b79SJean-Baptiste Boric }
4649f988b79SJean-Baptiste Boric #endif
4659f988b79SJean-Baptiste Boric 
4669f988b79SJean-Baptiste Boric 
4679f988b79SJean-Baptiste Boric int
udf_unmount(struct mount * mp,int mntflags)4689f988b79SJean-Baptiste Boric udf_unmount(struct mount *mp, int mntflags)
4699f988b79SJean-Baptiste Boric {
4709f988b79SJean-Baptiste Boric 	struct udf_mount *ump;
4719f988b79SJean-Baptiste Boric 	int error, flags, closeflags;
4729f988b79SJean-Baptiste Boric 
4739f988b79SJean-Baptiste Boric 	DPRINTF(CALL, ("udf_umount called\n"));
4749f988b79SJean-Baptiste Boric 
4759f988b79SJean-Baptiste Boric 	ump = VFSTOUDF(mp);
4769f988b79SJean-Baptiste Boric 	if (!ump)
4779f988b79SJean-Baptiste Boric 		panic("UDF unmount: empty ump\n");
4789f988b79SJean-Baptiste Boric 
4799f988b79SJean-Baptiste Boric 	flags = (mntflags & MNT_FORCE) ? FORCECLOSE : 0;
4809f988b79SJean-Baptiste Boric 	/* TODO remove these paranoid functions */
4819f988b79SJean-Baptiste Boric #ifdef DEBUG
4829f988b79SJean-Baptiste Boric 	if (udf_verbose & UDF_DEBUG_LOCKING)
4839f988b79SJean-Baptiste Boric 		udf_unmount_sanity_check(mp);
4849f988b79SJean-Baptiste Boric #endif
4859f988b79SJean-Baptiste Boric 
4869f988b79SJean-Baptiste Boric 	/*
4879f988b79SJean-Baptiste Boric 	 * By specifying SKIPSYSTEM we can skip vnodes marked with VV_SYSTEM.
4889f988b79SJean-Baptiste Boric 	 * This hardly documented feature allows us to exempt certain files
4899f988b79SJean-Baptiste Boric 	 * from being flushed.
4909f988b79SJean-Baptiste Boric 	 */
4919f988b79SJean-Baptiste Boric 	if ((error = vflush(mp, NULLVP, flags | SKIPSYSTEM)) != 0)
4929f988b79SJean-Baptiste Boric 		return error;
4939f988b79SJean-Baptiste Boric 
4949f988b79SJean-Baptiste Boric 	/* update nodes and wait for completion of writeout of system nodes */
4959f988b79SJean-Baptiste Boric 	udf_sync(mp, FSYNC_WAIT, NOCRED);
4969f988b79SJean-Baptiste Boric 
4979f988b79SJean-Baptiste Boric #ifdef DEBUG
4989f988b79SJean-Baptiste Boric 	if (udf_verbose & UDF_DEBUG_LOCKING)
4999f988b79SJean-Baptiste Boric 		udf_unmount_sanity_check(mp);
5009f988b79SJean-Baptiste Boric #endif
5019f988b79SJean-Baptiste Boric 
5029f988b79SJean-Baptiste Boric 	/* flush again, to check if we are still busy for something else */
5039f988b79SJean-Baptiste Boric 	if ((error = vflush(ump->vfs_mountp, NULLVP, flags | SKIPSYSTEM)) != 0)
5049f988b79SJean-Baptiste Boric 		return error;
5059f988b79SJean-Baptiste Boric 
5069f988b79SJean-Baptiste Boric 	DPRINTF(VOLUMES, ("flush OK on unmount\n"));
5079f988b79SJean-Baptiste Boric 
5089f988b79SJean-Baptiste Boric 	/* close logical volume and close session if requested */
5099f988b79SJean-Baptiste Boric 	if ((error = udf_close_logvol(ump, mntflags)) != 0)
5109f988b79SJean-Baptiste Boric 		return error;
5119f988b79SJean-Baptiste Boric 
5129f988b79SJean-Baptiste Boric #ifdef DEBUG
5139f988b79SJean-Baptiste Boric 	DPRINTF(VOLUMES, ("FINAL sanity check\n"));
5149f988b79SJean-Baptiste Boric 	if (udf_verbose & UDF_DEBUG_LOCKING)
5159f988b79SJean-Baptiste Boric 		udf_unmount_sanity_check(mp);
5169f988b79SJean-Baptiste Boric #endif
5179f988b79SJean-Baptiste Boric 
5189f988b79SJean-Baptiste Boric 	/* NOTE release system nodes should NOT write anything */
5199f988b79SJean-Baptiste Boric 	udf_release_system_nodes(mp);
5209f988b79SJean-Baptiste Boric 
5219f988b79SJean-Baptiste Boric 	/* finalise disc strategy */
5229f988b79SJean-Baptiste Boric 	udf_discstrat_finish(ump);
5239f988b79SJean-Baptiste Boric 
5249f988b79SJean-Baptiste Boric 	/* synchronise device caches */
5259f988b79SJean-Baptiste Boric 	(void) udf_synchronise_caches(ump);
5269f988b79SJean-Baptiste Boric 
5279f988b79SJean-Baptiste Boric 	/* close device */
5289f988b79SJean-Baptiste Boric 	DPRINTF(VOLUMES, ("closing device\n"));
5299f988b79SJean-Baptiste Boric 	if (mp->mnt_flag & MNT_RDONLY) {
5309f988b79SJean-Baptiste Boric 		closeflags = FREAD;
5319f988b79SJean-Baptiste Boric 	} else {
5329f988b79SJean-Baptiste Boric 		closeflags = FREAD | FWRITE;
5339f988b79SJean-Baptiste Boric 	}
5349f988b79SJean-Baptiste Boric 
5359f988b79SJean-Baptiste Boric 	/* devvp is still locked by us */
5369f988b79SJean-Baptiste Boric 	vn_lock(ump->devvp, LK_EXCLUSIVE | LK_RETRY);
5379f988b79SJean-Baptiste Boric 	error = VOP_CLOSE(ump->devvp, closeflags, NOCRED);
5389f988b79SJean-Baptiste Boric 	if (error)
5399f988b79SJean-Baptiste Boric 		printf("Error during closure of device! error %d, "
5409f988b79SJean-Baptiste Boric 		       "device might stay locked\n", error);
5419f988b79SJean-Baptiste Boric 	DPRINTF(VOLUMES, ("device close ok\n"));
5429f988b79SJean-Baptiste Boric 
5439f988b79SJean-Baptiste Boric 	/* clear our mount reference and release device node */
5449f988b79SJean-Baptiste Boric 	spec_node_setmountedfs(ump->devvp, NULL);
5459f988b79SJean-Baptiste Boric 	vput(ump->devvp);
5469f988b79SJean-Baptiste Boric 
5479f988b79SJean-Baptiste Boric 	/* free our ump */
5489f988b79SJean-Baptiste Boric 	free_udf_mountinfo(mp);
5499f988b79SJean-Baptiste Boric 
5509f988b79SJean-Baptiste Boric 	/* free ump struct references */
5519f988b79SJean-Baptiste Boric 	mp->mnt_data = NULL;
5529f988b79SJean-Baptiste Boric 	mp->mnt_flag &= ~MNT_LOCAL;
5539f988b79SJean-Baptiste Boric 
5549f988b79SJean-Baptiste Boric 	DPRINTF(VOLUMES, ("Fin unmount\n"));
5559f988b79SJean-Baptiste Boric 	return error;
5569f988b79SJean-Baptiste Boric }
5579f988b79SJean-Baptiste Boric 
5589f988b79SJean-Baptiste Boric /* --------------------------------------------------------------------- */
5599f988b79SJean-Baptiste Boric 
5609f988b79SJean-Baptiste Boric /*
5619f988b79SJean-Baptiste Boric  * Helper function of udf_mount() that actually mounts the disc.
5629f988b79SJean-Baptiste Boric  */
5639f988b79SJean-Baptiste Boric 
5649f988b79SJean-Baptiste Boric static int
udf_mountfs(struct vnode * devvp,struct mount * mp,struct lwp * l,struct udf_args * args)5659f988b79SJean-Baptiste Boric udf_mountfs(struct vnode *devvp, struct mount *mp,
5669f988b79SJean-Baptiste Boric 	    struct lwp *l, struct udf_args *args)
5679f988b79SJean-Baptiste Boric {
5689f988b79SJean-Baptiste Boric 	struct udf_mount     *ump;
5699f988b79SJean-Baptiste Boric 	uint32_t sector_size, lb_size, bshift;
5709f988b79SJean-Baptiste Boric 	uint32_t logvol_integrity;
5719f988b79SJean-Baptiste Boric 	int    num_anchors, error;
5729f988b79SJean-Baptiste Boric 
5739f988b79SJean-Baptiste Boric 	/* flush out any old buffers remaining from a previous use. */
5749f988b79SJean-Baptiste Boric 	if ((error = vinvalbuf(devvp, V_SAVE, l->l_cred, l, 0, 0)))
5759f988b79SJean-Baptiste Boric 		return error;
5769f988b79SJean-Baptiste Boric 
5779f988b79SJean-Baptiste Boric 	/* setup basic mount information */
5789f988b79SJean-Baptiste Boric 	mp->mnt_data = NULL;
5799f988b79SJean-Baptiste Boric 	mp->mnt_stat.f_fsidx.__fsid_val[0] = (uint32_t) devvp->v_rdev;
5809f988b79SJean-Baptiste Boric 	mp->mnt_stat.f_fsidx.__fsid_val[1] = makefstype(MOUNT_UDF);
5819f988b79SJean-Baptiste Boric 	mp->mnt_stat.f_fsid = mp->mnt_stat.f_fsidx.__fsid_val[0];
5829f988b79SJean-Baptiste Boric 	mp->mnt_stat.f_namemax = UDF_MAXNAMLEN;
5839f988b79SJean-Baptiste Boric 	mp->mnt_flag |= MNT_LOCAL;
5849f988b79SJean-Baptiste Boric //	mp->mnt_iflag |= IMNT_MPSAFE;
5859f988b79SJean-Baptiste Boric 
5869f988b79SJean-Baptiste Boric 	/* allocate udf part of mount structure; malloc always succeeds */
5879f988b79SJean-Baptiste Boric 	ump = malloc(sizeof(struct udf_mount), M_UDFMNT, M_WAITOK | M_ZERO);
5889f988b79SJean-Baptiste Boric 
5899f988b79SJean-Baptiste Boric 	/* init locks */
5909f988b79SJean-Baptiste Boric 	mutex_init(&ump->logvol_mutex, MUTEX_DEFAULT, IPL_NONE);
5919f988b79SJean-Baptiste Boric 	mutex_init(&ump->allocate_mutex, MUTEX_DEFAULT, IPL_NONE);
592*0a6a1f1dSLionel Sambuc 	mutex_init(&ump->sync_lock, MUTEX_DEFAULT, IPL_NONE);
5939f988b79SJean-Baptiste Boric 
5949f988b79SJean-Baptiste Boric 	/* init rbtree for nodes, ordered by their icb address (long_ad) */
5959f988b79SJean-Baptiste Boric 	udf_init_nodes_tree(ump);
5969f988b79SJean-Baptiste Boric 
5979f988b79SJean-Baptiste Boric 	/* set up linkage */
5989f988b79SJean-Baptiste Boric 	mp->mnt_data    = ump;
5999f988b79SJean-Baptiste Boric 	ump->vfs_mountp = mp;
6009f988b79SJean-Baptiste Boric 
6019f988b79SJean-Baptiste Boric 	/* set up arguments and device */
6029f988b79SJean-Baptiste Boric 	ump->mount_args = *args;
6039f988b79SJean-Baptiste Boric 	ump->devvp      = devvp;
6049f988b79SJean-Baptiste Boric 	if ((error = udf_update_discinfo(ump))) {
6059f988b79SJean-Baptiste Boric 		printf("UDF mount: error inspecting fs node\n");
6069f988b79SJean-Baptiste Boric 		return error;
6079f988b79SJean-Baptiste Boric 	}
6089f988b79SJean-Baptiste Boric 
6099f988b79SJean-Baptiste Boric 	/* inspect sector size */
6109f988b79SJean-Baptiste Boric 	sector_size = ump->discinfo.sector_size;
6119f988b79SJean-Baptiste Boric 	bshift = 1;
6129f988b79SJean-Baptiste Boric 	while ((1 << bshift) < sector_size)
6139f988b79SJean-Baptiste Boric 		bshift++;
6149f988b79SJean-Baptiste Boric 	if ((1 << bshift) != sector_size) {
6159f988b79SJean-Baptiste Boric 		printf("UDF mount: "
6169f988b79SJean-Baptiste Boric 		       "hit NetBSD implementation fence on sector size\n");
6179f988b79SJean-Baptiste Boric 		return EIO;
6189f988b79SJean-Baptiste Boric 	}
6199f988b79SJean-Baptiste Boric 
6209f988b79SJean-Baptiste Boric 	/* temporary check to overcome sectorsize >= 8192 bytes panic */
6219f988b79SJean-Baptiste Boric 	if (sector_size >= 8192) {
6229f988b79SJean-Baptiste Boric 		printf("UDF mount: "
6239f988b79SJean-Baptiste Boric 			"hit implementation limit, sectorsize to big\n");
6249f988b79SJean-Baptiste Boric 		return EIO;
6259f988b79SJean-Baptiste Boric 	}
6269f988b79SJean-Baptiste Boric 
6279f988b79SJean-Baptiste Boric 	/*
6289f988b79SJean-Baptiste Boric 	 * Inspect if we're asked to mount read-write on a non recordable or
6299f988b79SJean-Baptiste Boric 	 * closed sequential disc.
6309f988b79SJean-Baptiste Boric 	 */
6319f988b79SJean-Baptiste Boric 	if ((mp->mnt_flag & MNT_RDONLY) == 0) {
6329f988b79SJean-Baptiste Boric 		if ((ump->discinfo.mmc_cur & MMC_CAP_RECORDABLE) == 0) {
6339f988b79SJean-Baptiste Boric 			printf("UDF mount: disc is not recordable\n");
6349f988b79SJean-Baptiste Boric 			return EROFS;
6359f988b79SJean-Baptiste Boric 		}
6369f988b79SJean-Baptiste Boric 		if (ump->discinfo.mmc_cur & MMC_CAP_SEQUENTIAL) {
6379f988b79SJean-Baptiste Boric 			if (ump->discinfo.disc_state == MMC_STATE_FULL) {
6389f988b79SJean-Baptiste Boric 				printf("UDF mount: disc is not appendable\n");
6399f988b79SJean-Baptiste Boric 				return EROFS;
6409f988b79SJean-Baptiste Boric 			}
6419f988b79SJean-Baptiste Boric 
6429f988b79SJean-Baptiste Boric 			/*
6439f988b79SJean-Baptiste Boric 			 * TODO if the last session is closed check if there
6449f988b79SJean-Baptiste Boric 			 * is enough space to open/close new session
6459f988b79SJean-Baptiste Boric 			 */
6469f988b79SJean-Baptiste Boric 		}
6479f988b79SJean-Baptiste Boric 		/* double check if we're not mounting a pervious session RW */
6489f988b79SJean-Baptiste Boric 		if (args->sessionnr != 0) {
6499f988b79SJean-Baptiste Boric 			printf("UDF mount: updating a previous session "
6509f988b79SJean-Baptiste Boric 				"not yet allowed\n");
6519f988b79SJean-Baptiste Boric 			return EROFS;
6529f988b79SJean-Baptiste Boric 		}
6539f988b79SJean-Baptiste Boric 	}
6549f988b79SJean-Baptiste Boric 
6559f988b79SJean-Baptiste Boric 	/* initialise bootstrap disc strategy */
6569f988b79SJean-Baptiste Boric 	ump->strategy = &udf_strat_bootstrap;
6579f988b79SJean-Baptiste Boric 	udf_discstrat_init(ump);
6589f988b79SJean-Baptiste Boric 
6599f988b79SJean-Baptiste Boric 	/* read all anchors to get volume descriptor sequence */
6609f988b79SJean-Baptiste Boric 	num_anchors = udf_read_anchors(ump);
6619f988b79SJean-Baptiste Boric 	if (num_anchors == 0)
6629f988b79SJean-Baptiste Boric 		return EINVAL;
6639f988b79SJean-Baptiste Boric 
6649f988b79SJean-Baptiste Boric 	DPRINTF(VOLUMES, ("Read %d anchors on this disc, session %d\n",
6659f988b79SJean-Baptiste Boric 	    num_anchors, args->sessionnr));
6669f988b79SJean-Baptiste Boric 
6679f988b79SJean-Baptiste Boric 	/* read in volume descriptor sequence */
6689f988b79SJean-Baptiste Boric 	if ((error = udf_read_vds_space(ump))) {
6699f988b79SJean-Baptiste Boric 		printf("UDF mount: error reading volume space\n");
6709f988b79SJean-Baptiste Boric 		return error;
6719f988b79SJean-Baptiste Boric 	}
6729f988b79SJean-Baptiste Boric 
6739f988b79SJean-Baptiste Boric 	/* close down bootstrap disc strategy */
6749f988b79SJean-Baptiste Boric 	udf_discstrat_finish(ump);
6759f988b79SJean-Baptiste Boric 
6769f988b79SJean-Baptiste Boric 	/* check consistency and completeness */
6779f988b79SJean-Baptiste Boric 	if ((error = udf_process_vds(ump))) {
6789f988b79SJean-Baptiste Boric 		printf( "UDF mount: disc not properly formatted"
6799f988b79SJean-Baptiste Boric 			"(bad VDS)\n");
6809f988b79SJean-Baptiste Boric 		return error;
6819f988b79SJean-Baptiste Boric 	}
6829f988b79SJean-Baptiste Boric 
6839f988b79SJean-Baptiste Boric 	/* switch to new disc strategy */
6849f988b79SJean-Baptiste Boric 	KASSERT(ump->strategy != &udf_strat_bootstrap);
6859f988b79SJean-Baptiste Boric 	udf_discstrat_init(ump);
6869f988b79SJean-Baptiste Boric 
6879f988b79SJean-Baptiste Boric 	/* initialise late allocation administration space */
6889f988b79SJean-Baptiste Boric 	ump->la_lmapping = malloc(sizeof(uint64_t) * UDF_MAX_MAPPINGS,
6899f988b79SJean-Baptiste Boric 			M_TEMP, M_WAITOK);
6909f988b79SJean-Baptiste Boric 	ump->la_pmapping = malloc(sizeof(uint64_t) * UDF_MAX_MAPPINGS,
6919f988b79SJean-Baptiste Boric 			M_TEMP, M_WAITOK);
6929f988b79SJean-Baptiste Boric 
6939f988b79SJean-Baptiste Boric 	/* setup node cleanup extents copy space */
6949f988b79SJean-Baptiste Boric 	lb_size = udf_rw32(ump->logical_vol->lb_size);
6959f988b79SJean-Baptiste Boric 	ump->la_node_ad_cpy = malloc(lb_size * UDF_MAX_ALLOC_EXTENTS,
6969f988b79SJean-Baptiste Boric 		M_UDFMNT, M_WAITOK);
6979f988b79SJean-Baptiste Boric 	memset(ump->la_node_ad_cpy, 0, lb_size * UDF_MAX_ALLOC_EXTENTS);
6989f988b79SJean-Baptiste Boric 
6999f988b79SJean-Baptiste Boric 	/* setup rest of mount information */
7009f988b79SJean-Baptiste Boric 	mp->mnt_data = ump;
7019f988b79SJean-Baptiste Boric 
7029f988b79SJean-Baptiste Boric 	/* bshift is allways equal to disc sector size */
7039f988b79SJean-Baptiste Boric 	mp->mnt_dev_bshift = bshift;
7049f988b79SJean-Baptiste Boric 	mp->mnt_fs_bshift  = bshift;
7059f988b79SJean-Baptiste Boric 
7069f988b79SJean-Baptiste Boric 	/* note that the mp info needs to be initialised for reading! */
7079f988b79SJean-Baptiste Boric 	/* read vds support tables like VAT, sparable etc. */
7089f988b79SJean-Baptiste Boric 	if ((error = udf_read_vds_tables(ump))) {
7099f988b79SJean-Baptiste Boric 		printf( "UDF mount: error in format or damaged disc "
7109f988b79SJean-Baptiste Boric 			"(VDS tables failing)\n");
7119f988b79SJean-Baptiste Boric 		return error;
7129f988b79SJean-Baptiste Boric 	}
7139f988b79SJean-Baptiste Boric 
7149f988b79SJean-Baptiste Boric 	/* check if volume integrity is closed otherwise its dirty */
7159f988b79SJean-Baptiste Boric 	logvol_integrity = udf_rw32(ump->logvol_integrity->integrity_type);
7169f988b79SJean-Baptiste Boric 	if (logvol_integrity != UDF_INTEGRITY_CLOSED) {
7179f988b79SJean-Baptiste Boric 		printf("UDF mount: file system is not clean; ");
7189f988b79SJean-Baptiste Boric 		printf("please fsck(8)\n");
7199f988b79SJean-Baptiste Boric 		return EPERM;
7209f988b79SJean-Baptiste Boric 	}
7219f988b79SJean-Baptiste Boric 
7229f988b79SJean-Baptiste Boric 	/* read root directory */
7239f988b79SJean-Baptiste Boric 	if ((error = udf_read_rootdirs(ump))) {
7249f988b79SJean-Baptiste Boric 		printf( "UDF mount: "
7259f988b79SJean-Baptiste Boric 			"disc not properly formatted or damaged disc "
7269f988b79SJean-Baptiste Boric 			"(rootdirs failing)\n");
7279f988b79SJean-Baptiste Boric 		return error;
7289f988b79SJean-Baptiste Boric 	}
7299f988b79SJean-Baptiste Boric 
7309f988b79SJean-Baptiste Boric 	/* success! */
7319f988b79SJean-Baptiste Boric 	return 0;
7329f988b79SJean-Baptiste Boric }
7339f988b79SJean-Baptiste Boric 
7349f988b79SJean-Baptiste Boric /* --------------------------------------------------------------------- */
7359f988b79SJean-Baptiste Boric 
7369f988b79SJean-Baptiste Boric int
udf_start(struct mount * mp,int flags)7379f988b79SJean-Baptiste Boric udf_start(struct mount *mp, int flags)
7389f988b79SJean-Baptiste Boric {
7399f988b79SJean-Baptiste Boric 	/* do we have to do something here? */
7409f988b79SJean-Baptiste Boric 	return 0;
7419f988b79SJean-Baptiste Boric }
7429f988b79SJean-Baptiste Boric 
7439f988b79SJean-Baptiste Boric /* --------------------------------------------------------------------- */
7449f988b79SJean-Baptiste Boric 
7459f988b79SJean-Baptiste Boric int
udf_root(struct mount * mp,struct vnode ** vpp)7469f988b79SJean-Baptiste Boric udf_root(struct mount *mp, struct vnode **vpp)
7479f988b79SJean-Baptiste Boric {
7489f988b79SJean-Baptiste Boric 	struct vnode *vp;
7499f988b79SJean-Baptiste Boric 	struct long_ad *dir_loc;
7509f988b79SJean-Baptiste Boric 	struct udf_mount *ump = VFSTOUDF(mp);
7519f988b79SJean-Baptiste Boric 	struct udf_node *root_dir;
7529f988b79SJean-Baptiste Boric 	int error;
7539f988b79SJean-Baptiste Boric 
7549f988b79SJean-Baptiste Boric 	DPRINTF(CALL, ("udf_root called\n"));
7559f988b79SJean-Baptiste Boric 
7569f988b79SJean-Baptiste Boric 	dir_loc = &ump->fileset_desc->rootdir_icb;
7579f988b79SJean-Baptiste Boric 	error = udf_get_node(ump, dir_loc, &root_dir);
7589f988b79SJean-Baptiste Boric 
7599f988b79SJean-Baptiste Boric 	if (!root_dir)
7609f988b79SJean-Baptiste Boric 		error = ENOENT;
7619f988b79SJean-Baptiste Boric 	if (error)
7629f988b79SJean-Baptiste Boric 		return error;
7639f988b79SJean-Baptiste Boric 
7649f988b79SJean-Baptiste Boric 	vp = root_dir->vnode;
7659f988b79SJean-Baptiste Boric 	KASSERT(vp->v_vflag & VV_ROOT);
7669f988b79SJean-Baptiste Boric 
7679f988b79SJean-Baptiste Boric 	*vpp = vp;
7689f988b79SJean-Baptiste Boric 	return 0;
7699f988b79SJean-Baptiste Boric }
7709f988b79SJean-Baptiste Boric 
7719f988b79SJean-Baptiste Boric /* --------------------------------------------------------------------- */
7729f988b79SJean-Baptiste Boric 
7739f988b79SJean-Baptiste Boric int
udf_statvfs(struct mount * mp,struct statvfs * sbp)7749f988b79SJean-Baptiste Boric udf_statvfs(struct mount *mp, struct statvfs *sbp)
7759f988b79SJean-Baptiste Boric {
7769f988b79SJean-Baptiste Boric 	struct udf_mount *ump = VFSTOUDF(mp);
7779f988b79SJean-Baptiste Boric 	struct logvol_int_desc *lvid;
7789f988b79SJean-Baptiste Boric 	struct udf_logvol_info *impl;
7799f988b79SJean-Baptiste Boric 	uint64_t freeblks, sizeblks;
7809f988b79SJean-Baptiste Boric 	int num_part;
7819f988b79SJean-Baptiste Boric 
7829f988b79SJean-Baptiste Boric 	DPRINTF(CALL, ("udf_statvfs called\n"));
7839f988b79SJean-Baptiste Boric 	sbp->f_flag   = mp->mnt_flag;
7849f988b79SJean-Baptiste Boric 	sbp->f_bsize  = ump->discinfo.sector_size;
7859f988b79SJean-Baptiste Boric 	sbp->f_frsize = ump->discinfo.sector_size;
7869f988b79SJean-Baptiste Boric 	sbp->f_iosize = ump->discinfo.sector_size;
7879f988b79SJean-Baptiste Boric 
7889f988b79SJean-Baptiste Boric 	mutex_enter(&ump->allocate_mutex);
7899f988b79SJean-Baptiste Boric 
7909f988b79SJean-Baptiste Boric 	udf_calc_freespace(ump, &sizeblks, &freeblks);
7919f988b79SJean-Baptiste Boric 
7929f988b79SJean-Baptiste Boric 	sbp->f_blocks = sizeblks;
7939f988b79SJean-Baptiste Boric 	sbp->f_bfree  = freeblks;
7949f988b79SJean-Baptiste Boric 	sbp->f_files  = 0;
7959f988b79SJean-Baptiste Boric 
7969f988b79SJean-Baptiste Boric 	lvid = ump->logvol_integrity;
7979f988b79SJean-Baptiste Boric 	num_part = udf_rw32(lvid->num_part);
7989f988b79SJean-Baptiste Boric 	impl = (struct udf_logvol_info *) (lvid->tables + 2*num_part);
7999f988b79SJean-Baptiste Boric 	if (impl) {
8009f988b79SJean-Baptiste Boric 		sbp->f_files  = udf_rw32(impl->num_files);
8019f988b79SJean-Baptiste Boric 		sbp->f_files += udf_rw32(impl->num_directories);
8029f988b79SJean-Baptiste Boric 	}
8039f988b79SJean-Baptiste Boric 
8049f988b79SJean-Baptiste Boric 	/* XXX read only for now XXX */
8059f988b79SJean-Baptiste Boric 	sbp->f_bavail = 0;
8069f988b79SJean-Baptiste Boric 	sbp->f_bresvd = 0;
8079f988b79SJean-Baptiste Boric 
8089f988b79SJean-Baptiste Boric 	/* tricky, next only aplies to ffs i think, so set to zero */
8099f988b79SJean-Baptiste Boric 	sbp->f_ffree  = 0;
8109f988b79SJean-Baptiste Boric 	sbp->f_favail = 0;
8119f988b79SJean-Baptiste Boric 	sbp->f_fresvd = 0;
8129f988b79SJean-Baptiste Boric 
8139f988b79SJean-Baptiste Boric 	mutex_exit(&ump->allocate_mutex);
8149f988b79SJean-Baptiste Boric 
8159f988b79SJean-Baptiste Boric 	copy_statvfs_info(sbp, mp);
8169f988b79SJean-Baptiste Boric 	return 0;
8179f988b79SJean-Baptiste Boric }
8189f988b79SJean-Baptiste Boric 
8199f988b79SJean-Baptiste Boric /* --------------------------------------------------------------------- */
8209f988b79SJean-Baptiste Boric 
8219f988b79SJean-Baptiste Boric /*
8229f988b79SJean-Baptiste Boric  * TODO what about writing out free space maps, lvid etc? only on `waitfor'
8239f988b79SJean-Baptiste Boric  * i.e. explicit syncing by the user?
8249f988b79SJean-Baptiste Boric  */
8259f988b79SJean-Baptiste Boric 
8269f988b79SJean-Baptiste Boric static int
udf_sync_writeout_system_files(struct udf_mount * ump,int clearflags)8279f988b79SJean-Baptiste Boric udf_sync_writeout_system_files(struct udf_mount *ump, int clearflags)
8289f988b79SJean-Baptiste Boric {
8299f988b79SJean-Baptiste Boric 	int error;
8309f988b79SJean-Baptiste Boric 
8319f988b79SJean-Baptiste Boric 	/* XXX lock for VAT en bitmaps? */
8329f988b79SJean-Baptiste Boric 	/* metadata nodes are written synchronous */
8339f988b79SJean-Baptiste Boric 	DPRINTF(CALL, ("udf_sync: syncing metadata\n"));
8349f988b79SJean-Baptiste Boric 	if (ump->lvclose & UDF_WRITE_VAT)
8359f988b79SJean-Baptiste Boric 		udf_writeout_vat(ump);
8369f988b79SJean-Baptiste Boric 
8379f988b79SJean-Baptiste Boric 	error = 0;
8389f988b79SJean-Baptiste Boric 	if (ump->lvclose & UDF_WRITE_PART_BITMAPS) {
8399f988b79SJean-Baptiste Boric 		/* writeout metadata spacetable if existing */
8409f988b79SJean-Baptiste Boric 		error = udf_write_metadata_partition_spacetable(ump, MNT_WAIT);
8419f988b79SJean-Baptiste Boric 		if (error)
8429f988b79SJean-Baptiste Boric 			printf( "udf_writeout_system_files : "
8439f988b79SJean-Baptiste Boric 				" writeout of metadata space bitmap failed\n");
8449f988b79SJean-Baptiste Boric 
8459f988b79SJean-Baptiste Boric 		/* writeout partition spacetables */
8469f988b79SJean-Baptiste Boric 		error = udf_write_physical_partition_spacetables(ump, MNT_WAIT);
8479f988b79SJean-Baptiste Boric 		if (error)
8489f988b79SJean-Baptiste Boric 			printf( "udf_writeout_system_files : "
8499f988b79SJean-Baptiste Boric 				"writeout of space tables failed\n");
8509f988b79SJean-Baptiste Boric 		if (!error && clearflags)
8519f988b79SJean-Baptiste Boric 			ump->lvclose &= ~UDF_WRITE_PART_BITMAPS;
8529f988b79SJean-Baptiste Boric 	}
8539f988b79SJean-Baptiste Boric 
8549f988b79SJean-Baptiste Boric 	return error;
8559f988b79SJean-Baptiste Boric }
8569f988b79SJean-Baptiste Boric 
8579f988b79SJean-Baptiste Boric 
8589f988b79SJean-Baptiste Boric int
udf_sync(struct mount * mp,int waitfor,kauth_cred_t cred)8599f988b79SJean-Baptiste Boric udf_sync(struct mount *mp, int waitfor, kauth_cred_t cred)
8609f988b79SJean-Baptiste Boric {
8619f988b79SJean-Baptiste Boric 	struct udf_mount *ump = VFSTOUDF(mp);
8629f988b79SJean-Baptiste Boric 
8639f988b79SJean-Baptiste Boric 	DPRINTF(CALL, ("udf_sync called\n"));
8649f988b79SJean-Baptiste Boric 	/* if called when mounted readonly, just ignore */
8659f988b79SJean-Baptiste Boric 	if (mp->mnt_flag & MNT_RDONLY)
8669f988b79SJean-Baptiste Boric 		return 0;
8679f988b79SJean-Baptiste Boric 
8689f988b79SJean-Baptiste Boric 	if (ump->syncing && !waitfor) {
8699f988b79SJean-Baptiste Boric 		printf("UDF: skipping autosync\n");
8709f988b79SJean-Baptiste Boric 		return 0;
8719f988b79SJean-Baptiste Boric 	}
8729f988b79SJean-Baptiste Boric 
8739f988b79SJean-Baptiste Boric 	/* get sync lock */
8749f988b79SJean-Baptiste Boric 	ump->syncing = 1;
8759f988b79SJean-Baptiste Boric 
8769f988b79SJean-Baptiste Boric 	/* pre-sync */
8779f988b79SJean-Baptiste Boric 	udf_do_sync(ump, cred, waitfor);
8789f988b79SJean-Baptiste Boric 
8799f988b79SJean-Baptiste Boric 	if (waitfor == MNT_WAIT)
8809f988b79SJean-Baptiste Boric 		udf_sync_writeout_system_files(ump, true);
8819f988b79SJean-Baptiste Boric 
8829f988b79SJean-Baptiste Boric 	DPRINTF(CALL, ("end of udf_sync()\n"));
8839f988b79SJean-Baptiste Boric 	ump->syncing = 0;
8849f988b79SJean-Baptiste Boric 
8859f988b79SJean-Baptiste Boric 	return 0;
8869f988b79SJean-Baptiste Boric }
8879f988b79SJean-Baptiste Boric 
8889f988b79SJean-Baptiste Boric /* --------------------------------------------------------------------- */
8899f988b79SJean-Baptiste Boric 
8909f988b79SJean-Baptiste Boric /*
8919f988b79SJean-Baptiste Boric  * Get vnode for the file system type specific file id ino for the fs. Its
8929f988b79SJean-Baptiste Boric  * used for reference to files by unique ID and for NFSv3.
8939f988b79SJean-Baptiste Boric  * (optional) TODO lookup why some sources state NFSv3
8949f988b79SJean-Baptiste Boric  */
8959f988b79SJean-Baptiste Boric int
udf_vget(struct mount * mp,ino_t ino,struct vnode ** vpp)8969f988b79SJean-Baptiste Boric udf_vget(struct mount *mp, ino_t ino,
8979f988b79SJean-Baptiste Boric     struct vnode **vpp)
8989f988b79SJean-Baptiste Boric {
8999f988b79SJean-Baptiste Boric 	DPRINTF(NOTIMPL, ("udf_vget called\n"));
9009f988b79SJean-Baptiste Boric 	return EOPNOTSUPP;
9019f988b79SJean-Baptiste Boric }
9029f988b79SJean-Baptiste Boric 
9039f988b79SJean-Baptiste Boric /* --------------------------------------------------------------------- */
9049f988b79SJean-Baptiste Boric 
9059f988b79SJean-Baptiste Boric /*
9069f988b79SJean-Baptiste Boric  * Lookup vnode for file handle specified
9079f988b79SJean-Baptiste Boric  */
9089f988b79SJean-Baptiste Boric int
udf_fhtovp(struct mount * mp,struct fid * fhp,struct vnode ** vpp)9099f988b79SJean-Baptiste Boric udf_fhtovp(struct mount *mp, struct fid *fhp,
9109f988b79SJean-Baptiste Boric     struct vnode **vpp)
9119f988b79SJean-Baptiste Boric {
9129f988b79SJean-Baptiste Boric 	DPRINTF(NOTIMPL, ("udf_fhtovp called\n"));
9139f988b79SJean-Baptiste Boric 	return EOPNOTSUPP;
9149f988b79SJean-Baptiste Boric }
9159f988b79SJean-Baptiste Boric 
9169f988b79SJean-Baptiste Boric /* --------------------------------------------------------------------- */
9179f988b79SJean-Baptiste Boric 
9189f988b79SJean-Baptiste Boric /*
9199f988b79SJean-Baptiste Boric  * Create an unique file handle. Its structure is opaque and won't be used by
9209f988b79SJean-Baptiste Boric  * other subsystems. It should uniquely identify the file in the filingsystem
9219f988b79SJean-Baptiste Boric  * and enough information to know if a file has been removed and/or resources
9229f988b79SJean-Baptiste Boric  * have been recycled.
9239f988b79SJean-Baptiste Boric  */
9249f988b79SJean-Baptiste Boric int
udf_vptofh(struct vnode * vp,struct fid * fid,size_t * fh_size)9259f988b79SJean-Baptiste Boric udf_vptofh(struct vnode *vp, struct fid *fid,
9269f988b79SJean-Baptiste Boric     size_t *fh_size)
9279f988b79SJean-Baptiste Boric {
9289f988b79SJean-Baptiste Boric 	DPRINTF(NOTIMPL, ("udf_vptofh called\n"));
9299f988b79SJean-Baptiste Boric 	return EOPNOTSUPP;
9309f988b79SJean-Baptiste Boric }
9319f988b79SJean-Baptiste Boric 
9329f988b79SJean-Baptiste Boric /* --------------------------------------------------------------------- */
9339f988b79SJean-Baptiste Boric 
9349f988b79SJean-Baptiste Boric /*
9359f988b79SJean-Baptiste Boric  * Create a filingsystem snapshot at the specified timestamp. Could be
9369f988b79SJean-Baptiste Boric  * implemented by explicitly creating a new session or with spare room in the
9379f988b79SJean-Baptiste Boric  * integrity descriptor space
9389f988b79SJean-Baptiste Boric  */
9399f988b79SJean-Baptiste Boric int
udf_snapshot(struct mount * mp,struct vnode * vp,struct timespec * tm)9409f988b79SJean-Baptiste Boric udf_snapshot(struct mount *mp, struct vnode *vp,
9419f988b79SJean-Baptiste Boric     struct timespec *tm)
9429f988b79SJean-Baptiste Boric {
9439f988b79SJean-Baptiste Boric 	DPRINTF(NOTIMPL, ("udf_snapshot called\n"));
9449f988b79SJean-Baptiste Boric 	return EOPNOTSUPP;
9459f988b79SJean-Baptiste Boric }
9469f988b79SJean-Baptiste Boric 
9479f988b79SJean-Baptiste Boric /* --------------------------------------------------------------------- */
948