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.
27 #include <sys/types.h>
28 #include <sys/t_lock.h>
29 #include <sys/param.h>
31 #include <sys/systm.h>
32 #include <sys/sysmacros.h>
33 #include <sys/resource.h>
34 #include <sys/signal.h>
40 #include <sys/vnode.h>
45 #include <sys/fcntl.h>
46 #include <sys/flock.h>
51 #include <sys/errno.h>
54 #include <sys/pathname.h>
55 #include <sys/debug.h>
56 #include <sys/vmsystm.h>
57 #include <sys/cmn_err.h>
58 #include <sys/dirent.h>
59 #include <sys/errno.h>
60 #include <sys/modctl.h>
61 #include <sys/statvfs.h>
62 #include <sys/mount.h>
63 #include <sys/sunddi.h>
64 #include <sys/bootconf.h>
65 #include <sys/policy.h>
72 #include <vm/seg_map.h>
73 #include <vm/seg_kmem.h>
74 #include <vm/seg_vn.h>
78 #include <sys/mntent.h>
81 #include <sys/fs_subr.h>
84 #include <sys/fs/udf_volume.h>
85 #include <sys/fs/udf_inode.h>
88 extern struct vnode
*common_specvp(struct vnode
*vp
);
90 extern kmutex_t ud_sync_busy
;
91 static int32_t ud_mountfs(struct vfs
*,
92 enum whymountroot
, dev_t
, char *, struct cred
*, int32_t);
93 static struct udf_vfs
*ud_validate_and_fill_superblock(dev_t
,
95 void ud_destroy_fsp(struct udf_vfs
*);
96 void ud_convert_to_superblock(struct udf_vfs
*,
97 struct log_vol_int_desc
*);
98 void ud_update_superblock(struct vfs
*);
99 int32_t ud_get_last_block(dev_t
, daddr_t
*);
100 static int32_t ud_val_get_vat(struct udf_vfs
*,
101 dev_t
, daddr_t
, struct ud_map
*);
102 int32_t ud_read_sparing_tbls(struct udf_vfs
*,
103 dev_t
, struct ud_map
*, struct pmap_typ2
*);
104 uint32_t ud_get_lbsize(dev_t
, uint32_t *);
106 static int32_t udf_mount(struct vfs
*,
107 struct vnode
*, struct mounta
*, struct cred
*);
108 static int32_t udf_unmount(struct vfs
*, int, struct cred
*);
109 static int32_t udf_root(struct vfs
*, struct vnode
**);
110 static int32_t udf_statvfs(struct vfs
*, struct statvfs64
*);
111 static int32_t udf_sync(struct vfs
*, int16_t, struct cred
*);
112 static int32_t udf_vget(struct vfs
*, struct vnode
**, struct fid
*);
113 static int32_t udf_mountroot(struct vfs
*vfsp
, enum whymountroot
);
115 static int udfinit(int, char *);
117 static mntopts_t udfs_mntopts
;
119 static vfsdef_t vfw
= {
123 VSW_HASPROTO
|VSW_CANREMOUNT
|VSW_STATS
|VSW_CANLOFI
,
127 static mntopts_t udfs_mntopts
= {
133 * Module linkage information for the kernel.
135 extern struct mod_ops mod_fsops
;
137 static struct modlfs modlfs
= {
138 &mod_fsops
, "filesystem for UDFS", &vfw
141 static struct modlinkage modlinkage
= {
142 MODREV_1
, (void *)&modlfs
, NULL
145 int32_t udf_fstype
= -1;
150 return (mod_install(&modlinkage
));
160 _info(struct modinfo
*modinfop
)
162 return (mod_info(&modlinkage
, modinfop
));
166 /* -------------------- vfs routines -------------------- */
169 * XXX - this appears only to be used by the VM code to handle the case where
170 * UNIX is running off the mini-root. That probably wants to be done
173 struct vnode
*rootvp
;
174 _NOTE(SCHEME_PROTECTS_DATA("safe sharing", rootvp
))
176 udf_mount(struct vfs
*vfsp
, struct vnode
*mvp
,
177 struct mounta
*uap
, struct cred
*cr
)
180 struct vnode
*lvp
= NULL
;
181 struct vnode
*svp
= NULL
;
184 enum whymountroot why
;
187 ud_printf("udf_mount\n");
189 if ((error
= secpolicy_fs_mount(cr
, mvp
, vfsp
)) != 0) {
193 if (mvp
->v_type
!= VDIR
) {
197 mutex_enter(&mvp
->v_lock
);
198 if ((uap
->flags
& MS_REMOUNT
) == 0 &&
199 (uap
->flags
& MS_OVERLAY
) == 0 &&
200 (mvp
->v_count
!= 1 || (mvp
->v_flag
& VROOT
))) {
201 mutex_exit(&mvp
->v_lock
);
204 mutex_exit(&mvp
->v_lock
);
206 if (error
= pn_get(uap
->dir
, UIO_USERSPACE
, &dpn
)) {
211 * Resolve path name of the file being mounted.
213 if (error
= lookupname(uap
->spec
, UIO_USERSPACE
, FOLLOW
, NULLVPP
,
219 error
= vfs_get_lofi(vfsp
, &lvp
);
225 } else if (error
== 0) {
230 if (svp
->v_type
!= VBLK
) {
237 * Ensure that this device isn't already mounted,
238 * unless this is a REMOUNT request
240 if (vfs_devmounting(dev
, vfsp
)) {
244 if (vfs_devismounted(dev
)) {
245 if (uap
->flags
& MS_REMOUNT
) {
254 if (getmajor(dev
) >= devcnt
) {
260 * If the device is a tape, mount it read only
262 if (devopsp
[getmajor(dev
)]->devo_cb_ops
->cb_flag
& D_TAPE
) {
263 vfsp
->vfs_flag
|= VFS_RDONLY
;
266 if (uap
->flags
& MS_RDONLY
) {
267 vfsp
->vfs_flag
|= VFS_RDONLY
;
273 if (uap
->flags
& MS_RDONLY
) {
274 vfs_setmntopt(vfsp
, MNTOPT_RO
, NULL
, 0);
276 if (uap
->flags
& MS_NOSUID
) {
277 vfs_setmntopt(vfsp
, MNTOPT_NOSUID
, NULL
, 0);
281 * Verify that the caller can open the device special file as
282 * required. It is not until this moment that we know whether
283 * we're mounting "ro" or not.
285 if ((vfsp
->vfs_flag
& VFS_RDONLY
) != 0) {
289 oflag
= FREAD
| FWRITE
;
290 aflag
= VREAD
| VWRITE
;
294 (error
= secpolicy_spec_open(cr
, svp
, oflag
)) != 0)
297 if ((error
= fop_access(svp
, aflag
, 0, cr
, NULL
)) != 0)
301 * Mount the filesystem.
303 error
= ud_mountfs(vfsp
, why
, dev
, dpn
.pn_path
, cr
, 0);
315 * unmount the file system pointed
320 udf_unmount(struct vfs
*vfsp
, int fflag
, struct cred
*cr
)
322 struct udf_vfs
*udf_vfsp
;
323 struct vnode
*bvp
, *rvp
;
324 struct ud_inode
*rip
;
327 ud_printf("udf_unmount\n");
329 if (secpolicy_fs_unmount(cr
, vfsp
) != 0) {
334 * forced unmount is not supported by this file system
335 * and thus, ENOTSUP, is being returned.
337 if (fflag
& MS_FORCE
)
340 udf_vfsp
= (struct udf_vfs
*)vfsp
->vfs_data
;
341 flag
= !(udf_vfsp
->udf_flags
& UDF_FL_RDONLY
);
342 bvp
= udf_vfsp
->udf_devvp
;
344 rvp
= udf_vfsp
->udf_root
;
348 (void) ud_release_cache(udf_vfsp
);
351 /* Flush all inodes except root */
352 if (ud_iflush(vfsp
) < 0) {
356 rw_enter(&rip
->i_contents
, RW_WRITER
);
357 (void) ud_syncip(rip
, B_INVAL
, I_SYNC
);
358 rw_exit(&rip
->i_contents
);
360 mutex_enter(&ud_sync_busy
);
361 if ((udf_vfsp
->udf_flags
& UDF_FL_RDONLY
) == 0) {
362 bflush(vfsp
->vfs_dev
);
363 mutex_enter(&udf_vfsp
->udf_lock
);
364 udf_vfsp
->udf_clean
= UDF_CLEAN
;
365 mutex_exit(&udf_vfsp
->udf_lock
);
366 ud_update_superblock(vfsp
);
368 mutex_exit(&ud_sync_busy
);
370 mutex_destroy(&udf_vfsp
->udf_lock
);
371 mutex_destroy(&udf_vfsp
->udf_rename_lck
);
377 ud_destroy_fsp(udf_vfsp
);
379 (void) fop_putpage(bvp
, (offset_t
)0, (uint32_t)0, B_INVAL
, cr
, NULL
);
380 (void) fop_close(bvp
, flag
, 1, (offset_t
)0, cr
, NULL
);
382 (void) bfinval(vfsp
->vfs_dev
, 1);
391 * Get the root vp for the
395 udf_root(struct vfs
*vfsp
, struct vnode
**vpp
)
397 struct udf_vfs
*udf_vfsp
;
400 ud_printf("udf_root\n");
402 udf_vfsp
= (struct udf_vfs
*)vfsp
->vfs_data
;
404 ASSERT(udf_vfsp
!= NULL
);
405 ASSERT(udf_vfsp
->udf_root
!= NULL
);
407 vp
= udf_vfsp
->udf_root
;
415 * Get file system statistics.
418 udf_statvfs(struct vfs
*vfsp
, struct statvfs64
*sp
)
420 struct udf_vfs
*udf_vfsp
;
421 struct ud_part
*parts
;
425 ud_printf("udf_statvfs\n");
427 udf_vfsp
= (struct udf_vfs
*)vfsp
->vfs_data
;
428 (void) bzero(sp
, sizeof (struct statvfs64
));
430 mutex_enter(&udf_vfsp
->udf_lock
);
431 sp
->f_bsize
= udf_vfsp
->udf_lbsize
;
432 sp
->f_frsize
= udf_vfsp
->udf_lbsize
;
435 parts
= udf_vfsp
->udf_parts
;
436 for (index
= 0; index
< udf_vfsp
->udf_npart
; index
++) {
437 sp
->f_blocks
+= parts
->udp_nblocks
;
438 sp
->f_bfree
+= parts
->udp_nfree
;
441 sp
->f_bavail
= sp
->f_bfree
;
444 * Since there are no real inodes allocated
445 * we will approximate
446 * each new file will occupy :
447 * 38(over head each dent) + MAXNAMLEN / 2 + inode_size(==block size)
449 sp
->f_ffree
= sp
->f_favail
=
450 (sp
->f_bavail
* sp
->f_bsize
) / (146 + sp
->f_bsize
);
453 * The total number of inodes is
454 * the sum of files + directories + free inodes
456 sp
->f_files
= sp
->f_ffree
+ udf_vfsp
->udf_nfiles
+ udf_vfsp
->udf_ndirs
;
457 (void) cmpldev(&d32
, vfsp
->vfs_dev
);
459 (void) strcpy(sp
->f_basetype
, vfssw
[vfsp
->vfs_fstype
].vsw_name
);
460 sp
->f_flag
= vf_to_stf(vfsp
->vfs_flag
);
461 sp
->f_namemax
= MAXNAMLEN
;
462 (void) strcpy(sp
->f_fstr
, udf_vfsp
->udf_volid
);
464 mutex_exit(&udf_vfsp
->udf_lock
);
471 * Flush any pending I/O to file system vfsp.
472 * The ud_update() routine will only flush *all* udf files.
477 udf_sync(struct vfs
*vfsp
, int16_t flag
, struct cred
*cr
)
479 ud_printf("udf_sync\n");
489 udf_vget(struct vfs
*vfsp
,
490 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
, (offset_t
)0,
567 (uint32_t)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,
578 (offset_t
)0, CRED(), NULL
);
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
,
613 enum whymountroot why
, dev_t dev
, char *name
,
614 struct cred
*cr
, int32_t isroot
)
616 struct vnode
*devvp
= NULL
;
618 int32_t needclose
= 0;
619 struct udf_vfs
*udf_vfsp
= NULL
;
620 struct log_vol_int_desc
*lvid
;
621 struct ud_inode
*rip
= NULL
;
622 struct vnode
*rvp
= NULL
;
628 ud_printf("ud_mountfs\n");
630 if (why
== ROOT_INIT
) {
634 devvp
= makespecvp(dev
, VBLK
);
637 * Open block device mounted on.
638 * When bio is fixed for vnodes this can all be vnode
641 error
= fop_open(&devvp
,
642 (vfsp
->vfs_flag
& VFS_RDONLY
) ? FREAD
: FREAD
|FWRITE
,
650 * Refuse to go any further if this
651 * device is being used for swapping.
653 if (IS_SWAPVP(devvp
)) {
660 * check for dev already mounted on
662 if (vfsp
->vfs_flag
& VFS_REMOUNT
) {
664 int32_t index
, count
;
669 /* cannot remount to RDONLY */
670 if (vfsp
->vfs_flag
& VFS_RDONLY
) {
674 if (vfsp
->vfs_dev
!= dev
) {
678 udf_vfsp
= (struct udf_vfs
*)vfsp
->vfs_data
;
679 devvp
= udf_vfsp
->udf_devvp
;
682 * fsck may have altered the file system; discard
683 * as much incore data as possible. Don't flush
684 * if this is a rw to rw remount; it's just resetting
687 if (udf_vfsp
->udf_flags
& UDF_FL_RDONLY
) {
688 (void) dnlc_purge_vfsp(vfsp
, 0);
689 (void) fop_putpage(devvp
, (offset_t
)0, (uint_t
)0,
690 B_INVAL
, CRED(), NULL
);
691 (void) ud_iflush(vfsp
);
697 * We could read UDF1.50 and write UDF1.50 only
698 * disallow mount of any highier version
700 if ((udf_vfsp
->udf_miread
> UDF_150
) ||
701 (udf_vfsp
->udf_miwrite
> UDF_150
)) {
707 * read/write to read/write; all done
709 if (udf_vfsp
->udf_flags
& UDF_FL_RW
) {
714 * Does the media type allow a writable mount
716 if (udf_vfsp
->udf_mtype
!= UDF_MT_OW
) {
723 * and check if it is possible to
726 tpt
= ud_bread(vfsp
->vfs_dev
,
727 udf_vfsp
->udf_iseq_loc
<< udf_vfsp
->udf_l2d_shift
,
728 udf_vfsp
->udf_iseq_len
);
729 if (tpt
->b_flags
& B_ERROR
) {
733 count
= udf_vfsp
->udf_iseq_len
/ DEV_BSIZE
;
734 addr
= tpt
->b_un
.b_addr
;
735 for (index
= 0; index
< count
; index
++) {
736 ttag
= (struct tag
*)(addr
+ index
* DEV_BSIZE
);
737 desc_len
= udf_vfsp
->udf_iseq_len
- (index
* DEV_BSIZE
);
738 if (ud_verify_tag_and_desc(ttag
, UD_LOG_VOL_INT
,
739 udf_vfsp
->udf_iseq_loc
+
740 (index
>> udf_vfsp
->udf_l2d_shift
),
742 struct log_vol_int_desc
*lvid
;
744 lvid
= (struct log_vol_int_desc
*)ttag
;
746 if (SWAP_32(lvid
->lvid_int_type
) !=
753 * Copy new data to old data
755 bcopy(udf_vfsp
->udf_iseq
->b_un
.b_addr
,
756 tpt
->b_un
.b_addr
, udf_vfsp
->udf_iseq_len
);
761 udf_vfsp
->udf_flags
= UDF_FL_RW
;
763 mutex_enter(&udf_vfsp
->udf_lock
);
764 ud_sbwrite(udf_vfsp
);
765 mutex_exit(&udf_vfsp
->udf_lock
);
768 tpt
->b_flags
= B_AGE
| B_STALE
;
776 * Flush back any dirty pages on the block device to
777 * try and keep the buffer cache in sync with the page
778 * cache if someone is trying to use block devices when
779 * they really should be using the raw device.
781 (void) fop_putpage(common_specvp(devvp
), (offset_t
)0,
782 (uint32_t)0, B_INVAL
, cr
, NULL
);
786 * Check if the file system
787 * is a valid udfs and fill
788 * the required fields in udf_vfs
790 _NOTE(NO_COMPETING_THREADS_NOW
);
792 if ((lbsize
= ud_get_lbsize(dev
, &avd_loc
)) == 0) {
797 udf_vfsp
= ud_validate_and_fill_superblock(dev
, lbsize
, avd_loc
);
798 if (udf_vfsp
== NULL
) {
804 * Fill in vfs private data
806 vfsp
->vfs_fstype
= udf_fstype
;
807 vfs_make_fsid(&vfsp
->vfs_fsid
, dev
, udf_fstype
);
808 vfsp
->vfs_data
= (caddr_t
)udf_vfsp
;
810 vfsp
->vfs_flag
|= VFS_NOTRUNC
;
811 udf_vfsp
->udf_devvp
= devvp
;
813 udf_vfsp
->udf_fsmnt
= kmem_zalloc(strlen(name
) + 1, KM_SLEEP
);
814 (void) strcpy(udf_vfsp
->udf_fsmnt
, name
);
816 udf_vfsp
->udf_vfs
= vfsp
;
817 udf_vfsp
->udf_rdclustsz
= udf_vfsp
->udf_wrclustsz
= maxphys
;
819 udf_vfsp
->udf_mod
= 0;
822 lvid
= udf_vfsp
->udf_lvid
;
823 if (vfsp
->vfs_flag
& VFS_RDONLY
) {
825 * We could read only UDF1.50
826 * disallow mount of any highier version
828 if (udf_vfsp
->udf_miread
> UDF_150
) {
832 udf_vfsp
->udf_flags
= UDF_FL_RDONLY
;
833 if (SWAP_32(lvid
->lvid_int_type
) == LOG_VOL_CLOSE_INT
) {
834 udf_vfsp
->udf_clean
= UDF_CLEAN
;
836 /* Do we have a VAT at the end of the recorded media */
837 map
= udf_vfsp
->udf_maps
;
838 for (i
= 0; i
< udf_vfsp
->udf_nmaps
; i
++) {
839 if (map
->udm_flags
& UDM_MAP_VPM
) {
844 if (i
== udf_vfsp
->udf_nmaps
) {
848 udf_vfsp
->udf_clean
= UDF_CLEAN
;
852 * We could read UDF1.50 and write UDF1.50 only
853 * disallow mount of any highier version
855 if ((udf_vfsp
->udf_miread
> UDF_150
) ||
856 (udf_vfsp
->udf_miwrite
> UDF_150
)) {
861 * Check if the media allows
862 * us to mount read/write
864 if (udf_vfsp
->udf_mtype
!= UDF_MT_OW
) {
870 * Check if we have VAT on a writable media
871 * we cannot use the media in presence of VAT
874 map
= udf_vfsp
->udf_maps
;
876 for (i
= 0; i
< udf_vfsp
->udf_nmaps
; i
++) {
877 if (map
->udm_flags
& UDM_MAP_VPM
) {
885 * Check if the domain Id allows
888 if (udf_vfsp
->udf_lvd
->lvd_dom_id
.reg_ids
[2] & 0x3) {
892 udf_vfsp
->udf_flags
= UDF_FL_RW
;
894 if (SWAP_32(lvid
->lvid_int_type
) == LOG_VOL_CLOSE_INT
) {
895 udf_vfsp
->udf_clean
= UDF_CLEAN
;
898 udf_vfsp
->udf_clean
= UDF_DIRTY
;
906 mutex_init(&udf_vfsp
->udf_lock
, NULL
, MUTEX_DEFAULT
, NULL
);
908 mutex_init(&udf_vfsp
->udf_rename_lck
, NULL
, MUTEX_DEFAULT
, NULL
);
910 _NOTE(COMPETING_THREADS_NOW
);
911 if (error
= ud_iget(vfsp
, udf_vfsp
->udf_ricb_prn
,
912 udf_vfsp
->udf_ricb_loc
, &rip
, NULL
, cr
)) {
913 mutex_destroy(&udf_vfsp
->udf_lock
);
919 * Get the root inode and
920 * initialize the root vnode
923 mutex_enter(&rvp
->v_lock
);
924 rvp
->v_flag
|= VROOT
;
925 mutex_exit(&rvp
->v_lock
);
926 udf_vfsp
->udf_root
= rvp
;
929 if (why
== ROOT_INIT
&& isroot
)
932 ud_vfs_add(udf_vfsp
);
934 if (udf_vfsp
->udf_flags
== UDF_FL_RW
) {
935 udf_vfsp
->udf_clean
= UDF_DIRTY
;
936 ud_update_superblock(vfsp
);
942 ud_destroy_fsp(udf_vfsp
);
944 (void) fop_close(devvp
, (vfsp
->vfs_flag
& VFS_RDONLY
) ?
945 FREAD
: FREAD
|FWRITE
, 1, (offset_t
)0, cr
, NULL
);
955 static struct udf_vfs
*
956 ud_validate_and_fill_superblock(dev_t dev
, int32_t bsize
, uint32_t avd_loc
)
958 int32_t error
, count
, index
, shift
;
959 uint32_t dummy
, vds_loc
;
961 daddr_t blkno
, lblkno
;
962 struct buf
*secbp
, *bp
;
964 struct anch_vol_desc_ptr
*avdp
;
965 struct file_set_desc
*fsd
;
966 struct udf_vfs
*udf_vfsp
= NULL
;
967 struct pmap_hdr
*hdr
;
968 struct pmap_typ1
*typ1
;
969 struct pmap_typ2
*typ2
;
973 ud_printf("ud_validate_and_fill_superblock\n");
975 if (bsize
< DEV_BSIZE
) {
979 while ((bsize
>> shift
) > DEV_BSIZE
) {
984 * Read Anchor Volume Descriptor
985 * Verify it and get the location of
986 * Main Volume Descriptor Sequence
988 secbp
= ud_bread(dev
, avd_loc
<< shift
, ANCHOR_VOL_DESC_LEN
);
989 if ((error
= geterror(secbp
)) != 0) {
990 cmn_err(CE_NOTE
, "udfs : Could not read Anchor Volume Desc %x",
995 avdp
= (struct anch_vol_desc_ptr
*)secbp
->b_un
.b_addr
;
996 if (ud_verify_tag_and_desc(&avdp
->avd_tag
, UD_ANCH_VOL_DESC
,
997 avd_loc
, 1, ANCHOR_VOL_DESC_LEN
) != 0) {
1001 udf_vfsp
= (struct udf_vfs
*)
1002 kmem_zalloc(sizeof (struct udf_vfs
), KM_SLEEP
);
1003 udf_vfsp
->udf_mvds_loc
= SWAP_32(avdp
->avd_main_vdse
.ext_loc
);
1004 udf_vfsp
->udf_mvds_len
= SWAP_32(avdp
->avd_main_vdse
.ext_len
);
1005 udf_vfsp
->udf_rvds_loc
= SWAP_32(avdp
->avd_res_vdse
.ext_loc
);
1006 udf_vfsp
->udf_rvds_len
= SWAP_32(avdp
->avd_res_vdse
.ext_len
);
1007 secbp
->b_flags
= B_AGE
| B_STALE
;
1011 * Read Main Volume Descriptor Sequence
1014 vds_loc
= udf_vfsp
->udf_mvds_loc
;
1015 secbp
= ud_bread(dev
, vds_loc
<< shift
,
1016 udf_vfsp
->udf_mvds_len
);
1017 if ((error
= geterror(secbp
)) != 0) {
1019 cmn_err(CE_NOTE
, "udfs : Could not read Main Volume Desc %x",
1022 vds_loc
= udf_vfsp
->udf_rvds_loc
;
1023 secbp
= ud_bread(dev
, vds_loc
<< shift
,
1024 udf_vfsp
->udf_rvds_len
);
1025 if ((error
= geterror(secbp
)) != 0) {
1028 "udfs : Could not read Res Volume Desc %x", error
);
1033 udf_vfsp
->udf_vds
= ngeteblk(udf_vfsp
->udf_mvds_len
);
1034 bp
= udf_vfsp
->udf_vds
;
1036 bp
->b_dev
= cmpdev(dev
);
1037 bp
->b_blkno
= vds_loc
<< shift
;
1038 bp
->b_bcount
= udf_vfsp
->udf_mvds_len
;
1039 bcopy(secbp
->b_un
.b_addr
, bp
->b_un
.b_addr
, udf_vfsp
->udf_mvds_len
);
1040 secbp
->b_flags
|= B_STALE
| B_AGE
;
1044 count
= udf_vfsp
->udf_mvds_len
/ DEV_BSIZE
;
1045 addr
= bp
->b_un
.b_addr
;
1046 for (index
= 0; index
< count
; index
++) {
1047 ttag
= (struct tag
*)(addr
+ index
* DEV_BSIZE
);
1048 desc_len
= udf_vfsp
->udf_mvds_len
- (index
* DEV_BSIZE
);
1049 if (ud_verify_tag_and_desc(ttag
, UD_PRI_VOL_DESC
,
1050 vds_loc
+ (index
>> shift
),
1051 1, desc_len
) == 0) {
1052 if (udf_vfsp
->udf_pvd
== NULL
) {
1054 (struct pri_vol_desc
*)ttag
;
1056 struct pri_vol_desc
*opvd
, *npvd
;
1058 opvd
= udf_vfsp
->udf_pvd
;
1059 npvd
= (struct pri_vol_desc
*)ttag
;
1061 if ((strncmp(opvd
->pvd_vsi
,
1062 npvd
->pvd_vsi
, 128) == 0) &&
1063 (strncmp(opvd
->pvd_vol_id
,
1064 npvd
->pvd_vol_id
, 32) == 0) &&
1065 (strncmp((caddr_t
)&opvd
->pvd_desc_cs
,
1066 (caddr_t
)&npvd
->pvd_desc_cs
,
1067 sizeof (charspec_t
)) == 0)) {
1069 if (SWAP_32(opvd
->pvd_vdsn
) <
1070 SWAP_32(npvd
->pvd_vdsn
)) {
1071 udf_vfsp
->udf_pvd
= npvd
;
1077 } else if (ud_verify_tag_and_desc(ttag
, UD_LOG_VOL_DESC
,
1078 vds_loc
+ (index
>> shift
),
1079 1, desc_len
) == 0) {
1080 struct log_vol_desc
*lvd
;
1082 lvd
= (struct log_vol_desc
*)ttag
;
1083 if (strncmp(lvd
->lvd_dom_id
.reg_id
,
1084 UDF_DOMAIN_NAME
, 23) != 0) {
1085 printf("Domain ID in lvd is not valid\n");
1089 if (udf_vfsp
->udf_lvd
== NULL
) {
1090 udf_vfsp
->udf_lvd
= lvd
;
1092 struct log_vol_desc
*olvd
;
1094 olvd
= udf_vfsp
->udf_lvd
;
1095 if ((strncmp((caddr_t
)&olvd
->lvd_desc_cs
,
1096 (caddr_t
)&lvd
->lvd_desc_cs
,
1097 sizeof (charspec_t
)) == 0) &&
1098 (strncmp(olvd
->lvd_lvid
,
1099 lvd
->lvd_lvid
, 128) == 0)) {
1100 if (SWAP_32(olvd
->lvd_vdsn
) <
1101 SWAP_32(lvd
->lvd_vdsn
)) {
1102 udf_vfsp
->udf_lvd
= lvd
;
1108 } else if (ud_verify_tag_and_desc(ttag
, UD_PART_DESC
,
1109 vds_loc
+ (index
>> shift
),
1110 1, desc_len
) == 0) {
1112 struct phdr_desc
*hdr
;
1113 struct part_desc
*pdesc
;
1114 struct ud_part
*pnew
, *pold
, *part
;
1116 pdesc
= (struct part_desc
*)ttag
;
1117 pold
= udf_vfsp
->udf_parts
;
1118 for (i
= 0; i
< udf_vfsp
->udf_npart
; i
++) {
1119 if (pold
->udp_number
!=
1120 SWAP_16(pdesc
->pd_pnum
)) {
1125 if (SWAP_32(pdesc
->pd_vdsn
) >
1128 SWAP_32(pdesc
->pd_vdsn
);
1130 SWAP_32(pdesc
->pd_acc_type
);
1132 SWAP_32(pdesc
->pd_part_start
);
1134 SWAP_32(pdesc
->pd_part_length
);
1138 pold
= udf_vfsp
->udf_parts
;
1139 udf_vfsp
->udf_npart
++;
1140 pnew
= kmem_zalloc(udf_vfsp
->udf_npart
*
1141 sizeof (struct ud_part
), KM_SLEEP
);
1142 udf_vfsp
->udf_parts
= pnew
;
1145 sizeof (struct ud_part
) *
1146 (udf_vfsp
->udf_npart
- 1));
1148 sizeof (struct ud_part
) *
1149 (udf_vfsp
->udf_npart
- 1));
1151 part
= pnew
+ (udf_vfsp
->udf_npart
- 1);
1152 part
->udp_number
= SWAP_16(pdesc
->pd_pnum
);
1153 part
->udp_seqno
= SWAP_32(pdesc
->pd_vdsn
);
1154 part
->udp_access
= SWAP_32(pdesc
->pd_acc_type
);
1155 part
->udp_start
= SWAP_32(pdesc
->pd_part_start
);
1156 part
->udp_length
= SWAP_32(pdesc
->pd_part_length
);
1157 part
->udp_last_alloc
= 0;
1160 * Figure out space bitmaps
1163 hdr
= (struct phdr_desc
*)pdesc
->pd_pc_use
;
1164 if (hdr
->phdr_ust
.sad_ext_len
) {
1165 part
->udp_flags
= UDP_SPACETBLS
;
1166 part
->udp_unall_loc
=
1167 SWAP_32(hdr
->phdr_ust
.sad_ext_loc
);
1168 part
->udp_unall_len
=
1169 SWAP_32(hdr
->phdr_ust
.sad_ext_len
);
1170 part
->udp_freed_loc
=
1171 SWAP_32(hdr
->phdr_fst
.sad_ext_loc
);
1172 part
->udp_freed_len
=
1173 SWAP_32(hdr
->phdr_fst
.sad_ext_len
);
1175 part
->udp_flags
= UDP_BITMAPS
;
1176 part
->udp_unall_loc
=
1177 SWAP_32(hdr
->phdr_usb
.sad_ext_loc
);
1178 part
->udp_unall_len
=
1179 SWAP_32(hdr
->phdr_usb
.sad_ext_len
);
1180 part
->udp_freed_loc
=
1181 SWAP_32(hdr
->phdr_fsb
.sad_ext_loc
);
1182 part
->udp_freed_len
=
1183 SWAP_32(hdr
->phdr_fsb
.sad_ext_len
);
1185 } else if (ud_verify_tag_and_desc(ttag
, UD_TERM_DESC
,
1186 vds_loc
+ (index
>> shift
),
1187 1, desc_len
) == 0) {
1194 if ((udf_vfsp
->udf_pvd
== NULL
) ||
1195 (udf_vfsp
->udf_lvd
== NULL
) ||
1196 (udf_vfsp
->udf_parts
== NULL
)) {
1201 * Process Primary Volume Descriptor
1203 (void) strncpy(udf_vfsp
->udf_volid
, udf_vfsp
->udf_pvd
->pvd_vol_id
, 32);
1204 udf_vfsp
->udf_volid
[31] = '\0';
1205 udf_vfsp
->udf_tsno
= SWAP_16(udf_vfsp
->udf_pvd
->pvd_tag
.tag_sno
);
1208 * Process Logical Volume Descriptor
1210 udf_vfsp
->udf_lbsize
=
1211 SWAP_32(udf_vfsp
->udf_lvd
->lvd_log_bsize
);
1212 udf_vfsp
->udf_lbmask
= udf_vfsp
->udf_lbsize
- 1;
1213 udf_vfsp
->udf_l2d_shift
= shift
;
1214 udf_vfsp
->udf_l2b_shift
= shift
+ DEV_BSHIFT
;
1217 * Check if the media is in
1220 if (strcmp(udf_vfsp
->udf_lvd
->lvd_dom_id
.reg_id
,
1221 UDF_DOMAIN_NAME
) != 0) {
1226 * AVDS offset does not match with the lbsize
1229 if (udf_vfsp
->udf_lbsize
!= bsize
) {
1233 udf_vfsp
->udf_iseq_loc
=
1234 SWAP_32(udf_vfsp
->udf_lvd
->lvd_int_seq_ext
.ext_loc
);
1235 udf_vfsp
->udf_iseq_len
=
1236 SWAP_32(udf_vfsp
->udf_lvd
->lvd_int_seq_ext
.ext_len
);
1238 udf_vfsp
->udf_fsd_prn
=
1239 SWAP_16(udf_vfsp
->udf_lvd
->lvd_lvcu
.lad_ext_prn
);
1240 udf_vfsp
->udf_fsd_loc
=
1241 SWAP_32(udf_vfsp
->udf_lvd
->lvd_lvcu
.lad_ext_loc
);
1242 udf_vfsp
->udf_fsd_len
=
1243 SWAP_32(udf_vfsp
->udf_lvd
->lvd_lvcu
.lad_ext_len
);
1249 udf_vfsp
->udf_mtype
= udf_vfsp
->udf_parts
[0].udp_access
;
1250 for (index
= 0; index
< udf_vfsp
->udf_npart
; index
++) {
1251 if (udf_vfsp
->udf_parts
[index
].udp_access
<
1252 udf_vfsp
->udf_mtype
) {
1253 udf_vfsp
->udf_mtype
=
1254 udf_vfsp
->udf_parts
[index
].udp_access
;
1257 if ((udf_vfsp
->udf_mtype
< UDF_MT_RO
) ||
1258 (udf_vfsp
->udf_mtype
> UDF_MT_OW
)) {
1259 udf_vfsp
->udf_mtype
= UDF_MT_RO
;
1262 udf_vfsp
->udf_nmaps
= 0;
1263 hdr
= (struct pmap_hdr
*)udf_vfsp
->udf_lvd
->lvd_pmaps
;
1264 count
= SWAP_32(udf_vfsp
->udf_lvd
->lvd_num_pmaps
);
1265 for (index
= 0; index
< count
; index
++) {
1267 if ((hdr
->maph_type
== MAP_TYPE1
) &&
1268 (hdr
->maph_length
== MAP_TYPE1_LEN
)) {
1269 typ1
= (struct pmap_typ1
*)hdr
;
1271 map
= udf_vfsp
->udf_maps
;
1272 udf_vfsp
->udf_maps
=
1273 kmem_zalloc(sizeof (struct ud_map
) *
1274 (udf_vfsp
->udf_nmaps
+ 1), KM_SLEEP
);
1276 bcopy(map
, udf_vfsp
->udf_maps
,
1277 sizeof (struct ud_map
) *
1278 udf_vfsp
->udf_nmaps
);
1279 kmem_free(map
, sizeof (struct ud_map
) *
1280 udf_vfsp
->udf_nmaps
);
1282 map
= udf_vfsp
->udf_maps
+ udf_vfsp
->udf_nmaps
;
1283 map
->udm_flags
= UDM_MAP_NORM
;
1284 map
->udm_vsn
= SWAP_16(typ1
->map1_vsn
);
1285 map
->udm_pn
= SWAP_16(typ1
->map1_pn
);
1286 udf_vfsp
->udf_nmaps
++;
1287 } else if ((hdr
->maph_type
== MAP_TYPE2
) &&
1288 (hdr
->maph_length
== MAP_TYPE2_LEN
)) {
1289 typ2
= (struct pmap_typ2
*)hdr
;
1291 if (strncmp(typ2
->map2_pti
.reg_id
,
1292 UDF_VIRT_PART
, 23) == 0) {
1294 * Add this to the normal
1295 * partition table so that
1298 map
= udf_vfsp
->udf_maps
;
1299 udf_vfsp
->udf_maps
=
1300 kmem_zalloc(sizeof (struct ud_map
) *
1301 (udf_vfsp
->udf_nmaps
+ 1), KM_SLEEP
);
1303 bcopy(map
, udf_vfsp
->udf_maps
,
1304 sizeof (struct ud_map
) *
1305 udf_vfsp
->udf_nmaps
);
1307 sizeof (struct ud_map
) *
1308 udf_vfsp
->udf_nmaps
);
1310 map
= udf_vfsp
->udf_maps
+ udf_vfsp
->udf_nmaps
;
1311 map
->udm_flags
= UDM_MAP_VPM
;
1312 map
->udm_vsn
= SWAP_16(typ2
->map2_vsn
);
1313 map
->udm_pn
= SWAP_16(typ2
->map2_pn
);
1314 udf_vfsp
->udf_nmaps
++;
1315 if (error
= ud_get_last_block(dev
, &lblkno
)) {
1318 if (error
= ud_val_get_vat(udf_vfsp
, dev
,
1322 } else if (strncmp(typ2
->map2_pti
.reg_id
,
1323 UDF_SPAR_PART
, 23) == 0) {
1325 if (SWAP_16(typ2
->map2_pl
) != 32) {
1327 "Packet Length is not valid %x\n",
1328 SWAP_16(typ2
->map2_pl
));
1331 if ((typ2
->map2_nst
< 1) ||
1332 (typ2
->map2_nst
> 4)) {
1335 map
= udf_vfsp
->udf_maps
;
1336 udf_vfsp
->udf_maps
=
1337 kmem_zalloc(sizeof (struct ud_map
) *
1338 (udf_vfsp
->udf_nmaps
+ 1),
1341 bcopy(map
, udf_vfsp
->udf_maps
,
1342 sizeof (struct ud_map
) *
1343 udf_vfsp
->udf_nmaps
);
1345 sizeof (struct ud_map
) *
1346 udf_vfsp
->udf_nmaps
);
1348 map
= udf_vfsp
->udf_maps
+ udf_vfsp
->udf_nmaps
;
1349 map
->udm_flags
= UDM_MAP_SPM
;
1350 map
->udm_vsn
= SWAP_16(typ2
->map2_vsn
);
1351 map
->udm_pn
= SWAP_16(typ2
->map2_pn
);
1353 udf_vfsp
->udf_nmaps
++;
1355 if (error
= ud_read_sparing_tbls(udf_vfsp
,
1361 * Unknown type of partition
1368 * Unknown type of partition
1373 hdr
= (struct pmap_hdr
*)(((uint8_t *)hdr
) + hdr
->maph_length
);
1378 * Read Logical Volume Integrity Sequence
1381 secbp
= ud_bread(dev
, udf_vfsp
->udf_iseq_loc
<< shift
,
1382 udf_vfsp
->udf_iseq_len
);
1383 if ((error
= geterror(secbp
)) != 0) {
1385 "udfs : Could not read Logical Volume Integrity Sequence %x",
1390 udf_vfsp
->udf_iseq
= ngeteblk(udf_vfsp
->udf_iseq_len
);
1391 bp
= udf_vfsp
->udf_iseq
;
1393 bp
->b_dev
= cmpdev(dev
);
1394 bp
->b_blkno
= udf_vfsp
->udf_iseq_loc
<< shift
;
1395 bp
->b_bcount
= udf_vfsp
->udf_iseq_len
;
1396 bcopy(secbp
->b_un
.b_addr
, bp
->b_un
.b_addr
, udf_vfsp
->udf_iseq_len
);
1397 secbp
->b_flags
|= B_STALE
| B_AGE
;
1400 count
= udf_vfsp
->udf_iseq_len
/ DEV_BSIZE
;
1401 addr
= bp
->b_un
.b_addr
;
1402 for (index
= 0; index
< count
; index
++) {
1403 ttag
= (struct tag
*)(addr
+ index
* DEV_BSIZE
);
1404 desc_len
= udf_vfsp
->udf_iseq_len
- (index
* DEV_BSIZE
);
1405 if (ud_verify_tag_and_desc(ttag
, UD_LOG_VOL_INT
,
1406 udf_vfsp
->udf_iseq_loc
+ (index
>> shift
),
1407 1, desc_len
) == 0) {
1409 struct log_vol_int_desc
*lvid
;
1411 lvid
= (struct log_vol_int_desc
*)ttag
;
1412 udf_vfsp
->udf_lvid
= lvid
;
1414 if (SWAP_32(lvid
->lvid_int_type
) == LOG_VOL_CLOSE_INT
) {
1415 udf_vfsp
->udf_clean
= UDF_CLEAN
;
1417 udf_vfsp
->udf_clean
= UDF_DIRTY
;
1421 * update superblock with the metadata
1423 ud_convert_to_superblock(udf_vfsp
, lvid
);
1428 if (udf_vfsp
->udf_lvid
== NULL
) {
1432 if ((blkno
= ud_xlate_to_daddr(udf_vfsp
,
1433 udf_vfsp
->udf_fsd_prn
, udf_vfsp
->udf_fsd_loc
,
1437 secbp
= ud_bread(dev
, blkno
<< shift
, udf_vfsp
->udf_fsd_len
);
1438 if ((error
= geterror(secbp
)) != 0) {
1440 "udfs : Could not read File Set Descriptor %x", error
);
1444 fsd
= (struct file_set_desc
*)secbp
->b_un
.b_addr
;
1445 if (ud_verify_tag_and_desc(&fsd
->fsd_tag
, UD_FILE_SET_DESC
,
1446 udf_vfsp
->udf_fsd_loc
,
1447 1, udf_vfsp
->udf_fsd_len
) != 0) {
1448 secbp
->b_flags
= B_AGE
| B_STALE
;
1452 udf_vfsp
->udf_ricb_prn
= SWAP_16(fsd
->fsd_root_icb
.lad_ext_prn
);
1453 udf_vfsp
->udf_ricb_loc
= SWAP_32(fsd
->fsd_root_icb
.lad_ext_loc
);
1454 udf_vfsp
->udf_ricb_len
= SWAP_32(fsd
->fsd_root_icb
.lad_ext_len
);
1455 secbp
->b_flags
= B_AGE
| B_STALE
;
1457 udf_vfsp
->udf_root_blkno
= ud_xlate_to_daddr(udf_vfsp
,
1458 udf_vfsp
->udf_ricb_prn
, udf_vfsp
->udf_ricb_loc
,
1463 ud_destroy_fsp(udf_vfsp
);
1469 * release/free resources from one ud_map; map data was zalloc'd in
1470 * ud_validate_and_fill_superblock() and fields may later point to
1474 ud_free_map(struct ud_map
*map
)
1478 if (map
->udm_flags
& UDM_MAP_VPM
) {
1479 if (map
->udm_count
) {
1480 kmem_free(map
->udm_count
,
1481 map
->udm_nent
* sizeof (*map
->udm_count
));
1482 map
->udm_count
= NULL
;
1485 for (n
= 0; n
< map
->udm_nent
; n
++) {
1487 brelse(map
->udm_bp
[n
]);
1489 kmem_free(map
->udm_bp
,
1490 map
->udm_nent
* sizeof (*map
->udm_bp
));
1493 if (map
->udm_addr
) {
1494 kmem_free(map
->udm_addr
,
1495 map
->udm_nent
* sizeof (*map
->udm_addr
));
1496 map
->udm_addr
= NULL
;
1499 if (map
->udm_flags
& UDM_MAP_SPM
) {
1500 for (n
= 0; n
< MAX_SPM
; n
++) {
1501 if (map
->udm_sbp
[n
]) {
1502 brelse(map
->udm_sbp
[n
]);
1503 map
->udm_sbp
[n
] = NULL
;
1504 map
->udm_spaddr
[n
] = NULL
;
1511 ud_destroy_fsp(struct udf_vfs
*udf_vfsp
)
1515 ud_printf("ud_destroy_fsp\n");
1516 if (udf_vfsp
== NULL
)
1519 if (udf_vfsp
->udf_maps
) {
1520 for (i
= 0; i
< udf_vfsp
->udf_nmaps
; i
++)
1521 ud_free_map(&udf_vfsp
->udf_maps
[i
]);
1523 kmem_free(udf_vfsp
->udf_maps
,
1524 udf_vfsp
->udf_nmaps
* sizeof (*udf_vfsp
->udf_maps
));
1527 if (udf_vfsp
->udf_parts
) {
1528 kmem_free(udf_vfsp
->udf_parts
,
1529 udf_vfsp
->udf_npart
* sizeof (*udf_vfsp
->udf_parts
));
1531 if (udf_vfsp
->udf_iseq
) {
1532 udf_vfsp
->udf_iseq
->b_flags
|= (B_STALE
|B_AGE
);
1533 brelse(udf_vfsp
->udf_iseq
);
1535 if (udf_vfsp
->udf_vds
) {
1536 udf_vfsp
->udf_vds
->b_flags
|= (B_STALE
|B_AGE
);
1537 brelse(udf_vfsp
->udf_vds
);
1539 if (udf_vfsp
->udf_vfs
)
1540 ud_vfs_remove(udf_vfsp
);
1541 if (udf_vfsp
->udf_fsmnt
) {
1542 kmem_free(udf_vfsp
->udf_fsmnt
,
1543 strlen(udf_vfsp
->udf_fsmnt
) + 1);
1545 kmem_free(udf_vfsp
, sizeof (*udf_vfsp
));
1549 ud_convert_to_superblock(struct udf_vfs
*udf_vfsp
,
1550 struct log_vol_int_desc
*lvid
)
1554 struct ud_part
*ud_part
;
1557 udf_vfsp
->udf_maxuniq
= SWAP_64(lvid
->lvid_uniqid
);
1558 temp
= lvid
->lvid_fst
;
1559 c
= SWAP_32(lvid
->lvid_npart
);
1560 ud_part
= udf_vfsp
->udf_parts
;
1561 for (i
= 0; i
< c
; i
++) {
1562 if (i
>= udf_vfsp
->udf_npart
) {
1565 ud_part
->udp_nfree
= SWAP_32(temp
[i
]);
1566 ud_part
->udp_nblocks
= SWAP_32(temp
[c
+ i
]);
1567 udf_vfsp
->udf_freeblks
+= SWAP_32(temp
[i
]);
1568 udf_vfsp
->udf_totalblks
+= SWAP_32(temp
[c
+ i
]);
1572 iu
= (struct lvid_iu
*)(temp
+ c
* 2);
1573 udf_vfsp
->udf_nfiles
= SWAP_32(iu
->lvidiu_nfiles
);
1574 udf_vfsp
->udf_ndirs
= SWAP_32(iu
->lvidiu_ndirs
);
1575 udf_vfsp
->udf_miread
= BCD2HEX_16(SWAP_16(iu
->lvidiu_mread
));
1576 udf_vfsp
->udf_miwrite
= BCD2HEX_16(SWAP_16(iu
->lvidiu_mwrite
));
1577 udf_vfsp
->udf_mawrite
= BCD2HEX_16(SWAP_16(iu
->lvidiu_maxwr
));
1581 ud_update_superblock(struct vfs
*vfsp
)
1583 struct udf_vfs
*udf_vfsp
;
1585 ud_printf("ud_update_superblock\n");
1587 udf_vfsp
= (struct udf_vfs
*)vfsp
->vfs_data
;
1589 mutex_enter(&udf_vfsp
->udf_lock
);
1590 ud_sbwrite(udf_vfsp
);
1591 mutex_exit(&udf_vfsp
->udf_lock
);
1595 #include <sys/dkio.h>
1596 #include <sys/cdio.h>
1597 #include <sys/vtoc.h>
1600 * This part of the code is known
1601 * to work with only sparc. It needs
1602 * to be evluated before using it with x86
1605 ud_get_last_block(dev_t dev
, daddr_t
*blkno
)
1608 struct dk_cinfo dki_info
;
1609 int32_t rval
, error
;
1611 if ((error
= cdev_ioctl(dev
, DKIOCGVTOC
, (intptr_t)&vtoc
,
1612 FKIOCTL
|FREAD
|FNATIVE
, CRED(), &rval
)) != 0) {
1613 cmn_err(CE_NOTE
, "Could not get the vtoc information");
1617 if (vtoc
.v_sanity
!= VTOC_SANE
) {
1620 if ((error
= cdev_ioctl(dev
, DKIOCINFO
, (intptr_t)&dki_info
,
1621 FKIOCTL
|FREAD
|FNATIVE
, CRED(), &rval
)) != 0) {
1622 cmn_err(CE_NOTE
, "Could not get the slice information");
1626 if (dki_info
.dki_partition
> V_NUMPAR
) {
1631 *blkno
= vtoc
.v_part
[dki_info
.dki_partition
].p_size
;
1636 /* Search sequentially N - 2, N, N - 152, N - 150 for vat icb */
1638 * int32_t ud_sub_blks[] = {2, 0, 152, 150};
1640 int32_t ud_sub_blks
[] = {152, 150, 2, 0};
1641 int32_t ud_sub_count
= 4;
1644 * Validate the VAT ICB
1647 ud_val_get_vat(struct udf_vfs
*udf_vfsp
, dev_t dev
,
1648 daddr_t blkno
, struct ud_map
*udm
)
1651 struct file_entry
*fe
;
1652 int32_t end_loc
, i
, j
, ad_type
;
1653 struct short_ad
*sad
;
1654 struct long_ad
*lad
;
1655 uint32_t count
, blk
;
1656 struct ud_part
*ud_part
;
1659 end_loc
= (blkno
>> udf_vfsp
->udf_l2d_shift
) - 1;
1661 for (i
= 0; i
< ud_sub_count
; i
++) {
1662 udm
->udm_vat_icb
= end_loc
- ud_sub_blks
[i
];
1664 secbp
= ud_bread(dev
,
1665 udm
->udm_vat_icb
<< udf_vfsp
->udf_l2d_shift
,
1666 udf_vfsp
->udf_lbsize
);
1667 ASSERT(secbp
->b_un
.b_addr
);
1669 fe
= (struct file_entry
*)secbp
->b_un
.b_addr
;
1670 if (ud_verify_tag_and_desc(&fe
->fe_tag
, UD_FILE_ENTRY
, 0,
1672 if (ud_verify_tag_and_desc(&fe
->fe_tag
, UD_FILE_ENTRY
,
1673 SWAP_32(fe
->fe_tag
.tag_loc
),
1674 1, udf_vfsp
->udf_lbsize
) == 0) {
1675 if (fe
->fe_icb_tag
.itag_ftype
== 0) {
1680 secbp
->b_flags
|= B_AGE
| B_STALE
;
1683 if (i
== ud_sub_count
) {
1687 ad_type
= SWAP_16(fe
->fe_icb_tag
.itag_flags
) & 0x3;
1688 if (ad_type
== ICB_FLAG_ONE_AD
) {
1690 } else if (ad_type
== ICB_FLAG_SHORT_AD
) {
1692 SWAP_32(fe
->fe_len_adesc
) / sizeof (struct short_ad
);
1693 } else if (ad_type
== ICB_FLAG_LONG_AD
) {
1695 SWAP_32(fe
->fe_len_adesc
) / sizeof (struct long_ad
);
1701 udm
->udm_count
= kmem_zalloc(udm
->udm_nent
* sizeof (*udm
->udm_count
),
1703 udm
->udm_bp
= kmem_zalloc(udm
->udm_nent
* sizeof (*udm
->udm_bp
),
1705 udm
->udm_addr
= kmem_zalloc(udm
->udm_nent
* sizeof (*udm
->udm_addr
),
1708 if (ad_type
== ICB_FLAG_ONE_AD
) {
1709 udm
->udm_count
[0] = (SWAP_64(fe
->fe_info_len
) - 36) /
1711 udm
->udm_bp
[0] = secbp
;
1712 udm
->udm_addr
[0] = (uint32_t *)
1713 &fe
->fe_spec
[SWAP_32(fe
->fe_len_ear
)];
1716 for (i
= 0; i
< udm
->udm_nent
; i
++) {
1717 if (ad_type
== ICB_FLAG_SHORT_AD
) {
1718 sad
= (struct short_ad
*)
1719 (fe
->fe_spec
+ SWAP_32(fe
->fe_len_ear
));
1721 count
= SWAP_32(sad
->sad_ext_len
);
1722 blk
= SWAP_32(sad
->sad_ext_loc
);
1724 lad
= (struct long_ad
*)
1725 (fe
->fe_spec
+ SWAP_32(fe
->fe_len_ear
));
1727 count
= SWAP_32(lad
->lad_ext_len
);
1728 blk
= SWAP_32(lad
->lad_ext_loc
);
1729 ASSERT(SWAP_16(lad
->lad_ext_prn
) == udm
->udm_pn
);
1731 if ((count
& 0x3FFFFFFF) == 0) {
1734 if (i
< udm
->udm_nent
- 1) {
1735 udm
->udm_count
[i
] = count
/ 4;
1737 udm
->udm_count
[i
] = (count
- 36) / 4;
1739 ud_part
= udf_vfsp
->udf_parts
;
1740 for (j
= 0; j
< udf_vfsp
->udf_npart
; j
++) {
1741 if (udm
->udm_pn
== ud_part
->udp_number
) {
1742 blk
= ud_part
->udp_start
+ blk
;
1746 if (j
== udf_vfsp
->udf_npart
) {
1751 count
= (count
+ DEV_BSIZE
- 1) & ~(DEV_BSIZE
- 1);
1752 udm
->udm_bp
[i
] = ud_bread(dev
,
1753 blk
<< udf_vfsp
->udf_l2d_shift
, count
);
1754 if ((udm
->udm_bp
[i
]->b_error
!= 0) ||
1755 (udm
->udm_bp
[i
]->b_resid
)) {
1759 udm
->udm_addr
[i
] = (uint32_t *)udm
->udm_bp
[i
]->b_un
.b_addr
;
1765 secbp
->b_flags
|= B_AGE
| B_STALE
;
1771 ud_read_sparing_tbls(struct udf_vfs
*udf_vfsp
,
1772 dev_t dev
, struct ud_map
*map
, struct pmap_typ2
*typ2
)
1774 int32_t index
, valid
= 0;
1779 map
->udm_plen
= SWAP_16(typ2
->map2_pl
);
1780 map
->udm_nspm
= typ2
->map2_nst
;
1781 map
->udm_spsz
= SWAP_32(typ2
->map2_sest
);
1782 sz
= (map
->udm_spsz
+ udf_vfsp
->udf_lbmask
) & ~udf_vfsp
->udf_lbmask
;
1787 for (index
= 0; index
< map
->udm_nspm
; index
++) {
1788 map
->udm_loc
[index
] = SWAP_32(typ2
->map2_st
[index
]);
1791 map
->udm_loc
[index
] << udf_vfsp
->udf_l2d_shift
, sz
);
1792 if ((bp
->b_error
!= 0) || (bp
->b_resid
)) {
1796 stbl
= (struct stbl
*)bp
->b_un
.b_addr
;
1797 if (strncmp(stbl
->stbl_si
.reg_id
, UDF_SPAR_TBL
, 23) != 0) {
1798 printf("Sparing Identifier does not match\n");
1799 bp
->b_flags
|= B_AGE
| B_STALE
;
1803 map
->udm_sbp
[index
] = bp
;
1804 map
->udm_spaddr
[index
] = bp
->b_un
.b_addr
;
1807 struct stbl_entry
*te
;
1810 te
= (struct stbl_entry
*)&stbl
->stbl_entry
;
1811 tbl_len
= SWAP_16(stbl
->stbl_len
);
1813 printf("%x %x\n", tbl_len
, SWAP_32(stbl
->stbl_seqno
));
1814 printf("%x %x\n", bp
->b_un
.b_addr
, te
);
1816 for (i
= 0; i
< tbl_len
; i
++) {
1817 printf("%x %x\n", SWAP_32(te
->sent_ol
), SWAP_32(te
->sent_ml
));
1832 ud_get_lbsize(dev_t dev
, uint32_t *loc
)
1834 int32_t bsize
, shift
, index
, end_index
;
1838 struct anch_vol_desc_ptr
*avdp
;
1839 uint32_t session_offset
= 0;
1842 if (ud_get_last_block(dev
, &last_block
) != 0) {
1848 if (cdev_ioctl(dev
, CDROMREADOFFSET
, (intptr_t)&session_offset
,
1849 FKIOCTL
|FREAD
|FNATIVE
, CRED(), &rval
) != 0) {
1853 for (index
= 0; index
< end_index
; index
++) {
1855 for (bsize
= DEV_BSIZE
, shift
= 0;
1856 bsize
<= MAXBSIZE
; bsize
<<= 1, shift
++) {
1860 if (bsize
<= 2048) {
1862 session_offset
* 2048 / bsize
;
1865 session_offset
/ (bsize
/ 2048);
1867 } else if (index
== 1) {
1868 avd_loc
= last_block
- (1 << shift
);
1870 avd_loc
= last_block
- (256 << shift
);
1873 bp
= ud_bread(dev
, avd_loc
<< shift
,
1874 ANCHOR_VOL_DESC_LEN
);
1875 if (geterror(bp
) != 0) {
1881 * Verify if we have avdp here
1883 avdp
= (struct anch_vol_desc_ptr
*)bp
->b_un
.b_addr
;
1884 if (ud_verify_tag_and_desc(&avdp
->avd_tag
,
1885 UD_ANCH_VOL_DESC
, avd_loc
,
1886 1, ANCHOR_VOL_DESC_LEN
) != 0) {
1887 bp
->b_flags
|= B_AGE
| B_STALE
;
1891 bp
->b_flags
|= B_AGE
| B_STALE
;
1899 * Did not find AVD at all the locations
1904 static const struct vfsops udf_vfsops
= {
1905 .vfs_mount
= udf_mount
,
1906 .vfs_unmount
= udf_unmount
,
1907 .vfs_root
= udf_root
,
1908 .vfs_statvfs
= udf_statvfs
,
1909 .vfs_sync
= udf_sync
,
1910 .vfs_vget
= udf_vget
,
1911 .vfs_mountroot
= udf_mountroot
,
1915 udfinit(int fstype
, char *name
)
1919 ud_printf("udfinit\n");
1921 error
= vfs_setfsops(fstype
, &udf_vfsops
);
1923 cmn_err(CE_WARN
, "udfinit: bad fstype");
1927 udf_fstype
= fstype
;