1 /* $NetBSD: udf_vfsops.c,v 1.58 2009/06/29 05:08:17 dholland Exp $ */
4 * Copyright (c) 2006, 2008 Reinoud Zandijk
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 #include <sys/cdefs.h>
31 __KERNEL_RCSID(0, "$NetBSD: udf_vfsops.c,v 1.58 2009/06/29 05:08:17 dholland Exp $");
35 #if defined(_KERNEL_OPT)
36 #include "opt_compat_netbsd.h"
39 #include <sys/param.h>
40 #include <sys/systm.h>
41 #include <sys/sysctl.h>
42 #include <sys/namei.h>
44 #include <sys/kernel.h>
45 #include <sys/vnode.h>
46 #include <miscfs/genfs/genfs.h>
47 #include <miscfs/specfs/specdev.h>
48 #include <sys/mount.h>
51 #include <sys/device.h>
52 #include <sys/disklabel.h>
53 #include <sys/ioctl.h>
54 #include <sys/malloc.h>
55 #include <sys/dirent.h>
58 #include <sys/kauth.h>
59 #include <sys/module.h>
61 #include <fs/udf/ecma167-udf.h>
62 #include <fs/udf/udf_mount.h>
63 #include <sys/dirhash.h>
67 #include "udf_bswap.h"
69 MODULE(MODULE_CLASS_VFS
, udf
, NULL
);
71 #define VTOI(vnode) ((struct udf_node *) vnode->v_data)
73 /* verbose levels of the udf filingsystem */
74 int udf_verbose
= UDF_DEBUGGING
;
77 MALLOC_JUSTDEFINE(M_UDFMNT
, "UDF mount", "UDF mount structures");
78 MALLOC_JUSTDEFINE(M_UDFVOLD
, "UDF volspace", "UDF volume space descriptors");
79 MALLOC_JUSTDEFINE(M_UDFTEMP
, "UDF temp", "UDF scrap space");
80 struct pool udf_node_pool
;
82 /* supported functions predefined */
85 static struct sysctllog
*udf_sysctl_log
;
87 /* internal functions */
88 static int udf_mountfs(struct vnode
*, struct mount
*, struct lwp
*, struct udf_args
*);
91 /* --------------------------------------------------------------------- */
93 /* predefine vnode-op list descriptor */
94 extern const struct vnodeopv_desc udf_vnodeop_opv_desc
;
96 const struct vnodeopv_desc
* const udf_vnodeopv_descs
[] = {
97 &udf_vnodeop_opv_desc
,
102 /* vfsops descriptor linked in as anchor point for the filingsystem */
103 struct vfsops udf_vfsops
= {
104 MOUNT_UDF
, /* vfs_name */
105 sizeof (struct udf_args
),
110 (void *)eopnotsupp
, /* vfs_quotactl */
122 (void *)eopnotsupp
, /* vfs_suspendctl */
123 genfs_renamelock_enter
,
124 genfs_renamelock_exit
,
127 0, /* int vfs_refcount */
128 { NULL
, NULL
, }, /* LIST_ENTRY(vfsops) */
131 /* --------------------------------------------------------------------- */
133 /* file system starts here */
139 /* setup memory types */
140 malloc_type_attach(M_UDFMNT
);
141 malloc_type_attach(M_UDFVOLD
);
142 malloc_type_attach(M_UDFTEMP
);
144 /* init node pools */
145 size
= sizeof(struct udf_node
);
146 pool_init(&udf_node_pool
, size
, 0, 0, 0,
147 "udf_node_pool", NULL
, IPL_NONE
);
162 pool_destroy(&udf_node_pool
);
164 malloc_type_detach(M_UDFMNT
);
165 malloc_type_detach(M_UDFVOLD
);
166 malloc_type_detach(M_UDFTEMP
);
170 * If running a DEBUG kernel, provide an easy way to set the debug flags when
171 * running into a problem.
173 #define UDF_VERBOSE_SYSCTLOPT 1
176 udf_modcmd(modcmd_t cmd
, void *arg
)
178 const struct sysctlnode
*node
;
182 case MODULE_CMD_INIT
:
183 error
= vfs_attach(&udf_vfsops
);
187 * XXX the "24" below could be dynamic, thereby eliminating one
188 * more instance of the "number to vfs" mapping problem, but
189 * "24" is the order as taken from sys/mount.h
191 sysctl_createv(&udf_sysctl_log
, 0, NULL
, NULL
,
193 CTLTYPE_NODE
, "vfs", NULL
,
196 sysctl_createv(&udf_sysctl_log
, 0, NULL
, &node
,
199 SYSCTL_DESCR("OSTA Universal File System"),
201 CTL_VFS
, 24, CTL_EOL
);
203 sysctl_createv(&udf_sysctl_log
, 0, NULL
, &node
,
204 CTLFLAG_PERMANENT
|CTLFLAG_READWRITE
,
205 CTLTYPE_INT
, "verbose",
206 SYSCTL_DESCR("Bitmask for filesystem debugging"),
207 NULL
, 0, &udf_verbose
, 0,
208 CTL_VFS
, 24, UDF_VERBOSE_SYSCTLOPT
, CTL_EOL
);
211 case MODULE_CMD_FINI
:
212 error
= vfs_detach(&udf_vfsops
);
215 sysctl_teardown(&udf_sysctl_log
);
225 /* --------------------------------------------------------------------- */
233 /* --------------------------------------------------------------------- */
235 #define MPFREE(a, lst) \
236 if ((a)) free((a), lst);
238 free_udf_mountinfo(struct mount
*mp
)
240 struct udf_mount
*ump
;
249 for (i
= 0; i
< UDF_ANCHORS
; i
++)
250 MPFREE(ump
->anchors
[i
], M_UDFVOLD
);
251 MPFREE(ump
->primary_vol
, M_UDFVOLD
);
252 MPFREE(ump
->logical_vol
, M_UDFVOLD
);
253 MPFREE(ump
->unallocated
, M_UDFVOLD
);
254 MPFREE(ump
->implementation
, M_UDFVOLD
);
255 MPFREE(ump
->logvol_integrity
, M_UDFVOLD
);
256 for (i
= 0; i
< UDF_PARTITIONS
; i
++) {
257 MPFREE(ump
->partitions
[i
], M_UDFVOLD
);
258 MPFREE(ump
->part_unalloc_dscr
[i
], M_UDFVOLD
);
259 MPFREE(ump
->part_freed_dscr
[i
], M_UDFVOLD
);
261 MPFREE(ump
->metadata_unalloc_dscr
, M_UDFVOLD
);
263 MPFREE(ump
->fileset_desc
, M_UDFVOLD
);
264 MPFREE(ump
->sparing_table
, M_UDFVOLD
);
266 MPFREE(ump
->la_node_ad_cpy
, M_UDFMNT
);
267 MPFREE(ump
->la_pmapping
, M_TEMP
);
268 MPFREE(ump
->la_lmapping
, M_TEMP
);
270 mutex_destroy(&ump
->ihash_lock
);
271 mutex_destroy(&ump
->get_node_lock
);
272 mutex_destroy(&ump
->logvol_mutex
);
273 mutex_destroy(&ump
->allocate_mutex
);
274 cv_destroy(&ump
->dirtynodes_cv
);
276 MPFREE(ump
->vat_table
, M_UDFVOLD
);
283 /* --------------------------------------------------------------------- */
285 /* if the system nodes exist, release them */
287 udf_release_system_nodes(struct mount
*mp
)
289 struct udf_mount
*ump
= VFSTOUDF(mp
);
292 /* if we haven't even got an ump, dont bother */
296 /* VAT partition support */
298 vrele(ump
->vat_node
->vnode
);
300 /* Metadata partition support */
301 if (ump
->metadata_node
)
302 vrele(ump
->metadata_node
->vnode
);
303 if (ump
->metadatamirror_node
)
304 vrele(ump
->metadatamirror_node
->vnode
);
305 if (ump
->metadatabitmap_node
)
306 vrele(ump
->metadatabitmap_node
->vnode
);
308 /* This flush should NOT write anything nor allow any node to remain */
309 if ((error
= vflush(ump
->vfs_mountp
, NULLVP
, 0)) != 0)
310 panic("Failure to flush UDF system vnodes\n");
315 udf_mount(struct mount
*mp
, const char *path
,
316 void *data
, size_t *data_len
)
318 struct lwp
*l
= curlwp
;
319 struct udf_args
*args
= data
;
320 struct udf_mount
*ump
;
322 int openflags
, accessmode
, error
;
324 DPRINTF(CALL
, ("udf_mount called\n"));
326 if (*data_len
< sizeof *args
)
329 if (mp
->mnt_flag
& MNT_GETARGS
) {
330 /* request for the mount arguments */
334 *args
= ump
->mount_args
;
335 *data_len
= sizeof *args
;
339 /* handle request for updating mount parameters */
340 /* TODO can't update my mountpoint yet */
341 if (mp
->mnt_flag
& MNT_UPDATE
) {
345 /* OK, so we are asked to mount the device */
347 /* check/translate struct version */
348 /* TODO sanity checking other mount arguments */
349 if (args
->version
!= 1) {
350 printf("mount_udf: unrecognized argument structure version\n");
354 /* lookup name to get its vnode */
355 error
= namei_simple_user(args
->fspec
,
356 NSM_FOLLOW_NOEMULROOT
, &devvp
);
361 if (udf_verbose
& UDF_DEBUG_VOLUMES
)
362 vprint("UDF mount, trying to mount \n", devvp
);
365 /* check if its a block device specified */
366 if (devvp
->v_type
!= VBLK
) {
370 if (bdevsw_lookup(devvp
->v_rdev
) == NULL
) {
376 * If mount by non-root, then verify that user has necessary
377 * permissions on the device.
380 if ((mp
->mnt_flag
& MNT_RDONLY
) == 0)
381 accessmode
|= VWRITE
;
382 vn_lock(devvp
, LK_EXCLUSIVE
| LK_RETRY
);
383 error
= genfs_can_mount(devvp
, accessmode
, l
->l_cred
);
384 VOP_UNLOCK(devvp
, 0);
391 * Open device and try to mount it!
393 if (mp
->mnt_flag
& MNT_RDONLY
) {
396 openflags
= FREAD
| FWRITE
;
398 error
= VOP_OPEN(devvp
, openflags
, FSCRED
);
400 /* opened ok, try mounting */
401 error
= udf_mountfs(devvp
, mp
, l
, args
);
403 udf_release_system_nodes(mp
);
405 udf_discstrat_finish(VFSTOUDF(mp
));
406 free_udf_mountinfo(mp
);
407 vn_lock(devvp
, LK_EXCLUSIVE
| LK_RETRY
);
408 (void) VOP_CLOSE(devvp
, openflags
, NOCRED
);
409 VOP_UNLOCK(devvp
, 0);
413 /* devvp is still locked */
418 /* register our mountpoint being on this device */
419 devvp
->v_specmountpoint
= mp
;
421 /* successfully mounted */
422 DPRINTF(VOLUMES
, ("udf_mount() successfull\n"));
424 error
= set_statvfs_info(path
, UIO_USERSPACE
, args
->fspec
, UIO_USERSPACE
,
425 mp
->mnt_op
->vfs_name
, mp
, l
);
429 /* If we're not opened read-only, open its logical volume */
430 if ((mp
->mnt_flag
& MNT_RDONLY
) == 0) {
431 if ((error
= udf_open_logvol(VFSTOUDF(mp
))) != 0) {
432 printf( "mount_udf: can't open logical volume for "
433 "writing, downgrading access to read-only\n");
434 mp
->mnt_flag
|= MNT_RDONLY
;
435 /* FIXME we can't return error now on open failure */
443 /* --------------------------------------------------------------------- */
447 udf_unmount_sanity_check(struct mount
*mp
)
451 printf("On unmount, i found the following nodes:\n");
452 TAILQ_FOREACH(vp
, &mp
->mnt_vnodelist
, v_mntvnodes
) {
454 if (VOP_ISLOCKED(vp
) == LK_EXCLUSIVE
) {
455 printf(" is locked\n");
457 if (vp
->v_usecount
> 1)
458 printf(" more than one usecount %d\n", vp
->v_usecount
);
465 udf_unmount(struct mount
*mp
, int mntflags
)
467 struct udf_mount
*ump
;
468 int error
, flags
, closeflags
;
470 DPRINTF(CALL
, ("udf_umount called\n"));
474 panic("UDF unmount: empty ump\n");
476 flags
= (mntflags
& MNT_FORCE
) ? FORCECLOSE
: 0;
477 /* TODO remove these paranoid functions */
479 if (udf_verbose
& UDF_DEBUG_LOCKING
)
480 udf_unmount_sanity_check(mp
);
484 * By specifying SKIPSYSTEM we can skip vnodes marked with VV_SYSTEM.
485 * This hardly documented feature allows us to exempt certain files
486 * from being flushed.
488 if ((error
= vflush(mp
, NULLVP
, flags
| SKIPSYSTEM
)) != 0)
491 /* update nodes and wait for completion of writeout of system nodes */
492 udf_sync(mp
, FSYNC_WAIT
, NOCRED
);
495 if (udf_verbose
& UDF_DEBUG_LOCKING
)
496 udf_unmount_sanity_check(mp
);
499 /* flush again, to check if we are still busy for something else */
500 if ((error
= vflush(ump
->vfs_mountp
, NULLVP
, flags
| SKIPSYSTEM
)) != 0)
503 DPRINTF(VOLUMES
, ("flush OK on unmount\n"));
505 /* close logical volume and close session if requested */
506 if ((error
= udf_close_logvol(ump
, mntflags
)) != 0)
510 DPRINTF(VOLUMES
, ("FINAL sanity check\n"));
511 if (udf_verbose
& UDF_DEBUG_LOCKING
)
512 udf_unmount_sanity_check(mp
);
515 /* NOTE release system nodes should NOT write anything */
516 udf_release_system_nodes(mp
);
518 /* finalise disc strategy */
519 udf_discstrat_finish(ump
);
521 /* synchronise device caches */
522 (void) udf_synchronise_caches(ump
);
525 DPRINTF(VOLUMES
, ("closing device\n"));
526 if (mp
->mnt_flag
& MNT_RDONLY
) {
529 closeflags
= FREAD
| FWRITE
;
532 /* devvp is still locked by us */
533 vn_lock(ump
->devvp
, LK_EXCLUSIVE
| LK_RETRY
);
534 error
= VOP_CLOSE(ump
->devvp
, closeflags
, NOCRED
);
536 printf("Error during closure of device! error %d, "
537 "device might stay locked\n", error
);
538 DPRINTF(VOLUMES
, ("device close ok\n"));
540 /* clear our mount reference and release device node */
541 ump
->devvp
->v_specmountpoint
= NULL
;
545 free_udf_mountinfo(mp
);
547 /* free ump struct references */
549 mp
->mnt_flag
&= ~MNT_LOCAL
;
551 DPRINTF(VOLUMES
, ("Fin unmount\n"));
555 /* --------------------------------------------------------------------- */
558 * Helper function of udf_mount() that actually mounts the disc.
562 udf_mountfs(struct vnode
*devvp
, struct mount
*mp
,
563 struct lwp
*l
, struct udf_args
*args
)
565 struct udf_mount
*ump
;
566 uint32_t sector_size
, lb_size
, bshift
;
567 uint32_t logvol_integrity
;
568 int num_anchors
, error
;
570 /* flush out any old buffers remaining from a previous use. */
571 if ((error
= vinvalbuf(devvp
, V_SAVE
, l
->l_cred
, l
, 0, 0)))
574 /* setup basic mount information */
576 mp
->mnt_stat
.f_fsidx
.__fsid_val
[0] = (uint32_t) devvp
->v_rdev
;
577 mp
->mnt_stat
.f_fsidx
.__fsid_val
[1] = makefstype(MOUNT_UDF
);
578 mp
->mnt_stat
.f_fsid
= mp
->mnt_stat
.f_fsidx
.__fsid_val
[0];
579 mp
->mnt_stat
.f_namemax
= UDF_MAX_NAMELEN
;
580 mp
->mnt_flag
|= MNT_LOCAL
;
581 // mp->mnt_iflag |= IMNT_MPSAFE;
583 /* allocate udf part of mount structure; malloc always succeeds */
584 ump
= malloc(sizeof(struct udf_mount
), M_UDFMNT
, M_WAITOK
| M_ZERO
);
587 mutex_init(&ump
->logvol_mutex
, MUTEX_DEFAULT
, IPL_NONE
);
588 mutex_init(&ump
->ihash_lock
, MUTEX_DEFAULT
, IPL_NONE
);
589 mutex_init(&ump
->get_node_lock
, MUTEX_DEFAULT
, IPL_NONE
);
590 mutex_init(&ump
->allocate_mutex
, MUTEX_DEFAULT
, IPL_NONE
);
591 cv_init(&ump
->dirtynodes_cv
, "udfsync2");
593 /* init rbtree for nodes, ordered by their icb address (long_ad) */
594 udf_init_nodes_tree(ump
);
598 ump
->vfs_mountp
= mp
;
600 /* set up arguments and device */
601 ump
->mount_args
= *args
;
603 if ((error
= udf_update_discinfo(ump
))) {
604 printf("UDF mount: error inspecting fs node\n");
608 /* inspect sector size */
609 sector_size
= ump
->discinfo
.sector_size
;
611 while ((1 << bshift
) < sector_size
)
613 if ((1 << bshift
) != sector_size
) {
615 "hit NetBSD implementation fence on sector size\n");
619 /* temporary check to overcome sectorsize >= 8192 bytes panic */
620 if (sector_size
>= 8192) {
622 "hit implementation limit, sectorsize to big\n");
627 * Inspect if we're asked to mount read-write on a non recordable or
628 * closed sequential disc.
630 if ((mp
->mnt_flag
& MNT_RDONLY
) == 0) {
631 if ((ump
->discinfo
.mmc_cur
& MMC_CAP_RECORDABLE
) == 0) {
632 printf("UDF mount: disc is not recordable\n");
635 if (ump
->discinfo
.mmc_cur
& MMC_CAP_SEQUENTIAL
) {
636 if (ump
->discinfo
.disc_state
== MMC_STATE_FULL
) {
637 printf("UDF mount: disc is not appendable\n");
642 * TODO if the last session is closed check if there
643 * is enough space to open/close new session
646 /* double check if we're not mounting a pervious session RW */
647 if (args
->sessionnr
!= 0) {
648 printf("UDF mount: updating a previous session "
649 "not yet allowed\n");
654 /* initialise bootstrap disc strategy */
655 ump
->strategy
= &udf_strat_bootstrap
;
656 udf_discstrat_init(ump
);
658 /* read all anchors to get volume descriptor sequence */
659 num_anchors
= udf_read_anchors(ump
);
660 if (num_anchors
== 0)
663 DPRINTF(VOLUMES
, ("Read %d anchors on this disc, session %d\n",
664 num_anchors
, args
->sessionnr
));
666 /* read in volume descriptor sequence */
667 if ((error
= udf_read_vds_space(ump
))) {
668 printf("UDF mount: error reading volume space\n");
672 /* close down bootstrap disc strategy */
673 udf_discstrat_finish(ump
);
675 /* check consistency and completeness */
676 if ((error
= udf_process_vds(ump
))) {
677 printf( "UDF mount: disc not properly formatted"
682 /* switch to new disc strategy */
683 KASSERT(ump
->strategy
!= &udf_strat_bootstrap
);
684 udf_discstrat_init(ump
);
686 /* initialise late allocation administration space */
687 ump
->la_lmapping
= malloc(sizeof(uint64_t) * UDF_MAX_MAPPINGS
,
689 ump
->la_pmapping
= malloc(sizeof(uint64_t) * UDF_MAX_MAPPINGS
,
692 /* setup node cleanup extents copy space */
693 lb_size
= udf_rw32(ump
->logical_vol
->lb_size
);
694 ump
->la_node_ad_cpy
= malloc(lb_size
* UDF_MAX_ALLOC_EXTENTS
,
696 memset(ump
->la_node_ad_cpy
, 0, lb_size
* UDF_MAX_ALLOC_EXTENTS
);
698 /* setup rest of mount information */
701 /* bshift is allways equal to disc sector size */
702 mp
->mnt_dev_bshift
= bshift
;
703 mp
->mnt_fs_bshift
= bshift
;
705 /* note that the mp info needs to be initialised for reading! */
706 /* read vds support tables like VAT, sparable etc. */
707 if ((error
= udf_read_vds_tables(ump
))) {
708 printf( "UDF mount: error in format or damaged disc "
709 "(VDS tables failing)\n");
713 /* check if volume integrity is closed otherwise its dirty */
714 logvol_integrity
= udf_rw32(ump
->logvol_integrity
->integrity_type
);
715 if (logvol_integrity
!= UDF_INTEGRITY_CLOSED
) {
716 printf("UDF mount: file system is not clean; ");
717 printf("please fsck(8)\n");
721 /* read root directory */
722 if ((error
= udf_read_rootdirs(ump
))) {
723 printf( "UDF mount: "
724 "disc not properly formatted or damaged disc "
725 "(rootdirs failing)\n");
729 /* do we have to set this? */
730 devvp
->v_specmountpoint
= mp
;
736 /* --------------------------------------------------------------------- */
739 udf_start(struct mount
*mp
, int flags
)
741 /* do we have to do something here? */
745 /* --------------------------------------------------------------------- */
748 udf_root(struct mount
*mp
, struct vnode
**vpp
)
751 struct long_ad
*dir_loc
;
752 struct udf_mount
*ump
= VFSTOUDF(mp
);
753 struct udf_node
*root_dir
;
756 DPRINTF(CALL
, ("udf_root called\n"));
758 dir_loc
= &ump
->fileset_desc
->rootdir_icb
;
759 error
= udf_get_node(ump
, dir_loc
, &root_dir
);
766 vp
= root_dir
->vnode
;
767 KASSERT(vp
->v_vflag
& VV_ROOT
);
773 /* --------------------------------------------------------------------- */
776 udf_statvfs(struct mount
*mp
, struct statvfs
*sbp
)
778 struct udf_mount
*ump
= VFSTOUDF(mp
);
779 struct logvol_int_desc
*lvid
;
780 struct udf_logvol_info
*impl
;
781 uint64_t freeblks
, sizeblks
;
784 DPRINTF(CALL
, ("udf_statvfs called\n"));
785 sbp
->f_flag
= mp
->mnt_flag
;
786 sbp
->f_bsize
= ump
->discinfo
.sector_size
;
787 sbp
->f_frsize
= ump
->discinfo
.sector_size
;
788 sbp
->f_iosize
= ump
->discinfo
.sector_size
;
790 mutex_enter(&ump
->allocate_mutex
);
792 udf_calc_freespace(ump
, &sizeblks
, &freeblks
);
794 sbp
->f_blocks
= sizeblks
;
795 sbp
->f_bfree
= freeblks
;
798 lvid
= ump
->logvol_integrity
;
799 num_part
= udf_rw32(lvid
->num_part
);
800 impl
= (struct udf_logvol_info
*) (lvid
->tables
+ 2*num_part
);
802 sbp
->f_files
= udf_rw32(impl
->num_files
);
803 sbp
->f_files
+= udf_rw32(impl
->num_directories
);
806 /* XXX read only for now XXX */
810 /* tricky, next only aplies to ffs i think, so set to zero */
815 mutex_exit(&ump
->allocate_mutex
);
817 copy_statvfs_info(sbp
, mp
);
821 /* --------------------------------------------------------------------- */
824 * TODO what about writing out free space maps, lvid etc? only on `waitfor'
825 * i.e. explicit syncing by the user?
829 udf_sync_writeout_system_files(struct udf_mount
*ump
, int clearflags
)
833 /* XXX lock for VAT en bitmaps? */
834 /* metadata nodes are written synchronous */
835 DPRINTF(CALL
, ("udf_sync: syncing metadata\n"));
836 if (ump
->lvclose
& UDF_WRITE_VAT
)
837 udf_writeout_vat(ump
);
840 if (ump
->lvclose
& UDF_WRITE_PART_BITMAPS
) {
841 /* writeout metadata spacetable if existing */
842 error
= udf_write_metadata_partition_spacetable(ump
, MNT_WAIT
);
844 printf( "udf_writeout_system_files : "
845 " writeout of metadata space bitmap failed\n");
847 /* writeout partition spacetables */
848 error
= udf_write_physical_partition_spacetables(ump
, MNT_WAIT
);
850 printf( "udf_writeout_system_files : "
851 "writeout of space tables failed\n");
852 if (!error
&& clearflags
)
853 ump
->lvclose
&= ~UDF_WRITE_PART_BITMAPS
;
861 udf_sync(struct mount
*mp
, int waitfor
, kauth_cred_t cred
)
863 struct udf_mount
*ump
= VFSTOUDF(mp
);
865 DPRINTF(CALL
, ("udf_sync called\n"));
866 /* if called when mounted readonly, just ignore */
867 if (mp
->mnt_flag
& MNT_RDONLY
)
870 if (ump
->syncing
&& !waitfor
) {
871 printf("UDF: skipping autosync\n");
879 udf_do_sync(ump
, cred
, waitfor
);
881 if (waitfor
== MNT_WAIT
)
882 udf_sync_writeout_system_files(ump
, true);
884 DPRINTF(CALL
, ("end of udf_sync()\n"));
890 /* --------------------------------------------------------------------- */
893 * Get vnode for the file system type specific file id ino for the fs. Its
894 * used for reference to files by unique ID and for NFSv3.
895 * (optional) TODO lookup why some sources state NFSv3
898 udf_vget(struct mount
*mp
, ino_t ino
,
901 DPRINTF(NOTIMPL
, ("udf_vget called\n"));
905 /* --------------------------------------------------------------------- */
908 * Lookup vnode for file handle specified
911 udf_fhtovp(struct mount
*mp
, struct fid
*fhp
,
914 DPRINTF(NOTIMPL
, ("udf_fhtovp called\n"));
918 /* --------------------------------------------------------------------- */
921 * Create an unique file handle. Its structure is opaque and won't be used by
922 * other subsystems. It should uniquely identify the file in the filingsystem
923 * and enough information to know if a file has been removed and/or resources
924 * have been recycled.
927 udf_vptofh(struct vnode
*vp
, struct fid
*fid
,
930 DPRINTF(NOTIMPL
, ("udf_vptofh called\n"));
934 /* --------------------------------------------------------------------- */
937 * Create a filingsystem snapshot at the specified timestamp. Could be
938 * implemented by explicitly creating a new session or with spare room in the
939 * integrity descriptor space
942 udf_snapshot(struct mount
*mp
, struct vnode
*vp
,
945 DPRINTF(NOTIMPL
, ("udf_snapshot called\n"));
949 /* --------------------------------------------------------------------- */