1*d82e4b43Shannken /* $NetBSD: udf_vfsops.c,v 1.85 2022/05/03 07:33:07 hannken Exp $ */
2cff5e7adSreinoud
3cff5e7adSreinoud /*
4e979c658Sreinoud * Copyright (c) 2006, 2008 Reinoud Zandijk
5cff5e7adSreinoud * All rights reserved.
6cff5e7adSreinoud *
7cff5e7adSreinoud * Redistribution and use in source and binary forms, with or without
8cff5e7adSreinoud * modification, are permitted provided that the following conditions
9cff5e7adSreinoud * are met:
10cff5e7adSreinoud * 1. Redistributions of source code must retain the above copyright
11cff5e7adSreinoud * notice, this list of conditions and the following disclaimer.
12cff5e7adSreinoud * 2. Redistributions in binary form must reproduce the above copyright
13cff5e7adSreinoud * notice, this list of conditions and the following disclaimer in the
14cff5e7adSreinoud * documentation and/or other materials provided with the distribution.
15cff5e7adSreinoud *
16cff5e7adSreinoud * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17cff5e7adSreinoud * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18cff5e7adSreinoud * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19cff5e7adSreinoud * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20cff5e7adSreinoud * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21cff5e7adSreinoud * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22cff5e7adSreinoud * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23cff5e7adSreinoud * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24cff5e7adSreinoud * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25cff5e7adSreinoud * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26cff5e7adSreinoud *
27cff5e7adSreinoud */
28cff5e7adSreinoud
29cff5e7adSreinoud #include <sys/cdefs.h>
30cff5e7adSreinoud #ifndef lint
31*d82e4b43Shannken __KERNEL_RCSID(0, "$NetBSD: udf_vfsops.c,v 1.85 2022/05/03 07:33:07 hannken Exp $");
32cff5e7adSreinoud #endif /* not lint */
33cff5e7adSreinoud
34cff5e7adSreinoud
35cff5e7adSreinoud #if defined(_KERNEL_OPT)
36cff5e7adSreinoud #include "opt_compat_netbsd.h"
37cff5e7adSreinoud #endif
38cff5e7adSreinoud
39cff5e7adSreinoud #include <sys/param.h>
40cff5e7adSreinoud #include <sys/systm.h>
41cff5e7adSreinoud #include <sys/sysctl.h>
42cff5e7adSreinoud #include <sys/namei.h>
43cff5e7adSreinoud #include <sys/proc.h>
44cff5e7adSreinoud #include <sys/kernel.h>
45cff5e7adSreinoud #include <sys/vnode.h>
46717e1785Sdholland #include <miscfs/genfs/genfs.h>
47cff5e7adSreinoud #include <miscfs/specfs/specdev.h>
48cff5e7adSreinoud #include <sys/mount.h>
49cff5e7adSreinoud #include <sys/buf.h>
50cff5e7adSreinoud #include <sys/file.h>
51cff5e7adSreinoud #include <sys/device.h>
52cff5e7adSreinoud #include <sys/disklabel.h>
53cff5e7adSreinoud #include <sys/ioctl.h>
54cff5e7adSreinoud #include <sys/malloc.h>
55cff5e7adSreinoud #include <sys/dirent.h>
56cff5e7adSreinoud #include <sys/stat.h>
57cff5e7adSreinoud #include <sys/conf.h>
58fc6d984bSchristos #include <sys/kauth.h>
59a1221b6dSrumble #include <sys/module.h>
60cff5e7adSreinoud
61cff5e7adSreinoud #include <fs/udf/ecma167-udf.h>
62cff5e7adSreinoud #include <fs/udf/udf_mount.h>
631bd1646aSreinoud #include <sys/dirhash.h>
64cff5e7adSreinoud
65cff5e7adSreinoud #include "udf.h"
66cff5e7adSreinoud #include "udf_subr.h"
67cff5e7adSreinoud #include "udf_bswap.h"
68cff5e7adSreinoud
69a1221b6dSrumble MODULE(MODULE_CLASS_VFS, udf, NULL);
70cff5e7adSreinoud
71e979c658Sreinoud #define VTOI(vnode) ((struct udf_node *) vnode->v_data)
72e979c658Sreinoud
73cff5e7adSreinoud /* verbose levels of the udf filingsystem */
74cff5e7adSreinoud int udf_verbose = UDF_DEBUGGING;
75cff5e7adSreinoud
76cff5e7adSreinoud /* malloc regions */
77835b0326Spooka MALLOC_JUSTDEFINE(M_UDFMNT, "UDF mount", "UDF mount structures");
78835b0326Spooka MALLOC_JUSTDEFINE(M_UDFVOLD, "UDF volspace", "UDF volume space descriptors");
79835b0326Spooka MALLOC_JUSTDEFINE(M_UDFTEMP, "UDF temp", "UDF scrap space");
80cff5e7adSreinoud struct pool udf_node_pool;
81cff5e7adSreinoud
82cff5e7adSreinoud /* internal functions */
83cff5e7adSreinoud static int udf_mountfs(struct vnode *, struct mount *, struct lwp *, struct udf_args *);
84cff5e7adSreinoud
85cff5e7adSreinoud
86cff5e7adSreinoud /* --------------------------------------------------------------------- */
87cff5e7adSreinoud
88cff5e7adSreinoud /* predefine vnode-op list descriptor */
89cff5e7adSreinoud extern const struct vnodeopv_desc udf_vnodeop_opv_desc;
90cff5e7adSreinoud
91cff5e7adSreinoud const struct vnodeopv_desc * const udf_vnodeopv_descs[] = {
92cff5e7adSreinoud &udf_vnodeop_opv_desc,
93cff5e7adSreinoud NULL,
94cff5e7adSreinoud };
95cff5e7adSreinoud
96cff5e7adSreinoud
97cff5e7adSreinoud /* vfsops descriptor linked in as anchor point for the filingsystem */
98cff5e7adSreinoud struct vfsops udf_vfsops = {
996d285189Shannken .vfs_name = MOUNT_UDF,
1006d285189Shannken .vfs_min_mount_data = sizeof (struct udf_args),
1016d285189Shannken .vfs_mount = udf_mount,
1026d285189Shannken .vfs_start = udf_start,
1036d285189Shannken .vfs_unmount = udf_unmount,
1046d285189Shannken .vfs_root = udf_root,
1056d285189Shannken .vfs_quotactl = (void *)eopnotsupp,
1066d285189Shannken .vfs_statvfs = udf_statvfs,
1076d285189Shannken .vfs_sync = udf_sync,
1086d285189Shannken .vfs_vget = udf_vget,
109a494ee15Shannken .vfs_loadvnode = udf_loadvnode,
110a494ee15Shannken .vfs_newvnode = udf_newvnode,
1116d285189Shannken .vfs_fhtovp = udf_fhtovp,
1126d285189Shannken .vfs_vptofh = udf_vptofh,
1136d285189Shannken .vfs_init = udf_init,
1146d285189Shannken .vfs_reinit = udf_reinit,
1156d285189Shannken .vfs_done = udf_done,
1166d285189Shannken .vfs_mountroot = udf_mountroot,
1176d285189Shannken .vfs_snapshot = udf_snapshot,
1186d285189Shannken .vfs_extattrctl = vfs_stdextattrctl,
119326db3aaShannken .vfs_suspendctl = genfs_suspendctl,
1206d285189Shannken .vfs_renamelock_enter = genfs_renamelock_enter,
1216d285189Shannken .vfs_renamelock_exit = genfs_renamelock_exit,
1226d285189Shannken .vfs_fsync = (void *)eopnotsupp,
1236d285189Shannken .vfs_opv_descs = udf_vnodeopv_descs
124cff5e7adSreinoud };
125cff5e7adSreinoud
126cff5e7adSreinoud /* --------------------------------------------------------------------- */
127cff5e7adSreinoud
128cff5e7adSreinoud /* file system starts here */
129cff5e7adSreinoud void
udf_init(void)130cff5e7adSreinoud udf_init(void)
131cff5e7adSreinoud {
132cff5e7adSreinoud size_t size;
133ff7ad972Sreinoud
134ff7ad972Sreinoud /* setup memory types */
135cff5e7adSreinoud malloc_type_attach(M_UDFMNT);
136cff5e7adSreinoud malloc_type_attach(M_UDFVOLD);
137cff5e7adSreinoud malloc_type_attach(M_UDFTEMP);
138cff5e7adSreinoud
1392ac28d55Sreinoud /* init node pools */
140cff5e7adSreinoud size = sizeof(struct udf_node);
1412ac28d55Sreinoud pool_init(&udf_node_pool, size, 0, 0, 0,
1422ac28d55Sreinoud "udf_node_pool", NULL, IPL_NONE);
143cff5e7adSreinoud }
144cff5e7adSreinoud
145cff5e7adSreinoud
146cff5e7adSreinoud void
udf_reinit(void)147cff5e7adSreinoud udf_reinit(void)
148cff5e7adSreinoud {
1492ac28d55Sreinoud /* nothing to do */
150cff5e7adSreinoud }
151cff5e7adSreinoud
152cff5e7adSreinoud
153cff5e7adSreinoud void
udf_done(void)154cff5e7adSreinoud udf_done(void)
155cff5e7adSreinoud {
1562ac28d55Sreinoud /* remove pools */
157cff5e7adSreinoud pool_destroy(&udf_node_pool);
158cff5e7adSreinoud
159cff5e7adSreinoud malloc_type_detach(M_UDFMNT);
160cff5e7adSreinoud malloc_type_detach(M_UDFVOLD);
161cff5e7adSreinoud malloc_type_detach(M_UDFTEMP);
162cff5e7adSreinoud }
163cff5e7adSreinoud
16428f5ebd8Srumble /*
16528f5ebd8Srumble * If running a DEBUG kernel, provide an easy way to set the debug flags when
16628f5ebd8Srumble * running into a problem.
16728f5ebd8Srumble */
16828f5ebd8Srumble #define UDF_VERBOSE_SYSCTLOPT 1
169e979c658Sreinoud
1700376c5faSreinoud /*
1710376c5faSreinoud * XXX the "24" below could be dynamic, thereby eliminating one
1720376c5faSreinoud * more instance of the "number to vfs" mapping problem, but
1730376c5faSreinoud * "24" is the order as taken from sys/mount.h
1740376c5faSreinoud */
1759120d451Spgoyette SYSCTL_SETUP(udf_sysctl_setup, "udf sysctl")
1769120d451Spgoyette {
1779120d451Spgoyette const struct sysctlnode *node;
1789120d451Spgoyette
1799120d451Spgoyette sysctl_createv(clog, 0, NULL, &node,
1809120d451Spgoyette CTLFLAG_PERMANENT,
1819120d451Spgoyette CTLTYPE_NODE, "udf",
1829120d451Spgoyette SYSCTL_DESCR("OSTA Universal File System"),
1839120d451Spgoyette NULL, 0, NULL, 0,
1849120d451Spgoyette CTL_VFS, 24, CTL_EOL);
18529d402aeSreinoud #ifdef UDF_DEBUG
1869120d451Spgoyette sysctl_createv(clog, 0, NULL, &node,
1879120d451Spgoyette CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
1889120d451Spgoyette CTLTYPE_INT, "verbose",
1899120d451Spgoyette SYSCTL_DESCR("Bitmask for filesystem debugging"),
1909120d451Spgoyette NULL, 0, &udf_verbose, 0,
1919120d451Spgoyette CTL_VFS, 24, UDF_VERBOSE_SYSCTLOPT, CTL_EOL);
1929120d451Spgoyette #endif
1939120d451Spgoyette }
1949120d451Spgoyette
195e979c658Sreinoud static int
udf_modcmd(modcmd_t cmd,void * arg)196e979c658Sreinoud udf_modcmd(modcmd_t cmd, void *arg)
197e979c658Sreinoud {
19828f5ebd8Srumble int error;
199e979c658Sreinoud
200e979c658Sreinoud switch (cmd) {
201e979c658Sreinoud case MODULE_CMD_INIT:
20228f5ebd8Srumble error = vfs_attach(&udf_vfsops);
20328f5ebd8Srumble if (error != 0)
20428f5ebd8Srumble break;
20528f5ebd8Srumble break;
206e979c658Sreinoud case MODULE_CMD_FINI:
20728f5ebd8Srumble error = vfs_detach(&udf_vfsops);
20828f5ebd8Srumble if (error != 0)
20928f5ebd8Srumble break;
21028f5ebd8Srumble break;
211e979c658Sreinoud default:
21228f5ebd8Srumble error = ENOTTY;
21328f5ebd8Srumble break;
214e979c658Sreinoud }
21528f5ebd8Srumble
21628f5ebd8Srumble return (error);
217e979c658Sreinoud }
218e979c658Sreinoud
219cff5e7adSreinoud /* --------------------------------------------------------------------- */
220cff5e7adSreinoud
221cff5e7adSreinoud int
udf_mountroot(void)222cff5e7adSreinoud udf_mountroot(void)
223cff5e7adSreinoud {
224cff5e7adSreinoud return EOPNOTSUPP;
225cff5e7adSreinoud }
226cff5e7adSreinoud
227cff5e7adSreinoud /* --------------------------------------------------------------------- */
228cff5e7adSreinoud
229cff5e7adSreinoud #define MPFREE(a, lst) \
230cff5e7adSreinoud if ((a)) free((a), lst);
231cff5e7adSreinoud static void
free_udf_mountinfo(struct mount * mp)232cff5e7adSreinoud free_udf_mountinfo(struct mount *mp)
233cff5e7adSreinoud {
234cff5e7adSreinoud struct udf_mount *ump;
235cff5e7adSreinoud int i;
236cff5e7adSreinoud
23721d69215Sreinoud if (!mp)
23821d69215Sreinoud return;
23921d69215Sreinoud
240cff5e7adSreinoud ump = VFSTOUDF(mp);
241cff5e7adSreinoud if (ump) {
242445a215fSreinoud /* clear our data */
243cff5e7adSreinoud for (i = 0; i < UDF_ANCHORS; i++)
244cff5e7adSreinoud MPFREE(ump->anchors[i], M_UDFVOLD);
245cff5e7adSreinoud MPFREE(ump->primary_vol, M_UDFVOLD);
246cff5e7adSreinoud MPFREE(ump->logical_vol, M_UDFVOLD);
247cff5e7adSreinoud MPFREE(ump->unallocated, M_UDFVOLD);
248cff5e7adSreinoud MPFREE(ump->implementation, M_UDFVOLD);
249cff5e7adSreinoud MPFREE(ump->logvol_integrity, M_UDFVOLD);
250e979c658Sreinoud for (i = 0; i < UDF_PARTITIONS; i++) {
251cff5e7adSreinoud MPFREE(ump->partitions[i], M_UDFVOLD);
252e979c658Sreinoud MPFREE(ump->part_unalloc_dscr[i], M_UDFVOLD);
253e979c658Sreinoud MPFREE(ump->part_freed_dscr[i], M_UDFVOLD);
254e979c658Sreinoud }
2555c3627bcSreinoud MPFREE(ump->metadata_unalloc_dscr, M_UDFVOLD);
2565c3627bcSreinoud
257cff5e7adSreinoud MPFREE(ump->fileset_desc, M_UDFVOLD);
258cff5e7adSreinoud MPFREE(ump->sparing_table, M_UDFVOLD);
259e979c658Sreinoud
260e979c658Sreinoud MPFREE(ump->la_node_ad_cpy, M_UDFMNT);
261e979c658Sreinoud MPFREE(ump->la_pmapping, M_TEMP);
262e979c658Sreinoud MPFREE(ump->la_lmapping, M_TEMP);
263cff5e7adSreinoud
26417f11577Sreinoud mutex_destroy(&ump->logvol_mutex);
265e979c658Sreinoud mutex_destroy(&ump->allocate_mutex);
2664207afb7Shannken mutex_destroy(&ump->sync_lock);
26717f11577Sreinoud
268e979c658Sreinoud MPFREE(ump->vat_table, M_UDFVOLD);
269e979c658Sreinoud
270cff5e7adSreinoud free(ump, M_UDFMNT);
2710c1391f0Schristos }
272cff5e7adSreinoud }
273cff5e7adSreinoud #undef MPFREE
274cff5e7adSreinoud
275cff5e7adSreinoud /* --------------------------------------------------------------------- */
276cff5e7adSreinoud
277e979c658Sreinoud /* if the system nodes exist, release them */
278e979c658Sreinoud static void
udf_release_system_nodes(struct mount * mp)279e979c658Sreinoud udf_release_system_nodes(struct mount *mp)
280e979c658Sreinoud {
281e979c658Sreinoud struct udf_mount *ump = VFSTOUDF(mp);
282e979c658Sreinoud
283e979c658Sreinoud /* if we haven't even got an ump, dont bother */
284e979c658Sreinoud if (!ump)
285e979c658Sreinoud return;
286e979c658Sreinoud
287e979c658Sreinoud /* VAT partition support */
288e979c658Sreinoud if (ump->vat_node)
289e979c658Sreinoud vrele(ump->vat_node->vnode);
290e979c658Sreinoud
291e979c658Sreinoud /* Metadata partition support */
292e979c658Sreinoud if (ump->metadata_node)
293e979c658Sreinoud vrele(ump->metadata_node->vnode);
294e979c658Sreinoud if (ump->metadatamirror_node)
295e979c658Sreinoud vrele(ump->metadatamirror_node->vnode);
296e979c658Sreinoud if (ump->metadatabitmap_node)
297e979c658Sreinoud vrele(ump->metadatabitmap_node->vnode);
298e979c658Sreinoud }
299e979c658Sreinoud
300e979c658Sreinoud
301cff5e7adSreinoud int
udf_mount(struct mount * mp,const char * path,void * data,size_t * data_len)302cff5e7adSreinoud udf_mount(struct mount *mp, const char *path,
30361e8303eSpooka void *data, size_t *data_len)
304cff5e7adSreinoud {
30561e8303eSpooka struct lwp *l = curlwp;
3062721ab6cSdsl struct udf_args *args = data;
307cff5e7adSreinoud struct udf_mount *ump;
308cff5e7adSreinoud struct vnode *devvp;
309cff5e7adSreinoud int openflags, accessmode, error;
310cff5e7adSreinoud
311cff5e7adSreinoud DPRINTF(CALL, ("udf_mount called\n"));
312cff5e7adSreinoud
31323f76b6dSmaxv if (args == NULL)
31423f76b6dSmaxv return EINVAL;
3152721ab6cSdsl if (*data_len < sizeof *args)
3162721ab6cSdsl return EINVAL;
3172721ab6cSdsl
318cff5e7adSreinoud if (mp->mnt_flag & MNT_GETARGS) {
319cff5e7adSreinoud /* request for the mount arguments */
320cff5e7adSreinoud ump = VFSTOUDF(mp);
321cff5e7adSreinoud if (ump == NULL)
322cff5e7adSreinoud return EINVAL;
3232721ab6cSdsl *args = ump->mount_args;
3242721ab6cSdsl *data_len = sizeof *args;
3252721ab6cSdsl return 0;
3260c1391f0Schristos }
327cff5e7adSreinoud
328cff5e7adSreinoud /* handle request for updating mount parameters */
329cff5e7adSreinoud /* TODO can't update my mountpoint yet */
330cff5e7adSreinoud if (mp->mnt_flag & MNT_UPDATE) {
331cff5e7adSreinoud return EOPNOTSUPP;
3320c1391f0Schristos }
333cff5e7adSreinoud
33421d69215Sreinoud /* OK, so we are asked to mount the device */
335cff5e7adSreinoud
336cff5e7adSreinoud /* check/translate struct version */
337cff5e7adSreinoud /* TODO sanity checking other mount arguments */
3382721ab6cSdsl if (args->version != 1) {
339cff5e7adSreinoud printf("mount_udf: unrecognized argument structure version\n");
340cff5e7adSreinoud return EINVAL;
3410c1391f0Schristos }
342cff5e7adSreinoud
343cff5e7adSreinoud /* lookup name to get its vnode */
344effcf1afSdholland error = namei_simple_user(args->fspec,
345effcf1afSdholland NSM_FOLLOW_NOEMULROOT, &devvp);
346cff5e7adSreinoud if (error)
347cff5e7adSreinoud return error;
3486014bf8aSreinoud
349cff5e7adSreinoud #ifdef DEBUG
350cff5e7adSreinoud if (udf_verbose & UDF_DEBUG_VOLUMES)
351cff5e7adSreinoud vprint("UDF mount, trying to mount \n", devvp);
352cff5e7adSreinoud #endif
353cff5e7adSreinoud
354cff5e7adSreinoud /* check if its a block device specified */
355cff5e7adSreinoud if (devvp->v_type != VBLK) {
356cff5e7adSreinoud vrele(devvp);
357cff5e7adSreinoud return ENOTBLK;
358cff5e7adSreinoud }
359cff5e7adSreinoud if (bdevsw_lookup(devvp->v_rdev) == NULL) {
360cff5e7adSreinoud vrele(devvp);
361cff5e7adSreinoud return ENXIO;
362cff5e7adSreinoud }
363cff5e7adSreinoud
364cff5e7adSreinoud /*
365cff5e7adSreinoud * If mount by non-root, then verify that user has necessary
366cff5e7adSreinoud * permissions on the device.
367cff5e7adSreinoud */
368cff5e7adSreinoud accessmode = VREAD;
369cff5e7adSreinoud if ((mp->mnt_flag & MNT_RDONLY) == 0)
370cff5e7adSreinoud accessmode |= VWRITE;
3716014bf8aSreinoud vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY);
3720c9d8d15Selad error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_MOUNT,
3730c9d8d15Selad KAUTH_REQ_SYSTEM_MOUNT_DEVICE, mp, devvp, KAUTH_ARG(accessmode));
3741423e65bShannken VOP_UNLOCK(devvp);
375cff5e7adSreinoud if (error) {
3766014bf8aSreinoud vrele(devvp);
3776014bf8aSreinoud return error;
378cff5e7adSreinoud }
379cff5e7adSreinoud
380cff5e7adSreinoud /*
381cff5e7adSreinoud * Open device and try to mount it!
382cff5e7adSreinoud */
383cff5e7adSreinoud if (mp->mnt_flag & MNT_RDONLY) {
384cff5e7adSreinoud openflags = FREAD;
385cff5e7adSreinoud } else {
386cff5e7adSreinoud openflags = FREAD | FWRITE;
3870c1391f0Schristos }
388d84a65ddShannken vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY);
38961e8303eSpooka error = VOP_OPEN(devvp, openflags, FSCRED);
390d84a65ddShannken VOP_UNLOCK(devvp);
391cff5e7adSreinoud if (error == 0) {
392cff5e7adSreinoud /* opened ok, try mounting */
3932721ab6cSdsl error = udf_mountfs(devvp, mp, l, args);
394cff5e7adSreinoud if (error) {
395e979c658Sreinoud udf_release_system_nodes(mp);
396e979c658Sreinoud /* cleanup */
397e979c658Sreinoud udf_discstrat_finish(VFSTOUDF(mp));
398cff5e7adSreinoud free_udf_mountinfo(mp);
3996014bf8aSreinoud vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY);
40061e8303eSpooka (void) VOP_CLOSE(devvp, openflags, NOCRED);
4011423e65bShannken VOP_UNLOCK(devvp);
4020c1391f0Schristos }
4030c1391f0Schristos }
404cff5e7adSreinoud if (error) {
405cff5e7adSreinoud /* devvp is still locked */
4066014bf8aSreinoud vrele(devvp);
407cff5e7adSreinoud return error;
4080c1391f0Schristos }
409cff5e7adSreinoud
410cff5e7adSreinoud /* register our mountpoint being on this device */
4113881f4f3Shannken spec_node_setmountedfs(devvp, mp);
412cff5e7adSreinoud
413cff5e7adSreinoud /* successfully mounted */
414b5860281Sandvar DPRINTF(VOLUMES, ("udf_mount() successful\n"));
415cff5e7adSreinoud
416e979c658Sreinoud error = set_statvfs_info(path, UIO_USERSPACE, args->fspec, UIO_USERSPACE,
417e24b0872Spooka mp->mnt_op->vfs_name, mp, l);
418e979c658Sreinoud if (error)
419e979c658Sreinoud return error;
420e979c658Sreinoud
421e979c658Sreinoud /* If we're not opened read-only, open its logical volume */
422e979c658Sreinoud if ((mp->mnt_flag & MNT_RDONLY) == 0) {
423e979c658Sreinoud if ((error = udf_open_logvol(VFSTOUDF(mp))) != 0) {
424e979c658Sreinoud printf( "mount_udf: can't open logical volume for "
425e979c658Sreinoud "writing, downgrading access to read-only\n");
426e979c658Sreinoud mp->mnt_flag |= MNT_RDONLY;
427e979c658Sreinoud /* FIXME we can't return error now on open failure */
428e979c658Sreinoud return 0;
429e979c658Sreinoud }
430e979c658Sreinoud }
431e979c658Sreinoud
432e979c658Sreinoud return 0;
433cff5e7adSreinoud }
434cff5e7adSreinoud
435cff5e7adSreinoud /* --------------------------------------------------------------------- */
436cff5e7adSreinoud
437cff5e7adSreinoud #ifdef DEBUG
438f731f08dShannken static bool
udf_sanity_selector(void * cl,struct vnode * vp)439f731f08dShannken udf_sanity_selector(void *cl, struct vnode *vp)
440cff5e7adSreinoud {
441cff5e7adSreinoud
44230509f80Sriastradh KASSERT(mutex_owned(vp->v_interlock));
44330509f80Sriastradh
444cff5e7adSreinoud vprint("", vp);
445cff5e7adSreinoud if (VOP_ISLOCKED(vp) == LK_EXCLUSIVE) {
446cff5e7adSreinoud printf(" is locked\n");
4470c1391f0Schristos }
44823bf8800Sad if (vrefcnt(vp) > 1)
44923bf8800Sad printf(" more than one usecount %d\n", vrefcnt(vp));
450f731f08dShannken return false;
4510c1391f0Schristos }
452f731f08dShannken
453f731f08dShannken static void
udf_unmount_sanity_check(struct mount * mp)454f731f08dShannken udf_unmount_sanity_check(struct mount *mp)
455f731f08dShannken {
456f731f08dShannken struct vnode_iterator *marker;
457f731f08dShannken
458f731f08dShannken printf("On unmount, i found the following nodes:\n");
459f731f08dShannken vfs_vnode_iterator_init(mp, &marker);
460f731f08dShannken vfs_vnode_iterator_next(marker, udf_sanity_selector, NULL);
461f731f08dShannken vfs_vnode_iterator_destroy(marker);
462cff5e7adSreinoud }
463cff5e7adSreinoud #endif
464cff5e7adSreinoud
465cff5e7adSreinoud
466cff5e7adSreinoud int
udf_unmount(struct mount * mp,int mntflags)46761e8303eSpooka udf_unmount(struct mount *mp, int mntflags)
468cff5e7adSreinoud {
469cff5e7adSreinoud struct udf_mount *ump;
470cff5e7adSreinoud int error, flags, closeflags;
471cff5e7adSreinoud
472cff5e7adSreinoud DPRINTF(CALL, ("udf_umount called\n"));
473cff5e7adSreinoud
474cff5e7adSreinoud ump = VFSTOUDF(mp);
475cff5e7adSreinoud if (!ump)
476cff5e7adSreinoud panic("UDF unmount: empty ump\n");
477cff5e7adSreinoud
478e54e795bSreinoud flags = (mntflags & MNT_FORCE) ? FORCECLOSE : 0;
479cff5e7adSreinoud /* TODO remove these paranoid functions */
480cff5e7adSreinoud #ifdef DEBUG
481cff5e7adSreinoud if (udf_verbose & UDF_DEBUG_LOCKING)
482cff5e7adSreinoud udf_unmount_sanity_check(mp);
483cff5e7adSreinoud #endif
484cff5e7adSreinoud
485e54e795bSreinoud /*
4867dad9f73Sad * By specifying SKIPSYSTEM we can skip vnodes marked with VV_SYSTEM.
487e54e795bSreinoud * This hardly documented feature allows us to exempt certain files
488e54e795bSreinoud * from being flushed.
489e54e795bSreinoud */
4907dad9f73Sad if ((error = vflush(mp, NULLVP, flags | SKIPSYSTEM)) != 0)
491cff5e7adSreinoud return error;
492cff5e7adSreinoud
493e979c658Sreinoud /* update nodes and wait for completion of writeout of system nodes */
494e979c658Sreinoud udf_sync(mp, FSYNC_WAIT, NOCRED);
495e979c658Sreinoud
496cff5e7adSreinoud #ifdef DEBUG
497cff5e7adSreinoud if (udf_verbose & UDF_DEBUG_LOCKING)
498cff5e7adSreinoud udf_unmount_sanity_check(mp);
499cff5e7adSreinoud #endif
500cff5e7adSreinoud
501e979c658Sreinoud /* flush again, to check if we are still busy for something else */
502e979c658Sreinoud if ((error = vflush(ump->vfs_mountp, NULLVP, flags | SKIPSYSTEM)) != 0)
503e979c658Sreinoud return error;
504cff5e7adSreinoud
505e979c658Sreinoud DPRINTF(VOLUMES, ("flush OK on unmount\n"));
506e979c658Sreinoud
507e979c658Sreinoud /* close logical volume and close session if requested */
508e979c658Sreinoud if ((error = udf_close_logvol(ump, mntflags)) != 0)
509e979c658Sreinoud return error;
510e979c658Sreinoud
511e979c658Sreinoud #ifdef DEBUG
512e979c658Sreinoud DPRINTF(VOLUMES, ("FINAL sanity check\n"));
513e979c658Sreinoud if (udf_verbose & UDF_DEBUG_LOCKING)
514e979c658Sreinoud udf_unmount_sanity_check(mp);
515e979c658Sreinoud #endif
516e979c658Sreinoud
517e979c658Sreinoud /* NOTE release system nodes should NOT write anything */
518e979c658Sreinoud udf_release_system_nodes(mp);
519e979c658Sreinoud
5205985f105Shannken /* This flush should NOT write anything nor allow any node to remain */
5215985f105Shannken if ((error = vflush(ump->vfs_mountp, NULLVP, 0)) != 0)
5225985f105Shannken panic("Failure to flush UDF system vnodes\n");
5235985f105Shannken
524e979c658Sreinoud /* finalise disc strategy */
525e979c658Sreinoud udf_discstrat_finish(ump);
526e979c658Sreinoud
527e979c658Sreinoud /* synchronise device caches */
528e979c658Sreinoud (void) udf_synchronise_caches(ump);
529cff5e7adSreinoud
530cff5e7adSreinoud /* close device */
531cff5e7adSreinoud DPRINTF(VOLUMES, ("closing device\n"));
532cff5e7adSreinoud if (mp->mnt_flag & MNT_RDONLY) {
533cff5e7adSreinoud closeflags = FREAD;
534cff5e7adSreinoud } else {
535cff5e7adSreinoud closeflags = FREAD | FWRITE;
5360c1391f0Schristos }
537cff5e7adSreinoud
538cff5e7adSreinoud /* devvp is still locked by us */
539cff5e7adSreinoud vn_lock(ump->devvp, LK_EXCLUSIVE | LK_RETRY);
54061e8303eSpooka error = VOP_CLOSE(ump->devvp, closeflags, NOCRED);
541cff5e7adSreinoud if (error)
542cff5e7adSreinoud printf("Error during closure of device! error %d, "
543cff5e7adSreinoud "device might stay locked\n", error);
544cff5e7adSreinoud DPRINTF(VOLUMES, ("device close ok\n"));
545cff5e7adSreinoud
546cff5e7adSreinoud /* clear our mount reference and release device node */
5473881f4f3Shannken spec_node_setmountedfs(ump->devvp, NULL);
548cff5e7adSreinoud vput(ump->devvp);
549cff5e7adSreinoud
550e979c658Sreinoud /* free our ump */
551cff5e7adSreinoud free_udf_mountinfo(mp);
552cff5e7adSreinoud
553e979c658Sreinoud /* free ump struct references */
55421d69215Sreinoud mp->mnt_data = NULL;
55521d69215Sreinoud mp->mnt_flag &= ~MNT_LOCAL;
55621d69215Sreinoud
557cff5e7adSreinoud DPRINTF(VOLUMES, ("Fin unmount\n"));
558cff5e7adSreinoud return error;
559cff5e7adSreinoud }
560cff5e7adSreinoud
561cff5e7adSreinoud /* --------------------------------------------------------------------- */
562cff5e7adSreinoud
563cff5e7adSreinoud /*
564cff5e7adSreinoud * Helper function of udf_mount() that actually mounts the disc.
565cff5e7adSreinoud */
566cff5e7adSreinoud
567cff5e7adSreinoud static int
udf_mountfs(struct vnode * devvp,struct mount * mp,struct lwp * l,struct udf_args * args)568cff5e7adSreinoud udf_mountfs(struct vnode *devvp, struct mount *mp,
569cff5e7adSreinoud struct lwp *l, struct udf_args *args)
570cff5e7adSreinoud {
571cff5e7adSreinoud struct udf_mount *ump;
572cff5e7adSreinoud uint32_t sector_size, lb_size, bshift;
573e979c658Sreinoud uint32_t logvol_integrity;
574c093c252Sreinoud int num_anchors, error;
575cff5e7adSreinoud
576cff5e7adSreinoud /* flush out any old buffers remaining from a previous use. */
577*d82e4b43Shannken vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY);
578*d82e4b43Shannken error = vinvalbuf(devvp, V_SAVE, l->l_cred, l, 0, 0);
579*d82e4b43Shannken VOP_UNLOCK(devvp);
580*d82e4b43Shannken if (error)
581cff5e7adSreinoud return error;
582cff5e7adSreinoud
583e979c658Sreinoud /* setup basic mount information */
584e979c658Sreinoud mp->mnt_data = NULL;
585e979c658Sreinoud mp->mnt_stat.f_fsidx.__fsid_val[0] = (uint32_t) devvp->v_rdev;
586e979c658Sreinoud mp->mnt_stat.f_fsidx.__fsid_val[1] = makefstype(MOUNT_UDF);
587e979c658Sreinoud mp->mnt_stat.f_fsid = mp->mnt_stat.f_fsidx.__fsid_val[0];
5883a8df9f0Schristos mp->mnt_stat.f_namemax = UDF_MAXNAMLEN;
589e979c658Sreinoud mp->mnt_flag |= MNT_LOCAL;
590c093c252Sreinoud // mp->mnt_iflag |= IMNT_MPSAFE;
591e979c658Sreinoud
5928ce1f4ffSmsaitoh /* allocate udf part of mount structure; malloc always succeeds */
5937dad9f73Sad ump = malloc(sizeof(struct udf_mount), M_UDFMNT, M_WAITOK | M_ZERO);
594cff5e7adSreinoud
595cff5e7adSreinoud /* init locks */
596e979c658Sreinoud mutex_init(&ump->logvol_mutex, MUTEX_DEFAULT, IPL_NONE);
597e979c658Sreinoud mutex_init(&ump->allocate_mutex, MUTEX_DEFAULT, IPL_NONE);
5984207afb7Shannken mutex_init(&ump->sync_lock, MUTEX_DEFAULT, IPL_NONE);
599cff5e7adSreinoud
600c093c252Sreinoud /* init rbtree for nodes, ordered by their icb address (long_ad) */
601c093c252Sreinoud udf_init_nodes_tree(ump);
602cff5e7adSreinoud
603cff5e7adSreinoud /* set up linkage */
604cff5e7adSreinoud mp->mnt_data = ump;
605cff5e7adSreinoud ump->vfs_mountp = mp;
606cff5e7adSreinoud
607cff5e7adSreinoud /* set up arguments and device */
608cff5e7adSreinoud ump->mount_args = *args;
609cff5e7adSreinoud ump->devvp = devvp;
6109e6b6751Sreinoud if ((error = udf_update_discinfo(ump))) {
611cff5e7adSreinoud printf("UDF mount: error inspecting fs node\n");
612cff5e7adSreinoud return error;
6130c1391f0Schristos }
614cff5e7adSreinoud
615cff5e7adSreinoud /* inspect sector size */
616cff5e7adSreinoud sector_size = ump->discinfo.sector_size;
617cff5e7adSreinoud bshift = 1;
618cff5e7adSreinoud while ((1 << bshift) < sector_size)
619cff5e7adSreinoud bshift++;
620cff5e7adSreinoud if ((1 << bshift) != sector_size) {
621cff5e7adSreinoud printf("UDF mount: "
622cff5e7adSreinoud "hit NetBSD implementation fence on sector size\n");
623cff5e7adSreinoud return EIO;
6240c1391f0Schristos }
625cff5e7adSreinoud
6263efc85e7Sreinoud /* temporary check to overcome sectorsize >= 8192 bytes panic */
6273efc85e7Sreinoud if (sector_size >= 8192) {
6283efc85e7Sreinoud printf("UDF mount: "
6293efc85e7Sreinoud "hit implementation limit, sectorsize to big\n");
6303efc85e7Sreinoud return EIO;
6313efc85e7Sreinoud }
6323efc85e7Sreinoud
633e979c658Sreinoud /*
634e979c658Sreinoud * Inspect if we're asked to mount read-write on a non recordable or
635e979c658Sreinoud * closed sequential disc.
636e979c658Sreinoud */
637e979c658Sreinoud if ((mp->mnt_flag & MNT_RDONLY) == 0) {
638e979c658Sreinoud if ((ump->discinfo.mmc_cur & MMC_CAP_RECORDABLE) == 0) {
639e979c658Sreinoud printf("UDF mount: disc is not recordable\n");
640e979c658Sreinoud return EROFS;
641e979c658Sreinoud }
6423e0547f2Sreinoud if (ump->discinfo.mmc_cur & MMC_CAP_SEQUENTIAL) {
6433e0547f2Sreinoud if (ump->discinfo.disc_state == MMC_STATE_FULL) {
6443e0547f2Sreinoud printf("UDF mount: disc is not appendable\n");
6453e0547f2Sreinoud return EROFS;
6463e0547f2Sreinoud }
6473e0547f2Sreinoud
648e979c658Sreinoud /*
6493e0547f2Sreinoud * TODO if the last session is closed check if there
6503e0547f2Sreinoud * is enough space to open/close new session
651e979c658Sreinoud */
652e979c658Sreinoud }
653a41f6947Sandvar /* double check if we're not mounting a previous session RW */
6542ac9ba8cSreinoud if (args->sessionnr != 0) {
6552ac9ba8cSreinoud printf("UDF mount: updating a previous session "
6562ac9ba8cSreinoud "not yet allowed\n");
6572ac9ba8cSreinoud return EROFS;
6582ac9ba8cSreinoud }
6593e0547f2Sreinoud }
660e979c658Sreinoud
661e979c658Sreinoud /* initialise bootstrap disc strategy */
662e979c658Sreinoud ump->strategy = &udf_strat_bootstrap;
663e979c658Sreinoud udf_discstrat_init(ump);
664e979c658Sreinoud
665cff5e7adSreinoud /* read all anchors to get volume descriptor sequence */
666e979c658Sreinoud num_anchors = udf_read_anchors(ump);
667cff5e7adSreinoud if (num_anchors == 0)
668e979c658Sreinoud return EINVAL;
669cff5e7adSreinoud
670cff5e7adSreinoud DPRINTF(VOLUMES, ("Read %d anchors on this disc, session %d\n",
671cff5e7adSreinoud num_anchors, args->sessionnr));
672cff5e7adSreinoud
673cff5e7adSreinoud /* read in volume descriptor sequence */
6749e6b6751Sreinoud if ((error = udf_read_vds_space(ump))) {
675cff5e7adSreinoud printf("UDF mount: error reading volume space\n");
6769e6b6751Sreinoud return error;
6779e6b6751Sreinoud }
678cff5e7adSreinoud
6792ac9ba8cSreinoud /* close down bootstrap disc strategy */
680e979c658Sreinoud udf_discstrat_finish(ump);
681e979c658Sreinoud
682cff5e7adSreinoud /* check consistency and completeness */
683e979c658Sreinoud if ((error = udf_process_vds(ump))) {
684e54e795bSreinoud printf( "UDF mount: disc not properly formatted"
685e54e795bSreinoud "(bad VDS)\n");
6869e6b6751Sreinoud return error;
6870c1391f0Schristos }
688cff5e7adSreinoud
689e979c658Sreinoud /* switch to new disc strategy */
690e979c658Sreinoud KASSERT(ump->strategy != &udf_strat_bootstrap);
691e979c658Sreinoud udf_discstrat_init(ump);
692cff5e7adSreinoud
693e979c658Sreinoud /* initialise late allocation administration space */
694e979c658Sreinoud ump->la_lmapping = malloc(sizeof(uint64_t) * UDF_MAX_MAPPINGS,
695e979c658Sreinoud M_TEMP, M_WAITOK);
696e979c658Sreinoud ump->la_pmapping = malloc(sizeof(uint64_t) * UDF_MAX_MAPPINGS,
697e979c658Sreinoud M_TEMP, M_WAITOK);
698e979c658Sreinoud
699e979c658Sreinoud /* setup node cleanup extents copy space */
700e979c658Sreinoud lb_size = udf_rw32(ump->logical_vol->lb_size);
701e979c658Sreinoud ump->la_node_ad_cpy = malloc(lb_size * UDF_MAX_ALLOC_EXTENTS,
702e979c658Sreinoud M_UDFMNT, M_WAITOK);
703e979c658Sreinoud memset(ump->la_node_ad_cpy, 0, lb_size * UDF_MAX_ALLOC_EXTENTS);
704e979c658Sreinoud
705e979c658Sreinoud /* setup rest of mount information */
706e979c658Sreinoud mp->mnt_data = ump;
707e979c658Sreinoud
7087991f5a7Sandvar /* bshift is always equal to disc sector size */
709e979c658Sreinoud mp->mnt_dev_bshift = bshift;
710e979c658Sreinoud mp->mnt_fs_bshift = bshift;
711e979c658Sreinoud
712e979c658Sreinoud /* note that the mp info needs to be initialised for reading! */
713cff5e7adSreinoud /* read vds support tables like VAT, sparable etc. */
714e979c658Sreinoud if ((error = udf_read_vds_tables(ump))) {
715e54e795bSreinoud printf( "UDF mount: error in format or damaged disc "
716e54e795bSreinoud "(VDS tables failing)\n");
7179e6b6751Sreinoud return error;
7180c1391f0Schristos }
7199e6b6751Sreinoud
720e979c658Sreinoud /* check if volume integrity is closed otherwise its dirty */
721e979c658Sreinoud logvol_integrity = udf_rw32(ump->logvol_integrity->integrity_type);
722e979c658Sreinoud if (logvol_integrity != UDF_INTEGRITY_CLOSED) {
723e979c658Sreinoud printf("UDF mount: file system is not clean; ");
724e979c658Sreinoud printf("please fsck(8)\n");
725e979c658Sreinoud return EPERM;
726e979c658Sreinoud }
727e979c658Sreinoud
728e979c658Sreinoud /* read root directory */
729e979c658Sreinoud if ((error = udf_read_rootdirs(ump))) {
730cff5e7adSreinoud printf( "UDF mount: "
731e54e795bSreinoud "disc not properly formatted or damaged disc "
732e54e795bSreinoud "(rootdirs failing)\n");
733cff5e7adSreinoud return error;
7349e6b6751Sreinoud }
735cff5e7adSreinoud
736cff5e7adSreinoud /* success! */
737cff5e7adSreinoud return 0;
738cff5e7adSreinoud }
739cff5e7adSreinoud
740cff5e7adSreinoud /* --------------------------------------------------------------------- */
741cff5e7adSreinoud
742cff5e7adSreinoud int
udf_start(struct mount * mp,int flags)74361e8303eSpooka udf_start(struct mount *mp, int flags)
744cff5e7adSreinoud {
745cff5e7adSreinoud /* do we have to do something here? */
746cff5e7adSreinoud return 0;
747cff5e7adSreinoud }
748cff5e7adSreinoud
749cff5e7adSreinoud /* --------------------------------------------------------------------- */
750cff5e7adSreinoud
751cff5e7adSreinoud int
udf_root(struct mount * mp,int lktype,struct vnode ** vpp)752c2e9cb94Sad udf_root(struct mount *mp, int lktype, struct vnode **vpp)
753cff5e7adSreinoud {
754cff5e7adSreinoud struct vnode *vp;
755cff5e7adSreinoud struct long_ad *dir_loc;
756cff5e7adSreinoud struct udf_mount *ump = VFSTOUDF(mp);
757cff5e7adSreinoud struct udf_node *root_dir;
758cff5e7adSreinoud int error;
759cff5e7adSreinoud
760cff5e7adSreinoud DPRINTF(CALL, ("udf_root called\n"));
761cff5e7adSreinoud
762cff5e7adSreinoud dir_loc = &ump->fileset_desc->rootdir_icb;
763c2e9cb94Sad error = udf_get_node(ump, dir_loc, &root_dir, lktype);
764cff5e7adSreinoud
765cff5e7adSreinoud if (error)
766cff5e7adSreinoud return error;
767cff5e7adSreinoud
768d384368fSchristos if (!root_dir)
769d384368fSchristos error = ENOENT;
770d384368fSchristos
771cff5e7adSreinoud vp = root_dir->vnode;
77262c3c2d1Sreinoud KASSERT(vp->v_vflag & VV_ROOT);
773cff5e7adSreinoud
774cff5e7adSreinoud *vpp = vp;
775cff5e7adSreinoud return 0;
776cff5e7adSreinoud }
777cff5e7adSreinoud
778cff5e7adSreinoud /* --------------------------------------------------------------------- */
779cff5e7adSreinoud
780cff5e7adSreinoud int
udf_statvfs(struct mount * mp,struct statvfs * sbp)78161e8303eSpooka udf_statvfs(struct mount *mp, struct statvfs *sbp)
782cff5e7adSreinoud {
783cff5e7adSreinoud struct udf_mount *ump = VFSTOUDF(mp);
784cff5e7adSreinoud struct logvol_int_desc *lvid;
785cff5e7adSreinoud struct udf_logvol_info *impl;
786cff5e7adSreinoud uint64_t freeblks, sizeblks;
787706de0e5Sreinoud int num_part;
788cff5e7adSreinoud
789cff5e7adSreinoud DPRINTF(CALL, ("udf_statvfs called\n"));
790cff5e7adSreinoud sbp->f_flag = mp->mnt_flag;
791cff5e7adSreinoud sbp->f_bsize = ump->discinfo.sector_size;
792cff5e7adSreinoud sbp->f_frsize = ump->discinfo.sector_size;
793cff5e7adSreinoud sbp->f_iosize = ump->discinfo.sector_size;
794cff5e7adSreinoud
795e979c658Sreinoud mutex_enter(&ump->allocate_mutex);
796e979c658Sreinoud
797706de0e5Sreinoud udf_calc_freespace(ump, &sizeblks, &freeblks);
798e979c658Sreinoud
799cff5e7adSreinoud sbp->f_blocks = sizeblks;
800cff5e7adSreinoud sbp->f_bfree = freeblks;
801e979c658Sreinoud sbp->f_files = 0;
802706de0e5Sreinoud
803706de0e5Sreinoud lvid = ump->logvol_integrity;
804706de0e5Sreinoud num_part = udf_rw32(lvid->num_part);
805706de0e5Sreinoud impl = (struct udf_logvol_info *) (lvid->tables + 2*num_part);
806e979c658Sreinoud if (impl) {
807cff5e7adSreinoud sbp->f_files = udf_rw32(impl->num_files);
808cff5e7adSreinoud sbp->f_files += udf_rw32(impl->num_directories);
809e979c658Sreinoud }
810cff5e7adSreinoud
811cff5e7adSreinoud /* XXX read only for now XXX */
812cff5e7adSreinoud sbp->f_bavail = 0;
813cff5e7adSreinoud sbp->f_bresvd = 0;
814cff5e7adSreinoud
815cff5e7adSreinoud /* tricky, next only aplies to ffs i think, so set to zero */
816cff5e7adSreinoud sbp->f_ffree = 0;
817cff5e7adSreinoud sbp->f_favail = 0;
818cff5e7adSreinoud sbp->f_fresvd = 0;
819e979c658Sreinoud
820e979c658Sreinoud mutex_exit(&ump->allocate_mutex);
821cff5e7adSreinoud
822cff5e7adSreinoud copy_statvfs_info(sbp, mp);
823cff5e7adSreinoud return 0;
824cff5e7adSreinoud }
825cff5e7adSreinoud
826cff5e7adSreinoud /* --------------------------------------------------------------------- */
827cff5e7adSreinoud
828e979c658Sreinoud /*
829e979c658Sreinoud * TODO what about writing out free space maps, lvid etc? only on `waitfor'
830e979c658Sreinoud * i.e. explicit syncing by the user?
831e979c658Sreinoud */
832e979c658Sreinoud
833a287d23dSreinoud static int
udf_sync_writeout_system_files(struct udf_mount * ump,int clearflags)834a287d23dSreinoud udf_sync_writeout_system_files(struct udf_mount *ump, int clearflags)
835a287d23dSreinoud {
836a287d23dSreinoud int error;
837a287d23dSreinoud
838a287d23dSreinoud /* XXX lock for VAT en bitmaps? */
839a287d23dSreinoud /* metadata nodes are written synchronous */
840a287d23dSreinoud DPRINTF(CALL, ("udf_sync: syncing metadata\n"));
841a287d23dSreinoud if (ump->lvclose & UDF_WRITE_VAT)
842a287d23dSreinoud udf_writeout_vat(ump);
843a287d23dSreinoud
844a287d23dSreinoud error = 0;
845a287d23dSreinoud if (ump->lvclose & UDF_WRITE_PART_BITMAPS) {
846a287d23dSreinoud /* writeout metadata spacetable if existing */
847a287d23dSreinoud error = udf_write_metadata_partition_spacetable(ump, MNT_WAIT);
848a287d23dSreinoud if (error)
849a287d23dSreinoud printf( "udf_writeout_system_files : "
850a287d23dSreinoud " writeout of metadata space bitmap failed\n");
851a287d23dSreinoud
852a287d23dSreinoud /* writeout partition spacetables */
853a287d23dSreinoud error = udf_write_physical_partition_spacetables(ump, MNT_WAIT);
854a287d23dSreinoud if (error)
855a287d23dSreinoud printf( "udf_writeout_system_files : "
856a287d23dSreinoud "writeout of space tables failed\n");
857a287d23dSreinoud if (!error && clearflags)
858a287d23dSreinoud ump->lvclose &= ~UDF_WRITE_PART_BITMAPS;
859a287d23dSreinoud }
860a287d23dSreinoud
861a287d23dSreinoud return error;
862a287d23dSreinoud }
863a287d23dSreinoud
864a287d23dSreinoud
865cff5e7adSreinoud int
udf_sync(struct mount * mp,int waitfor,kauth_cred_t cred)866e979c658Sreinoud udf_sync(struct mount *mp, int waitfor, kauth_cred_t cred)
867cff5e7adSreinoud {
868e979c658Sreinoud struct udf_mount *ump = VFSTOUDF(mp);
869e979c658Sreinoud
870cff5e7adSreinoud DPRINTF(CALL, ("udf_sync called\n"));
871e979c658Sreinoud /* if called when mounted readonly, just ignore */
872e979c658Sreinoud if (mp->mnt_flag & MNT_RDONLY)
873e979c658Sreinoud return 0;
874e979c658Sreinoud
875e979c658Sreinoud if (ump->syncing && !waitfor) {
876e979c658Sreinoud printf("UDF: skipping autosync\n");
877e979c658Sreinoud return 0;
878e979c658Sreinoud }
879e979c658Sreinoud
880e979c658Sreinoud /* get sync lock */
881e979c658Sreinoud ump->syncing = 1;
882e979c658Sreinoud
88371c9aa33Sreinoud /* pre-sync */
884e979c658Sreinoud udf_do_sync(ump, cred, waitfor);
885e979c658Sreinoud
886a287d23dSreinoud if (waitfor == MNT_WAIT)
887a287d23dSreinoud udf_sync_writeout_system_files(ump, true);
88871c9aa33Sreinoud
889e979c658Sreinoud DPRINTF(CALL, ("end of udf_sync()\n"));
890e979c658Sreinoud ump->syncing = 0;
891e979c658Sreinoud
892cff5e7adSreinoud return 0;
893cff5e7adSreinoud }
894cff5e7adSreinoud
895cff5e7adSreinoud /* --------------------------------------------------------------------- */
896cff5e7adSreinoud
897cff5e7adSreinoud /*
898cff5e7adSreinoud * Get vnode for the file system type specific file id ino for the fs. Its
899cff5e7adSreinoud * used for reference to files by unique ID and for NFSv3.
900cff5e7adSreinoud * (optional) TODO lookup why some sources state NFSv3
901cff5e7adSreinoud */
902cff5e7adSreinoud int
udf_vget(struct mount * mp,ino_t ino,int lktype,struct vnode ** vpp)903c2e9cb94Sad udf_vget(struct mount *mp, ino_t ino, int lktype,
904168cd830Schristos struct vnode **vpp)
905cff5e7adSreinoud {
906cff5e7adSreinoud DPRINTF(NOTIMPL, ("udf_vget called\n"));
907cff5e7adSreinoud return EOPNOTSUPP;
908cff5e7adSreinoud }
909cff5e7adSreinoud
910cff5e7adSreinoud /* --------------------------------------------------------------------- */
911cff5e7adSreinoud
912cff5e7adSreinoud /*
913cff5e7adSreinoud * Lookup vnode for file handle specified
914cff5e7adSreinoud */
915cff5e7adSreinoud int
udf_fhtovp(struct mount * mp,struct fid * fhp,int lktype,struct vnode ** vpp)916c2e9cb94Sad udf_fhtovp(struct mount *mp, struct fid *fhp, int lktype,
917168cd830Schristos struct vnode **vpp)
918cff5e7adSreinoud {
919cff5e7adSreinoud DPRINTF(NOTIMPL, ("udf_fhtovp called\n"));
920cff5e7adSreinoud return EOPNOTSUPP;
921cff5e7adSreinoud }
922cff5e7adSreinoud
923cff5e7adSreinoud /* --------------------------------------------------------------------- */
924cff5e7adSreinoud
925cff5e7adSreinoud /*
926cff5e7adSreinoud * Create an unique file handle. Its structure is opaque and won't be used by
927cff5e7adSreinoud * other subsystems. It should uniquely identify the file in the filingsystem
928cff5e7adSreinoud * and enough information to know if a file has been removed and/or resources
929cff5e7adSreinoud * have been recycled.
930cff5e7adSreinoud */
931cff5e7adSreinoud int
udf_vptofh(struct vnode * vp,struct fid * fid,size_t * fh_size)932168cd830Schristos udf_vptofh(struct vnode *vp, struct fid *fid,
933168cd830Schristos size_t *fh_size)
934cff5e7adSreinoud {
935cff5e7adSreinoud DPRINTF(NOTIMPL, ("udf_vptofh called\n"));
936cff5e7adSreinoud return EOPNOTSUPP;
937cff5e7adSreinoud }
938cff5e7adSreinoud
939cff5e7adSreinoud /* --------------------------------------------------------------------- */
940cff5e7adSreinoud
941cff5e7adSreinoud /*
942cff5e7adSreinoud * Create a filingsystem snapshot at the specified timestamp. Could be
943cff5e7adSreinoud * implemented by explicitly creating a new session or with spare room in the
944cff5e7adSreinoud * integrity descriptor space
945cff5e7adSreinoud */
946cff5e7adSreinoud int
udf_snapshot(struct mount * mp,struct vnode * vp,struct timespec * tm)947168cd830Schristos udf_snapshot(struct mount *mp, struct vnode *vp,
948168cd830Schristos struct timespec *tm)
949cff5e7adSreinoud {
950cff5e7adSreinoud DPRINTF(NOTIMPL, ("udf_snapshot called\n"));
951cff5e7adSreinoud return EOPNOTSUPP;
952cff5e7adSreinoud }
953d9df4ed2Sreinoud
954d9df4ed2Sreinoud /* --------------------------------------------------------------------- */
955