PSARC 2008/290 lofi mount 6384817 Need persistent lofi based mounts and direct mount(1m) support for lofi
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 } --- EOF ---