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