1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  23  * Use is subject to license terms.
  24  * Copyright (c) 2011 Bayard G. Bell. All rights reserved.
  25  */
  26 
  27 #include <sys/types.h>
  28 #include <sys/t_lock.h>
  29 #include <sys/param.h>
  30 #include <sys/time.h>
  31 #include <sys/systm.h>
  32 #include <sys/sysmacros.h>
  33 #include <sys/resource.h>
  34 #include <sys/signal.h>
  35 #include <sys/cred.h>
  36 #include <sys/user.h>
  37 #include <sys/buf.h>
  38 #include <sys/vfs.h>
  39 #include <sys/vfs_opreg.h>
  40 #include <sys/stat.h>
  41 #include <sys/vnode.h>
  42 #include <sys/mode.h>
  43 #include <sys/proc.h>
  44 #include <sys/disp.h>
  45 #include <sys/file.h>
  46 #include <sys/fcntl.h>
  47 #include <sys/flock.h>
  48 #include <sys/kmem.h>
  49 #include <sys/uio.h>
  50 #include <sys/dnlc.h>
  51 #include <sys/conf.h>
  52 #include <sys/errno.h>
  53 #include <sys/mman.h>
  54 #include <sys/fbuf.h>
  55 #include <sys/pathname.h>
  56 #include <sys/debug.h>
  57 #include <sys/vmsystm.h>
  58 #include <sys/cmn_err.h>
  59 #include <sys/dirent.h>
  60 #include <sys/errno.h>
  61 #include <sys/modctl.h>
  62 #include <sys/statvfs.h>
  63 #include <sys/mount.h>
  64 #include <sys/sunddi.h>
  65 #include <sys/bootconf.h>
  66 #include <sys/policy.h>
  67 
  68 #include <vm/hat.h>
  69 #include <vm/page.h>
  70 #include <vm/pvn.h>
  71 #include <vm/as.h>
  72 #include <vm/seg.h>
  73 #include <vm/seg_map.h>
  74 #include <vm/seg_kmem.h>
  75 #include <vm/seg_vn.h>
  76 #include <vm/rm.h>
  77 #include <vm/page.h>
  78 #include <sys/swap.h>
  79 #include <sys/mntent.h>
  80 
  81 
  82 #include <fs/fs_subr.h>
  83 
  84 
  85 #include <sys/fs/udf_volume.h>
  86 #include <sys/fs/udf_inode.h>
  87 
  88 
  89 extern struct vnode *common_specvp(struct vnode *vp);
  90 
  91 extern kmutex_t ud_sync_busy;
  92 static int32_t ud_mountfs(struct vfs *,
  93     enum whymountroot, dev_t, char *, struct cred *, int32_t);
  94 static struct udf_vfs *ud_validate_and_fill_superblock(dev_t,
  95     int32_t, uint32_t);
  96 void ud_destroy_fsp(struct udf_vfs *);
  97 void ud_convert_to_superblock(struct udf_vfs *,
  98     struct log_vol_int_desc *);
  99 void ud_update_superblock(struct vfs *);
 100 int32_t ud_get_last_block(dev_t, daddr_t *);
 101 static int32_t ud_val_get_vat(struct udf_vfs *,
 102     dev_t, daddr_t, struct ud_map *);
 103 int32_t ud_read_sparing_tbls(struct udf_vfs *,
 104     dev_t, struct ud_map *, struct pmap_typ2 *);
 105 uint32_t ud_get_lbsize(dev_t, uint32_t *);
 106 
 107 static int32_t udf_mount(struct vfs *,
 108     struct vnode *, struct mounta *, struct cred *);
 109 static int32_t udf_unmount(struct vfs *, int, struct cred *);
 110 static int32_t udf_root(struct vfs *, struct vnode **);
 111 static int32_t udf_statvfs(struct vfs *, struct statvfs64 *);
 112 static int32_t udf_sync(struct vfs *, int16_t, struct cred *);
 113 static int32_t udf_vget(struct vfs *, struct vnode **, struct fid *);
 114 static int32_t udf_mountroot(struct vfs *vfsp, enum whymountroot);
 115 
 116 static int udfinit(int, char *);
 117 
 118 static mntopts_t udfs_mntopts;
 119 
 120 static vfsdef_t vfw = {
 121         VFSDEF_VERSION,
 122         "udfs",
 123         udfinit,
 124         VSW_HASPROTO|VSW_CANREMOUNT|VSW_STATS|VSW_CANLOFI,
 125         &udfs_mntopts
 126 };
 127 
 128 static mntopts_t udfs_mntopts = {
 129         0,
 130         NULL
 131 };
 132 
 133 /*
 134  * Module linkage information for the kernel.
 135  */
 136 extern struct mod_ops mod_fsops;
 137 
 138 static struct modlfs modlfs = {
 139         &mod_fsops, "filesystem for UDFS", &vfw
 140 };
 141 
 142 static struct modlinkage modlinkage = {
 143         MODREV_1, { (void *)&modlfs, NULL }
 144 };
 145 
 146 int32_t udf_fstype = -1;
 147 
 148 int
 149 _init()
 150 {
 151         return (mod_install(&modlinkage));
 152 }
 153 
 154 int
 155 _fini()
 156 {
 157         return (EBUSY);
 158 }
 159 
 160 int
 161 _info(struct modinfo *modinfop)
 162 {
 163         return (mod_info(&modlinkage, modinfop));
 164 }
 165 
 166 
 167 /* -------------------- vfs routines -------------------- */
 168 
 169 /*
 170  * XXX - this appears only to be used by the VM code to handle the case where
 171  * UNIX is running off the mini-root.  That probably wants to be done
 172  * differently.
 173  */
 174 struct vnode *rootvp;
 175 #ifndef __lint
 176 _NOTE(SCHEME_PROTECTS_DATA("safe sharing", rootvp))
 177 #endif
 178 static int32_t
 179 udf_mount(struct vfs *vfsp, struct vnode *mvp,
 180         struct mounta *uap, struct cred *cr)
 181 {
 182         dev_t dev;
 183         struct vnode *lvp = NULL;
 184         struct vnode *svp = NULL;
 185         struct pathname dpn;
 186         int32_t error;
 187         enum whymountroot why;
 188         int oflag, aflag;
 189 
 190         ud_printf("udf_mount\n");
 191 
 192         if ((error = secpolicy_fs_mount(cr, mvp, vfsp)) != 0) {
 193                 return (error);
 194         }
 195 
 196         if (mvp->v_type != VDIR) {
 197                 return (ENOTDIR);
 198         }
 199 
 200         mutex_enter(&mvp->v_lock);
 201         if ((uap->flags & MS_REMOUNT) == 0 &&
 202             (uap->flags & MS_OVERLAY) == 0 &&
 203             (mvp->v_count != 1 || (mvp->v_flag & VROOT))) {
 204                 mutex_exit(&mvp->v_lock);
 205                 return (EBUSY);
 206         }
 207         mutex_exit(&mvp->v_lock);
 208 
 209         if (error = pn_get(uap->dir, UIO_USERSPACE, &dpn)) {
 210                 return (error);
 211         }
 212 
 213         /*
 214          * Resolve path name of the file being mounted.
 215          */
 216         if (error = lookupname(uap->spec, UIO_USERSPACE, FOLLOW, NULLVPP,
 217             &svp)) {
 218                 pn_free(&dpn);
 219                 return (error);
 220         }
 221 
 222         error = vfs_get_lofi(vfsp, &lvp);
 223 
 224         if (error > 0) {
 225                 if (error == ENOENT)
 226                         error = ENODEV;
 227                 goto out;
 228         } else if (error == 0) {
 229                 dev = lvp->v_rdev;
 230         } else {
 231                 dev = svp->v_rdev;
 232 
 233                 if (svp->v_type != VBLK) {
 234                         error = ENOTBLK;
 235                         goto out;
 236                 }
 237         }
 238 
 239         /*
 240          * Ensure that this device isn't already mounted,
 241          * unless this is a REMOUNT request
 242          */
 243         if (vfs_devmounting(dev, vfsp)) {
 244                 error = EBUSY;
 245                 goto out;
 246         }
 247         if (vfs_devismounted(dev)) {
 248                 if (uap->flags & MS_REMOUNT) {
 249                         why = ROOT_REMOUNT;
 250                 } else {
 251                         error = EBUSY;
 252                         goto out;
 253                 }
 254         } else {
 255                 why = ROOT_INIT;
 256         }
 257         if (getmajor(dev) >= devcnt) {
 258                 error = ENXIO;
 259                 goto out;
 260         }
 261 
 262         /*
 263          * If the device is a tape, mount it read only
 264          */
 265         if (devopsp[getmajor(dev)]->devo_cb_ops->cb_flag & D_TAPE) {
 266                 vfsp->vfs_flag |= VFS_RDONLY;
 267         }
 268 
 269         if (uap->flags & MS_RDONLY) {
 270                 vfsp->vfs_flag |= VFS_RDONLY;
 271         }
 272 
 273         /*
 274          * Set mount options.
 275          */
 276         if (uap->flags & MS_RDONLY) {
 277                 vfs_setmntopt(vfsp, MNTOPT_RO, NULL, 0);
 278         }
 279         if (uap->flags & MS_NOSUID) {
 280                 vfs_setmntopt(vfsp, MNTOPT_NOSUID, NULL, 0);
 281         }
 282 
 283         /*
 284          * Verify that the caller can open the device special file as
 285          * required.  It is not until this moment that we know whether
 286          * we're mounting "ro" or not.
 287          */
 288         if ((vfsp->vfs_flag & VFS_RDONLY) != 0) {
 289                 oflag = FREAD;
 290                 aflag = VREAD;
 291         } else {
 292                 oflag = FREAD | FWRITE;
 293                 aflag = VREAD | VWRITE;
 294         }
 295 
 296         if (lvp == NULL &&
 297             (error = secpolicy_spec_open(cr, svp, oflag)) != 0)
 298                 goto out;
 299 
 300         if ((error = VOP_ACCESS(svp, aflag, 0, cr, NULL)) != 0)
 301                 goto out;
 302 
 303         /*
 304          * Mount the filesystem.
 305          */
 306         error = ud_mountfs(vfsp, why, dev, dpn.pn_path, cr, 0);
 307 out:
 308         VN_RELE(svp);
 309         if (lvp != NULL)
 310                 VN_RELE(lvp);
 311         pn_free(&dpn);
 312         return (error);
 313 }
 314 
 315 
 316 
 317 /*
 318  * unmount the file system pointed
 319  * by vfsp
 320  */
 321 /* ARGSUSED */
 322 static int32_t
 323 udf_unmount(struct vfs *vfsp, int fflag, struct cred *cr)
 324 {
 325         struct udf_vfs *udf_vfsp;
 326         struct vnode *bvp, *rvp;
 327         struct ud_inode *rip;
 328         int32_t flag;
 329 
 330         ud_printf("udf_unmount\n");
 331 
 332         if (secpolicy_fs_unmount(cr, vfsp) != 0) {
 333                 return (EPERM);
 334         }
 335 
 336         /*
 337          * forced unmount is not supported by this file system
 338          * and thus, ENOTSUP, is being returned.
 339          */
 340         if (fflag & MS_FORCE)
 341                 return (ENOTSUP);
 342 
 343         udf_vfsp = (struct udf_vfs *)vfsp->vfs_data;
 344         flag = !(udf_vfsp->udf_flags & UDF_FL_RDONLY);
 345         bvp = udf_vfsp->udf_devvp;
 346 
 347         rvp = udf_vfsp->udf_root;
 348         ASSERT(rvp != NULL);
 349         rip = VTOI(rvp);
 350 
 351         (void) ud_release_cache(udf_vfsp);
 352 
 353 
 354         /* Flush all inodes except root */
 355         if (ud_iflush(vfsp) < 0) {
 356                 return (EBUSY);
 357         }
 358 
 359         rw_enter(&rip->i_contents, RW_WRITER);
 360         (void) ud_syncip(rip, B_INVAL, I_SYNC);
 361         rw_exit(&rip->i_contents);
 362 
 363         mutex_enter(&ud_sync_busy);
 364         if ((udf_vfsp->udf_flags & UDF_FL_RDONLY) == 0) {
 365                 bflush(vfsp->vfs_dev);
 366                 mutex_enter(&udf_vfsp->udf_lock);
 367                 udf_vfsp->udf_clean = UDF_CLEAN;
 368                 mutex_exit(&udf_vfsp->udf_lock);
 369                 ud_update_superblock(vfsp);
 370         }
 371         mutex_exit(&ud_sync_busy);
 372 
 373         mutex_destroy(&udf_vfsp->udf_lock);
 374         mutex_destroy(&udf_vfsp->udf_rename_lck);
 375 
 376         ud_delcache(rip);
 377         ITIMES(rip);
 378         VN_RELE(rvp);
 379 
 380         ud_destroy_fsp(udf_vfsp);
 381 
 382         (void) VOP_PUTPAGE(bvp, (offset_t)0, (uint32_t)0, B_INVAL, cr, NULL);
 383         (void) VOP_CLOSE(bvp, flag, 1, (offset_t)0, cr, NULL);
 384 
 385         (void) bfinval(vfsp->vfs_dev, 1);
 386         VN_RELE(bvp);
 387 
 388 
 389         return (0);
 390 }
 391 
 392 
 393 /*
 394  * Get the root vp for the
 395  * file system
 396  */
 397 static int32_t
 398 udf_root(struct vfs *vfsp, struct vnode **vpp)
 399 {
 400         struct udf_vfs *udf_vfsp;
 401         struct vnode *vp;
 402 
 403         ud_printf("udf_root\n");
 404 
 405         udf_vfsp = (struct udf_vfs *)vfsp->vfs_data;
 406 
 407         ASSERT(udf_vfsp != NULL);
 408         ASSERT(udf_vfsp->udf_root != NULL);
 409 
 410         vp = udf_vfsp->udf_root;
 411         VN_HOLD(vp);
 412         *vpp = vp;
 413         return (0);
 414 }
 415 
 416 
 417 /*
 418  * Get file system statistics.
 419  */
 420 static int32_t
 421 udf_statvfs(struct vfs *vfsp, struct statvfs64 *sp)
 422 {
 423         struct udf_vfs *udf_vfsp;
 424         struct ud_part *parts;
 425         dev32_t d32;
 426         int32_t index;
 427 
 428         ud_printf("udf_statvfs\n");
 429 
 430         udf_vfsp = (struct udf_vfs *)vfsp->vfs_data;
 431         (void) bzero(sp, sizeof (struct statvfs64));
 432 
 433         mutex_enter(&udf_vfsp->udf_lock);
 434         sp->f_bsize = udf_vfsp->udf_lbsize;
 435         sp->f_frsize = udf_vfsp->udf_lbsize;
 436         sp->f_blocks = 0;
 437         sp->f_bfree = 0;
 438         parts = udf_vfsp->udf_parts;
 439         for (index = 0; index < udf_vfsp->udf_npart; index++) {
 440                 sp->f_blocks += parts->udp_nblocks;
 441                 sp->f_bfree += parts->udp_nfree;
 442                 parts++;
 443         }
 444         sp->f_bavail = sp->f_bfree;
 445 
 446         /*
 447          * Since there are no real inodes allocated
 448          * we will approximate
 449          * each new file will occupy :
 450          * 38(over head each dent) + MAXNAMLEN / 2 + inode_size(==block size)
 451          */
 452         sp->f_ffree = sp->f_favail =
 453             (sp->f_bavail * sp->f_bsize) / (146 + sp->f_bsize);
 454 
 455         /*
 456          * The total number of inodes is
 457          * the sum of files + directories + free inodes
 458          */
 459         sp->f_files = sp->f_ffree + udf_vfsp->udf_nfiles + udf_vfsp->udf_ndirs;
 460         (void) cmpldev(&d32, vfsp->vfs_dev);
 461         sp->f_fsid = d32;
 462         (void) strcpy(sp->f_basetype, vfssw[vfsp->vfs_fstype].vsw_name);
 463         sp->f_flag = vf_to_stf(vfsp->vfs_flag);
 464         sp->f_namemax = MAXNAMLEN;
 465         (void) strcpy(sp->f_fstr, udf_vfsp->udf_volid);
 466 
 467         mutex_exit(&udf_vfsp->udf_lock);
 468 
 469         return (0);
 470 }
 471 
 472 
 473 /*
 474  * Flush any pending I/O to file system vfsp.
 475  * The ud_update() routine will only flush *all* udf files.
 476  */
 477 /*ARGSUSED*/
 478 /* ARGSUSED */
 479 static int32_t
 480 udf_sync(struct vfs *vfsp, int16_t flag, struct cred *cr)
 481 {
 482         ud_printf("udf_sync\n");
 483 
 484         ud_update(flag);
 485         return (0);
 486 }
 487 
 488 
 489 
 490 /* ARGSUSED */
 491 static int32_t
 492 udf_vget(struct vfs *vfsp,
 493         struct vnode **vpp, struct fid *fidp)
 494 {
 495         int32_t error = 0;
 496         struct udf_fid *udfid;
 497         struct udf_vfs *udf_vfsp;
 498         struct ud_inode *ip;
 499 
 500         ud_printf("udf_vget\n");
 501 
 502         udf_vfsp = (struct udf_vfs *)vfsp->vfs_data;
 503         if (udf_vfsp == NULL) {
 504                 *vpp = NULL;
 505                 return (0);
 506         }
 507 
 508         udfid = (struct udf_fid *)fidp;
 509         if ((error = ud_iget(vfsp, udfid->udfid_prn,
 510             udfid->udfid_icb_lbn, &ip, NULL, CRED())) != 0) {
 511                 *vpp = NULL;
 512                 return (error);
 513         }
 514 
 515         rw_enter(&ip->i_contents, RW_READER);
 516         if ((udfid->udfid_uinq_lo != (ip->i_uniqid & 0xffffffff)) ||
 517             (udfid->udfid_prn != ip->i_icb_prn)) {
 518                 rw_exit(&ip->i_contents);
 519                 VN_RELE(ITOV(ip));
 520                 *vpp = NULL;
 521                 return (EINVAL);
 522         }
 523         rw_exit(&ip->i_contents);
 524 
 525         *vpp = ITOV(ip);
 526         return (0);
 527 }
 528 
 529 
 530 /*
 531  * Mount root file system.
 532  * "why" is ROOT_INIT on initial call, ROOT_REMOUNT if called to
 533  * remount the root file system, and ROOT_UNMOUNT if called to
 534  * unmount the root (e.g., as part of a system shutdown).
 535  *
 536  * XXX - this may be partially machine-dependent; it, along with the VFS_SWAPVP
 537  * operation, goes along with auto-configuration.  A mechanism should be
 538  * provided by which machine-INdependent code in the kernel can say "get me the
 539  * right root file system" and "get me the right initial swap area", and have
 540  * that done in what may well be a machine-dependent fashion.
 541  * Unfortunately, it is also file-system-type dependent (NFS gets it via
 542  * bootparams calls, UFS gets it from various and sundry machine-dependent
 543  * mechanisms, as SPECFS does for swap).
 544  */
 545 /* ARGSUSED */
 546 static int32_t
 547 udf_mountroot(struct vfs *vfsp, enum whymountroot why)
 548 {
 549         dev_t rootdev;
 550         static int32_t udf_rootdone = 0;
 551         struct vnode *vp = NULL;
 552         int32_t ovflags, error;
 553         ud_printf("udf_mountroot\n");
 554 
 555         if (why == ROOT_INIT) {
 556                 if (udf_rootdone++) {
 557                         return (EBUSY);
 558                 }
 559                 rootdev = getrootdev();
 560                 if (rootdev == (dev_t)NODEV) {
 561                         return (ENODEV);
 562                 }
 563                 vfsp->vfs_dev = rootdev;
 564                 vfsp->vfs_flag |= VFS_RDONLY;
 565         } else if (why == ROOT_REMOUNT) {
 566                 vp = ((struct udf_vfs *)vfsp->vfs_data)->udf_devvp;
 567                 (void) dnlc_purge_vfsp(vfsp, 0);
 568                 vp = common_specvp(vp);
 569                 (void) VOP_PUTPAGE(vp, (offset_t)0,
 570                     (uint32_t)0, B_INVAL, CRED(), NULL);
 571                 binval(vfsp->vfs_dev);
 572 
 573                 ovflags = vfsp->vfs_flag;
 574                 vfsp->vfs_flag &= ~VFS_RDONLY;
 575                 vfsp->vfs_flag |= VFS_REMOUNT;
 576                 rootdev = vfsp->vfs_dev;
 577         } else if (why == ROOT_UNMOUNT) {
 578                 ud_update(0);
 579                 vp = ((struct udf_vfs *)vfsp->vfs_data)->udf_devvp;
 580                 (void) VOP_CLOSE(vp, FREAD|FWRITE, 1,
 581                     (offset_t)0, CRED(), NULL);
 582                 return (0);
 583         }
 584 
 585         if ((error = vfs_lock(vfsp)) != 0) {
 586                 return (error);
 587         }
 588 
 589         error = ud_mountfs(vfsp, why, rootdev, "/", CRED(), 1);
 590         if (error) {
 591                 vfs_unlock(vfsp);
 592                 if (why == ROOT_REMOUNT) {
 593                         vfsp->vfs_flag = ovflags;
 594                 }
 595                 if (rootvp) {
 596                         VN_RELE(rootvp);
 597                         rootvp = (struct vnode *)0;
 598                 }
 599                 return (error);
 600         }
 601 
 602         if (why == ROOT_INIT) {
 603                 vfs_add((struct vnode *)0, vfsp,
 604                     (vfsp->vfs_flag & VFS_RDONLY) ? MS_RDONLY : 0);
 605         }
 606         vfs_unlock(vfsp);
 607         return (0);
 608 }
 609 
 610 
 611 /* ------------------------- local routines ------------------------- */
 612 
 613 
 614 static int32_t
 615 ud_mountfs(struct vfs *vfsp,
 616         enum whymountroot why, dev_t dev, char *name,
 617         struct cred *cr, int32_t isroot)
 618 {
 619         struct vnode *devvp = NULL;
 620         int32_t error = 0;
 621         int32_t needclose = 0;
 622         struct udf_vfs *udf_vfsp = NULL;
 623         struct log_vol_int_desc *lvid;
 624         struct ud_inode *rip = NULL;
 625         struct vnode *rvp = NULL;
 626         int32_t i, lbsize;
 627         uint32_t avd_loc;
 628         struct ud_map *map;
 629         int32_t desc_len;
 630 
 631         ud_printf("ud_mountfs\n");
 632 
 633         if (why == ROOT_INIT) {
 634                 /*
 635                  * Open the device.
 636                  */
 637                 devvp = makespecvp(dev, VBLK);
 638 
 639                 /*
 640                  * Open block device mounted on.
 641                  * When bio is fixed for vnodes this can all be vnode
 642                  * operations.
 643                  */
 644                 error = VOP_OPEN(&devvp,
 645                     (vfsp->vfs_flag & VFS_RDONLY) ? FREAD : FREAD|FWRITE,
 646                     cr, NULL);
 647                 if (error) {
 648                         goto out;
 649                 }
 650                 needclose = 1;
 651 
 652                 /*
 653                  * Refuse to go any further if this
 654                  * device is being used for swapping.
 655                  */
 656                 if (IS_SWAPVP(devvp)) {
 657                         error = EBUSY;
 658                         goto out;
 659                 }
 660         }
 661 
 662         /*
 663          * check for dev already mounted on
 664          */
 665         if (vfsp->vfs_flag & VFS_REMOUNT) {
 666                 struct tag *ttag;
 667                 int32_t index, count;
 668                 struct buf *tpt = 0;
 669                 caddr_t addr;
 670 
 671 
 672                 /* cannot remount to RDONLY */
 673                 if (vfsp->vfs_flag & VFS_RDONLY) {
 674                         return (EINVAL);
 675                 }
 676 
 677                 if (vfsp->vfs_dev != dev) {
 678                         return (EINVAL);
 679                 }
 680 
 681                 udf_vfsp = (struct udf_vfs *)vfsp->vfs_data;
 682                 devvp = udf_vfsp->udf_devvp;
 683 
 684                 /*
 685                  * fsck may have altered the file system; discard
 686                  * as much incore data as possible.  Don't flush
 687                  * if this is a rw to rw remount; it's just resetting
 688                  * the options.
 689                  */
 690                 if (udf_vfsp->udf_flags & UDF_FL_RDONLY) {
 691                         (void) dnlc_purge_vfsp(vfsp, 0);
 692                         (void) VOP_PUTPAGE(devvp, (offset_t)0, (uint_t)0,
 693                             B_INVAL, CRED(), NULL);
 694                         (void) ud_iflush(vfsp);
 695                         bflush(dev);
 696                         binval(dev);
 697                 }
 698 
 699                 /*
 700                  * We could read UDF1.50 and write UDF1.50 only
 701                  * disallow mount of any highier version
 702                  */
 703                 if ((udf_vfsp->udf_miread > UDF_150) ||
 704                     (udf_vfsp->udf_miwrite > UDF_150)) {
 705                         error = EINVAL;
 706                         goto remountout;
 707                 }
 708 
 709                 /*
 710                  * read/write to read/write; all done
 711                  */
 712                 if (udf_vfsp->udf_flags & UDF_FL_RW) {
 713                         goto remountout;
 714                 }
 715 
 716                 /*
 717                  * Does the media type allow a writable mount
 718                  */
 719                 if (udf_vfsp->udf_mtype != UDF_MT_OW) {
 720                         error = EINVAL;
 721                         goto remountout;
 722                 }
 723 
 724                 /*
 725                  * Read the metadata
 726                  * and check if it is possible to
 727                  * mount in rw mode
 728                  */
 729                 tpt = ud_bread(vfsp->vfs_dev,
 730                     udf_vfsp->udf_iseq_loc << udf_vfsp->udf_l2d_shift,
 731                     udf_vfsp->udf_iseq_len);
 732                 if (tpt->b_flags & B_ERROR) {
 733                         error = EIO;
 734                         goto remountout;
 735                 }
 736                 count = udf_vfsp->udf_iseq_len / DEV_BSIZE;
 737                 addr = tpt->b_un.b_addr;
 738                 for (index = 0; index < count; index ++) {
 739                         ttag = (struct tag *)(addr + index * DEV_BSIZE);
 740                         desc_len = udf_vfsp->udf_iseq_len - (index * DEV_BSIZE);
 741                         if (ud_verify_tag_and_desc(ttag, UD_LOG_VOL_INT,
 742                             udf_vfsp->udf_iseq_loc +
 743                             (index >> udf_vfsp->udf_l2d_shift),
 744                             1, desc_len) == 0) {
 745                                 struct log_vol_int_desc *lvid;
 746 
 747                                 lvid = (struct log_vol_int_desc *)ttag;
 748 
 749                                 if (SWAP_32(lvid->lvid_int_type) !=
 750                                     LOG_VOL_CLOSE_INT) {
 751                                         error = EINVAL;
 752                                         goto remountout;
 753                                 }
 754 
 755                                 /*
 756                                  * Copy new data to old data
 757                                  */
 758                                 bcopy(udf_vfsp->udf_iseq->b_un.b_addr,
 759                                     tpt->b_un.b_addr, udf_vfsp->udf_iseq_len);
 760                                 break;
 761                         }
 762                 }
 763 
 764                 udf_vfsp->udf_flags = UDF_FL_RW;
 765 
 766                 mutex_enter(&udf_vfsp->udf_lock);
 767                 ud_sbwrite(udf_vfsp);
 768                 mutex_exit(&udf_vfsp->udf_lock);
 769 remountout:
 770                 if (tpt != NULL) {
 771                         tpt->b_flags = B_AGE | B_STALE;
 772                         brelse(tpt);
 773                 }
 774                 return (error);
 775         }
 776 
 777         ASSERT(devvp != 0);
 778         /*
 779          * Flush back any dirty pages on the block device to
 780          * try and keep the buffer cache in sync with the page
 781          * cache if someone is trying to use block devices when
 782          * they really should be using the raw device.
 783          */
 784         (void) VOP_PUTPAGE(common_specvp(devvp), (offset_t)0,
 785             (uint32_t)0, B_INVAL, cr, NULL);
 786 
 787 
 788         /*
 789          * Check if the file system
 790          * is a valid udfs and fill
 791          * the required fields in udf_vfs
 792          */
 793 #ifndef __lint
 794         _NOTE(NO_COMPETING_THREADS_NOW);
 795 #endif
 796 
 797         if ((lbsize = ud_get_lbsize(dev, &avd_loc)) == 0) {
 798                 error = EINVAL;
 799                 goto out;
 800         }
 801 
 802         udf_vfsp = ud_validate_and_fill_superblock(dev, lbsize, avd_loc);
 803         if (udf_vfsp == NULL) {
 804                 error = EINVAL;
 805                 goto out;
 806         }
 807 
 808         /*
 809          * Fill in vfs private data
 810          */
 811         vfsp->vfs_fstype = udf_fstype;
 812         vfs_make_fsid(&vfsp->vfs_fsid, dev, udf_fstype);
 813         vfsp->vfs_data = (caddr_t)udf_vfsp;
 814         vfsp->vfs_dev = dev;
 815         vfsp->vfs_flag |= VFS_NOTRUNC;
 816         udf_vfsp->udf_devvp = devvp;
 817 
 818         udf_vfsp->udf_fsmnt = kmem_zalloc(strlen(name) + 1, KM_SLEEP);
 819         (void) strcpy(udf_vfsp->udf_fsmnt, name);
 820 
 821         udf_vfsp->udf_vfs = vfsp;
 822         udf_vfsp->udf_rdclustsz = udf_vfsp->udf_wrclustsz = maxphys;
 823 
 824         udf_vfsp->udf_mod = 0;
 825 
 826 
 827         lvid = udf_vfsp->udf_lvid;
 828         if (vfsp->vfs_flag & VFS_RDONLY) {
 829                 /*
 830                  * We could read only UDF1.50
 831                  * disallow mount of any highier version
 832                  */
 833                 if (udf_vfsp->udf_miread > UDF_150) {
 834                         error = EINVAL;
 835                         goto out;
 836                 }
 837                 udf_vfsp->udf_flags = UDF_FL_RDONLY;
 838                 if (SWAP_32(lvid->lvid_int_type) == LOG_VOL_CLOSE_INT) {
 839                         udf_vfsp->udf_clean = UDF_CLEAN;
 840                 } else {
 841                         /* Do we have a VAT at the end of the recorded media */
 842                         map = udf_vfsp->udf_maps;
 843                         for (i = 0; i < udf_vfsp->udf_nmaps; i++) {
 844                                 if (map->udm_flags & UDM_MAP_VPM) {
 845                                         break;
 846                                 }
 847                                 map++;
 848                         }
 849                         if (i == udf_vfsp->udf_nmaps) {
 850                                 error = ENOSPC;
 851                                 goto out;
 852                         }
 853                         udf_vfsp->udf_clean = UDF_CLEAN;
 854                 }
 855         } else {
 856                 /*
 857                  * We could read UDF1.50 and write UDF1.50 only
 858                  * disallow mount of any highier version
 859                  */
 860                 if ((udf_vfsp->udf_miread > UDF_150) ||
 861                     (udf_vfsp->udf_miwrite > UDF_150)) {
 862                         error = EINVAL;
 863                         goto out;
 864                 }
 865                 /*
 866                  * Check if the media allows
 867                  * us to mount read/write
 868                  */
 869                 if (udf_vfsp->udf_mtype != UDF_MT_OW) {
 870                         error = EACCES;
 871                         goto out;
 872                 }
 873 
 874                 /*
 875                  * Check if we have VAT on a writable media
 876                  * we cannot use the media in presence of VAT
 877                  * Dent RW mount.
 878                  */
 879                 map = udf_vfsp->udf_maps;
 880                 ASSERT(map != NULL);
 881                 for (i = 0; i < udf_vfsp->udf_nmaps; i++) {
 882                         if (map->udm_flags & UDM_MAP_VPM) {
 883                                 error = EACCES;
 884                                 goto out;
 885                         }
 886                         map++;
 887                 }
 888 
 889                 /*
 890                  * Check if the domain Id allows
 891                  * us to write
 892                  */
 893                 if (udf_vfsp->udf_lvd->lvd_dom_id.reg_ids[2] & 0x3) {
 894                         error = EACCES;
 895                         goto out;
 896                 }
 897                 udf_vfsp->udf_flags = UDF_FL_RW;
 898 
 899                 if (SWAP_32(lvid->lvid_int_type) == LOG_VOL_CLOSE_INT) {
 900                         udf_vfsp->udf_clean = UDF_CLEAN;
 901                 } else {
 902                         if (isroot) {
 903                                 udf_vfsp->udf_clean = UDF_DIRTY;
 904                         } else {
 905                                 error = ENOSPC;
 906                                 goto out;
 907                         }
 908                 }
 909         }
 910 
 911         mutex_init(&udf_vfsp->udf_lock, NULL, MUTEX_DEFAULT, NULL);
 912 
 913         mutex_init(&udf_vfsp->udf_rename_lck, NULL, MUTEX_DEFAULT, NULL);
 914 
 915 #ifndef __lint
 916         _NOTE(COMPETING_THREADS_NOW);
 917 #endif
 918         if (error = ud_iget(vfsp, udf_vfsp->udf_ricb_prn,
 919             udf_vfsp->udf_ricb_loc, &rip, NULL, cr)) {
 920                 mutex_destroy(&udf_vfsp->udf_lock);
 921                 goto out;
 922         }
 923 
 924 
 925         /*
 926          * Get the root inode and
 927          * initialize the root vnode
 928          */
 929         rvp = ITOV(rip);
 930         mutex_enter(&rvp->v_lock);
 931         rvp->v_flag |= VROOT;
 932         mutex_exit(&rvp->v_lock);
 933         udf_vfsp->udf_root = rvp;
 934 
 935 
 936         if (why == ROOT_INIT && isroot)
 937                 rootvp = devvp;
 938 
 939         ud_vfs_add(udf_vfsp);
 940 
 941         if (udf_vfsp->udf_flags == UDF_FL_RW) {
 942                 udf_vfsp->udf_clean = UDF_DIRTY;
 943                 ud_update_superblock(vfsp);
 944         }
 945 
 946         return (0);
 947 
 948 out:
 949         ud_destroy_fsp(udf_vfsp);
 950         if (needclose) {
 951                 (void) VOP_CLOSE(devvp, (vfsp->vfs_flag & VFS_RDONLY) ?
 952                     FREAD : FREAD|FWRITE, 1, (offset_t)0, cr, NULL);
 953                 bflush(dev);
 954                 binval(dev);
 955         }
 956         VN_RELE(devvp);
 957 
 958         return (error);
 959 }
 960 
 961 
 962 static struct udf_vfs *
 963 ud_validate_and_fill_superblock(dev_t dev, int32_t bsize, uint32_t avd_loc)
 964 {
 965         int32_t error, count, index, shift;
 966         uint32_t dummy, vds_loc;
 967         caddr_t addr;
 968         daddr_t blkno, lblkno;
 969         struct buf *secbp, *bp;
 970         struct tag *ttag;
 971         struct anch_vol_desc_ptr *avdp;
 972         struct file_set_desc *fsd;
 973         struct udf_vfs *udf_vfsp = NULL;
 974         struct pmap_hdr *hdr;
 975         struct pmap_typ1 *typ1;
 976         struct pmap_typ2 *typ2;
 977         struct ud_map *map;
 978         int32_t desc_len;
 979 
 980         ud_printf("ud_validate_and_fill_superblock\n");
 981 
 982         if (bsize < DEV_BSIZE) {
 983                 return (NULL);
 984         }
 985         shift = 0;
 986         while ((bsize >> shift) > DEV_BSIZE) {
 987                 shift++;
 988         }
 989 
 990         /*
 991          * Read Anchor Volume Descriptor
 992          * Verify it and get the location of
 993          * Main Volume Descriptor Sequence
 994          */
 995         secbp = ud_bread(dev, avd_loc << shift, ANCHOR_VOL_DESC_LEN);
 996         if ((error = geterror(secbp)) != 0) {
 997                 cmn_err(CE_NOTE, "udfs : Could not read Anchor Volume Desc %x",
 998                     error);
 999                 brelse(secbp);
1000                 return (NULL);
1001         }
1002         avdp = (struct anch_vol_desc_ptr *)secbp->b_un.b_addr;
1003         if (ud_verify_tag_and_desc(&avdp->avd_tag, UD_ANCH_VOL_DESC,
1004             avd_loc, 1, ANCHOR_VOL_DESC_LEN) != 0) {
1005                 brelse(secbp);
1006                 return (NULL);
1007         }
1008         udf_vfsp = (struct udf_vfs *)
1009             kmem_zalloc(sizeof (struct udf_vfs), KM_SLEEP);
1010         udf_vfsp->udf_mvds_loc = SWAP_32(avdp->avd_main_vdse.ext_loc);
1011         udf_vfsp->udf_mvds_len = SWAP_32(avdp->avd_main_vdse.ext_len);
1012         udf_vfsp->udf_rvds_loc = SWAP_32(avdp->avd_res_vdse.ext_loc);
1013         udf_vfsp->udf_rvds_len = SWAP_32(avdp->avd_res_vdse.ext_len);
1014         secbp->b_flags = B_AGE | B_STALE;
1015         brelse(secbp);
1016 
1017         /*
1018          * Read Main Volume Descriptor Sequence
1019          * and process it
1020          */
1021         vds_loc = udf_vfsp->udf_mvds_loc;
1022         secbp = ud_bread(dev, vds_loc << shift,
1023             udf_vfsp->udf_mvds_len);
1024         if ((error = geterror(secbp)) != 0) {
1025                 brelse(secbp);
1026                 cmn_err(CE_NOTE, "udfs : Could not read Main Volume Desc %x",
1027                     error);
1028 
1029                 vds_loc = udf_vfsp->udf_rvds_loc;
1030                 secbp = ud_bread(dev, vds_loc << shift,
1031                     udf_vfsp->udf_rvds_len);
1032                 if ((error = geterror(secbp)) != 0) {
1033                         brelse(secbp);
1034                         cmn_err(CE_NOTE,
1035                         "udfs : Could not read Res Volume Desc %x", error);
1036                         return (NULL);
1037                 }
1038         }
1039 
1040         udf_vfsp->udf_vds = ngeteblk(udf_vfsp->udf_mvds_len);
1041         bp = udf_vfsp->udf_vds;
1042         bp->b_edev = dev;
1043         bp->b_dev = cmpdev(dev);
1044         bp->b_blkno = vds_loc << shift;
1045         bp->b_bcount = udf_vfsp->udf_mvds_len;
1046         bcopy(secbp->b_un.b_addr, bp->b_un.b_addr, udf_vfsp->udf_mvds_len);
1047         secbp->b_flags |= B_STALE | B_AGE;
1048         brelse(secbp);
1049 
1050 
1051         count = udf_vfsp->udf_mvds_len / DEV_BSIZE;
1052         addr = bp->b_un.b_addr;
1053         for (index = 0; index < count; index ++) {
1054                 ttag = (struct tag *)(addr + index * DEV_BSIZE);
1055                 desc_len = udf_vfsp->udf_mvds_len - (index * DEV_BSIZE);
1056                 if (ud_verify_tag_and_desc(ttag, UD_PRI_VOL_DESC,
1057                     vds_loc + (index >> shift),
1058                     1, desc_len) == 0) {
1059                         if (udf_vfsp->udf_pvd == NULL) {
1060                                 udf_vfsp->udf_pvd =
1061                                     (struct pri_vol_desc *)ttag;
1062                         } else {
1063                                 struct pri_vol_desc *opvd, *npvd;
1064 
1065                                 opvd = udf_vfsp->udf_pvd;
1066                                 npvd = (struct pri_vol_desc *)ttag;
1067 
1068                                 if ((strncmp(opvd->pvd_vsi,
1069                                     npvd->pvd_vsi, 128) == 0) &&
1070                                     (strncmp(opvd->pvd_vol_id,
1071                                     npvd->pvd_vol_id, 32) == 0) &&
1072                                     (strncmp((caddr_t)&opvd->pvd_desc_cs,
1073                                     (caddr_t)&npvd->pvd_desc_cs,
1074                                     sizeof (charspec_t)) == 0)) {
1075 
1076                                         if (SWAP_32(opvd->pvd_vdsn) <
1077                                             SWAP_32(npvd->pvd_vdsn)) {
1078                                                 udf_vfsp->udf_pvd = npvd;
1079                                         }
1080                                 } else {
1081                                         goto out;
1082                                 }
1083                         }
1084                 } else if (ud_verify_tag_and_desc(ttag, UD_LOG_VOL_DESC,
1085                     vds_loc + (index >> shift),
1086                     1, desc_len) == 0) {
1087                         struct log_vol_desc *lvd;
1088 
1089                         lvd = (struct log_vol_desc *)ttag;
1090                         if (strncmp(lvd->lvd_dom_id.reg_id,
1091                             UDF_DOMAIN_NAME, 23) != 0) {
1092                                 printf("Domain ID in lvd is not valid\n");
1093                                 goto out;
1094                         }
1095 
1096                         if (udf_vfsp->udf_lvd == NULL) {
1097                                 udf_vfsp->udf_lvd = lvd;
1098                         } else {
1099                                 struct log_vol_desc *olvd;
1100 
1101                                 olvd = udf_vfsp->udf_lvd;
1102                                 if ((strncmp((caddr_t)&olvd->lvd_desc_cs,
1103                                     (caddr_t)&lvd->lvd_desc_cs,
1104                                     sizeof (charspec_t)) == 0) &&
1105                                     (strncmp(olvd->lvd_lvid,
1106                                     lvd->lvd_lvid, 128) == 0)) {
1107                                         if (SWAP_32(olvd->lvd_vdsn) <
1108                                             SWAP_32(lvd->lvd_vdsn)) {
1109                                                 udf_vfsp->udf_lvd = lvd;
1110                                         }
1111                                 } else {
1112                                         goto out;
1113                                 }
1114                         }
1115                 } else if (ud_verify_tag_and_desc(ttag, UD_PART_DESC,
1116                     vds_loc + (index >> shift),
1117                     1, desc_len) == 0) {
1118                         int32_t i;
1119                         struct phdr_desc *hdr;
1120                         struct part_desc *pdesc;
1121                         struct ud_part *pnew, *pold, *part;
1122 
1123                         pdesc = (struct part_desc *)ttag;
1124                         pold = udf_vfsp->udf_parts;
1125                         for (i = 0; i < udf_vfsp->udf_npart; i++) {
1126                                 if (pold->udp_number !=
1127                                     SWAP_16(pdesc->pd_pnum)) {
1128                                         pold++;
1129                                         continue;
1130                                 }
1131 
1132                                 if (SWAP_32(pdesc->pd_vdsn) >
1133                                     pold->udp_seqno) {
1134                                         pold->udp_seqno =
1135                                             SWAP_32(pdesc->pd_vdsn);
1136                                         pold->udp_access =
1137                                             SWAP_32(pdesc->pd_acc_type);
1138                                         pold->udp_start =
1139                                             SWAP_32(pdesc->pd_part_start);
1140                                         pold->udp_length =
1141                                             SWAP_32(pdesc->pd_part_length);
1142                                 }
1143                                 goto loop_end;
1144                         }
1145                         pold = udf_vfsp->udf_parts;
1146                         udf_vfsp->udf_npart++;
1147                         pnew = kmem_zalloc(udf_vfsp->udf_npart *
1148                             sizeof (struct ud_part), KM_SLEEP);
1149                         udf_vfsp->udf_parts = pnew;
1150                         if (pold) {
1151                                 bcopy(pold, pnew,
1152                                     sizeof (struct ud_part) *
1153                                     (udf_vfsp->udf_npart - 1));
1154                                 kmem_free(pold,
1155                                     sizeof (struct ud_part) *
1156                                     (udf_vfsp->udf_npart - 1));
1157                         }
1158                         part = pnew + (udf_vfsp->udf_npart - 1);
1159                         part->udp_number = SWAP_16(pdesc->pd_pnum);
1160                         part->udp_seqno = SWAP_32(pdesc->pd_vdsn);
1161                         part->udp_access = SWAP_32(pdesc->pd_acc_type);
1162                         part->udp_start = SWAP_32(pdesc->pd_part_start);
1163                         part->udp_length = SWAP_32(pdesc->pd_part_length);
1164                         part->udp_last_alloc = 0;
1165 
1166                         /*
1167                          * Figure out space bitmaps
1168                          * or space tables
1169                          */
1170                         hdr = (struct phdr_desc *)pdesc->pd_pc_use;
1171                         if (hdr->phdr_ust.sad_ext_len) {
1172                                 part->udp_flags = UDP_SPACETBLS;
1173                                 part->udp_unall_loc =
1174                                     SWAP_32(hdr->phdr_ust.sad_ext_loc);
1175                                 part->udp_unall_len =
1176                                     SWAP_32(hdr->phdr_ust.sad_ext_len);
1177                                 part->udp_freed_loc =
1178                                     SWAP_32(hdr->phdr_fst.sad_ext_loc);
1179                                 part->udp_freed_len =
1180                                     SWAP_32(hdr->phdr_fst.sad_ext_len);
1181                         } else {
1182                                 part->udp_flags = UDP_BITMAPS;
1183                                 part->udp_unall_loc =
1184                                     SWAP_32(hdr->phdr_usb.sad_ext_loc);
1185                                 part->udp_unall_len =
1186                                     SWAP_32(hdr->phdr_usb.sad_ext_len);
1187                                 part->udp_freed_loc =
1188                                     SWAP_32(hdr->phdr_fsb.sad_ext_loc);
1189                                 part->udp_freed_len =
1190                                     SWAP_32(hdr->phdr_fsb.sad_ext_len);
1191                         }
1192                 } else if (ud_verify_tag_and_desc(ttag, UD_TERM_DESC,
1193                     vds_loc + (index >> shift),
1194                     1, desc_len) == 0) {
1195 
1196                         break;
1197                 }
1198 loop_end:
1199                 ;
1200         }
1201         if ((udf_vfsp->udf_pvd == NULL) ||
1202             (udf_vfsp->udf_lvd == NULL) ||
1203             (udf_vfsp->udf_parts == NULL)) {
1204                 goto out;
1205         }
1206 
1207         /*
1208          * Process Primary Volume Descriptor
1209          */
1210         (void) strncpy(udf_vfsp->udf_volid, udf_vfsp->udf_pvd->pvd_vol_id, 32);
1211         udf_vfsp->udf_volid[31] = '\0';
1212         udf_vfsp->udf_tsno = SWAP_16(udf_vfsp->udf_pvd->pvd_tag.tag_sno);
1213 
1214         /*
1215          * Process Logical Volume Descriptor
1216          */
1217         udf_vfsp->udf_lbsize =
1218             SWAP_32(udf_vfsp->udf_lvd->lvd_log_bsize);
1219         udf_vfsp->udf_lbmask = udf_vfsp->udf_lbsize - 1;
1220         udf_vfsp->udf_l2d_shift = shift;
1221         udf_vfsp->udf_l2b_shift = shift + DEV_BSHIFT;
1222 
1223         /*
1224          * Check if the media is in
1225          * proper domain.
1226          */
1227         if (strcmp(udf_vfsp->udf_lvd->lvd_dom_id.reg_id,
1228             UDF_DOMAIN_NAME) != 0) {
1229                 goto out;
1230         }
1231 
1232         /*
1233          * AVDS offset does not match with the lbsize
1234          * in the lvd
1235          */
1236         if (udf_vfsp->udf_lbsize != bsize) {
1237                 goto out;
1238         }
1239 
1240         udf_vfsp->udf_iseq_loc =
1241             SWAP_32(udf_vfsp->udf_lvd->lvd_int_seq_ext.ext_loc);
1242         udf_vfsp->udf_iseq_len =
1243             SWAP_32(udf_vfsp->udf_lvd->lvd_int_seq_ext.ext_len);
1244 
1245         udf_vfsp->udf_fsd_prn =
1246             SWAP_16(udf_vfsp->udf_lvd->lvd_lvcu.lad_ext_prn);
1247         udf_vfsp->udf_fsd_loc =
1248             SWAP_32(udf_vfsp->udf_lvd->lvd_lvcu.lad_ext_loc);
1249         udf_vfsp->udf_fsd_len =
1250             SWAP_32(udf_vfsp->udf_lvd->lvd_lvcu.lad_ext_len);
1251 
1252 
1253         /*
1254          * process paritions
1255          */
1256         udf_vfsp->udf_mtype = udf_vfsp->udf_parts[0].udp_access;
1257         for (index = 0; index < udf_vfsp->udf_npart; index ++) {
1258                 if (udf_vfsp->udf_parts[index].udp_access <
1259                     udf_vfsp->udf_mtype) {
1260                         udf_vfsp->udf_mtype =
1261                             udf_vfsp->udf_parts[index].udp_access;
1262                 }
1263         }
1264         if ((udf_vfsp->udf_mtype < UDF_MT_RO) ||
1265             (udf_vfsp->udf_mtype > UDF_MT_OW)) {
1266                 udf_vfsp->udf_mtype = UDF_MT_RO;
1267         }
1268 
1269         udf_vfsp->udf_nmaps = 0;
1270         hdr = (struct pmap_hdr *)udf_vfsp->udf_lvd->lvd_pmaps;
1271         count = SWAP_32(udf_vfsp->udf_lvd->lvd_num_pmaps);
1272         for (index = 0; index < count; index++) {
1273 
1274                 if ((hdr->maph_type == MAP_TYPE1) &&
1275                     (hdr->maph_length == MAP_TYPE1_LEN)) {
1276                         typ1 = (struct pmap_typ1 *)hdr;
1277 
1278                         map = udf_vfsp->udf_maps;
1279                         udf_vfsp->udf_maps =
1280                             kmem_zalloc(sizeof (struct ud_map) *
1281                             (udf_vfsp->udf_nmaps + 1), KM_SLEEP);
1282                         if (map != NULL) {
1283                                 bcopy(map, udf_vfsp->udf_maps,
1284                                     sizeof (struct ud_map) *
1285                                     udf_vfsp->udf_nmaps);
1286                                 kmem_free(map, sizeof (struct ud_map) *
1287                                     udf_vfsp->udf_nmaps);
1288                         }
1289                         map = udf_vfsp->udf_maps + udf_vfsp->udf_nmaps;
1290                         map->udm_flags = UDM_MAP_NORM;
1291                         map->udm_vsn = SWAP_16(typ1->map1_vsn);
1292                         map->udm_pn = SWAP_16(typ1->map1_pn);
1293                         udf_vfsp->udf_nmaps ++;
1294                 } else if ((hdr->maph_type == MAP_TYPE2) &&
1295                     (hdr->maph_length == MAP_TYPE2_LEN)) {
1296                         typ2 = (struct pmap_typ2 *)hdr;
1297 
1298                         if (strncmp(typ2->map2_pti.reg_id,
1299                             UDF_VIRT_PART, 23) == 0) {
1300                                 /*
1301                                  * Add this to the normal
1302                                  * partition table so that
1303                                  * we donot
1304                                  */
1305                                 map = udf_vfsp->udf_maps;
1306                                 udf_vfsp->udf_maps =
1307                                     kmem_zalloc(sizeof (struct ud_map) *
1308                                     (udf_vfsp->udf_nmaps + 1), KM_SLEEP);
1309                                 if (map != NULL) {
1310                                         bcopy(map, udf_vfsp->udf_maps,
1311                                             sizeof (struct ud_map) *
1312                                             udf_vfsp->udf_nmaps);
1313                                         kmem_free(map,
1314                                             sizeof (struct ud_map) *
1315                                             udf_vfsp->udf_nmaps);
1316                                 }
1317                                 map = udf_vfsp->udf_maps + udf_vfsp->udf_nmaps;
1318                                 map->udm_flags = UDM_MAP_VPM;
1319                                 map->udm_vsn = SWAP_16(typ2->map2_vsn);
1320                                 map->udm_pn = SWAP_16(typ2->map2_pn);
1321                                 udf_vfsp->udf_nmaps ++;
1322                                 if (error = ud_get_last_block(dev, &lblkno)) {
1323                                         goto out;
1324                                 }
1325                                 if (error = ud_val_get_vat(udf_vfsp, dev,
1326                                     lblkno, map)) {
1327                                         goto out;
1328                                 }
1329                         } else if (strncmp(typ2->map2_pti.reg_id,
1330                             UDF_SPAR_PART, 23) == 0) {
1331 
1332                                 if (SWAP_16(typ2->map2_pl) != 32) {
1333                                         printf(
1334                                             "Packet Length is not valid %x\n",
1335                                             SWAP_16(typ2->map2_pl));
1336                                         goto out;
1337                                 }
1338                                 if ((typ2->map2_nst < 1) ||
1339                                     (typ2->map2_nst > 4)) {
1340                                         goto out;
1341                                 }
1342                                 map = udf_vfsp->udf_maps;
1343                                 udf_vfsp->udf_maps =
1344                                     kmem_zalloc(sizeof (struct ud_map) *
1345                                     (udf_vfsp->udf_nmaps + 1),
1346                                     KM_SLEEP);
1347                                 if (map != NULL) {
1348                                         bcopy(map, udf_vfsp->udf_maps,
1349                                             sizeof (struct ud_map) *
1350                                             udf_vfsp->udf_nmaps);
1351                                         kmem_free(map,
1352                                             sizeof (struct ud_map) *
1353                                             udf_vfsp->udf_nmaps);
1354                                 }
1355                                 map = udf_vfsp->udf_maps + udf_vfsp->udf_nmaps;
1356                                 map->udm_flags = UDM_MAP_SPM;
1357                                 map->udm_vsn = SWAP_16(typ2->map2_vsn);
1358                                 map->udm_pn = SWAP_16(typ2->map2_pn);
1359 
1360                                 udf_vfsp->udf_nmaps ++;
1361 
1362                                 if (error = ud_read_sparing_tbls(udf_vfsp,
1363                                     dev, map, typ2)) {
1364                                         goto out;
1365                                 }
1366                         } else {
1367                                 /*
1368                                  * Unknown type of partition
1369                                  * Bail out
1370                                  */
1371                                 goto out;
1372                         }
1373                 } else {
1374                         /*
1375                          * Unknown type of partition
1376                          * Bail out
1377                          */
1378                         goto out;
1379                 }
1380                 hdr = (struct pmap_hdr *)(((uint8_t *)hdr) + hdr->maph_length);
1381         }
1382 
1383 
1384         /*
1385          * Read Logical Volume Integrity Sequence
1386          * and process it
1387          */
1388         secbp = ud_bread(dev, udf_vfsp->udf_iseq_loc << shift,
1389             udf_vfsp->udf_iseq_len);
1390         if ((error = geterror(secbp)) != 0) {
1391                 cmn_err(CE_NOTE,
1392                 "udfs : Could not read Logical Volume Integrity Sequence %x",
1393                     error);
1394                 brelse(secbp);
1395                 goto out;
1396         }
1397         udf_vfsp->udf_iseq = ngeteblk(udf_vfsp->udf_iseq_len);
1398         bp = udf_vfsp->udf_iseq;
1399         bp->b_edev = dev;
1400         bp->b_dev = cmpdev(dev);
1401         bp->b_blkno = udf_vfsp->udf_iseq_loc << shift;
1402         bp->b_bcount = udf_vfsp->udf_iseq_len;
1403         bcopy(secbp->b_un.b_addr, bp->b_un.b_addr, udf_vfsp->udf_iseq_len);
1404         secbp->b_flags |= B_STALE | B_AGE;
1405         brelse(secbp);
1406 
1407         count = udf_vfsp->udf_iseq_len / DEV_BSIZE;
1408         addr = bp->b_un.b_addr;
1409         for (index = 0; index < count; index ++) {
1410                 ttag = (struct tag *)(addr + index * DEV_BSIZE);
1411                 desc_len = udf_vfsp->udf_iseq_len - (index * DEV_BSIZE);
1412                 if (ud_verify_tag_and_desc(ttag, UD_LOG_VOL_INT,
1413                     udf_vfsp->udf_iseq_loc + (index >> shift),
1414                     1, desc_len) == 0) {
1415 
1416                         struct log_vol_int_desc *lvid;
1417 
1418                         lvid = (struct log_vol_int_desc *)ttag;
1419                         udf_vfsp->udf_lvid = lvid;
1420 
1421                         if (SWAP_32(lvid->lvid_int_type) == LOG_VOL_CLOSE_INT) {
1422                                 udf_vfsp->udf_clean = UDF_CLEAN;
1423                         } else {
1424                                 udf_vfsp->udf_clean = UDF_DIRTY;
1425                         }
1426 
1427                         /*
1428                          * update superblock with the metadata
1429                          */
1430                         ud_convert_to_superblock(udf_vfsp, lvid);
1431                         break;
1432                 }
1433         }
1434 
1435         if (udf_vfsp->udf_lvid == NULL) {
1436                 goto out;
1437         }
1438 
1439         if ((blkno = ud_xlate_to_daddr(udf_vfsp,
1440             udf_vfsp->udf_fsd_prn, udf_vfsp->udf_fsd_loc,
1441             1, &dummy)) == 0) {
1442                 goto out;
1443         }
1444         secbp = ud_bread(dev, blkno << shift, udf_vfsp->udf_fsd_len);
1445         if ((error = geterror(secbp)) != 0) {
1446                 cmn_err(CE_NOTE,
1447                 "udfs : Could not read File Set Descriptor %x", error);
1448                 brelse(secbp);
1449                 goto out;
1450         }
1451         fsd = (struct file_set_desc *)secbp->b_un.b_addr;
1452         if (ud_verify_tag_and_desc(&fsd->fsd_tag, UD_FILE_SET_DESC,
1453             udf_vfsp->udf_fsd_loc,
1454             1, udf_vfsp->udf_fsd_len) != 0) {
1455                 secbp->b_flags = B_AGE | B_STALE;
1456                 brelse(secbp);
1457                 goto out;
1458         }
1459         udf_vfsp->udf_ricb_prn = SWAP_16(fsd->fsd_root_icb.lad_ext_prn);
1460         udf_vfsp->udf_ricb_loc = SWAP_32(fsd->fsd_root_icb.lad_ext_loc);
1461         udf_vfsp->udf_ricb_len = SWAP_32(fsd->fsd_root_icb.lad_ext_len);
1462         secbp->b_flags = B_AGE | B_STALE;
1463         brelse(secbp);
1464         udf_vfsp->udf_root_blkno = ud_xlate_to_daddr(udf_vfsp,
1465             udf_vfsp->udf_ricb_prn, udf_vfsp->udf_ricb_loc,
1466             1, &dummy);
1467 
1468         return (udf_vfsp);
1469 out:
1470         ud_destroy_fsp(udf_vfsp);
1471 
1472         return (NULL);
1473 }
1474 
1475 /*
1476  * release/free resources from one ud_map; map data was zalloc'd in
1477  * ud_validate_and_fill_superblock() and fields may later point to
1478  * valid data
1479  */
1480 static void
1481 ud_free_map(struct ud_map *map)
1482 {
1483         uint32_t n;
1484 
1485         if (map->udm_flags & UDM_MAP_VPM) {
1486                 if (map->udm_count) {
1487                         kmem_free(map->udm_count,
1488                             map->udm_nent * sizeof (*map->udm_count));
1489                         map->udm_count = NULL;
1490                 }
1491                 if (map->udm_bp) {
1492                         for (n = 0; n < map->udm_nent; n++) {
1493                                 if (map->udm_bp[n])
1494                                         brelse(map->udm_bp[n]);
1495                         }
1496                         kmem_free(map->udm_bp,
1497                             map->udm_nent * sizeof (*map->udm_bp));
1498                         map->udm_bp = NULL;
1499                 }
1500                 if (map->udm_addr) {
1501                         kmem_free(map->udm_addr,
1502                             map->udm_nent * sizeof (*map->udm_addr));
1503                         map->udm_addr = NULL;
1504                 }
1505         }
1506         if (map->udm_flags & UDM_MAP_SPM) {
1507                 for (n = 0; n < MAX_SPM; n++) {
1508                         if (map->udm_sbp[n]) {
1509                                 brelse(map->udm_sbp[n]);
1510                                 map->udm_sbp[n] = NULL;
1511                                 map->udm_spaddr[n] = NULL;
1512                         }
1513                 }
1514         }
1515 }
1516 
1517 void
1518 ud_destroy_fsp(struct udf_vfs *udf_vfsp)
1519 {
1520         int32_t i;
1521 
1522         ud_printf("ud_destroy_fsp\n");
1523         if (udf_vfsp == NULL)
1524                 return;
1525 
1526         if (udf_vfsp->udf_maps) {
1527                 for (i = 0; i < udf_vfsp->udf_nmaps; i++)
1528                         ud_free_map(&udf_vfsp->udf_maps[i]);
1529 
1530                 kmem_free(udf_vfsp->udf_maps,
1531                     udf_vfsp->udf_nmaps * sizeof (*udf_vfsp->udf_maps));
1532         }
1533 
1534         if (udf_vfsp->udf_parts) {
1535                 kmem_free(udf_vfsp->udf_parts,
1536                     udf_vfsp->udf_npart * sizeof (*udf_vfsp->udf_parts));
1537         }
1538         if (udf_vfsp->udf_iseq) {
1539                 udf_vfsp->udf_iseq->b_flags |= (B_STALE|B_AGE);
1540                 brelse(udf_vfsp->udf_iseq);
1541         }
1542         if (udf_vfsp->udf_vds) {
1543                 udf_vfsp->udf_vds->b_flags |= (B_STALE|B_AGE);
1544                 brelse(udf_vfsp->udf_vds);
1545         }
1546         if (udf_vfsp->udf_vfs)
1547                 ud_vfs_remove(udf_vfsp);
1548         if (udf_vfsp->udf_fsmnt) {
1549                 kmem_free(udf_vfsp->udf_fsmnt,
1550                     strlen(udf_vfsp->udf_fsmnt) + 1);
1551         }
1552         kmem_free(udf_vfsp, sizeof (*udf_vfsp));
1553 }
1554 
1555 void
1556 ud_convert_to_superblock(struct udf_vfs *udf_vfsp,
1557         struct log_vol_int_desc *lvid)
1558 {
1559         int32_t i, c;
1560         uint32_t *temp;
1561         struct ud_part *ud_part;
1562         struct lvid_iu *iu;
1563 
1564         udf_vfsp->udf_maxuniq = SWAP_64(lvid->lvid_uniqid);
1565         temp = lvid->lvid_fst;
1566         c = SWAP_32(lvid->lvid_npart);
1567         ud_part = udf_vfsp->udf_parts;
1568         for (i = 0; i < c; i++) {
1569                 if (i >= udf_vfsp->udf_npart) {
1570                         continue;
1571                 }
1572                 ud_part->udp_nfree =  SWAP_32(temp[i]);
1573                 ud_part->udp_nblocks =  SWAP_32(temp[c + i]);
1574                 udf_vfsp->udf_freeblks += SWAP_32(temp[i]);
1575                 udf_vfsp->udf_totalblks += SWAP_32(temp[c + i]);
1576                 ud_part++;
1577         }
1578 
1579         iu = (struct lvid_iu *)(temp + c * 2);
1580         udf_vfsp->udf_nfiles = SWAP_32(iu->lvidiu_nfiles);
1581         udf_vfsp->udf_ndirs = SWAP_32(iu->lvidiu_ndirs);
1582         udf_vfsp->udf_miread = BCD2HEX_16(SWAP_16(iu->lvidiu_mread));
1583         udf_vfsp->udf_miwrite = BCD2HEX_16(SWAP_16(iu->lvidiu_mwrite));
1584         udf_vfsp->udf_mawrite = BCD2HEX_16(SWAP_16(iu->lvidiu_maxwr));
1585 }
1586 
1587 void
1588 ud_update_superblock(struct vfs *vfsp)
1589 {
1590         struct udf_vfs *udf_vfsp;
1591 
1592         ud_printf("ud_update_superblock\n");
1593 
1594         udf_vfsp = (struct udf_vfs *)vfsp->vfs_data;
1595 
1596         mutex_enter(&udf_vfsp->udf_lock);
1597         ud_sbwrite(udf_vfsp);
1598         mutex_exit(&udf_vfsp->udf_lock);
1599 }
1600 
1601 
1602 #include <sys/dkio.h>
1603 #include <sys/cdio.h>
1604 #include <sys/vtoc.h>
1605 
1606 /*
1607  * This part of the code is known
1608  * to work with only sparc. It needs
1609  * to be evluated before using it with x86
1610  */
1611 int32_t
1612 ud_get_last_block(dev_t dev, daddr_t *blkno)
1613 {
1614         struct vtoc vtoc;
1615         struct dk_cinfo dki_info;
1616         int32_t rval, error;
1617 
1618         if ((error = cdev_ioctl(dev, DKIOCGVTOC, (intptr_t)&vtoc,
1619             FKIOCTL|FREAD|FNATIVE, CRED(), &rval)) != 0) {
1620                 cmn_err(CE_NOTE, "Could not get the vtoc information");
1621                 return (error);
1622         }
1623 
1624         if (vtoc.v_sanity != VTOC_SANE) {
1625                 return (EINVAL);
1626         }
1627         if ((error = cdev_ioctl(dev, DKIOCINFO, (intptr_t)&dki_info,
1628             FKIOCTL|FREAD|FNATIVE, CRED(), &rval)) != 0) {
1629                 cmn_err(CE_NOTE, "Could not get the slice information");
1630                 return (error);
1631         }
1632 
1633         if (dki_info.dki_partition > V_NUMPAR) {
1634                 return (EINVAL);
1635         }
1636 
1637 
1638         *blkno = vtoc.v_part[dki_info.dki_partition].p_size;
1639 
1640         return (0);
1641 }
1642 
1643 /* Search sequentially N - 2, N, N - 152, N - 150 for vat icb */
1644 /*
1645  * int32_t ud_sub_blks[] = {2, 0, 152, 150};
1646  */
1647 int32_t ud_sub_blks[] = {152, 150, 2, 0};
1648 int32_t ud_sub_count = 4;
1649 
1650 /*
1651  * Validate the VAT ICB
1652  */
1653 static int32_t
1654 ud_val_get_vat(struct udf_vfs *udf_vfsp, dev_t dev,
1655         daddr_t blkno, struct ud_map *udm)
1656 {
1657         struct buf *secbp;
1658         struct file_entry *fe;
1659         int32_t end_loc, i, j, ad_type;
1660         struct short_ad *sad;
1661         struct long_ad *lad;
1662         uint32_t count, blk;
1663         struct ud_part *ud_part;
1664         int err = 0;
1665 
1666         end_loc = (blkno >> udf_vfsp->udf_l2d_shift) - 1;
1667 
1668         for (i = 0; i < ud_sub_count; i++) {
1669                 udm->udm_vat_icb = end_loc - ud_sub_blks[i];
1670 
1671                 secbp = ud_bread(dev,
1672                     udm->udm_vat_icb << udf_vfsp->udf_l2d_shift,
1673                     udf_vfsp->udf_lbsize);
1674                 ASSERT(secbp->b_un.b_addr);
1675 
1676                 fe = (struct file_entry *)secbp->b_un.b_addr;
1677                 if (ud_verify_tag_and_desc(&fe->fe_tag, UD_FILE_ENTRY, 0,
1678                     0, 0) == 0) {
1679                         if (ud_verify_tag_and_desc(&fe->fe_tag, UD_FILE_ENTRY,
1680                             SWAP_32(fe->fe_tag.tag_loc),
1681                             1, udf_vfsp->udf_lbsize) == 0) {
1682                                 if (fe->fe_icb_tag.itag_ftype == 0) {
1683                                         break;
1684                                 }
1685                         }
1686                 }
1687                 secbp->b_flags |= B_AGE | B_STALE;
1688                 brelse(secbp);
1689         }
1690         if (i == ud_sub_count) {
1691                 return (EINVAL);
1692         }
1693 
1694         ad_type = SWAP_16(fe->fe_icb_tag.itag_flags) & 0x3;
1695         if (ad_type == ICB_FLAG_ONE_AD) {
1696                 udm->udm_nent = 1;
1697         } else if (ad_type == ICB_FLAG_SHORT_AD) {
1698                 udm->udm_nent =
1699                     SWAP_32(fe->fe_len_adesc) / sizeof (struct short_ad);
1700         } else if (ad_type == ICB_FLAG_LONG_AD) {
1701                 udm->udm_nent =
1702                     SWAP_32(fe->fe_len_adesc) / sizeof (struct long_ad);
1703         } else {
1704                 err = EINVAL;
1705                 goto end;
1706         }
1707 
1708         udm->udm_count = kmem_zalloc(udm->udm_nent * sizeof (*udm->udm_count),
1709             KM_SLEEP);
1710         udm->udm_bp = kmem_zalloc(udm->udm_nent * sizeof (*udm->udm_bp),
1711             KM_SLEEP);
1712         udm->udm_addr = kmem_zalloc(udm->udm_nent * sizeof (*udm->udm_addr),
1713             KM_SLEEP);
1714 
1715         if (ad_type == ICB_FLAG_ONE_AD) {
1716                         udm->udm_count[0] = (SWAP_64(fe->fe_info_len) - 36) /
1717                             sizeof (uint32_t);
1718                         udm->udm_bp[0] = secbp;
1719                         udm->udm_addr[0] = (uint32_t *)
1720                             &fe->fe_spec[SWAP_32(fe->fe_len_ear)];
1721                         return (0);
1722         }
1723         for (i = 0; i < udm->udm_nent; i++) {
1724                 if (ad_type == ICB_FLAG_SHORT_AD) {
1725                         sad = (struct short_ad *)
1726                             (fe->fe_spec + SWAP_32(fe->fe_len_ear));
1727                         sad += i;
1728                         count = SWAP_32(sad->sad_ext_len);
1729                         blk = SWAP_32(sad->sad_ext_loc);
1730                 } else {
1731                         lad = (struct long_ad *)
1732                             (fe->fe_spec + SWAP_32(fe->fe_len_ear));
1733                         lad += i;
1734                         count = SWAP_32(lad->lad_ext_len);
1735                         blk = SWAP_32(lad->lad_ext_loc);
1736                         ASSERT(SWAP_16(lad->lad_ext_prn) == udm->udm_pn);
1737                 }
1738                 if ((count & 0x3FFFFFFF) == 0) {
1739                         break;
1740                 }
1741                 if (i < udm->udm_nent - 1) {
1742                         udm->udm_count[i] = count / 4;
1743                 } else {
1744                         udm->udm_count[i] = (count - 36) / 4;
1745                 }
1746                 ud_part = udf_vfsp->udf_parts;
1747                 for (j = 0; j < udf_vfsp->udf_npart; j++) {
1748                         if (udm->udm_pn == ud_part->udp_number) {
1749                                 blk = ud_part->udp_start + blk;
1750                                 break;
1751                         }
1752                 }
1753                 if (j == udf_vfsp->udf_npart) {
1754                         err = EINVAL;
1755                         break;
1756                 }
1757 
1758                 count = (count + DEV_BSIZE - 1) & ~(DEV_BSIZE - 1);
1759                 udm->udm_bp[i] = ud_bread(dev,
1760                     blk << udf_vfsp->udf_l2d_shift, count);
1761                 if ((udm->udm_bp[i]->b_error != 0) ||
1762                     (udm->udm_bp[i]->b_resid)) {
1763                         err = EINVAL;
1764                         break;
1765                 }
1766                 udm->udm_addr[i] = (uint32_t *)udm->udm_bp[i]->b_un.b_addr;
1767         }
1768 
1769 end:
1770         if (err)
1771                 ud_free_map(udm);
1772         secbp->b_flags |= B_AGE | B_STALE;
1773         brelse(secbp);
1774         return (err);
1775 }
1776 
1777 int32_t
1778 ud_read_sparing_tbls(struct udf_vfs *udf_vfsp,
1779         dev_t dev, struct ud_map *map, struct pmap_typ2 *typ2)
1780 {
1781         int32_t index, valid = 0;
1782         uint32_t sz;
1783         struct buf *bp;
1784         struct stbl *stbl;
1785 
1786         map->udm_plen = SWAP_16(typ2->map2_pl);
1787         map->udm_nspm = typ2->map2_nst;
1788         map->udm_spsz = SWAP_32(typ2->map2_sest);
1789         sz = (map->udm_spsz + udf_vfsp->udf_lbmask) & ~udf_vfsp->udf_lbmask;
1790         if (sz == 0) {
1791                 return (0);
1792         }
1793 
1794         for (index = 0; index < map->udm_nspm; index++) {
1795                 map->udm_loc[index] = SWAP_32(typ2->map2_st[index]);
1796 
1797                 bp = ud_bread(dev,
1798                     map->udm_loc[index] << udf_vfsp->udf_l2d_shift, sz);
1799                 if ((bp->b_error != 0) || (bp->b_resid)) {
1800                         brelse(bp);
1801                         continue;
1802                 }
1803                 stbl = (struct stbl *)bp->b_un.b_addr;
1804                 if (strncmp(stbl->stbl_si.reg_id, UDF_SPAR_TBL, 23) != 0) {
1805                         printf("Sparing Identifier does not match\n");
1806                         bp->b_flags |= B_AGE | B_STALE;
1807                         brelse(bp);
1808                         continue;
1809                 }
1810                 map->udm_sbp[index] = bp;
1811                 map->udm_spaddr[index] = bp->b_un.b_addr;
1812 #ifdef  UNDEF
1813 {
1814         struct stbl_entry *te;
1815         int32_t i, tbl_len;
1816 
1817         te = (struct stbl_entry *)&stbl->stbl_entry;
1818         tbl_len = SWAP_16(stbl->stbl_len);
1819 
1820         printf("%x %x\n", tbl_len, SWAP_32(stbl->stbl_seqno));
1821         printf("%x %x\n", bp->b_un.b_addr, te);
1822 
1823         for (i = 0; i < tbl_len; i++) {
1824                 printf("%x %x\n", SWAP_32(te->sent_ol), SWAP_32(te->sent_ml));
1825                 te ++;
1826         }
1827 }
1828 #endif
1829                 valid ++;
1830         }
1831 
1832         if (valid) {
1833                 return (0);
1834         }
1835         return (EINVAL);
1836 }
1837 
1838 uint32_t
1839 ud_get_lbsize(dev_t dev, uint32_t *loc)
1840 {
1841         int32_t bsize, shift, index, end_index;
1842         daddr_t last_block;
1843         uint32_t avd_loc;
1844         struct buf *bp;
1845         struct anch_vol_desc_ptr *avdp;
1846         uint32_t session_offset = 0;
1847         int32_t rval;
1848 
1849         if (ud_get_last_block(dev, &last_block) != 0) {
1850                 end_index = 1;
1851         } else {
1852                 end_index = 3;
1853         }
1854 
1855         if (cdev_ioctl(dev, CDROMREADOFFSET, (intptr_t)&session_offset,
1856             FKIOCTL|FREAD|FNATIVE, CRED(), &rval) != 0) {
1857                 session_offset = 0;
1858         }
1859 
1860         for (index = 0; index < end_index; index++) {
1861 
1862                 for (bsize = DEV_BSIZE, shift = 0;
1863                     bsize <= MAXBSIZE; bsize <<= 1, shift++) {
1864 
1865                         if (index == 0) {
1866                                 avd_loc = 256;
1867                                 if (bsize <= 2048) {
1868                                         avd_loc +=
1869                                             session_offset * 2048 / bsize;
1870                                 } else {
1871                                         avd_loc +=
1872                                             session_offset / (bsize / 2048);
1873                                 }
1874                         } else if (index == 1) {
1875                                 avd_loc = last_block - (1 << shift);
1876                         } else {
1877                                 avd_loc = last_block - (256 << shift);
1878                         }
1879 
1880                         bp = ud_bread(dev, avd_loc << shift,
1881                             ANCHOR_VOL_DESC_LEN);
1882                         if (geterror(bp) != 0) {
1883                                 brelse(bp);
1884                                 continue;
1885                         }
1886 
1887                         /*
1888                          * Verify if we have avdp here
1889                          */
1890                         avdp = (struct anch_vol_desc_ptr *)bp->b_un.b_addr;
1891                         if (ud_verify_tag_and_desc(&avdp->avd_tag,
1892                             UD_ANCH_VOL_DESC, avd_loc,
1893                             1, ANCHOR_VOL_DESC_LEN) != 0) {
1894                                 bp->b_flags |= B_AGE | B_STALE;
1895                                 brelse(bp);
1896                                 continue;
1897                         }
1898                         bp->b_flags |= B_AGE | B_STALE;
1899                         brelse(bp);
1900                         *loc = avd_loc;
1901                         return (bsize);
1902                 }
1903         }
1904 
1905         /*
1906          * Did not find AVD at all the locations
1907          */
1908         return (0);
1909 }
1910 
1911 static int
1912 udfinit(int fstype, char *name)
1913 {
1914         static const fs_operation_def_t udf_vfsops_template[] = {
1915                 { VFSNAME_MOUNT,        { .vfs_mount = udf_mount } },
1916                 { VFSNAME_UNMOUNT,      { .vfs_unmount = udf_unmount } },
1917                 { VFSNAME_ROOT,         { .vfs_root = udf_root } },
1918                 { VFSNAME_STATVFS,      { .vfs_statvfs = udf_statvfs } },
1919                 { VFSNAME_SYNC,         { .vfs_sync = udf_sync } },
1920                 { VFSNAME_VGET,         { .vfs_vget = udf_vget } },
1921                 { VFSNAME_MOUNTROOT,    { .vfs_mountroot = udf_mountroot } },
1922                 { NULL,                 { NULL } }
1923         };
1924         extern struct vnodeops *udf_vnodeops;
1925         extern const fs_operation_def_t udf_vnodeops_template[];
1926         int error;
1927 
1928         ud_printf("udfinit\n");
1929 
1930         error = vfs_setfsops(fstype, udf_vfsops_template, NULL);
1931         if (error != 0) {
1932                 cmn_err(CE_WARN, "udfinit: bad vfs ops template");
1933                 return (error);
1934         }
1935 
1936         error = vn_make_ops(name, udf_vnodeops_template, &udf_vnodeops);
1937         if (error != 0) {
1938                 (void) vfs_freevfsops_by_type(fstype);
1939                 cmn_err(CE_WARN, "udfinit: bad vnode ops template");
1940                 return (error);
1941         }
1942 
1943         udf_fstype = fstype;
1944 
1945         ud_init_inodes();
1946 
1947         return (0);
1948 }