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