194663Sscottl/*- 294663Sscottl * Copyright (c) 2001, 2002 Scott Long <scottl@freebsd.org> 394663Sscottl * All rights reserved. 494663Sscottl * 594663Sscottl * Redistribution and use in source and binary forms, with or without 694663Sscottl * modification, are permitted provided that the following conditions 794663Sscottl * are met: 894663Sscottl * 1. Redistributions of source code must retain the above copyright 994663Sscottl * notice, this list of conditions and the following disclaimer. 1094663Sscottl * 2. Redistributions in binary form must reproduce the above copyright 1194663Sscottl * notice, this list of conditions and the following disclaimer in the 1294663Sscottl * documentation and/or other materials provided with the distribution. 1394663Sscottl * 1494663Sscottl * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1594663Sscottl * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1694663Sscottl * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1794663Sscottl * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1894663Sscottl * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1994663Sscottl * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2094663Sscottl * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2194663Sscottl * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2294663Sscottl * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2394663Sscottl * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2494663Sscottl * SUCH DAMAGE. 2594663Sscottl * 2694663Sscottl * $FreeBSD: releng/10.3/sys/fs/udf/udf_vfsops.c 242833 2012-11-09 18:02:25Z attilio $ 2794663Sscottl */ 2894663Sscottl 2994663Sscottl/* udf_vfsops.c */ 3094663Sscottl/* Implement the VFS side of things */ 3194663Sscottl 3294663Sscottl/* 3394663Sscottl * Ok, here's how it goes. The UDF specs are pretty clear on how each data 3494663Sscottl * structure is made up, but not very clear on how they relate to each other. 3594663Sscottl * Here is the skinny... This demostrates a filesystem with one file in the 3694663Sscottl * root directory. Subdirectories are treated just as normal files, but they 3794663Sscottl * have File Id Descriptors of their children as their file data. As for the 3894663Sscottl * Anchor Volume Descriptor Pointer, it can exist in two of the following three 3994663Sscottl * places: sector 256, sector n (the max sector of the disk), or sector 4094663Sscottl * n - 256. It's a pretty good bet that one will exist at sector 256 though. 4194663Sscottl * One caveat is unclosed CD media. For that, sector 256 cannot be written, 4294663Sscottl * so the Anchor Volume Descriptor Pointer can exist at sector 512 until the 4394663Sscottl * media is closed. 4494663Sscottl * 4594663Sscottl * Sector: 4694663Sscottl * 256: 4794663Sscottl * n: Anchor Volume Descriptor Pointer 4894663Sscottl * n - 256: | 4994663Sscottl * | 5094663Sscottl * |-->Main Volume Descriptor Sequence 5194663Sscottl * | | 5294663Sscottl * | | 5394663Sscottl * | |-->Logical Volume Descriptor 5494663Sscottl * | | 5594663Sscottl * |-->Partition Descriptor | 5694663Sscottl * | | 5794663Sscottl * | | 5894663Sscottl * |-->Fileset Descriptor 5994663Sscottl * | 6094663Sscottl * | 6194663Sscottl * |-->Root Dir File Entry 6294663Sscottl * | 6394663Sscottl * | 6494663Sscottl * |-->File data: 6594663Sscottl * File Id Descriptor 6694663Sscottl * | 6794663Sscottl * | 6894663Sscottl * |-->File Entry 6994663Sscottl * | 7094663Sscottl * | 7194663Sscottl * |-->File data 7294663Sscottl */ 7394663Sscottl#include <sys/types.h> 7494663Sscottl#include <sys/param.h> 7594663Sscottl#include <sys/systm.h> 76100164Smarkm#include <sys/uio.h> 7794663Sscottl#include <sys/bio.h> 7894663Sscottl#include <sys/buf.h> 79100164Smarkm#include <sys/conf.h> 80100164Smarkm#include <sys/dirent.h> 81100164Smarkm#include <sys/fcntl.h> 82122102Sscottl#include <sys/iconv.h> 83100164Smarkm#include <sys/kernel.h> 8494663Sscottl#include <sys/malloc.h> 8594663Sscottl#include <sys/mount.h> 86100164Smarkm#include <sys/namei.h> 87164033Srwatson#include <sys/priv.h> 88100164Smarkm#include <sys/proc.h> 8994663Sscottl#include <sys/queue.h> 90100164Smarkm#include <sys/vnode.h> 91130986Sscottl#include <sys/endian.h> 9294663Sscottl 93137037Sphk#include <geom/geom.h> 94137037Sphk#include <geom/geom_vfs.h> 95137037Sphk 9694663Sscottl#include <vm/uma.h> 9794663Sscottl 9894663Sscottl#include <fs/udf/ecma167-udf.h> 99122102Sscottl#include <fs/udf/osta.h> 10094663Sscottl#include <fs/udf/udf.h> 101122102Sscottl#include <fs/udf/udf_mount.h> 10294663Sscottl 103151897Srwatsonstatic MALLOC_DEFINE(M_UDFMOUNT, "udf_mount", "UDF mount structure"); 104151897SrwatsonMALLOC_DEFINE(M_UDFFENTRY, "udf_fentry", "UDF file entry structure"); 10594663Sscottl 106122102Sscottlstruct iconv_functions *udf_iconv = NULL; 107122102Sscottl 10894663Sscottl/* Zones */ 10994663Sscottluma_zone_t udf_zone_trans = NULL; 11094663Sscottluma_zone_t udf_zone_node = NULL; 111101890Sscottluma_zone_t udf_zone_ds = NULL; 11294663Sscottl 113116271Sphkstatic vfs_init_t udf_init; 114116271Sphkstatic vfs_uninit_t udf_uninit; 115132902Sphkstatic vfs_mount_t udf_mount; 116116271Sphkstatic vfs_root_t udf_root; 117116271Sphkstatic vfs_statfs_t udf_statfs; 118116271Sphkstatic vfs_unmount_t udf_unmount; 119116271Sphkstatic vfs_fhtovp_t udf_fhtovp; 120116271Sphk 12194663Sscottlstatic int udf_find_partmaps(struct udf_mnt *, struct logvol_desc *); 12294663Sscottl 12394663Sscottlstatic struct vfsops udf_vfsops = { 124116271Sphk .vfs_fhtovp = udf_fhtovp, 125116271Sphk .vfs_init = udf_init, 126132902Sphk .vfs_mount = udf_mount, 127116271Sphk .vfs_root = udf_root, 128116271Sphk .vfs_statfs = udf_statfs, 129116271Sphk .vfs_uninit = udf_uninit, 130116271Sphk .vfs_unmount = udf_unmount, 131116271Sphk .vfs_vget = udf_vget, 13294663Sscottl}; 13394663SscottlVFS_SET(udf_vfsops, udf, VFCF_READONLY); 13494663Sscottl 135122102SscottlMODULE_VERSION(udf, 1); 136122102Sscottl 137183754Sattiliostatic int udf_mountfs(struct vnode *, struct mount *); 13894663Sscottl 13994663Sscottlstatic int 14094663Sscottludf_init(struct vfsconf *foo) 14194663Sscottl{ 14294663Sscottl 14394663Sscottl /* 14494663Sscottl * This code used to pre-allocate a certain number of pages for each 14594663Sscottl * pool, reducing the need to grow the zones later on. UMA doesn't 14694663Sscottl * advertise any such functionality, unfortunately =-< 14794663Sscottl */ 14894663Sscottl udf_zone_trans = uma_zcreate("UDF translation buffer, zone", MAXNAMLEN * 14994663Sscottl sizeof(unicode_t), NULL, NULL, NULL, NULL, 0, 0); 15094663Sscottl 15194663Sscottl udf_zone_node = uma_zcreate("UDF Node zone", sizeof(struct udf_node), 15294663Sscottl NULL, NULL, NULL, NULL, 0, 0); 15394663Sscottl 154101890Sscottl udf_zone_ds = uma_zcreate("UDF Dirstream zone", 155101890Sscottl sizeof(struct udf_dirstream), NULL, NULL, NULL, NULL, 0, 0); 156101890Sscottl 157101890Sscottl if ((udf_zone_node == NULL) || (udf_zone_trans == NULL) || 158101890Sscottl (udf_zone_ds == NULL)) { 15994663Sscottl printf("Cannot create allocation zones.\n"); 16094663Sscottl return (ENOMEM); 16194663Sscottl } 16294663Sscottl 16394663Sscottl return 0; 16494663Sscottl} 16594663Sscottl 16694663Sscottlstatic int 16794663Sscottludf_uninit(struct vfsconf *foo) 16894663Sscottl{ 16994663Sscottl 17094663Sscottl if (udf_zone_trans != NULL) { 17194663Sscottl uma_zdestroy(udf_zone_trans); 17294663Sscottl udf_zone_trans = NULL; 17394663Sscottl } 17494663Sscottl 17594663Sscottl if (udf_zone_node != NULL) { 17694663Sscottl uma_zdestroy(udf_zone_node); 17794663Sscottl udf_zone_node = NULL; 17894663Sscottl } 17994663Sscottl 180101890Sscottl if (udf_zone_ds != NULL) { 181101890Sscottl uma_zdestroy(udf_zone_ds); 182101890Sscottl udf_zone_ds = NULL; 183101890Sscottl } 184101890Sscottl 18594663Sscottl return (0); 18694663Sscottl} 18794663Sscottl 18894663Sscottlstatic int 189191990Sattilioudf_mount(struct mount *mp) 19094663Sscottl{ 19194663Sscottl struct vnode *devvp; /* vnode of the mount device */ 192191990Sattilio struct thread *td; 193238697Skevlo struct udf_mnt *imp = NULL; 19498265Smux struct vfsoptlist *opts; 195122102Sscottl char *fspec, *cs_disk, *cs_local; 196122102Sscottl int error, len, *udf_flags; 197132902Sphk struct nameidata nd, *ndp = &nd; 19894663Sscottl 199191990Sattilio td = curthread; 20098265Smux opts = mp->mnt_optnew; 20198265Smux 202151405Srodrigc /* 203151405Srodrigc * Unconditionally mount as read-only. 204151405Srodrigc */ 205162647Stegge MNT_ILOCK(mp); 206151405Srodrigc mp->mnt_flag |= MNT_RDONLY; 207162647Stegge MNT_IUNLOCK(mp); 20894663Sscottl 20994663Sscottl /* 21094663Sscottl * No root filesystem support. Probably not a big deal, since the 21194663Sscottl * bootloader doesn't understand UDF. 21294663Sscottl */ 21394663Sscottl if (mp->mnt_flag & MNT_ROOTFS) 21494663Sscottl return (ENOTSUP); 21594663Sscottl 21698265Smux fspec = NULL; 21798265Smux error = vfs_getopt(opts, "from", (void **)&fspec, &len); 21898265Smux if (!error && fspec[len - 1] != '\0') 21998265Smux return (EINVAL); 22094663Sscottl 22194663Sscottl if (mp->mnt_flag & MNT_UPDATE) { 222158927Srodrigc return (0); 22394663Sscottl } 22494663Sscottl 22594663Sscottl /* Check that the mount device exists */ 22698265Smux if (fspec == NULL) 22798265Smux return (EINVAL); 228149720Sssouhlal NDINIT(ndp, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE, fspec, td); 22994663Sscottl if ((error = namei(ndp))) 23094663Sscottl return (error); 23194663Sscottl NDFREE(ndp, NDF_ONLY_PNBUF); 23294663Sscottl devvp = ndp->ni_vp; 23394663Sscottl 23494663Sscottl if (vn_isdisk(devvp, &error) == 0) { 235149720Sssouhlal vput(devvp); 23694663Sscottl return (error); 23794663Sscottl } 23894663Sscottl 23994663Sscottl /* Check the access rights on the mount device */ 24094663Sscottl error = VOP_ACCESS(devvp, VREAD, td->td_ucred, td); 24194663Sscottl if (error) 242164033Srwatson error = priv_check(td, PRIV_VFS_MOUNT_PERM); 24394663Sscottl if (error) { 24494663Sscottl vput(devvp); 24594663Sscottl return (error); 24694663Sscottl } 24794663Sscottl 248183754Sattilio if ((error = udf_mountfs(devvp, mp))) { 24994663Sscottl vrele(devvp); 25094663Sscottl return (error); 25194663Sscottl } 25294663Sscottl 25394663Sscottl imp = VFSTOUDFFS(mp); 254122102Sscottl 255122102Sscottl udf_flags = NULL; 256122102Sscottl error = vfs_getopt(opts, "flags", (void **)&udf_flags, &len); 257122102Sscottl if (error || len != sizeof(int)) 258122102Sscottl return (EINVAL); 259122102Sscottl imp->im_flags = *udf_flags; 260122102Sscottl 261122102Sscottl if (imp->im_flags & UDFMNT_KICONV && udf_iconv) { 262122102Sscottl cs_disk = NULL; 263122102Sscottl error = vfs_getopt(opts, "cs_disk", (void **)&cs_disk, &len); 264122102Sscottl if (!error && cs_disk[len - 1] != '\0') 265122102Sscottl return (EINVAL); 266122102Sscottl cs_local = NULL; 267122102Sscottl error = vfs_getopt(opts, "cs_local", (void **)&cs_local, &len); 268122102Sscottl if (!error && cs_local[len - 1] != '\0') 269122102Sscottl return (EINVAL); 270122102Sscottl udf_iconv->open(cs_local, cs_disk, &imp->im_d2l); 271122102Sscottl#if 0 272122102Sscottl udf_iconv->open(cs_disk, cs_local, &imp->im_l2d); 273122102Sscottl#endif 274122102Sscottl } 275122102Sscottl 276138484Sphk vfs_mountedfrom(mp, fspec); 27794663Sscottl return 0; 27894663Sscottl}; 27994663Sscottl 28094663Sscottl/* 28194663Sscottl * Check the descriptor tag for both the correct id and correct checksum. 28294663Sscottl * Return zero if all is good, EINVAL if not. 28394663Sscottl */ 28494663Sscottlint 28594795Sasmodaiudf_checktag(struct desc_tag *tag, uint16_t id) 28694663Sscottl{ 28794795Sasmodai uint8_t *itag; 28894795Sasmodai uint8_t i, cksum = 0; 28994663Sscottl 29094795Sasmodai itag = (uint8_t *)tag; 29194663Sscottl 292155256Swill if (le16toh(tag->id) != id) 29394663Sscottl return (EINVAL); 29494663Sscottl 295174538Smarkus for (i = 0; i < 16; i++) 29694663Sscottl cksum = cksum + itag[i]; 29794663Sscottl cksum = cksum - itag[4]; 29894663Sscottl 29994663Sscottl if (cksum == tag->cksum) 30094663Sscottl return (0); 30194663Sscottl 30294663Sscottl return (EINVAL); 30394663Sscottl} 30494663Sscottl 30594663Sscottlstatic int 306188502Sjhbudf_mountfs(struct vnode *devvp, struct mount *mp) 307188502Sjhb{ 30894663Sscottl struct buf *bp = NULL; 309188502Sjhb struct cdev *dev; 31094663Sscottl struct anchor_vdp avdp; 31194663Sscottl struct udf_mnt *udfmp = NULL; 31294663Sscottl struct part_desc *pd; 31394663Sscottl struct logvol_desc *lvd; 31494663Sscottl struct fileset_desc *fsd; 31594663Sscottl struct file_entry *root_fentry; 31694795Sasmodai uint32_t sector, size, mvds_start, mvds_end; 317151157Srodrigc uint32_t logical_secsize; 31894795Sasmodai uint32_t fsd_offset = 0; 31994795Sasmodai uint16_t part_num = 0, fsd_part = 0; 320137037Sphk int error = EINVAL; 32194663Sscottl int logvol_found = 0, part_found = 0, fsd_found = 0; 32294663Sscottl int bsize; 323137037Sphk struct g_consumer *cp; 324137037Sphk struct bufobj *bo; 32594663Sscottl 326188502Sjhb dev = devvp->v_rdev; 327188502Sjhb dev_ref(dev); 328137037Sphk DROP_GIANT(); 329137037Sphk g_topology_lock(); 330137037Sphk error = g_vfs_open(devvp, &cp, "udf", 0); 331137037Sphk g_topology_unlock(); 332137037Sphk PICKUP_GIANT(); 333175294Sattilio VOP_UNLOCK(devvp, 0); 33494663Sscottl if (error) 335188502Sjhb goto bail; 33694663Sscottl 337137037Sphk bo = &devvp->v_bufobj; 338137037Sphk 339189070Savg if (devvp->v_rdev->si_iosize_max != 0) 340189070Savg mp->mnt_iosize_max = devvp->v_rdev->si_iosize_max; 341189070Savg if (mp->mnt_iosize_max > MAXPHYS) 342189070Savg mp->mnt_iosize_max = MAXPHYS; 343189070Savg 344137037Sphk /* XXX: should be M_WAITOK */ 345184205Sdes udfmp = malloc(sizeof(struct udf_mnt), M_UDFMOUNT, 34694663Sscottl M_NOWAIT | M_ZERO); 34794663Sscottl if (udfmp == NULL) { 34894663Sscottl printf("Cannot allocate UDF mount struct\n"); 34994663Sscottl error = ENOMEM; 35094663Sscottl goto bail; 35194663Sscottl } 35294663Sscottl 353172697Salfred mp->mnt_data = udfmp; 35494663Sscottl mp->mnt_stat.f_fsid.val[0] = dev2udev(devvp->v_rdev); 35594663Sscottl mp->mnt_stat.f_fsid.val[1] = mp->mnt_vfc->vfc_typenum; 356162647Stegge MNT_ILOCK(mp); 35794663Sscottl mp->mnt_flag |= MNT_LOCAL; 358242833Sattilio mp->mnt_kern_flag |= MNTK_LOOKUP_SHARED | MNTK_EXTENDED_SHARED; 359162647Stegge MNT_IUNLOCK(mp); 36094663Sscottl udfmp->im_mountp = mp; 361188502Sjhb udfmp->im_dev = dev; 36294663Sscottl udfmp->im_devvp = devvp; 363122102Sscottl udfmp->im_d2l = NULL; 364137037Sphk udfmp->im_cp = cp; 365137037Sphk udfmp->im_bo = bo; 366137037Sphk 367122102Sscottl#if 0 368122102Sscottl udfmp->im_l2d = NULL; 369122102Sscottl#endif 370151157Srodrigc /* 371151157Srodrigc * The UDF specification defines a logical sectorsize of 2048 372151157Srodrigc * for DVD media. 373151157Srodrigc */ 374151157Srodrigc logical_secsize = 2048; 37594663Sscottl 376151157Srodrigc if (((logical_secsize % cp->provider->sectorsize) != 0) || 377151157Srodrigc (logical_secsize < cp->provider->sectorsize)) { 378188502Sjhb error = EINVAL; 379188502Sjhb goto bail; 380151157Srodrigc } 38194663Sscottl 382151157Srodrigc bsize = cp->provider->sectorsize; 383151157Srodrigc 38494663Sscottl /* 38594663Sscottl * Get the Anchor Volume Descriptor Pointer from sector 256. 38694663Sscottl * XXX Should also check sector n - 256, n, and 512. 38794663Sscottl */ 38894663Sscottl sector = 256; 389151157Srodrigc if ((error = bread(devvp, sector * btodb(logical_secsize), bsize, 390151157Srodrigc NOCRED, &bp)) != 0) 39194663Sscottl goto bail; 39294663Sscottl if ((error = udf_checktag((struct desc_tag *)bp->b_data, TAGID_ANCHOR))) 39394663Sscottl goto bail; 39494663Sscottl 39594663Sscottl bcopy(bp->b_data, &avdp, sizeof(struct anchor_vdp)); 39694663Sscottl brelse(bp); 39794663Sscottl bp = NULL; 39894663Sscottl 39994663Sscottl /* 40094663Sscottl * Extract the Partition Descriptor and Logical Volume Descriptor 40194663Sscottl * from the Volume Descriptor Sequence. 40294663Sscottl * XXX Should we care about the partition type right now? 40394663Sscottl * XXX What about multiple partitions? 40494663Sscottl */ 405130986Sscottl mvds_start = le32toh(avdp.main_vds_ex.loc); 406130986Sscottl mvds_end = mvds_start + (le32toh(avdp.main_vds_ex.len) - 1) / bsize; 40794663Sscottl for (sector = mvds_start; sector < mvds_end; sector++) { 408151157Srodrigc if ((error = bread(devvp, sector * btodb(logical_secsize), 409151157Srodrigc bsize, NOCRED, &bp)) != 0) { 41094663Sscottl printf("Can't read sector %d of VDS\n", sector); 41194663Sscottl goto bail; 41294663Sscottl } 41394663Sscottl lvd = (struct logvol_desc *)bp->b_data; 41494663Sscottl if (!udf_checktag(&lvd->tag, TAGID_LOGVOL)) { 415130986Sscottl udfmp->bsize = le32toh(lvd->lb_size); 41694663Sscottl udfmp->bmask = udfmp->bsize - 1; 41794663Sscottl udfmp->bshift = ffs(udfmp->bsize) - 1; 418130986Sscottl fsd_part = le16toh(lvd->_lvd_use.fsd_loc.loc.part_num); 419130986Sscottl fsd_offset = le32toh(lvd->_lvd_use.fsd_loc.loc.lb_num); 42094663Sscottl if (udf_find_partmaps(udfmp, lvd)) 42194663Sscottl break; 42294663Sscottl logvol_found = 1; 42394663Sscottl } 42494663Sscottl pd = (struct part_desc *)bp->b_data; 42594663Sscottl if (!udf_checktag(&pd->tag, TAGID_PARTITION)) { 42694663Sscottl part_found = 1; 427130986Sscottl part_num = le16toh(pd->part_num); 428130986Sscottl udfmp->part_len = le32toh(pd->part_len); 429130986Sscottl udfmp->part_start = le32toh(pd->start_loc); 43094663Sscottl } 43194663Sscottl 43294663Sscottl brelse(bp); 43394663Sscottl bp = NULL; 43494663Sscottl if ((part_found) && (logvol_found)) 43594663Sscottl break; 43694663Sscottl } 43794663Sscottl 43894663Sscottl if (!part_found || !logvol_found) { 43994663Sscottl error = EINVAL; 44094663Sscottl goto bail; 44194663Sscottl } 44294663Sscottl 44394663Sscottl if (fsd_part != part_num) { 44494663Sscottl printf("FSD does not lie within the partition!\n"); 44594663Sscottl error = EINVAL; 44694663Sscottl goto bail; 44794663Sscottl } 44894663Sscottl 44994663Sscottl 45094663Sscottl /* 45194663Sscottl * Grab the Fileset Descriptor 45294663Sscottl * Thanks to Chuck McCrobie <mccrobie@cablespeed.com> for pointing 45394663Sscottl * me in the right direction here. 45494663Sscottl */ 45594663Sscottl sector = udfmp->part_start + fsd_offset; 45694663Sscottl if ((error = RDSECTOR(devvp, sector, udfmp->bsize, &bp)) != 0) { 45794663Sscottl printf("Cannot read sector %d of FSD\n", sector); 45894663Sscottl goto bail; 45994663Sscottl } 46094663Sscottl fsd = (struct fileset_desc *)bp->b_data; 46194663Sscottl if (!udf_checktag(&fsd->tag, TAGID_FSD)) { 46294663Sscottl fsd_found = 1; 46394663Sscottl bcopy(&fsd->rootdir_icb, &udfmp->root_icb, 46494663Sscottl sizeof(struct long_ad)); 46594663Sscottl } 46694663Sscottl 46794663Sscottl brelse(bp); 46894663Sscottl bp = NULL; 46994663Sscottl 47094663Sscottl if (!fsd_found) { 47194663Sscottl printf("Couldn't find the fsd\n"); 47294663Sscottl error = EINVAL; 47394663Sscottl goto bail; 47494663Sscottl } 47594663Sscottl 47694663Sscottl /* 47794663Sscottl * Find the file entry for the root directory. 47894663Sscottl */ 479130986Sscottl sector = le32toh(udfmp->root_icb.loc.lb_num) + udfmp->part_start; 480130986Sscottl size = le32toh(udfmp->root_icb.len); 481189082Savg if ((error = udf_readdevblks(udfmp, sector, size, &bp)) != 0) { 48294663Sscottl printf("Cannot read sector %d\n", sector); 48394663Sscottl goto bail; 48494663Sscottl } 48594663Sscottl 48694663Sscottl root_fentry = (struct file_entry *)bp->b_data; 48794663Sscottl if ((error = udf_checktag(&root_fentry->tag, TAGID_FENTRY))) { 48894663Sscottl printf("Invalid root file entry!\n"); 48994663Sscottl goto bail; 49094663Sscottl } 49194663Sscottl 49294663Sscottl brelse(bp); 49394663Sscottl bp = NULL; 49494663Sscottl 49594663Sscottl return 0; 49694663Sscottl 49794663Sscottlbail: 49894663Sscottl if (udfmp != NULL) 499184205Sdes free(udfmp, M_UDFMOUNT); 50094663Sscottl if (bp != NULL) 50194663Sscottl brelse(bp); 502188502Sjhb if (cp != NULL) { 503188502Sjhb DROP_GIANT(); 504188502Sjhb g_topology_lock(); 505188502Sjhb g_vfs_close(cp); 506188502Sjhb g_topology_unlock(); 507188502Sjhb PICKUP_GIANT(); 508188502Sjhb } 509188502Sjhb dev_rel(dev); 51094663Sscottl return error; 51194663Sscottl}; 51294663Sscottl 51394663Sscottlstatic int 514191990Sattilioudf_unmount(struct mount *mp, int mntflags) 51594663Sscottl{ 51694663Sscottl struct udf_mnt *udfmp; 51794663Sscottl int error, flags = 0; 51894663Sscottl 51994663Sscottl udfmp = VFSTOUDFFS(mp); 52094663Sscottl 52194663Sscottl if (mntflags & MNT_FORCE) 52294663Sscottl flags |= FORCECLOSE; 52394663Sscottl 524191990Sattilio if ((error = vflush(mp, 0, flags, curthread))) 52594663Sscottl return (error); 52694663Sscottl 527122102Sscottl if (udfmp->im_flags & UDFMNT_KICONV && udf_iconv) { 528122102Sscottl if (udfmp->im_d2l) 529122102Sscottl udf_iconv->close(udfmp->im_d2l); 530122102Sscottl#if 0 531122102Sscottl if (udfmp->im_l2d) 532122102Sscottl udf_iconv->close(udfmp->im_l2d); 533122102Sscottl#endif 534122102Sscottl } 535122102Sscottl 536143571Sphk DROP_GIANT(); 537143571Sphk g_topology_lock(); 538183754Sattilio g_vfs_close(udfmp->im_cp); 539143571Sphk g_topology_unlock(); 540143571Sphk PICKUP_GIANT(); 54194663Sscottl vrele(udfmp->im_devvp); 542188502Sjhb dev_rel(udfmp->im_dev); 54394663Sscottl 54494663Sscottl if (udfmp->s_table != NULL) 545184205Sdes free(udfmp->s_table, M_UDFMOUNT); 546114632Sscottl 547184205Sdes free(udfmp, M_UDFMOUNT); 54894663Sscottl 549172697Salfred mp->mnt_data = NULL; 550162647Stegge MNT_ILOCK(mp); 55194663Sscottl mp->mnt_flag &= ~MNT_LOCAL; 552162647Stegge MNT_IUNLOCK(mp); 55394663Sscottl 55494663Sscottl return (0); 55594663Sscottl} 55694663Sscottl 55794663Sscottlstatic int 558191990Sattilioudf_root(struct mount *mp, int flags, struct vnode **vpp) 55994663Sscottl{ 56094663Sscottl struct udf_mnt *udfmp; 56194663Sscottl ino_t id; 56294663Sscottl 56394663Sscottl udfmp = VFSTOUDFFS(mp); 56494663Sscottl 56594663Sscottl id = udf_getid(&udfmp->root_icb); 56694663Sscottl 567188407Sjhb return (udf_vget(mp, id, flags, vpp)); 56894663Sscottl} 56994663Sscottl 57094663Sscottlstatic int 571191990Sattilioudf_statfs(struct mount *mp, struct statfs *sbp) 57294663Sscottl{ 57394663Sscottl struct udf_mnt *udfmp; 57494663Sscottl 57594663Sscottl udfmp = VFSTOUDFFS(mp); 57694663Sscottl 57794663Sscottl sbp->f_bsize = udfmp->bsize; 57894663Sscottl sbp->f_iosize = udfmp->bsize; 57994663Sscottl sbp->f_blocks = udfmp->part_len; 58094663Sscottl sbp->f_bfree = 0; 58194663Sscottl sbp->f_bavail = 0; 58294663Sscottl sbp->f_files = 0; 58394663Sscottl sbp->f_ffree = 0; 58494663Sscottl return 0; 58594663Sscottl} 58694663Sscottl 58794663Sscottlint 58894663Sscottludf_vget(struct mount *mp, ino_t ino, int flags, struct vnode **vpp) 58994663Sscottl{ 59094663Sscottl struct buf *bp; 59194663Sscottl struct vnode *devvp; 59294663Sscottl struct udf_mnt *udfmp; 59394663Sscottl struct thread *td; 59494663Sscottl struct vnode *vp; 59594663Sscottl struct udf_node *unode; 59694663Sscottl struct file_entry *fe; 59794663Sscottl int error, sector, size; 59894663Sscottl 599143692Sphk error = vfs_hash_get(mp, ino, flags, curthread, vpp, NULL, NULL); 600143619Sphk if (error || *vpp != NULL) 601143571Sphk return (error); 602143571Sphk 603188407Sjhb /* 604188407Sjhb * We must promote to an exclusive lock for vnode creation. This 605188407Sjhb * can happen if lookup is passed LOCKSHARED. 606188407Sjhb */ 607188407Sjhb if ((flags & LK_TYPE_MASK) == LK_SHARED) { 608188407Sjhb flags &= ~LK_TYPE_MASK; 609188407Sjhb flags |= LK_EXCLUSIVE; 610188407Sjhb } 611188407Sjhb 612188407Sjhb /* 613188407Sjhb * We do not lock vnode creation as it is believed to be too 614188407Sjhb * expensive for such rare case as simultaneous creation of vnode 615188407Sjhb * for same ino by different processes. We just allow them to race 616188407Sjhb * and check later to decide who wins. Let the race begin! 617188407Sjhb */ 618188407Sjhb 61994663Sscottl td = curthread; 62094663Sscottl udfmp = VFSTOUDFFS(mp); 62194663Sscottl 622143571Sphk unode = uma_zalloc(udf_zone_node, M_WAITOK | M_ZERO); 623143571Sphk 624143571Sphk if ((error = udf_allocv(mp, &vp, td))) { 625143571Sphk printf("Error from udf_allocv\n"); 626143571Sphk uma_zfree(udf_zone_node, unode); 62794663Sscottl return (error); 62894663Sscottl } 62994663Sscottl 630143571Sphk unode->i_vnode = vp; 631143571Sphk unode->hash_id = ino; 632143571Sphk unode->udfmp = udfmp; 633143571Sphk vp->v_data = unode; 634143571Sphk 635175635Sattilio lockmgr(vp->v_vnlock, LK_EXCLUSIVE, NULL); 636167497Stegge error = insmntque(vp, mp); 637167497Stegge if (error != 0) { 638167497Stegge uma_zfree(udf_zone_node, unode); 639167497Stegge return (error); 640167497Stegge } 641167497Stegge error = vfs_hash_insert(vp, ino, flags, td, vpp, NULL, NULL); 642143663Sphk if (error || *vpp != NULL) 643143571Sphk return (error); 64494663Sscottl 64594663Sscottl /* 64694663Sscottl * Copy in the file entry. Per the spec, the size can only be 1 block. 64794663Sscottl */ 64894663Sscottl sector = ino + udfmp->part_start; 64994663Sscottl devvp = udfmp->im_devvp; 65094663Sscottl if ((error = RDSECTOR(devvp, sector, udfmp->bsize, &bp)) != 0) { 65194663Sscottl printf("Cannot read sector %d\n", sector); 652175436Skib vgone(vp); 653143571Sphk vput(vp); 654143571Sphk brelse(bp); 655143571Sphk *vpp = NULL; 65694663Sscottl return (error); 65794663Sscottl } 65894663Sscottl 65994663Sscottl fe = (struct file_entry *)bp->b_data; 66094663Sscottl if (udf_checktag(&fe->tag, TAGID_FENTRY)) { 66194663Sscottl printf("Invalid file entry!\n"); 662175436Skib vgone(vp); 663143571Sphk vput(vp); 66494663Sscottl brelse(bp); 665143571Sphk *vpp = NULL; 66694663Sscottl return (ENOMEM); 66794663Sscottl } 668130986Sscottl size = UDF_FENTRY_SIZE + le32toh(fe->l_ea) + le32toh(fe->l_ad); 669184214Sdes unode->fentry = malloc(size, M_UDFFENTRY, M_NOWAIT | M_ZERO); 67094663Sscottl if (unode->fentry == NULL) { 67194663Sscottl printf("Cannot allocate file entry block\n"); 672175436Skib vgone(vp); 673143571Sphk vput(vp); 67494663Sscottl brelse(bp); 675143571Sphk *vpp = NULL; 67694663Sscottl return (ENOMEM); 67794663Sscottl } 67894663Sscottl 67994663Sscottl bcopy(bp->b_data, unode->fentry, size); 68094663Sscottl 68194663Sscottl brelse(bp); 68294663Sscottl bp = NULL; 68394663Sscottl 68494663Sscottl switch (unode->fentry->icbtag.file_type) { 68594663Sscottl default: 68694663Sscottl vp->v_type = VBAD; 68794663Sscottl break; 68894663Sscottl case 4: 68994663Sscottl vp->v_type = VDIR; 69094663Sscottl break; 69194663Sscottl case 5: 69294663Sscottl vp->v_type = VREG; 69394663Sscottl break; 69494663Sscottl case 6: 69594663Sscottl vp->v_type = VBLK; 69694663Sscottl break; 69794663Sscottl case 7: 69894663Sscottl vp->v_type = VCHR; 69994663Sscottl break; 70094663Sscottl case 9: 70194663Sscottl vp->v_type = VFIFO; 702188245Sjhb vp->v_op = &udf_fifoops; 70394663Sscottl break; 70494663Sscottl case 10: 70594663Sscottl vp->v_type = VSOCK; 70694663Sscottl break; 70794663Sscottl case 12: 70894663Sscottl vp->v_type = VLNK; 70994663Sscottl break; 71094663Sscottl } 711188407Sjhb 712210172Sjhb if (vp->v_type != VFIFO) 713188407Sjhb VN_LOCK_ASHARE(vp); 714188407Sjhb 715188407Sjhb if (ino == udf_getid(&udfmp->root_icb)) 716188407Sjhb vp->v_vflag |= VV_ROOT; 717188407Sjhb 71894663Sscottl *vpp = vp; 71994663Sscottl 72094663Sscottl return (0); 72194663Sscottl} 72294663Sscottl 72394663Sscottlstatic int 724222167Srmacklemudf_fhtovp(struct mount *mp, struct fid *fhp, int flags, struct vnode **vpp) 72594663Sscottl{ 72694663Sscottl struct ifid *ifhp; 72794663Sscottl struct vnode *nvp; 728165879Spav struct udf_node *np; 729165879Spav off_t fsize; 73094663Sscottl int error; 73194663Sscottl 73294663Sscottl ifhp = (struct ifid *)fhp; 73394663Sscottl 73494663Sscottl if ((error = VFS_VGET(mp, ifhp->ifid_ino, LK_EXCLUSIVE, &nvp)) != 0) { 73594663Sscottl *vpp = NULLVP; 73694663Sscottl return (error); 73794663Sscottl } 73894663Sscottl 739165879Spav np = VTON(nvp); 740165879Spav fsize = le64toh(np->fentry->inf_len); 741165879Spav 74294663Sscottl *vpp = nvp; 743165879Spav vnode_create_vobject(*vpp, fsize, curthread); 74494663Sscottl return (0); 74594663Sscottl} 74694663Sscottl 74794663Sscottlstatic int 74894663Sscottludf_find_partmaps(struct udf_mnt *udfmp, struct logvol_desc *lvd) 74994663Sscottl{ 75094663Sscottl struct part_map_spare *pms; 75194663Sscottl struct regid *pmap_id; 75294663Sscottl struct buf *bp; 75394663Sscottl unsigned char regid_id[UDF_REGID_ID_SIZE + 1]; 754159939Sscottl int i, k, ptype, psize, error; 755160664Syar uint8_t *pmap = (uint8_t *) &lvd->maps[0]; 75694663Sscottl 757130986Sscottl for (i = 0; i < le32toh(lvd->n_pm); i++) { 758160664Syar ptype = pmap[0]; 759160664Syar psize = pmap[1]; 76094663Sscottl if (((ptype != 1) && (ptype != 2)) || 761160664Syar ((psize != UDF_PMAP_TYPE1_SIZE) && 762160664Syar (psize != UDF_PMAP_TYPE2_SIZE))) { 76394663Sscottl printf("Invalid partition map found\n"); 76494663Sscottl return (1); 76594663Sscottl } 76694663Sscottl 76794663Sscottl if (ptype == 1) { 76894663Sscottl /* Type 1 map. We don't care */ 769160664Syar pmap += UDF_PMAP_TYPE1_SIZE; 77094663Sscottl continue; 77194663Sscottl } 77294663Sscottl 77394663Sscottl /* Type 2 map. Gotta find out the details */ 774160664Syar pmap_id = (struct regid *)&pmap[4]; 77594663Sscottl bzero(®id_id[0], UDF_REGID_ID_SIZE); 77694663Sscottl bcopy(&pmap_id->id[0], ®id_id[0], UDF_REGID_ID_SIZE); 77794663Sscottl 77894663Sscottl if (bcmp(®id_id[0], "*UDF Sparable Partition", 77994663Sscottl UDF_REGID_ID_SIZE)) { 78094663Sscottl printf("Unsupported partition map: %s\n", ®id_id[0]); 78194663Sscottl return (1); 78294663Sscottl } 78394663Sscottl 784160664Syar pms = (struct part_map_spare *)pmap; 785160664Syar pmap += UDF_PMAP_TYPE2_SIZE; 786184214Sdes udfmp->s_table = malloc(le32toh(pms->st_size), 787184214Sdes M_UDFMOUNT, M_NOWAIT | M_ZERO); 78894663Sscottl if (udfmp->s_table == NULL) 78994663Sscottl return (ENOMEM); 79094663Sscottl 79194663Sscottl /* Calculate the number of sectors per packet. */ 79294663Sscottl /* XXX Logical or physical? */ 793130986Sscottl udfmp->p_sectors = le16toh(pms->packet_len) / udfmp->bsize; 79494663Sscottl 79594663Sscottl /* 79694663Sscottl * XXX If reading the first Sparing Table fails, should look 79794663Sscottl * for another table. 79894663Sscottl */ 799189082Savg if ((error = udf_readdevblks(udfmp, le32toh(pms->st_loc[0]), 800130986Sscottl le32toh(pms->st_size), &bp)) != 0) { 801127603Sscottl if (bp != NULL) 802127603Sscottl brelse(bp); 80394663Sscottl printf("Failed to read Sparing Table at sector %d\n", 804130986Sscottl le32toh(pms->st_loc[0])); 805184205Sdes free(udfmp->s_table, M_UDFMOUNT); 80694663Sscottl return (error); 80794663Sscottl } 808130986Sscottl bcopy(bp->b_data, udfmp->s_table, le32toh(pms->st_size)); 80994663Sscottl brelse(bp); 81094663Sscottl 81194663Sscottl if (udf_checktag(&udfmp->s_table->tag, 0)) { 81294663Sscottl printf("Invalid sparing table found\n"); 813184205Sdes free(udfmp->s_table, M_UDFMOUNT); 81494663Sscottl return (EINVAL); 81594663Sscottl } 81694663Sscottl 81794663Sscottl /* See how many valid entries there are here. The list is 81894663Sscottl * supposed to be sorted. 0xfffffff0 and higher are not valid 81994663Sscottl */ 820159939Sscottl for (k = 0; k < le16toh(udfmp->s_table->rt_l); k++) { 821159939Sscottl udfmp->s_table_entries = k; 822159939Sscottl if (le32toh(udfmp->s_table->entries[k].org) >= 823130986Sscottl 0xfffffff0) 82494663Sscottl break; 82594663Sscottl } 82694663Sscottl } 82794663Sscottl 82894663Sscottl return (0); 82994663Sscottl} 830