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.
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.
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]
22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 * Copyright (c) 2011 Bayard G. Bell. All rights reserved.
25 * Copyright (c) 2017 by Delphix. All rights reserved.
28 #include <sys/types.h>
29 #include <sys/t_lock.h>
30 #include <sys/param.h>
32 #include <sys/systm.h>
33 #include <sys/sysmacros.h>
34 #include <sys/resource.h>
35 #include <sys/signal.h>
41 #include <sys/vnode.h>
46 #include <sys/fcntl.h>
47 #include <sys/flock.h>
52 #include <sys/errno.h>
55 #include <sys/pathname.h>
56 #include <sys/debug.h>
57 #include <sys/vmsystm.h>
58 #include <sys/cmn_err.h>
59 #include <sys/dirent.h>
60 #include <sys/errno.h>
61 #include <sys/modctl.h>
62 #include <sys/statvfs.h>
63 #include <sys/mount.h>
64 #include <sys/sunddi.h>
65 #include <sys/bootconf.h>
66 #include <sys/policy.h>
73 #include <vm/seg_map.h>
74 #include <vm/seg_kmem.h>
75 #include <vm/seg_vn.h>
79 #include <sys/mntent.h>
82 #include <sys/fs_subr.h>
85 #include <sys/fs/udf_volume.h>
86 #include <sys/fs/udf_inode.h>
89 extern struct vnode
*common_specvp(struct vnode
*vp
);
91 extern kmutex_t ud_sync_busy
;
92 static int32_t ud_mountfs(struct vfs
*,
93 enum whymountroot
, dev_t
, char *, struct cred
*, int32_t);
94 static struct udf_vfs
*ud_validate_and_fill_superblock(dev_t
,
96 void ud_destroy_fsp(struct udf_vfs
*);
97 void ud_convert_to_superblock(struct udf_vfs
*,
98 struct log_vol_int_desc
*);
99 void ud_update_superblock(struct vfs
*);
100 int32_t ud_get_last_block(dev_t
, daddr_t
*);
101 static int32_t ud_val_get_vat(struct udf_vfs
*,
102 dev_t
, daddr_t
, struct ud_map
*);
103 int32_t ud_read_sparing_tbls(struct udf_vfs
*,
104 dev_t
, struct ud_map
*, struct pmap_typ2
*);
105 uint32_t ud_get_lbsize(dev_t
, uint32_t *);
107 static int32_t udf_mount(struct vfs
*,
108 struct vnode
*, struct mounta
*, struct cred
*);
109 static int32_t udf_unmount(struct vfs
*, int, struct cred
*);
110 static int32_t udf_root(struct vfs
*, struct vnode
**);
111 static int32_t udf_statvfs(struct vfs
*, struct statvfs64
*);
112 static int32_t udf_sync(struct vfs
*, int16_t, struct cred
*);
113 static int32_t udf_vget(struct vfs
*, struct vnode
**, struct fid
*);
114 static int32_t udf_mountroot(struct vfs
*vfsp
, enum whymountroot
);
116 static int udfinit(int, char *);
118 static mntopts_t udfs_mntopts
;
120 static vfsdef_t vfw
= {
124 VSW_HASPROTO
|VSW_CANREMOUNT
|VSW_STATS
|VSW_CANLOFI
|VSW_MOUNTDEV
,
128 static mntopts_t udfs_mntopts
= {
134 * Module linkage information for the kernel.
136 extern struct mod_ops mod_fsops
;
138 static struct modlfs modlfs
= {
139 &mod_fsops
, "filesystem for UDFS", &vfw
142 static struct modlinkage modlinkage
= {
143 MODREV_1
, (void *)&modlfs
, NULL
146 int32_t udf_fstype
= -1;
151 return (mod_install(&modlinkage
));
161 _info(struct modinfo
*modinfop
)
163 return (mod_info(&modlinkage
, modinfop
));
167 /* -------------------- vfs routines -------------------- */
170 * XXX - this appears only to be used by the VM code to handle the case where
171 * UNIX is running off the mini-root. That probably wants to be done
174 struct vnode
*rootvp
;
175 _NOTE(SCHEME_PROTECTS_DATA("safe sharing", rootvp
))
177 udf_mount(struct vfs
*vfsp
, struct vnode
*mvp
,
178 struct mounta
*uap
, struct cred
*cr
)
181 struct vnode
*lvp
= NULL
;
182 struct vnode
*svp
= NULL
;
185 enum whymountroot why
;
188 ud_printf("udf_mount\n");
190 if ((error
= secpolicy_fs_mount(cr
, mvp
, vfsp
)) != 0) {
194 if (mvp
->v_type
!= VDIR
) {
198 mutex_enter(&mvp
->v_lock
);
199 if ((uap
->flags
& MS_REMOUNT
) == 0 &&
200 (uap
->flags
& MS_OVERLAY
) == 0 &&
201 (mvp
->v_count
!= 1 || (mvp
->v_flag
& VROOT
))) {
202 mutex_exit(&mvp
->v_lock
);
205 mutex_exit(&mvp
->v_lock
);
207 if (error
= pn_get(uap
->dir
, UIO_USERSPACE
, &dpn
)) {
212 * Resolve path name of the file being mounted.
214 if (error
= lookupname(uap
->spec
, UIO_USERSPACE
, FOLLOW
, NULLVPP
,
220 error
= vfs_get_lofi(vfsp
, &lvp
);
226 } else if (error
== 0) {
231 if (svp
->v_type
!= VBLK
) {
238 * Ensure that this device isn't already mounted,
239 * unless this is a REMOUNT request
241 if (vfs_devmounting(dev
, vfsp
)) {
245 if (vfs_devismounted(dev
)) {
246 if (uap
->flags
& MS_REMOUNT
) {
255 if (getmajor(dev
) >= devcnt
) {
261 * If the device is a tape, mount it read only
263 if (devopsp
[getmajor(dev
)]->devo_cb_ops
->cb_flag
& D_TAPE
) {
264 vfsp
->vfs_flag
|= VFS_RDONLY
;
267 if (uap
->flags
& MS_RDONLY
) {
268 vfsp
->vfs_flag
|= VFS_RDONLY
;
274 if (uap
->flags
& MS_RDONLY
) {
275 vfs_setmntopt(vfsp
, MNTOPT_RO
, NULL
, 0);
277 if (uap
->flags
& MS_NOSUID
) {
278 vfs_setmntopt(vfsp
, MNTOPT_NOSUID
, NULL
, 0);
282 * Verify that the caller can open the device special file as
283 * required. It is not until this moment that we know whether
284 * we're mounting "ro" or not.
286 if ((vfsp
->vfs_flag
& VFS_RDONLY
) != 0) {
290 oflag
= FREAD
| FWRITE
;
291 aflag
= VREAD
| VWRITE
;
295 (error
= secpolicy_spec_open(cr
, svp
, oflag
)) != 0)
298 if ((error
= fop_access(svp
, aflag
, 0, cr
, NULL
)) != 0)
302 * Mount the filesystem.
304 error
= ud_mountfs(vfsp
, why
, dev
, dpn
.pn_path
, cr
, 0);
316 * unmount the file system pointed
321 udf_unmount(struct vfs
*vfsp
, int fflag
, struct cred
*cr
)
323 struct udf_vfs
*udf_vfsp
;
324 struct vnode
*bvp
, *rvp
;
325 struct ud_inode
*rip
;
328 ud_printf("udf_unmount\n");
330 if (secpolicy_fs_unmount(cr
, vfsp
) != 0) {
335 * forced unmount is not supported by this file system
336 * and thus, ENOTSUP, is being returned.
338 if (fflag
& MS_FORCE
)
341 udf_vfsp
= (struct udf_vfs
*)vfsp
->vfs_data
;
342 flag
= !(udf_vfsp
->udf_flags
& UDF_FL_RDONLY
);
343 bvp
= udf_vfsp
->udf_devvp
;
345 rvp
= udf_vfsp
->udf_root
;
349 (void) ud_release_cache(udf_vfsp
);
352 /* Flush all inodes except root */
353 if (ud_iflush(vfsp
) < 0) {
357 rw_enter(&rip
->i_contents
, RW_WRITER
);
358 (void) ud_syncip(rip
, B_INVAL
, I_SYNC
);
359 rw_exit(&rip
->i_contents
);
361 mutex_enter(&ud_sync_busy
);
362 if ((udf_vfsp
->udf_flags
& UDF_FL_RDONLY
) == 0) {
363 bflush(vfsp
->vfs_dev
);
364 mutex_enter(&udf_vfsp
->udf_lock
);
365 udf_vfsp
->udf_clean
= UDF_CLEAN
;
366 mutex_exit(&udf_vfsp
->udf_lock
);
367 ud_update_superblock(vfsp
);
369 mutex_exit(&ud_sync_busy
);
371 mutex_destroy(&udf_vfsp
->udf_lock
);
372 mutex_destroy(&udf_vfsp
->udf_rename_lck
);
378 ud_destroy_fsp(udf_vfsp
);
380 (void) fop_putpage(bvp
, 0, 0, B_INVAL
, cr
, NULL
);
381 (void) fop_close(bvp
, flag
, 1, 0, cr
, NULL
);
383 (void) bfinval(vfsp
->vfs_dev
, 1);
392 * Get the root vp for the
396 udf_root(struct vfs
*vfsp
, struct vnode
**vpp
)
398 struct udf_vfs
*udf_vfsp
;
401 ud_printf("udf_root\n");
403 udf_vfsp
= (struct udf_vfs
*)vfsp
->vfs_data
;
405 ASSERT(udf_vfsp
!= NULL
);
406 ASSERT(udf_vfsp
->udf_root
!= NULL
);
408 vp
= udf_vfsp
->udf_root
;
416 * Get file system statistics.
419 udf_statvfs(struct vfs
*vfsp
, struct statvfs64
*sp
)
421 struct udf_vfs
*udf_vfsp
;
422 struct ud_part
*parts
;
426 ud_printf("udf_statvfs\n");
428 udf_vfsp
= (struct udf_vfs
*)vfsp
->vfs_data
;
429 (void) bzero(sp
, sizeof (struct statvfs64
));
431 mutex_enter(&udf_vfsp
->udf_lock
);
432 sp
->f_bsize
= udf_vfsp
->udf_lbsize
;
433 sp
->f_frsize
= udf_vfsp
->udf_lbsize
;
436 parts
= udf_vfsp
->udf_parts
;
437 for (index
= 0; index
< udf_vfsp
->udf_npart
; index
++) {
438 sp
->f_blocks
+= parts
->udp_nblocks
;
439 sp
->f_bfree
+= parts
->udp_nfree
;
442 sp
->f_bavail
= sp
->f_bfree
;
445 * Since there are no real inodes allocated
446 * we will approximate
447 * each new file will occupy :
448 * 38(over head each dent) + MAXNAMLEN / 2 + inode_size(==block size)
450 sp
->f_ffree
= sp
->f_favail
=
451 (sp
->f_bavail
* sp
->f_bsize
) / (146 + sp
->f_bsize
);
454 * The total number of inodes is
455 * the sum of files + directories + free inodes
457 sp
->f_files
= sp
->f_ffree
+ udf_vfsp
->udf_nfiles
+ udf_vfsp
->udf_ndirs
;
458 (void) cmpldev(&d32
, vfsp
->vfs_dev
);
460 (void) strcpy(sp
->f_basetype
, vfssw
[vfsp
->vfs_fstype
].vsw_name
);
461 sp
->f_flag
= vf_to_stf(vfsp
->vfs_flag
);
462 sp
->f_namemax
= MAXNAMLEN
;
463 (void) strcpy(sp
->f_fstr
, udf_vfsp
->udf_volid
);
465 mutex_exit(&udf_vfsp
->udf_lock
);
472 * Flush any pending I/O to file system vfsp.
473 * The ud_update() routine will only flush *all* udf files.
478 udf_sync(struct vfs
*vfsp
, int16_t flag
, struct cred
*cr
)
480 ud_printf("udf_sync\n");
490 udf_vget(struct vfs
*vfsp
, struct vnode
**vpp
, struct fid
*fidp
)
493 struct udf_fid
*udfid
;
494 struct udf_vfs
*udf_vfsp
;
497 ud_printf("udf_vget\n");
499 udf_vfsp
= (struct udf_vfs
*)vfsp
->vfs_data
;
500 if (udf_vfsp
== NULL
) {
505 udfid
= (struct udf_fid
*)fidp
;
506 if ((error
= ud_iget(vfsp
, udfid
->udfid_prn
,
507 udfid
->udfid_icb_lbn
, &ip
, NULL
, CRED())) != 0) {
512 rw_enter(&ip
->i_contents
, RW_READER
);
513 if ((udfid
->udfid_uinq_lo
!= (ip
->i_uniqid
& 0xffffffff)) ||
514 (udfid
->udfid_prn
!= ip
->i_icb_prn
)) {
515 rw_exit(&ip
->i_contents
);
520 rw_exit(&ip
->i_contents
);
528 * Mount root file system.
529 * "why" is ROOT_INIT on initial call, ROOT_REMOUNT if called to
530 * remount the root file system, and ROOT_UNMOUNT if called to
531 * unmount the root (e.g., as part of a system shutdown).
533 * XXX - this may be partially machine-dependent; it, along with the VFS_SWAPVP
534 * operation, goes along with auto-configuration. A mechanism should be
535 * provided by which machine-INdependent code in the kernel can say "get me the
536 * right root file system" and "get me the right initial swap area", and have
537 * that done in what may well be a machine-dependent fashion.
538 * Unfortunately, it is also file-system-type dependent (NFS gets it via
539 * bootparams calls, UFS gets it from various and sundry machine-dependent
540 * mechanisms, as SPECFS does for swap).
544 udf_mountroot(struct vfs
*vfsp
, enum whymountroot why
)
547 static int32_t udf_rootdone
= 0;
548 struct vnode
*vp
= NULL
;
549 int32_t ovflags
, error
;
550 ud_printf("udf_mountroot\n");
552 if (why
== ROOT_INIT
) {
553 if (udf_rootdone
++) {
556 rootdev
= getrootdev();
557 if (rootdev
== (dev_t
)NODEV
) {
560 vfsp
->vfs_dev
= rootdev
;
561 vfsp
->vfs_flag
|= VFS_RDONLY
;
562 } else if (why
== ROOT_REMOUNT
) {
563 vp
= ((struct udf_vfs
*)vfsp
->vfs_data
)->udf_devvp
;
564 (void) dnlc_purge_vfsp(vfsp
, 0);
565 vp
= common_specvp(vp
);
566 (void) fop_putpage(vp
, 0,
567 0, B_INVAL
, CRED(), NULL
);
568 binval(vfsp
->vfs_dev
);
570 ovflags
= vfsp
->vfs_flag
;
571 vfsp
->vfs_flag
&= ~VFS_RDONLY
;
572 vfsp
->vfs_flag
|= VFS_REMOUNT
;
573 rootdev
= vfsp
->vfs_dev
;
574 } else if (why
== ROOT_UNMOUNT
) {
576 vp
= ((struct udf_vfs
*)vfsp
->vfs_data
)->udf_devvp
;
577 (void) fop_close(vp
, FREAD
|FWRITE
, 1,
582 if ((error
= vfs_lock(vfsp
)) != 0) {
586 error
= ud_mountfs(vfsp
, why
, rootdev
, "/", CRED(), 1);
589 if (why
== ROOT_REMOUNT
) {
590 vfsp
->vfs_flag
= ovflags
;
599 if (why
== ROOT_INIT
) {
601 (vfsp
->vfs_flag
& VFS_RDONLY
) ? MS_RDONLY
: 0);
608 /* ------------------------- local routines ------------------------- */
612 ud_mountfs(struct vfs
*vfsp
, enum whymountroot why
, dev_t dev
, char *name
,
613 struct cred
*cr
, int32_t isroot
)
615 struct vnode
*devvp
= NULL
;
617 int32_t needclose
= 0;
618 struct udf_vfs
*udf_vfsp
= NULL
;
619 struct log_vol_int_desc
*lvid
;
620 struct ud_inode
*rip
= NULL
;
621 struct vnode
*rvp
= NULL
;
627 ud_printf("ud_mountfs\n");
629 if (why
== ROOT_INIT
) {
633 devvp
= makespecvp(dev
, VBLK
);
636 * Open block device mounted on.
637 * When bio is fixed for vnodes this can all be vnode
640 error
= fop_open(&devvp
,
641 (vfsp
->vfs_flag
& VFS_RDONLY
) ? FREAD
: FREAD
|FWRITE
,
649 * Refuse to go any further if this
650 * device is being used for swapping.
652 if (IS_SWAPVP(devvp
)) {
659 * check for dev already mounted on
661 if (vfsp
->vfs_flag
& VFS_REMOUNT
) {
663 int32_t index
, count
;
668 /* cannot remount to RDONLY */
669 if (vfsp
->vfs_flag
& VFS_RDONLY
) {
673 if (vfsp
->vfs_dev
!= dev
) {
677 udf_vfsp
= (struct udf_vfs
*)vfsp
->vfs_data
;
678 devvp
= udf_vfsp
->udf_devvp
;
681 * fsck may have altered the file system; discard
682 * as much incore data as possible. Don't flush
683 * if this is a rw to rw remount; it's just resetting
686 if (udf_vfsp
->udf_flags
& UDF_FL_RDONLY
) {
687 (void) dnlc_purge_vfsp(vfsp
, 0);
688 (void) fop_putpage(devvp
, 0, 0,
689 B_INVAL
, CRED(), NULL
);
690 (void) ud_iflush(vfsp
);
696 * We could read UDF1.50 and write UDF1.50 only
697 * disallow mount of any highier version
699 if ((udf_vfsp
->udf_miread
> UDF_150
) ||
700 (udf_vfsp
->udf_miwrite
> UDF_150
)) {
706 * read/write to read/write; all done
708 if (udf_vfsp
->udf_flags
& UDF_FL_RW
) {
713 * Does the media type allow a writable mount
715 if (udf_vfsp
->udf_mtype
!= UDF_MT_OW
) {
722 * and check if it is possible to
725 tpt
= ud_bread(vfsp
->vfs_dev
,
726 udf_vfsp
->udf_iseq_loc
<< udf_vfsp
->udf_l2d_shift
,
727 udf_vfsp
->udf_iseq_len
);
728 if (tpt
->b_flags
& B_ERROR
) {
732 count
= udf_vfsp
->udf_iseq_len
/ DEV_BSIZE
;
733 addr
= tpt
->b_un
.b_addr
;
734 for (index
= 0; index
< count
; index
++) {
735 ttag
= (struct tag
*)(addr
+ index
* DEV_BSIZE
);
736 desc_len
= udf_vfsp
->udf_iseq_len
- (index
* DEV_BSIZE
);
737 if (ud_verify_tag_and_desc(ttag
, UD_LOG_VOL_INT
,
738 udf_vfsp
->udf_iseq_loc
+
739 (index
>> udf_vfsp
->udf_l2d_shift
),
741 struct log_vol_int_desc
*lvid
;
743 lvid
= (struct log_vol_int_desc
*)ttag
;
745 if (SWAP_32(lvid
->lvid_int_type
) !=
752 * Copy new data to old data
754 bcopy(udf_vfsp
->udf_iseq
->b_un
.b_addr
,
755 tpt
->b_un
.b_addr
, udf_vfsp
->udf_iseq_len
);
760 udf_vfsp
->udf_flags
= UDF_FL_RW
;
762 mutex_enter(&udf_vfsp
->udf_lock
);
763 ud_sbwrite(udf_vfsp
);
764 mutex_exit(&udf_vfsp
->udf_lock
);
767 tpt
->b_flags
= B_AGE
| B_STALE
;
775 * Flush back any dirty pages on the block device to
776 * try and keep the buffer cache in sync with the page
777 * cache if someone is trying to use block devices when
778 * they really should be using the raw device.
780 (void) fop_putpage(common_specvp(devvp
), 0,
781 0, B_INVAL
, cr
, NULL
);
785 * Check if the file system
786 * is a valid udfs and fill
787 * the required fields in udf_vfs
789 _NOTE(NO_COMPETING_THREADS_NOW
);
791 if ((lbsize
= ud_get_lbsize(dev
, &avd_loc
)) == 0) {
796 udf_vfsp
= ud_validate_and_fill_superblock(dev
, lbsize
, avd_loc
);
797 if (udf_vfsp
== NULL
) {
803 * Fill in vfs private data
805 vfsp
->vfs_fstype
= udf_fstype
;
806 vfs_make_fsid(&vfsp
->vfs_fsid
, dev
, udf_fstype
);
807 vfsp
->vfs_data
= (caddr_t
)udf_vfsp
;
809 vfsp
->vfs_flag
|= VFS_NOTRUNC
;
810 udf_vfsp
->udf_devvp
= devvp
;
812 udf_vfsp
->udf_fsmnt
= kmem_zalloc(strlen(name
) + 1, KM_SLEEP
);
813 (void) strcpy(udf_vfsp
->udf_fsmnt
, name
);
815 udf_vfsp
->udf_vfs
= vfsp
;
816 udf_vfsp
->udf_rdclustsz
= udf_vfsp
->udf_wrclustsz
= maxphys
;
818 udf_vfsp
->udf_mod
= 0;
821 lvid
= udf_vfsp
->udf_lvid
;
822 if (vfsp
->vfs_flag
& VFS_RDONLY
) {
824 * We could read only UDF1.50
825 * disallow mount of any highier version
827 if (udf_vfsp
->udf_miread
> UDF_150
) {
831 udf_vfsp
->udf_flags
= UDF_FL_RDONLY
;
832 if (SWAP_32(lvid
->lvid_int_type
) == LOG_VOL_CLOSE_INT
) {
833 udf_vfsp
->udf_clean
= UDF_CLEAN
;
835 /* Do we have a VAT at the end of the recorded media */
836 map
= udf_vfsp
->udf_maps
;
837 for (i
= 0; i
< udf_vfsp
->udf_nmaps
; i
++) {
838 if (map
->udm_flags
& UDM_MAP_VPM
) {
843 if (i
== udf_vfsp
->udf_nmaps
) {
847 udf_vfsp
->udf_clean
= UDF_CLEAN
;
851 * We could read UDF1.50 and write UDF1.50 only
852 * disallow mount of any highier version
854 if ((udf_vfsp
->udf_miread
> UDF_150
) ||
855 (udf_vfsp
->udf_miwrite
> UDF_150
)) {
860 * Check if the media allows
861 * us to mount read/write
863 if (udf_vfsp
->udf_mtype
!= UDF_MT_OW
) {
869 * Check if we have VAT on a writable media
870 * we cannot use the media in presence of VAT
873 map
= udf_vfsp
->udf_maps
;
875 for (i
= 0; i
< udf_vfsp
->udf_nmaps
; i
++) {
876 if (map
->udm_flags
& UDM_MAP_VPM
) {
884 * Check if the domain Id allows
887 if (udf_vfsp
->udf_lvd
->lvd_dom_id
.reg_ids
[2] & 0x3) {
891 udf_vfsp
->udf_flags
= UDF_FL_RW
;
893 if (SWAP_32(lvid
->lvid_int_type
) == LOG_VOL_CLOSE_INT
) {
894 udf_vfsp
->udf_clean
= UDF_CLEAN
;
897 udf_vfsp
->udf_clean
= UDF_DIRTY
;
905 mutex_init(&udf_vfsp
->udf_lock
, NULL
, MUTEX_DEFAULT
, NULL
);
907 mutex_init(&udf_vfsp
->udf_rename_lck
, NULL
, MUTEX_DEFAULT
, NULL
);
909 _NOTE(COMPETING_THREADS_NOW
);
910 if (error
= ud_iget(vfsp
, udf_vfsp
->udf_ricb_prn
,
911 udf_vfsp
->udf_ricb_loc
, &rip
, NULL
, cr
)) {
912 mutex_destroy(&udf_vfsp
->udf_lock
);
918 * Get the root inode and
919 * initialize the root vnode
922 mutex_enter(&rvp
->v_lock
);
923 rvp
->v_flag
|= VROOT
;
924 mutex_exit(&rvp
->v_lock
);
925 udf_vfsp
->udf_root
= rvp
;
928 if (why
== ROOT_INIT
&& isroot
)
931 ud_vfs_add(udf_vfsp
);
933 if (udf_vfsp
->udf_flags
== UDF_FL_RW
) {
934 udf_vfsp
->udf_clean
= UDF_DIRTY
;
935 ud_update_superblock(vfsp
);
941 ud_destroy_fsp(udf_vfsp
);
943 (void) fop_close(devvp
, (vfsp
->vfs_flag
& VFS_RDONLY
) ?
944 FREAD
: FREAD
|FWRITE
, 1, 0, cr
, NULL
);
954 static struct udf_vfs
*
955 ud_validate_and_fill_superblock(dev_t dev
, int32_t bsize
, uint32_t avd_loc
)
957 int32_t error
, count
, index
, shift
;
958 uint32_t dummy
, vds_loc
;
960 daddr_t blkno
, lblkno
;
961 struct buf
*secbp
, *bp
;
963 struct anch_vol_desc_ptr
*avdp
;
964 struct file_set_desc
*fsd
;
965 struct udf_vfs
*udf_vfsp
= NULL
;
966 struct pmap_hdr
*hdr
;
967 struct pmap_typ1
*typ1
;
968 struct pmap_typ2
*typ2
;
972 ud_printf("ud_validate_and_fill_superblock\n");
974 if (bsize
< DEV_BSIZE
) {
978 while ((bsize
>> shift
) > DEV_BSIZE
) {
983 * Read Anchor Volume Descriptor
984 * Verify it and get the location of
985 * Main Volume Descriptor Sequence
987 secbp
= ud_bread(dev
, avd_loc
<< shift
, ANCHOR_VOL_DESC_LEN
);
988 if ((error
= geterror(secbp
)) != 0) {
989 cmn_err(CE_NOTE
, "udfs : Could not read Anchor Volume Desc %x",
994 avdp
= (struct anch_vol_desc_ptr
*)secbp
->b_un
.b_addr
;
995 if (ud_verify_tag_and_desc(&avdp
->avd_tag
, UD_ANCH_VOL_DESC
,
996 avd_loc
, 1, ANCHOR_VOL_DESC_LEN
) != 0) {
1000 udf_vfsp
= (struct udf_vfs
*)
1001 kmem_zalloc(sizeof (struct udf_vfs
), KM_SLEEP
);
1002 udf_vfsp
->udf_mvds_loc
= SWAP_32(avdp
->avd_main_vdse
.ext_loc
);
1003 udf_vfsp
->udf_mvds_len
= SWAP_32(avdp
->avd_main_vdse
.ext_len
);
1004 udf_vfsp
->udf_rvds_loc
= SWAP_32(avdp
->avd_res_vdse
.ext_loc
);
1005 udf_vfsp
->udf_rvds_len
= SWAP_32(avdp
->avd_res_vdse
.ext_len
);
1006 secbp
->b_flags
= B_AGE
| B_STALE
;
1010 * Read Main Volume Descriptor Sequence
1013 vds_loc
= udf_vfsp
->udf_mvds_loc
;
1014 secbp
= ud_bread(dev
, vds_loc
<< shift
,
1015 udf_vfsp
->udf_mvds_len
);
1016 if ((error
= geterror(secbp
)) != 0) {
1018 cmn_err(CE_NOTE
, "udfs : Could not read Main Volume Desc %x",
1021 vds_loc
= udf_vfsp
->udf_rvds_loc
;
1022 secbp
= ud_bread(dev
, vds_loc
<< shift
,
1023 udf_vfsp
->udf_rvds_len
);
1024 if ((error
= geterror(secbp
)) != 0) {
1027 "udfs : Could not read Res Volume Desc %x", error
);
1032 udf_vfsp
->udf_vds
= ngeteblk(udf_vfsp
->udf_mvds_len
);
1033 bp
= udf_vfsp
->udf_vds
;
1035 bp
->b_dev
= cmpdev(dev
);
1036 bp
->b_blkno
= vds_loc
<< shift
;
1037 bp
->b_bcount
= udf_vfsp
->udf_mvds_len
;
1038 bcopy(secbp
->b_un
.b_addr
, bp
->b_un
.b_addr
, udf_vfsp
->udf_mvds_len
);
1039 secbp
->b_flags
|= B_STALE
| B_AGE
;
1043 count
= udf_vfsp
->udf_mvds_len
/ DEV_BSIZE
;
1044 addr
= bp
->b_un
.b_addr
;
1045 for (index
= 0; index
< count
; index
++) {
1046 ttag
= (struct tag
*)(addr
+ index
* DEV_BSIZE
);
1047 desc_len
= udf_vfsp
->udf_mvds_len
- (index
* DEV_BSIZE
);
1048 if (ud_verify_tag_and_desc(ttag
, UD_PRI_VOL_DESC
,
1049 vds_loc
+ (index
>> shift
),
1050 1, desc_len
) == 0) {
1051 if (udf_vfsp
->udf_pvd
== NULL
) {
1053 (struct pri_vol_desc
*)ttag
;
1055 struct pri_vol_desc
*opvd
, *npvd
;
1057 opvd
= udf_vfsp
->udf_pvd
;
1058 npvd
= (struct pri_vol_desc
*)ttag
;
1060 if ((strncmp(opvd
->pvd_vsi
,
1061 npvd
->pvd_vsi
, 128) == 0) &&
1062 (strncmp(opvd
->pvd_vol_id
,
1063 npvd
->pvd_vol_id
, 32) == 0) &&
1064 (strncmp((caddr_t
)&opvd
->pvd_desc_cs
,
1065 (caddr_t
)&npvd
->pvd_desc_cs
,
1066 sizeof (charspec_t
)) == 0)) {
1068 if (SWAP_32(opvd
->pvd_vdsn
) <
1069 SWAP_32(npvd
->pvd_vdsn
)) {
1070 udf_vfsp
->udf_pvd
= npvd
;
1076 } else if (ud_verify_tag_and_desc(ttag
, UD_LOG_VOL_DESC
,
1077 vds_loc
+ (index
>> shift
),
1078 1, desc_len
) == 0) {
1079 struct log_vol_desc
*lvd
;
1081 lvd
= (struct log_vol_desc
*)ttag
;
1082 if (strncmp(lvd
->lvd_dom_id
.reg_id
,
1083 UDF_DOMAIN_NAME
, 23) != 0) {
1084 printf("Domain ID in lvd is not valid\n");
1088 if (udf_vfsp
->udf_lvd
== NULL
) {
1089 udf_vfsp
->udf_lvd
= lvd
;
1091 struct log_vol_desc
*olvd
;
1093 olvd
= udf_vfsp
->udf_lvd
;
1094 if ((strncmp((caddr_t
)&olvd
->lvd_desc_cs
,
1095 (caddr_t
)&lvd
->lvd_desc_cs
,
1096 sizeof (charspec_t
)) == 0) &&
1097 (strncmp(olvd
->lvd_lvid
,
1098 lvd
->lvd_lvid
, 128) == 0)) {
1099 if (SWAP_32(olvd
->lvd_vdsn
) <
1100 SWAP_32(lvd
->lvd_vdsn
)) {
1101 udf_vfsp
->udf_lvd
= lvd
;
1107 } else if (ud_verify_tag_and_desc(ttag
, UD_PART_DESC
,
1108 vds_loc
+ (index
>> shift
),
1109 1, desc_len
) == 0) {
1111 struct phdr_desc
*hdr
;
1112 struct part_desc
*pdesc
;
1113 struct ud_part
*pnew
, *pold
, *part
;
1115 pdesc
= (struct part_desc
*)ttag
;
1116 pold
= udf_vfsp
->udf_parts
;
1117 for (i
= 0; i
< udf_vfsp
->udf_npart
; i
++) {
1118 if (pold
->udp_number
!=
1119 SWAP_16(pdesc
->pd_pnum
)) {
1124 if (SWAP_32(pdesc
->pd_vdsn
) >
1127 SWAP_32(pdesc
->pd_vdsn
);
1129 SWAP_32(pdesc
->pd_acc_type
);
1131 SWAP_32(pdesc
->pd_part_start
);
1133 SWAP_32(pdesc
->pd_part_length
);
1137 pold
= udf_vfsp
->udf_parts
;
1138 udf_vfsp
->udf_npart
++;
1139 pnew
= kmem_zalloc(udf_vfsp
->udf_npart
*
1140 sizeof (struct ud_part
), KM_SLEEP
);
1141 udf_vfsp
->udf_parts
= pnew
;
1144 sizeof (struct ud_part
) *
1145 (udf_vfsp
->udf_npart
- 1));
1147 sizeof (struct ud_part
) *
1148 (udf_vfsp
->udf_npart
- 1));
1150 part
= pnew
+ (udf_vfsp
->udf_npart
- 1);
1151 part
->udp_number
= SWAP_16(pdesc
->pd_pnum
);
1152 part
->udp_seqno
= SWAP_32(pdesc
->pd_vdsn
);
1153 part
->udp_access
= SWAP_32(pdesc
->pd_acc_type
);
1154 part
->udp_start
= SWAP_32(pdesc
->pd_part_start
);
1155 part
->udp_length
= SWAP_32(pdesc
->pd_part_length
);
1156 part
->udp_last_alloc
= 0;
1159 * Figure out space bitmaps
1162 hdr
= (struct phdr_desc
*)pdesc
->pd_pc_use
;
1163 if (hdr
->phdr_ust
.sad_ext_len
) {
1164 part
->udp_flags
= UDP_SPACETBLS
;
1165 part
->udp_unall_loc
=
1166 SWAP_32(hdr
->phdr_ust
.sad_ext_loc
);
1167 part
->udp_unall_len
=
1168 SWAP_32(hdr
->phdr_ust
.sad_ext_len
);
1169 part
->udp_freed_loc
=
1170 SWAP_32(hdr
->phdr_fst
.sad_ext_loc
);
1171 part
->udp_freed_len
=
1172 SWAP_32(hdr
->phdr_fst
.sad_ext_len
);
1174 part
->udp_flags
= UDP_BITMAPS
;
1175 part
->udp_unall_loc
=
1176 SWAP_32(hdr
->phdr_usb
.sad_ext_loc
);
1177 part
->udp_unall_len
=
1178 SWAP_32(hdr
->phdr_usb
.sad_ext_len
);
1179 part
->udp_freed_loc
=
1180 SWAP_32(hdr
->phdr_fsb
.sad_ext_loc
);
1181 part
->udp_freed_len
=
1182 SWAP_32(hdr
->phdr_fsb
.sad_ext_len
);
1184 } else if (ud_verify_tag_and_desc(ttag
, UD_TERM_DESC
,
1185 vds_loc
+ (index
>> shift
),
1186 1, desc_len
) == 0) {
1193 if ((udf_vfsp
->udf_pvd
== NULL
) ||
1194 (udf_vfsp
->udf_lvd
== NULL
) ||
1195 (udf_vfsp
->udf_parts
== NULL
)) {
1200 * Process Primary Volume Descriptor
1202 (void) strncpy(udf_vfsp
->udf_volid
, udf_vfsp
->udf_pvd
->pvd_vol_id
, 32);
1203 udf_vfsp
->udf_volid
[31] = '\0';
1204 udf_vfsp
->udf_tsno
= SWAP_16(udf_vfsp
->udf_pvd
->pvd_tag
.tag_sno
);
1207 * Process Logical Volume Descriptor
1209 udf_vfsp
->udf_lbsize
=
1210 SWAP_32(udf_vfsp
->udf_lvd
->lvd_log_bsize
);
1211 udf_vfsp
->udf_lbmask
= udf_vfsp
->udf_lbsize
- 1;
1212 udf_vfsp
->udf_l2d_shift
= shift
;
1213 udf_vfsp
->udf_l2b_shift
= shift
+ DEV_BSHIFT
;
1216 * Check if the media is in
1219 if (strcmp(udf_vfsp
->udf_lvd
->lvd_dom_id
.reg_id
,
1220 UDF_DOMAIN_NAME
) != 0) {
1225 * AVDS offset does not match with the lbsize
1228 if (udf_vfsp
->udf_lbsize
!= bsize
) {
1232 udf_vfsp
->udf_iseq_loc
=
1233 SWAP_32(udf_vfsp
->udf_lvd
->lvd_int_seq_ext
.ext_loc
);
1234 udf_vfsp
->udf_iseq_len
=
1235 SWAP_32(udf_vfsp
->udf_lvd
->lvd_int_seq_ext
.ext_len
);
1237 udf_vfsp
->udf_fsd_prn
=
1238 SWAP_16(udf_vfsp
->udf_lvd
->lvd_lvcu
.lad_ext_prn
);
1239 udf_vfsp
->udf_fsd_loc
=
1240 SWAP_32(udf_vfsp
->udf_lvd
->lvd_lvcu
.lad_ext_loc
);
1241 udf_vfsp
->udf_fsd_len
=
1242 SWAP_32(udf_vfsp
->udf_lvd
->lvd_lvcu
.lad_ext_len
);
1248 udf_vfsp
->udf_mtype
= udf_vfsp
->udf_parts
[0].udp_access
;
1249 for (index
= 0; index
< udf_vfsp
->udf_npart
; index
++) {
1250 if (udf_vfsp
->udf_parts
[index
].udp_access
<
1251 udf_vfsp
->udf_mtype
) {
1252 udf_vfsp
->udf_mtype
=
1253 udf_vfsp
->udf_parts
[index
].udp_access
;
1256 if ((udf_vfsp
->udf_mtype
< UDF_MT_RO
) ||
1257 (udf_vfsp
->udf_mtype
> UDF_MT_OW
)) {
1258 udf_vfsp
->udf_mtype
= UDF_MT_RO
;
1261 udf_vfsp
->udf_nmaps
= 0;
1262 hdr
= (struct pmap_hdr
*)udf_vfsp
->udf_lvd
->lvd_pmaps
;
1263 count
= SWAP_32(udf_vfsp
->udf_lvd
->lvd_num_pmaps
);
1264 for (index
= 0; index
< count
; index
++) {
1266 if ((hdr
->maph_type
== MAP_TYPE1
) &&
1267 (hdr
->maph_length
== MAP_TYPE1_LEN
)) {
1268 typ1
= (struct pmap_typ1
*)hdr
;
1270 map
= udf_vfsp
->udf_maps
;
1271 udf_vfsp
->udf_maps
=
1272 kmem_zalloc(sizeof (struct ud_map
) *
1273 (udf_vfsp
->udf_nmaps
+ 1), KM_SLEEP
);
1275 bcopy(map
, udf_vfsp
->udf_maps
,
1276 sizeof (struct ud_map
) *
1277 udf_vfsp
->udf_nmaps
);
1278 kmem_free(map
, sizeof (struct ud_map
) *
1279 udf_vfsp
->udf_nmaps
);
1281 map
= udf_vfsp
->udf_maps
+ udf_vfsp
->udf_nmaps
;
1282 map
->udm_flags
= UDM_MAP_NORM
;
1283 map
->udm_vsn
= SWAP_16(typ1
->map1_vsn
);
1284 map
->udm_pn
= SWAP_16(typ1
->map1_pn
);
1285 udf_vfsp
->udf_nmaps
++;
1286 } else if ((hdr
->maph_type
== MAP_TYPE2
) &&
1287 (hdr
->maph_length
== MAP_TYPE2_LEN
)) {
1288 typ2
= (struct pmap_typ2
*)hdr
;
1290 if (strncmp(typ2
->map2_pti
.reg_id
,
1291 UDF_VIRT_PART
, 23) == 0) {
1293 * Add this to the normal
1294 * partition table so that
1297 map
= udf_vfsp
->udf_maps
;
1298 udf_vfsp
->udf_maps
=
1299 kmem_zalloc(sizeof (struct ud_map
) *
1300 (udf_vfsp
->udf_nmaps
+ 1), KM_SLEEP
);
1302 bcopy(map
, udf_vfsp
->udf_maps
,
1303 sizeof (struct ud_map
) *
1304 udf_vfsp
->udf_nmaps
);
1306 sizeof (struct ud_map
) *
1307 udf_vfsp
->udf_nmaps
);
1309 map
= udf_vfsp
->udf_maps
+ udf_vfsp
->udf_nmaps
;
1310 map
->udm_flags
= UDM_MAP_VPM
;
1311 map
->udm_vsn
= SWAP_16(typ2
->map2_vsn
);
1312 map
->udm_pn
= SWAP_16(typ2
->map2_pn
);
1313 udf_vfsp
->udf_nmaps
++;
1314 if (error
= ud_get_last_block(dev
, &lblkno
)) {
1317 if (error
= ud_val_get_vat(udf_vfsp
, dev
,
1321 } else if (strncmp(typ2
->map2_pti
.reg_id
,
1322 UDF_SPAR_PART
, 23) == 0) {
1324 if (SWAP_16(typ2
->map2_pl
) != 32) {
1326 "Packet Length is not valid %x\n",
1327 SWAP_16(typ2
->map2_pl
));
1330 if ((typ2
->map2_nst
< 1) ||
1331 (typ2
->map2_nst
> 4)) {
1334 map
= udf_vfsp
->udf_maps
;
1335 udf_vfsp
->udf_maps
=
1336 kmem_zalloc(sizeof (struct ud_map
) *
1337 (udf_vfsp
->udf_nmaps
+ 1),
1340 bcopy(map
, udf_vfsp
->udf_maps
,
1341 sizeof (struct ud_map
) *
1342 udf_vfsp
->udf_nmaps
);
1344 sizeof (struct ud_map
) *
1345 udf_vfsp
->udf_nmaps
);
1347 map
= udf_vfsp
->udf_maps
+ udf_vfsp
->udf_nmaps
;
1348 map
->udm_flags
= UDM_MAP_SPM
;
1349 map
->udm_vsn
= SWAP_16(typ2
->map2_vsn
);
1350 map
->udm_pn
= SWAP_16(typ2
->map2_pn
);
1352 udf_vfsp
->udf_nmaps
++;
1354 if (error
= ud_read_sparing_tbls(udf_vfsp
,
1360 * Unknown type of partition
1367 * Unknown type of partition
1372 hdr
= (struct pmap_hdr
*)(((uint8_t *)hdr
) + hdr
->maph_length
);
1377 * Read Logical Volume Integrity Sequence
1380 secbp
= ud_bread(dev
, udf_vfsp
->udf_iseq_loc
<< shift
,
1381 udf_vfsp
->udf_iseq_len
);
1382 if ((error
= geterror(secbp
)) != 0) {
1384 "udfs : Could not read Logical Volume Integrity Sequence %x",
1389 udf_vfsp
->udf_iseq
= ngeteblk(udf_vfsp
->udf_iseq_len
);
1390 bp
= udf_vfsp
->udf_iseq
;
1392 bp
->b_dev
= cmpdev(dev
);
1393 bp
->b_blkno
= udf_vfsp
->udf_iseq_loc
<< shift
;
1394 bp
->b_bcount
= udf_vfsp
->udf_iseq_len
;
1395 bcopy(secbp
->b_un
.b_addr
, bp
->b_un
.b_addr
, udf_vfsp
->udf_iseq_len
);
1396 secbp
->b_flags
|= B_STALE
| B_AGE
;
1399 count
= udf_vfsp
->udf_iseq_len
/ DEV_BSIZE
;
1400 addr
= bp
->b_un
.b_addr
;
1401 for (index
= 0; index
< count
; index
++) {
1402 ttag
= (struct tag
*)(addr
+ index
* DEV_BSIZE
);
1403 desc_len
= udf_vfsp
->udf_iseq_len
- (index
* DEV_BSIZE
);
1404 if (ud_verify_tag_and_desc(ttag
, UD_LOG_VOL_INT
,
1405 udf_vfsp
->udf_iseq_loc
+ (index
>> shift
),
1406 1, desc_len
) == 0) {
1408 struct log_vol_int_desc
*lvid
;
1410 lvid
= (struct log_vol_int_desc
*)ttag
;
1411 udf_vfsp
->udf_lvid
= lvid
;
1413 if (SWAP_32(lvid
->lvid_int_type
) == LOG_VOL_CLOSE_INT
) {
1414 udf_vfsp
->udf_clean
= UDF_CLEAN
;
1416 udf_vfsp
->udf_clean
= UDF_DIRTY
;
1420 * update superblock with the metadata
1422 ud_convert_to_superblock(udf_vfsp
, lvid
);
1427 if (udf_vfsp
->udf_lvid
== NULL
) {
1431 if ((blkno
= ud_xlate_to_daddr(udf_vfsp
,
1432 udf_vfsp
->udf_fsd_prn
, udf_vfsp
->udf_fsd_loc
,
1436 secbp
= ud_bread(dev
, blkno
<< shift
, udf_vfsp
->udf_fsd_len
);
1437 if ((error
= geterror(secbp
)) != 0) {
1439 "udfs : Could not read File Set Descriptor %x", error
);
1443 fsd
= (struct file_set_desc
*)secbp
->b_un
.b_addr
;
1444 if (ud_verify_tag_and_desc(&fsd
->fsd_tag
, UD_FILE_SET_DESC
,
1445 udf_vfsp
->udf_fsd_loc
,
1446 1, udf_vfsp
->udf_fsd_len
) != 0) {
1447 secbp
->b_flags
= B_AGE
| B_STALE
;
1451 udf_vfsp
->udf_ricb_prn
= SWAP_16(fsd
->fsd_root_icb
.lad_ext_prn
);
1452 udf_vfsp
->udf_ricb_loc
= SWAP_32(fsd
->fsd_root_icb
.lad_ext_loc
);
1453 udf_vfsp
->udf_ricb_len
= SWAP_32(fsd
->fsd_root_icb
.lad_ext_len
);
1454 secbp
->b_flags
= B_AGE
| B_STALE
;
1456 udf_vfsp
->udf_root_blkno
= ud_xlate_to_daddr(udf_vfsp
,
1457 udf_vfsp
->udf_ricb_prn
, udf_vfsp
->udf_ricb_loc
,
1462 ud_destroy_fsp(udf_vfsp
);
1468 * release/free resources from one ud_map; map data was zalloc'd in
1469 * ud_validate_and_fill_superblock() and fields may later point to
1473 ud_free_map(struct ud_map
*map
)
1477 if (map
->udm_flags
& UDM_MAP_VPM
) {
1478 if (map
->udm_count
) {
1479 kmem_free(map
->udm_count
,
1480 map
->udm_nent
* sizeof (*map
->udm_count
));
1481 map
->udm_count
= NULL
;
1484 for (n
= 0; n
< map
->udm_nent
; n
++) {
1486 brelse(map
->udm_bp
[n
]);
1488 kmem_free(map
->udm_bp
,
1489 map
->udm_nent
* sizeof (*map
->udm_bp
));
1492 if (map
->udm_addr
) {
1493 kmem_free(map
->udm_addr
,
1494 map
->udm_nent
* sizeof (*map
->udm_addr
));
1495 map
->udm_addr
= NULL
;
1498 if (map
->udm_flags
& UDM_MAP_SPM
) {
1499 for (n
= 0; n
< MAX_SPM
; n
++) {
1500 if (map
->udm_sbp
[n
]) {
1501 brelse(map
->udm_sbp
[n
]);
1502 map
->udm_sbp
[n
] = NULL
;
1503 map
->udm_spaddr
[n
] = NULL
;
1510 ud_destroy_fsp(struct udf_vfs
*udf_vfsp
)
1514 ud_printf("ud_destroy_fsp\n");
1515 if (udf_vfsp
== NULL
)
1518 if (udf_vfsp
->udf_maps
) {
1519 for (i
= 0; i
< udf_vfsp
->udf_nmaps
; i
++)
1520 ud_free_map(&udf_vfsp
->udf_maps
[i
]);
1522 kmem_free(udf_vfsp
->udf_maps
,
1523 udf_vfsp
->udf_nmaps
* sizeof (*udf_vfsp
->udf_maps
));
1526 if (udf_vfsp
->udf_parts
) {
1527 kmem_free(udf_vfsp
->udf_parts
,
1528 udf_vfsp
->udf_npart
* sizeof (*udf_vfsp
->udf_parts
));
1530 if (udf_vfsp
->udf_iseq
) {
1531 udf_vfsp
->udf_iseq
->b_flags
|= (B_STALE
|B_AGE
);
1532 brelse(udf_vfsp
->udf_iseq
);
1534 if (udf_vfsp
->udf_vds
) {
1535 udf_vfsp
->udf_vds
->b_flags
|= (B_STALE
|B_AGE
);
1536 brelse(udf_vfsp
->udf_vds
);
1538 if (udf_vfsp
->udf_vfs
)
1539 ud_vfs_remove(udf_vfsp
);
1540 if (udf_vfsp
->udf_fsmnt
) {
1541 kmem_free(udf_vfsp
->udf_fsmnt
,
1542 strlen(udf_vfsp
->udf_fsmnt
) + 1);
1544 kmem_free(udf_vfsp
, sizeof (*udf_vfsp
));
1548 ud_convert_to_superblock(struct udf_vfs
*udf_vfsp
,
1549 struct log_vol_int_desc
*lvid
)
1553 struct ud_part
*ud_part
;
1556 udf_vfsp
->udf_maxuniq
= SWAP_64(lvid
->lvid_uniqid
);
1557 temp
= lvid
->lvid_fst
;
1558 c
= SWAP_32(lvid
->lvid_npart
);
1559 ud_part
= udf_vfsp
->udf_parts
;
1560 for (i
= 0; i
< c
; i
++) {
1561 if (i
>= udf_vfsp
->udf_npart
) {
1564 ud_part
->udp_nfree
= SWAP_32(temp
[i
]);
1565 ud_part
->udp_nblocks
= SWAP_32(temp
[c
+ i
]);
1566 udf_vfsp
->udf_freeblks
+= SWAP_32(temp
[i
]);
1567 udf_vfsp
->udf_totalblks
+= SWAP_32(temp
[c
+ i
]);
1571 iu
= (struct lvid_iu
*)(temp
+ c
* 2);
1572 udf_vfsp
->udf_nfiles
= SWAP_32(iu
->lvidiu_nfiles
);
1573 udf_vfsp
->udf_ndirs
= SWAP_32(iu
->lvidiu_ndirs
);
1574 udf_vfsp
->udf_miread
= BCD2HEX_16(SWAP_16(iu
->lvidiu_mread
));
1575 udf_vfsp
->udf_miwrite
= BCD2HEX_16(SWAP_16(iu
->lvidiu_mwrite
));
1576 udf_vfsp
->udf_mawrite
= BCD2HEX_16(SWAP_16(iu
->lvidiu_maxwr
));
1580 ud_update_superblock(struct vfs
*vfsp
)
1582 struct udf_vfs
*udf_vfsp
;
1584 ud_printf("ud_update_superblock\n");
1586 udf_vfsp
= (struct udf_vfs
*)vfsp
->vfs_data
;
1588 mutex_enter(&udf_vfsp
->udf_lock
);
1589 ud_sbwrite(udf_vfsp
);
1590 mutex_exit(&udf_vfsp
->udf_lock
);
1594 #include <sys/dkio.h>
1595 #include <sys/cdio.h>
1596 #include <sys/vtoc.h>
1599 * This part of the code is known
1600 * to work with only sparc. It needs
1601 * to be evluated before using it with x86
1604 ud_get_last_block(dev_t dev
, daddr_t
*blkno
)
1607 struct dk_cinfo dki_info
;
1608 int32_t rval
, error
;
1610 if ((error
= cdev_ioctl(dev
, DKIOCGVTOC
, (intptr_t)&vtoc
,
1611 FKIOCTL
|FREAD
|FNATIVE
, CRED(), &rval
)) != 0) {
1612 cmn_err(CE_NOTE
, "Could not get the vtoc information");
1616 if (vtoc
.v_sanity
!= VTOC_SANE
) {
1619 if ((error
= cdev_ioctl(dev
, DKIOCINFO
, (intptr_t)&dki_info
,
1620 FKIOCTL
|FREAD
|FNATIVE
, CRED(), &rval
)) != 0) {
1621 cmn_err(CE_NOTE
, "Could not get the slice information");
1625 if (dki_info
.dki_partition
> V_NUMPAR
) {
1630 *blkno
= vtoc
.v_part
[dki_info
.dki_partition
].p_size
;
1635 /* Search sequentially N - 2, N, N - 152, N - 150 for vat icb */
1637 * int32_t ud_sub_blks[] = {2, 0, 152, 150};
1639 int32_t ud_sub_blks
[] = {152, 150, 2, 0};
1640 int32_t ud_sub_count
= 4;
1643 * Validate the VAT ICB
1646 ud_val_get_vat(struct udf_vfs
*udf_vfsp
, dev_t dev
,
1647 daddr_t blkno
, struct ud_map
*udm
)
1650 struct file_entry
*fe
;
1651 int32_t end_loc
, i
, j
, ad_type
;
1652 struct short_ad
*sad
;
1653 struct long_ad
*lad
;
1654 uint32_t count
, blk
;
1655 struct ud_part
*ud_part
;
1658 end_loc
= (blkno
>> udf_vfsp
->udf_l2d_shift
) - 1;
1660 for (i
= 0; i
< ud_sub_count
; i
++) {
1661 udm
->udm_vat_icb
= end_loc
- ud_sub_blks
[i
];
1663 secbp
= ud_bread(dev
,
1664 udm
->udm_vat_icb
<< udf_vfsp
->udf_l2d_shift
,
1665 udf_vfsp
->udf_lbsize
);
1666 ASSERT(secbp
->b_un
.b_addr
);
1668 fe
= (struct file_entry
*)secbp
->b_un
.b_addr
;
1669 if (ud_verify_tag_and_desc(&fe
->fe_tag
, UD_FILE_ENTRY
, 0,
1671 if (ud_verify_tag_and_desc(&fe
->fe_tag
, UD_FILE_ENTRY
,
1672 SWAP_32(fe
->fe_tag
.tag_loc
),
1673 1, udf_vfsp
->udf_lbsize
) == 0) {
1674 if (fe
->fe_icb_tag
.itag_ftype
== 0) {
1679 secbp
->b_flags
|= B_AGE
| B_STALE
;
1682 if (i
== ud_sub_count
) {
1686 ad_type
= SWAP_16(fe
->fe_icb_tag
.itag_flags
) & 0x3;
1687 if (ad_type
== ICB_FLAG_ONE_AD
) {
1689 } else if (ad_type
== ICB_FLAG_SHORT_AD
) {
1691 SWAP_32(fe
->fe_len_adesc
) / sizeof (struct short_ad
);
1692 } else if (ad_type
== ICB_FLAG_LONG_AD
) {
1694 SWAP_32(fe
->fe_len_adesc
) / sizeof (struct long_ad
);
1700 udm
->udm_count
= kmem_zalloc(udm
->udm_nent
* sizeof (*udm
->udm_count
),
1702 udm
->udm_bp
= kmem_zalloc(udm
->udm_nent
* sizeof (*udm
->udm_bp
),
1704 udm
->udm_addr
= kmem_zalloc(udm
->udm_nent
* sizeof (*udm
->udm_addr
),
1707 if (ad_type
== ICB_FLAG_ONE_AD
) {
1708 udm
->udm_count
[0] = (SWAP_64(fe
->fe_info_len
) - 36) /
1710 udm
->udm_bp
[0] = secbp
;
1711 udm
->udm_addr
[0] = (uint32_t *)
1712 &fe
->fe_spec
[SWAP_32(fe
->fe_len_ear
)];
1715 for (i
= 0; i
< udm
->udm_nent
; i
++) {
1716 if (ad_type
== ICB_FLAG_SHORT_AD
) {
1717 sad
= (struct short_ad
*)
1718 (fe
->fe_spec
+ SWAP_32(fe
->fe_len_ear
));
1720 count
= SWAP_32(sad
->sad_ext_len
);
1721 blk
= SWAP_32(sad
->sad_ext_loc
);
1723 lad
= (struct long_ad
*)
1724 (fe
->fe_spec
+ SWAP_32(fe
->fe_len_ear
));
1726 count
= SWAP_32(lad
->lad_ext_len
);
1727 blk
= SWAP_32(lad
->lad_ext_loc
);
1728 ASSERT(SWAP_16(lad
->lad_ext_prn
) == udm
->udm_pn
);
1730 if ((count
& 0x3FFFFFFF) == 0) {
1733 if (i
< udm
->udm_nent
- 1) {
1734 udm
->udm_count
[i
] = count
/ 4;
1736 udm
->udm_count
[i
] = (count
- 36) / 4;
1738 ud_part
= udf_vfsp
->udf_parts
;
1739 for (j
= 0; j
< udf_vfsp
->udf_npart
; j
++) {
1740 if (udm
->udm_pn
== ud_part
->udp_number
) {
1741 blk
= ud_part
->udp_start
+ blk
;
1745 if (j
== udf_vfsp
->udf_npart
) {
1750 count
= (count
+ DEV_BSIZE
- 1) & ~(DEV_BSIZE
- 1);
1751 udm
->udm_bp
[i
] = ud_bread(dev
,
1752 blk
<< udf_vfsp
->udf_l2d_shift
, count
);
1753 if ((udm
->udm_bp
[i
]->b_error
!= 0) ||
1754 (udm
->udm_bp
[i
]->b_resid
)) {
1758 udm
->udm_addr
[i
] = (uint32_t *)udm
->udm_bp
[i
]->b_un
.b_addr
;
1764 secbp
->b_flags
|= B_AGE
| B_STALE
;
1770 ud_read_sparing_tbls(struct udf_vfs
*udf_vfsp
,
1771 dev_t dev
, struct ud_map
*map
, struct pmap_typ2
*typ2
)
1773 int32_t index
, valid
= 0;
1778 map
->udm_plen
= SWAP_16(typ2
->map2_pl
);
1779 map
->udm_nspm
= typ2
->map2_nst
;
1780 map
->udm_spsz
= SWAP_32(typ2
->map2_sest
);
1781 sz
= (map
->udm_spsz
+ udf_vfsp
->udf_lbmask
) & ~udf_vfsp
->udf_lbmask
;
1786 for (index
= 0; index
< map
->udm_nspm
; index
++) {
1787 map
->udm_loc
[index
] = SWAP_32(typ2
->map2_st
[index
]);
1790 map
->udm_loc
[index
] << udf_vfsp
->udf_l2d_shift
, sz
);
1791 if ((bp
->b_error
!= 0) || (bp
->b_resid
)) {
1795 stbl
= (struct stbl
*)bp
->b_un
.b_addr
;
1796 if (strncmp(stbl
->stbl_si
.reg_id
, UDF_SPAR_TBL
, 23) != 0) {
1797 printf("Sparing Identifier does not match\n");
1798 bp
->b_flags
|= B_AGE
| B_STALE
;
1802 map
->udm_sbp
[index
] = bp
;
1803 map
->udm_spaddr
[index
] = bp
->b_un
.b_addr
;
1806 struct stbl_entry
*te
;
1809 te
= (struct stbl_entry
*)&stbl
->stbl_entry
;
1810 tbl_len
= SWAP_16(stbl
->stbl_len
);
1812 printf("%x %x\n", tbl_len
, SWAP_32(stbl
->stbl_seqno
));
1813 printf("%x %x\n", bp
->b_un
.b_addr
, te
);
1815 for (i
= 0; i
< tbl_len
; i
++) {
1816 printf("%x %x\n", SWAP_32(te
->sent_ol
), SWAP_32(te
->sent_ml
));
1831 ud_get_lbsize(dev_t dev
, uint32_t *loc
)
1833 int32_t bsize
, shift
, index
, end_index
;
1837 struct anch_vol_desc_ptr
*avdp
;
1838 uint32_t session_offset
= 0;
1841 if (ud_get_last_block(dev
, &last_block
) != 0) {
1847 if (cdev_ioctl(dev
, CDROMREADOFFSET
, (intptr_t)&session_offset
,
1848 FKIOCTL
|FREAD
|FNATIVE
, CRED(), &rval
) != 0) {
1852 for (index
= 0; index
< end_index
; index
++) {
1854 for (bsize
= DEV_BSIZE
, shift
= 0;
1855 bsize
<= MAXBSIZE
; bsize
<<= 1, shift
++) {
1859 if (bsize
<= 2048) {
1861 session_offset
* 2048 / bsize
;
1864 session_offset
/ (bsize
/ 2048);
1866 } else if (index
== 1) {
1867 avd_loc
= last_block
- (1 << shift
);
1869 avd_loc
= last_block
- (256 << shift
);
1872 bp
= ud_bread(dev
, avd_loc
<< shift
,
1873 ANCHOR_VOL_DESC_LEN
);
1874 if (geterror(bp
) != 0) {
1880 * Verify if we have avdp here
1882 avdp
= (struct anch_vol_desc_ptr
*)bp
->b_un
.b_addr
;
1883 if (ud_verify_tag_and_desc(&avdp
->avd_tag
,
1884 UD_ANCH_VOL_DESC
, avd_loc
,
1885 1, ANCHOR_VOL_DESC_LEN
) != 0) {
1886 bp
->b_flags
|= B_AGE
| B_STALE
;
1890 bp
->b_flags
|= B_AGE
| B_STALE
;
1898 * Did not find AVD at all the locations
1903 static const struct vfsops udf_vfsops
= {
1904 .vfs_mount
= udf_mount
,
1905 .vfs_unmount
= udf_unmount
,
1906 .vfs_root
= udf_root
,
1907 .vfs_statvfs
= udf_statvfs
,
1908 .vfs_sync
= udf_sync
,
1909 .vfs_vget
= udf_vget
,
1910 .vfs_mountroot
= udf_mountroot
,
1914 udfinit(int fstype
, char *name
)
1918 ud_printf("udfinit\n");
1920 error
= vfs_setfsops(fstype
, &udf_vfsops
);
1922 cmn_err(CE_WARN
, "udfinit: bad fstype");
1926 udf_fstype
= fstype
;