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 (c) 1990, 2010, Oracle and/or its affiliates. All rights reserved.
23 * Copyright (c) 2011 Bayard G. Bell. All rights reserved.
24 * Copyright 2013 Joyent, Inc. All rights reserved.
28 * VFS operations for High Sierra filesystem
31 #include <sys/types.h>
32 #include <sys/isa_defs.h>
33 #include <sys/t_lock.h>
34 #include <sys/param.h>
35 #include <sys/systm.h>
36 #include <sys/sysmacros.h>
38 #include <sys/signal.h>
43 #include <sys/pathname.h>
45 #include <sys/vfs_opreg.h>
46 #include <sys/vnode.h>
50 #include <sys/policy.h>
54 #include <sys/fs/snode.h>
55 #include <sys/fs/hsfs_spec.h>
56 #include <sys/fs/hsfs_isospec.h>
57 #include <sys/fs/hsfs_node.h>
58 #include <sys/fs/hsfs_impl.h>
59 #include <sys/fs/hsfs_susp.h>
60 #include <sys/fs/hsfs_rrip.h>
62 #include <sys/statvfs.h>
63 #include <sys/mount.h>
64 #include <sys/mntent.h>
66 #include <sys/errno.h>
67 #include <sys/debug.h>
68 #include "fs/fs_subr.h"
69 #include <sys/cmn_err.h>
70 #include <sys/bootconf.h>
75 * These are needed for the CDROMREADOFFSET Code
78 #include <sys/sunddi.h>
82 #include <sys/modctl.h>
87 #define HOPT_GLOBAL MNTOPT_GLOBAL
88 #define HOPT_NOGLOBAL MNTOPT_NOGLOBAL
89 #define HOPT_MAPLCASE "maplcase"
90 #define HOPT_NOMAPLCASE "nomaplcase"
91 #define HOPT_NOTRAILDOT "notraildot"
92 #define HOPT_TRAILDOT "traildot"
93 #define HOPT_NRR "nrr"
95 #define HOPT_JOLIET "joliet"
96 #define HOPT_NOJOLIET "nojoliet"
97 #define HOPT_JOLIETLONG "jolietlong"
98 #define HOPT_VERS2 "vers2"
99 #define HOPT_NOVERS2 "novers2"
100 #define HOPT_RO MNTOPT_RO
102 static char *global_cancel
[] = { HOPT_NOGLOBAL
, NULL
};
103 static char *noglobal_cancel
[] = { HOPT_GLOBAL
, NULL
};
104 static char *mapl_cancel
[] = { HOPT_NOMAPLCASE
, NULL
};
105 static char *nomapl_cancel
[] = { HOPT_MAPLCASE
, NULL
};
106 static char *ro_cancel
[] = { MNTOPT_RW
, NULL
};
107 static char *rr_cancel
[] = { HOPT_NRR
, NULL
};
108 static char *nrr_cancel
[] = { HOPT_RR
, NULL
};
109 static char *joliet_cancel
[] = { HOPT_NOJOLIET
, NULL
};
110 static char *nojoliet_cancel
[] = { HOPT_JOLIET
, NULL
};
111 static char *vers2_cancel
[] = { HOPT_NOVERS2
, NULL
};
112 static char *novers2_cancel
[] = { HOPT_VERS2
, NULL
};
113 static char *trail_cancel
[] = { HOPT_NOTRAILDOT
, NULL
};
114 static char *notrail_cancel
[] = { HOPT_TRAILDOT
, NULL
};
116 static mntopt_t hsfs_options
[] = {
117 { HOPT_GLOBAL
, global_cancel
, NULL
, 0, NULL
},
118 { HOPT_NOGLOBAL
, noglobal_cancel
, NULL
, MO_DEFAULT
, NULL
},
119 { HOPT_MAPLCASE
, mapl_cancel
, NULL
, MO_DEFAULT
, NULL
},
120 { HOPT_NOMAPLCASE
, nomapl_cancel
, NULL
, 0, NULL
},
121 { HOPT_RO
, ro_cancel
, NULL
, MO_DEFAULT
, NULL
},
122 { HOPT_RR
, rr_cancel
, NULL
, MO_DEFAULT
, NULL
},
123 { HOPT_NRR
, nrr_cancel
, NULL
, 0, NULL
},
124 { HOPT_JOLIET
, joliet_cancel
, NULL
, 0, NULL
},
125 { HOPT_NOJOLIET
, nojoliet_cancel
, NULL
, 0, NULL
},
126 { HOPT_JOLIETLONG
, NULL
, NULL
, 0, NULL
},
127 { HOPT_VERS2
, vers2_cancel
, NULL
, 0, NULL
},
128 { HOPT_NOVERS2
, novers2_cancel
, NULL
, 0, NULL
},
129 { HOPT_TRAILDOT
, trail_cancel
, NULL
, MO_DEFAULT
, NULL
},
130 { HOPT_NOTRAILDOT
, notrail_cancel
, NULL
, 0, NULL
},
131 { "sector", NULL
, "0", MO_HASVALUE
, NULL
},
134 static mntopts_t hsfs_proto_opttbl
= {
135 sizeof (hsfs_options
) / sizeof (mntopt_t
),
140 * Indicates whether to enable the I/O scheduling and readahead logic
141 * 1 - Enable, 0 - Do not Enable.
142 * Debugging purposes.
145 static int hsfsfstype
;
146 static int hsfsinit(int, char *);
148 static vfsdef_t vfw
= {
152 /* We don't suppport remounting */
153 VSW_HASPROTO
|VSW_STATS
|VSW_CANLOFI
,
157 static struct modlfs modlfs
= {
158 &mod_fsops
, "filesystem for HSFS", &vfw
161 static struct modlinkage modlinkage
= {
162 MODREV_1
, (void *)&modlfs
, NULL
165 extern void hsched_init_caches(void);
166 extern void hsched_fini_caches(void);
172 return (mod_install(&modlinkage
));
180 error
= mod_remove(&modlinkage
);
182 DTRACE_PROBE1(mod_remove
, int, error
);
187 mutex_destroy(&hs_mounttab_lock
);
190 * Tear down the operations vectors
192 (void) vfs_freevfsops_by_type(hsfsfstype
);
193 vn_freevnodeops(hsfs_vnodeops
);
195 hs_fini_hsnode_cache();
196 hsched_fini_caches();
201 _info(struct modinfo
*modinfop
)
203 return (mod_info(&modlinkage
, modinfop
));
206 #define BDEVFLAG(dev) ((devopsp[getmajor(dev)])->devo_cb_ops->cb_flag)
208 kmutex_t hs_mounttab_lock
;
209 struct hsfs
*hs_mounttab
= NULL
;
211 /* default mode, uid, gid */
212 mode_t hsfs_default_mode
= 0555;
213 uid_t hsfs_default_uid
= 0;
214 gid_t hsfs_default_gid
= 3;
216 extern void hsched_init(struct hsfs
*fsp
, int fsid
,
217 struct modlinkage
*modlinkage
);
218 extern void hsched_fini(struct hsfs_queue
*hqueue
);
219 extern void hsfs_init_kstats(struct hsfs
*fsp
, int fsid
);
220 extern void hsfs_fini_kstats(struct hsfs
*fsp
);
222 static int hsfs_mount(struct vfs
*vfsp
, struct vnode
*mvp
,
223 struct mounta
*uap
, struct cred
*cr
);
224 static int hsfs_unmount(struct vfs
*vfsp
, int, struct cred
*cr
);
225 static int hsfs_root(struct vfs
*vfsp
, struct vnode
**vpp
);
226 static int hsfs_statvfs(struct vfs
*vfsp
, struct statvfs64
*sbp
);
227 static int hsfs_vget(struct vfs
*vfsp
, struct vnode
**vpp
, struct fid
*fidp
);
228 static int hsfs_mountroot(struct vfs
*, enum whymountroot
);
230 static int hs_mountfs(struct vfs
*vfsp
, dev_t dev
, char *path
,
231 mode_t mode
, int flags
, struct cred
*cr
, int isroot
);
232 static int hs_getrootvp(struct vfs
*vfsp
, struct hsfs
*fsp
, size_t pathsize
);
233 static int hs_findhsvol(struct hsfs
*fsp
, struct vnode
*vp
,
234 struct hs_volume
*hvp
);
235 static int hs_parsehsvol(struct hsfs
*fsp
, uchar_t
*volp
,
236 struct hs_volume
*hvp
);
237 static int hs_findisovol(struct hsfs
*fsp
, struct vnode
*vp
,
238 struct hs_volume
*hvp
,
239 struct hs_volume
*svp
,
240 struct hs_volume
*jvp
);
241 static int hs_joliet_level(uchar_t
*volp
);
242 static int hs_parseisovol(struct hsfs
*fsp
, uchar_t
*volp
,
243 struct hs_volume
*hvp
);
244 static void hs_copylabel(struct hs_volume
*, unsigned char *, int);
245 static int hs_getmdev(struct vfs
*, char *fspec
, int flags
, dev_t
*pdev
,
246 mode_t
*mode
, cred_t
*cr
);
247 static int hs_findvoldesc(dev_t rdev
, int desc_sec
);
250 hsfsinit(int fstype
, char *name
)
252 static const fs_operation_def_t hsfs_vfsops_template
[] = {
253 VFSNAME_MOUNT
, { .vfs_mount
= hsfs_mount
},
254 VFSNAME_UNMOUNT
, { .vfs_unmount
= hsfs_unmount
},
255 VFSNAME_ROOT
, { .vfs_root
= hsfs_root
},
256 VFSNAME_STATVFS
, { .vfs_statvfs
= hsfs_statvfs
},
257 VFSNAME_VGET
, { .vfs_vget
= hsfs_vget
},
258 VFSNAME_MOUNTROOT
, { .vfs_mountroot
= hsfs_mountroot
},
263 error
= vfs_setfsops(fstype
, hsfs_vfsops_template
, NULL
);
265 cmn_err(CE_WARN
, "hsfsinit: bad vfs ops template");
269 error
= vn_make_ops(name
, hsfs_vnodeops_template
, &hsfs_vnodeops
);
271 (void) vfs_freevfsops_by_type(fstype
);
272 cmn_err(CE_WARN
, "hsfsinit: bad vnode ops template");
277 mutex_init(&hs_mounttab_lock
, NULL
, MUTEX_DEFAULT
, NULL
);
278 hs_init_hsnode_cache();
279 hsched_init_caches();
285 hsfs_mount(struct vfs
*vfsp
, struct vnode
*mvp
,
286 struct mounta
*uap
, struct cred
*cr
)
293 int flags
; /* this will hold the mount specific data */
295 if ((error
= secpolicy_fs_mount(cr
, mvp
, vfsp
)) != 0)
298 if (mvp
->v_type
!= VDIR
)
301 /* mount option must be read only, else mount will be rejected */
302 if (!(uap
->flags
& MS_RDONLY
))
306 * We already told the framework that we don't support remounting.
308 ASSERT(!(uap
->flags
& MS_REMOUNT
));
310 mutex_enter(&mvp
->v_lock
);
311 vnode_busy
= (mvp
->v_count
!= 1) || (mvp
->v_flag
& VROOT
);
312 mutex_exit(&mvp
->v_lock
);
314 if ((uap
->flags
& MS_OVERLAY
) == 0 && vnode_busy
) {
319 * Check for the options that actually affect things
323 if (vfs_optionisset(vfsp
, HOPT_NOMAPLCASE
, NULL
))
324 flags
|= HSFSMNT_NOMAPLCASE
;
325 if (vfs_optionisset(vfsp
, HOPT_NOTRAILDOT
, NULL
))
326 flags
|= HSFSMNT_NOTRAILDOT
;
327 if (vfs_optionisset(vfsp
, HOPT_NRR
, NULL
))
328 flags
|= HSFSMNT_NORRIP
;
329 if (vfs_optionisset(vfsp
, HOPT_NOJOLIET
, NULL
))
330 flags
|= HSFSMNT_NOJOLIET
;
331 if (vfs_optionisset(vfsp
, HOPT_JOLIETLONG
, NULL
))
332 flags
|= HSFSMNT_JOLIETLONG
;
333 if (vfs_optionisset(vfsp
, HOPT_NOVERS2
, NULL
))
334 flags
|= HSFSMNT_NOVERS2
;
336 error
= pn_get(uap
->dir
, (uap
->flags
& MS_SYSSPACE
) ?
337 UIO_SYSSPACE
: UIO_USERSPACE
, &dpn
);
341 error
= hs_getmdev(vfsp
, uap
->spec
, uap
->flags
, &dev
, &mode
, cr
);
348 * If the device is a tape, return error
350 if ((BDEVFLAG(dev
) & D_TAPE
) == D_TAPE
) {
356 * Mount the filesystem.
358 error
= hs_mountfs(vfsp
, dev
, dpn
.pn_path
, mode
, flags
, cr
, 0);
373 if (secpolicy_fs_unmount(cr
, vfsp
) != 0)
377 * forced unmount is not supported by this file system
378 * and thus, ENOTSUP is being returned.
383 fsp
= VFS_TO_HSFS(vfsp
);
385 if (fsp
->hsfs_rootvp
->v_count
!= 1)
388 /* destroy all old pages and hsnodes for this vfs */
389 if (hs_synchash(vfsp
))
392 mutex_enter(&hs_mounttab_lock
);
393 for (tspp
= &hs_mounttab
; *tspp
!= NULL
; tspp
= &(*tspp
)->hsfs_next
) {
398 mutex_exit(&hs_mounttab_lock
);
399 panic("hsfs_unmount: vfs not mounted?");
403 *tspp
= fsp
->hsfs_next
;
405 mutex_exit(&hs_mounttab_lock
);
407 hsfs_fini_kstats(fsp
);
408 (void) VOP_CLOSE(fsp
->hsfs_devvp
, FREAD
, 1, (offset_t
)0, cr
, NULL
);
409 VN_RELE(fsp
->hsfs_devvp
);
410 /* free path table space */
411 if (fsp
->hsfs_ptbl
!= NULL
)
412 kmem_free(fsp
->hsfs_ptbl
, (size_t)fsp
->hsfs_vol
.ptbl_len
);
413 /* free path table index table */
414 if (fsp
->hsfs_ptbl_idx
!= NULL
)
415 kmem_free(fsp
->hsfs_ptbl_idx
, (size_t)
416 (fsp
->hsfs_ptbl_idx_size
* sizeof (struct ptable_idx
)));
418 /* free "mounted on" pathame */
419 if (fsp
->hsfs_fsmnt
!= NULL
)
420 kmem_free(fsp
->hsfs_fsmnt
, strlen(fsp
->hsfs_fsmnt
) + 1);
422 hsched_fini(fsp
->hqueue
);
423 kmem_free(fsp
->hqueue
, sizeof (struct hsfs_queue
));
425 mutex_destroy(&fsp
->hsfs_free_lock
);
426 rw_destroy(&fsp
->hsfs_hash_lock
);
428 kmem_free(fsp
, sizeof (*fsp
));
434 hsfs_root(struct vfs
*vfsp
, struct vnode
**vpp
)
436 *vpp
= (VFS_TO_HSFS(vfsp
))->hsfs_rootvp
;
443 hsfs_statvfs(struct vfs
*vfsp
, struct statvfs64
*sbp
)
448 fsp
= VFS_TO_HSFS(vfsp
);
449 if (fsp
->hsfs_magic
!= HSFS_MAGIC
)
451 bzero(sbp
, sizeof (*sbp
));
452 sbp
->f_bsize
= vfsp
->vfs_bsize
;
453 sbp
->f_frsize
= sbp
->f_bsize
; /* no fragment, same as block size */
454 sbp
->f_blocks
= (fsblkcnt64_t
)fsp
->hsfs_vol
.vol_size
;
456 sbp
->f_bfree
= (fsblkcnt64_t
)0;
457 sbp
->f_bavail
= (fsblkcnt64_t
)0;
458 sbp
->f_files
= (fsfilcnt64_t
)-1;
459 sbp
->f_ffree
= (fsfilcnt64_t
)0;
460 sbp
->f_favail
= (fsfilcnt64_t
)0;
461 (void) cmpldev(&d32
, vfsp
->vfs_dev
);
463 (void) strcpy(sbp
->f_basetype
, vfssw
[vfsp
->vfs_fstype
].vsw_name
);
464 sbp
->f_flag
= vf_to_stf(vfsp
->vfs_flag
);
465 sbp
->f_namemax
= fsp
->hsfs_namemax
;
466 (void) strcpy(sbp
->f_fstr
, fsp
->hsfs_vol
.vol_id
);
472 * Previously nodeid was declared as uint32_t. This has been changed
473 * to conform better with the ISO9660 standard. The standard states that
474 * a LBN can be a 32 bit number, as the MAKE_NODEID macro shifts this
475 * LBN 11 places left (LBN_TO_BYTE) and then shifts the result 5 right
476 * (divide by 32) we are left with the potential of an overflow if
477 * confined to a 32 bit value.
481 hsfs_vget(struct vfs
*vfsp
, struct vnode
**vpp
, struct fid
*fidp
)
488 fsp
= (struct hsfs
*)VFS_TO_HSFS(vfsp
);
489 fid
= (struct hsfid
*)fidp
;
492 * Look for vnode on hashlist.
493 * If found, it's now active and the refcnt was incremented.
496 rw_enter(&fsp
->hsfs_hash_lock
, RW_READER
);
498 nodeid
= fid
->hf_ino
;
500 if ((*vpp
= hs_findhash(nodeid
, fid
->hf_dir_lbn
,
501 (uint_t
)fid
->hf_dir_off
, vfsp
)) == NULL
) {
503 * Not in cache, so we need to remake it.
504 * hs_remakenode() will read the directory entry
505 * and then check again to see if anyone else has
506 * put it in the cache.
508 rw_exit(&fsp
->hsfs_hash_lock
);
509 error
= hs_remakenode(fid
->hf_dir_lbn
, (uint_t
)fid
->hf_dir_off
,
513 rw_exit(&fsp
->hsfs_hash_lock
);
518 #define CHECKSUM_SIZE (64 * 1024)
521 * Compute a CD-ROM fsid by checksumming the first 64K of data on the CD
522 * We use the 'fsp' argument to determine the location of the root
523 * directory entry, and we start reading from there.
526 compute_cdrom_id(struct hsfs
*fsp
, vnode_t
*devvp
)
529 struct hs_volume
*hsvp
= &fsp
->hsfs_vol
;
534 secno
= hsvp
->root_dir
.ext_lbn
>> hsvp
->lbn_secshift
;
535 bp
= bread(devvp
->v_rdev
, secno
* 4, CHECKSUM_SIZE
);
536 error
= geterror(bp
);
539 * An error on read or a partial read means we asked
540 * for a nonexistant/corrupted piece of the device
541 * (including past-the-end of the media). Don't
542 * try to use the checksumming method then.
544 if (!error
&& bp
->b_bcount
== CHECKSUM_SIZE
) {
545 int *ibuf
= (int *)bp
->b_un
.b_addr
;
550 for (i
= 0; i
< CHECKSUM_SIZE
/ sizeof (int); i
++)
554 * Fallback - use creation date
556 fsid
= hsvp
->cre_date
.tv_sec
;
578 struct hsfs
*fsp
= NULL
;
592 int force_joliet_off
;
593 size_t pathbufsz
= strlen(path
) + 1;
596 struct hs_volume
*svp
= NULL
; /* Supplemental VD for ISO-9660:1999 */
597 struct hs_volume
*jvp
= NULL
; /* Joliet VD */
600 * The rules for which extension will be used are:
601 * 1. No specific mount options given:
602 * - use rrip if available
603 * - use ISO9660:1999 if available
604 * - use joliet if available.
605 * 2. rrip/ISO9660:1999/joliet explicitly disabled via mount option:
606 * - use next "lower" extension
607 * 3. joliet/ISO9660:1999/rrip explicitly requested via mount option:
608 * - disable rrip support even if available
609 * - disable IOS9660:1999 support even if available
611 * We need to adjust these flags as we discover the extensions
612 * present. See below. These are just the starting values.
614 use_rrip
= (mount_flags
& HSFSMNT_NORRIP
) == 0;
615 use_vers2
= (mount_flags
& HSFSMNT_NOVERS2
) == 0;
616 use_joliet
= (mount_flags
& HSFSMNT_NOJOLIET
) == 0;
621 devvp
= makespecvp(dev
, VBLK
);
625 * Open the target device (file) for read only.
627 if (error
= VOP_OPEN(&devvp
, FREAD
, cr
, NULL
)) {
633 * Refuse to go any further if this
634 * device is being used for swapping
636 if (IS_SWAPVP(common_specvp(devvp
))) {
641 vap
.va_mask
= AT_SIZE
;
642 if ((error
= VOP_GETATTR(devvp
, &vap
, ATTR_COMM
, cr
, NULL
)) != 0) {
643 cmn_err(CE_NOTE
, "Cannot get attributes of the CD-ROM driver");
648 * Make sure we have a nonzero size partition.
649 * The current version of the SD driver will *not* fail the open
650 * of such a partition so we have to check for it here.
652 if (vap
.va_size
== 0) {
658 * Init a new hsfs structure.
660 fsp
= kmem_zalloc(sizeof (*fsp
), KM_SLEEP
);
661 svp
= kmem_zalloc(sizeof (*svp
), KM_SLEEP
);
662 jvp
= kmem_zalloc(sizeof (*jvp
), KM_SLEEP
);
664 /* hardwire perms, uid, gid */
665 fsp
->hsfs_vol
.vol_uid
= hsfs_default_uid
;
666 fsp
->hsfs_vol
.vol_gid
= hsfs_default_gid
;
667 fsp
->hsfs_vol
.vol_prot
= hsfs_default_mode
;
668 svp
->vol_uid
= hsfs_default_uid
;
669 svp
->vol_gid
= hsfs_default_gid
;
670 svp
->vol_prot
= hsfs_default_mode
;
671 jvp
->vol_uid
= hsfs_default_uid
;
672 jvp
->vol_gid
= hsfs_default_gid
;
673 jvp
->vol_prot
= hsfs_default_mode
;
676 * Look for a Standard File Structure Volume Descriptor,
677 * of which there must be at least one.
678 * If found, check for volume size consistency.
680 * If svp->lbn_size is != 0, we did find a ISO-9660:1999 SVD
681 * If jvp->lbn_size is != 0, we did find a Joliet SVD.
683 fsp
->hsfs_namemax
= ISO_FILE_NAMELEN
;
684 fsp
->hsfs_namelen
= ISO_FILE_NAMELEN
;
685 error
= hs_findisovol(fsp
, devvp
, &fsp
->hsfs_vol
, svp
, jvp
);
686 if (error
== EINVAL
) /* no iso 9660 - try high sierra ... */
687 error
= hs_findhsvol(fsp
, devvp
, &fsp
->hsfs_vol
);
692 DTRACE_PROBE4(findvol
,
694 struct hs_volume
*, &fsp
->hsfs_vol
,
695 struct hs_volume
*, svp
,
696 struct hs_volume
*, jvp
);
699 * Generate a file system ID from the CD-ROM,
700 * and check it for uniqueness.
702 * What we are aiming for is some chance of integrity
703 * across disk change. That is, if a client has an fhandle,
704 * it will be valid as long as the same disk is mounted.
706 fsid
= compute_cdrom_id(fsp
, devvp
);
708 mutex_enter(&hs_mounttab_lock
);
710 if (fsid
== 0 || fsid
== -1) {
713 } else /* make sure that the fsid is unique */
714 for (tsp
= hs_mounttab
; tsp
!= NULL
; tsp
= tsp
->hsfs_next
) {
715 if (fsid
== tsp
->hsfs_vfs
->vfs_fsid
.val
[0]) {
722 fsp
->hsfs_next
= hs_mounttab
;
725 fsp
->hsfs_devvp
= devvp
;
726 fsp
->hsfs_vfs
= vfsp
;
727 fsp
->hsfs_fsmnt
= kmem_alloc(pathbufsz
, KM_SLEEP
);
728 (void) strlcpy(fsp
->hsfs_fsmnt
, path
, pathbufsz
);
730 mutex_init(&fsp
->hsfs_free_lock
, NULL
, MUTEX_DEFAULT
, NULL
);
731 rw_init(&fsp
->hsfs_hash_lock
, NULL
, RW_DEFAULT
, NULL
);
733 vfsp
->vfs_data
= (caddr_t
)fsp
;
735 vfsp
->vfs_fstype
= hsfsfstype
;
736 vfsp
->vfs_bsize
= fsp
->hsfs_vol
.lbn_size
; /* %% */
737 vfsp
->vfs_fsid
.val
[0] = fsid
;
738 vfsp
->vfs_fsid
.val
[1] = hsfsfstype
;
740 if (!hs_getrootvp(vfsp
, fsp
, pathbufsz
)) {
741 DTRACE_PROBE1(rootvp__failed
, struct hsfs
*, fsp
);
745 DTRACE_PROBE1(rootvp
, struct hsfs
*, fsp
);
748 * Attempt to discover a RR extension.
751 hp
= VTOH(fsp
->hsfs_rootvp
);
752 hs_check_root_dirent(fsp
->hsfs_rootvp
, &(hp
->hs_dirent
));
755 has_rrip
= IS_RRIP_IMPLEMENTED(fsp
);
756 has_vers2
= (svp
->lbn_size
!= 0);
757 has_joliet
= (jvp
->lbn_size
!= 0);
759 DTRACE_PROBE4(voltype__suggested
, struct hsfs
*, fsp
,
760 int, use_rrip
, int, use_vers2
, int, use_joliet
);
762 DTRACE_PROBE4(voltype__actual
, struct hsfs
*, fsp
,
763 int, has_rrip
, int, has_vers2
, int, has_joliet
);
765 DTRACE_PROBE4(findvol
,
767 struct hs_volume
*, &fsp
->hsfs_vol
,
768 struct hs_volume
*, svp
,
769 struct hs_volume
*, jvp
);
771 force_rrip_off
= !use_rrip
||
772 (vfs_optionisset(vfsp
, HOPT_JOLIET
, NULL
) && has_joliet
) ||
773 (vfs_optionisset(vfsp
, HOPT_VERS2
, NULL
) && has_vers2
);
775 force_vers2_off
= !use_vers2
||
776 (vfs_optionisset(vfsp
, HOPT_JOLIET
, NULL
) && has_joliet
);
778 force_joliet_off
= !use_joliet
;
780 DTRACE_PROBE4(voltype__force_off
, struct hsfs
*, fsp
,
781 int, force_rrip_off
, int, force_vers2_off
, int, force_joliet_off
);
784 * At the moment, we have references of all three possible
785 * extensions (RR, ISO9660:1999/v2 and Joliet) if present.
787 * The "active" volume descriptor is RRIP (or ISO9660:1988).
788 * We now switch to the user-requested one.
792 if (force_rrip_off
|| !has_rrip
) {
793 if (has_vers2
&& !force_vers2_off
) {
794 VN_RELE(fsp
->hsfs_rootvp
);
795 bcopy(svp
, &fsp
->hsfs_vol
, sizeof (struct hs_volume
));
796 fsp
->hsfs_vol_type
= HS_VOL_TYPE_ISO_V2
;
797 vfsp
->vfs_bsize
= fsp
->hsfs_vol
.lbn_size
;
800 } else if (has_joliet
&& !force_joliet_off
) {
801 VN_RELE(fsp
->hsfs_rootvp
);
802 bcopy(jvp
, &fsp
->hsfs_vol
, sizeof (struct hs_volume
));
803 fsp
->hsfs_vol_type
= HS_VOL_TYPE_JOLIET
;
804 vfsp
->vfs_bsize
= fsp
->hsfs_vol
.lbn_size
;
812 * Make sure not to use Rock Ridge.
814 UNSET_IMPL_BIT(fsp
, RRIP_BIT
);
818 if (!hs_getrootvp(vfsp
, fsp
, pathbufsz
)) {
819 DTRACE_PROBE1(rootvp__failed
, struct hsfs
*, fsp
);
823 DTRACE_PROBE1(rootvp
, struct hsfs
*, fsp
);
825 if (IS_RRIP_IMPLEMENTED(fsp
)) {
831 if (force_joliet_off
)
833 DTRACE_PROBE4(voltype__taken
, struct hsfs
*, fsp
,
834 int, has_rrip
, int, has_vers2
, int, has_joliet
);
837 * mark root node as VROOT
839 fsp
->hsfs_rootvp
->v_flag
|= VROOT
;
841 /* Here we take care of some special case stuff for mountroot */
843 fsp
->hsfs_rootvp
->v_rdev
= devvp
->v_rdev
;
844 rootvp
= fsp
->hsfs_rootvp
;
847 if (IS_RRIP_IMPLEMENTED(fsp
)) {
849 * if RRIP, don't copy NOMAPLCASE or NOTRAILDOT to hsfs_flags
851 mount_flags
&= ~(HSFSMNT_NOMAPLCASE
| HSFSMNT_NOTRAILDOT
);
853 fsp
->hsfs_namemax
= RRIP_FILE_NAMELEN
;
854 fsp
->hsfs_namelen
= RRIP_FILE_NAMELEN
;
856 ASSERT(vfs_optionisset(vfsp
, HOPT_RR
, NULL
));
857 vfs_clearmntopt(vfsp
, HOPT_VERS2
);
858 vfs_clearmntopt(vfsp
, HOPT_JOLIET
);
860 } else switch (fsp
->hsfs_vol_type
) {
863 case HS_VOL_TYPE_ISO
:
866 * if iso v1, don't allow trailing spaces in iso file names
868 mount_flags
|= HSFSMNT_NOTRAILSPACE
;
869 fsp
->hsfs_namemax
= ISO_NAMELEN_V2_MAX
;
870 fsp
->hsfs_namelen
= ISO_FILE_NAMELEN
;
871 vfs_clearmntopt(vfsp
, HOPT_RR
);
872 vfs_clearmntopt(vfsp
, HOPT_VERS2
);
873 vfs_clearmntopt(vfsp
, HOPT_JOLIET
);
876 case HS_VOL_TYPE_ISO_V2
:
878 * if iso v2, don't copy NOTRAILDOT to hsfs_flags
880 mount_flags
&= ~HSFSMNT_NOTRAILDOT
;
881 mount_flags
|= HSFSMNT_NOMAPLCASE
| HSFSMNT_NOVERSION
;
882 fsp
->hsfs_namemax
= ISO_NAMELEN_V2_MAX
;
883 fsp
->hsfs_namelen
= ISO_NAMELEN_V2
;
884 vfs_setmntopt(vfsp
, HOPT_VERS2
, NULL
, 0);
885 vfs_clearmntopt(vfsp
, HOPT_RR
);
886 vfs_clearmntopt(vfsp
, HOPT_JOLIET
);
889 case HS_VOL_TYPE_JOLIET
:
891 * if Joliet, don't copy NOMAPLCASE or NOTRAILDOT to hsfs_flags
893 mount_flags
&= ~(HSFSMNT_NOMAPLCASE
| HSFSMNT_NOTRAILDOT
);
894 mount_flags
|= HSFSMNT_NOMAPLCASE
;
895 if (mount_flags
& HSFSMNT_JOLIETLONG
)
896 fsp
->hsfs_namemax
= JOLIET_NAMELEN_MAX
*3; /* UTF-8 */
898 fsp
->hsfs_namemax
= MAXNAMELEN
-1;
899 fsp
->hsfs_namelen
= JOLIET_NAMELEN
*2;
900 vfs_setmntopt(vfsp
, HOPT_JOLIET
, NULL
, 0);
901 vfs_clearmntopt(vfsp
, HOPT_RR
);
902 vfs_clearmntopt(vfsp
, HOPT_VERS2
);
907 * Add the HSFSMNT_INODE pseudo mount flag to the current mount flags.
909 fsp
->hsfs_flags
= mount_flags
| (fsp
->hsfs_flags
& HSFSMNT_INODE
);
912 * Setup I/O Scheduling structures
915 fsp
->hqueue
= kmem_alloc(sizeof (struct hsfs_queue
), KM_SLEEP
);
916 hsched_init(fsp
, fsid
, &modlinkage
);
922 hsfs_init_kstats(fsp
, fsid
);
924 DTRACE_PROBE1(mount__done
, struct hsfs
*, fsp
);
929 fsp
->hsfs_magic
= HSFS_MAGIC
;
930 mutex_exit(&hs_mounttab_lock
);
932 kmem_free(svp
, sizeof (*svp
));
933 kmem_free(jvp
, sizeof (*jvp
));
938 (void) VOP_CLOSE(devvp
, FREAD
, 1, (offset_t
)0, cr
, NULL
);
941 kmem_free(fsp
, sizeof (*fsp
));
943 kmem_free(svp
, sizeof (*svp
));
945 kmem_free(jvp
, sizeof (*jvp
));
950 * Get the rootvp associated with fsp->hsfs_vol
960 ASSERT(pathsize
== strlen(fsp
->hsfs_fsmnt
) + 1);
963 * If the root directory does not appear to be
964 * valid, use what it points to as "." instead.
965 * Some Defense Mapping Agency disks are non-conformant
968 if (!hsfs_valid_dir(&fsp
->hsfs_vol
.root_dir
)) {
969 hs_log_bogus_disk_warning(fsp
, HSFS_ERR_BAD_ROOT_DIR
, 0);
970 if (hs_remakenode(fsp
->hsfs_vol
.root_dir
.ext_lbn
,
971 (uint_t
)0, vfsp
, &fsp
->hsfs_rootvp
)) {
972 hs_mounttab
= hs_mounttab
->hsfs_next
;
973 mutex_destroy(&fsp
->hsfs_free_lock
);
974 rw_destroy(&fsp
->hsfs_hash_lock
);
975 kmem_free(fsp
->hsfs_fsmnt
, pathsize
);
976 mutex_exit(&hs_mounttab_lock
);
980 fsp
->hsfs_rootvp
= hs_makenode(&fsp
->hsfs_vol
.root_dir
,
981 fsp
->hsfs_vol
.root_dir
.ext_lbn
, 0, vfsp
);
984 /* XXX - ignore the path table for now */
985 fsp
->hsfs_ptbl
= NULL
;
986 hp
= VTOH(fsp
->hsfs_rootvp
);
987 hp
->hs_ptbl_idx
= NULL
;
995 * Locate the Standard File Structure Volume Descriptor and
996 * parse it into an hs_volume structure.
998 * XXX - May someday want to look for Coded Character Set FSVD, too.
1001 hs_findhsvol(struct hsfs
*fsp
, struct vnode
*vp
, struct hs_volume
*hvp
)
1010 secno
= hs_findvoldesc(vp
->v_rdev
, HS_VOLDESC_SEC
);
1011 secbp
= bread(vp
->v_rdev
, secno
* 4, HS_SECTOR_SIZE
);
1012 error
= geterror(secbp
);
1015 cmn_err(CE_NOTE
, "hs_findhsvol: bread: error=(%d)", error
);
1020 volp
= (uchar_t
*)secbp
->b_un
.b_addr
;
1023 * To avoid that we read the whole medium in case that someone prepares
1024 * a malicious "fs image", we read at most 32 blocks.
1026 for (n
= 0; n
< 32 &&
1027 HSV_DESC_TYPE(volp
) != VD_EOV
; n
++) {
1028 for (i
= 0; i
< HSV_ID_STRLEN
; i
++)
1029 if (HSV_STD_ID(volp
)[i
] != HSV_ID_STRING
[i
])
1031 if (HSV_STD_VER(volp
) != HSV_ID_VER
)
1033 switch (HSV_DESC_TYPE(volp
)) {
1035 /* Standard File Structure */
1036 fsp
->hsfs_vol_type
= HS_VOL_TYPE_HS
;
1037 error
= hs_parsehsvol(fsp
, volp
, hvp
);
1042 /* Coded Character File Structure */
1050 secbp
= bread(vp
->v_rdev
, secno
* 4, HS_SECTOR_SIZE
);
1052 error
= geterror(secbp
);
1055 cmn_err(CE_NOTE
, "hs_findhsvol: bread: error=(%d)",
1061 volp
= (uchar_t
*)secbp
->b_un
.b_addr
;
1071 * Parse the Standard File Structure Volume Descriptor into
1072 * an hs_volume structure. We can't just bcopy it into the
1073 * structure because of byte-ordering problems.
1077 hs_parsehsvol(struct hsfs
*fsp
, uchar_t
*volp
, struct hs_volume
*hvp
)
1079 hvp
->vol_size
= HSV_VOL_SIZE(volp
);
1080 hvp
->lbn_size
= HSV_BLK_SIZE(volp
);
1081 if (hvp
->lbn_size
== 0) {
1082 cmn_err(CE_NOTE
, "hs_parsehsvol: logical block size in the "
1086 hvp
->lbn_shift
= ffs((long)hvp
->lbn_size
) - 1;
1088 ffs((long)howmany(HS_SECTOR_SIZE
, (int)hvp
->lbn_size
)) - 1;
1089 hvp
->lbn_maxoffset
= hvp
->lbn_size
- 1;
1090 hs_parse_longdate(HSV_cre_date(volp
), &hvp
->cre_date
);
1091 hs_parse_longdate(HSV_mod_date(volp
), &hvp
->mod_date
);
1092 hvp
->file_struct_ver
= HSV_FILE_STRUCT_VER(volp
);
1093 hvp
->ptbl_len
= HSV_PTBL_SIZE(volp
);
1094 hvp
->vol_set_size
= (ushort_t
)HSV_SET_SIZE(volp
);
1095 hvp
->vol_set_seq
= (ushort_t
)HSV_SET_SEQ(volp
);
1096 #if defined(_LITTLE_ENDIAN)
1097 hvp
->ptbl_lbn
= HSV_PTBL_MAN_LS(volp
);
1099 hvp
->ptbl_lbn
= HSV_PTBL_MAN_MS(volp
);
1101 hs_copylabel(hvp
, HSV_VOL_ID(volp
), 0);
1104 * Make sure that lbn_size is a power of two and otherwise valid.
1106 if (hvp
->lbn_size
& ~(1 << hvp
->lbn_shift
)) {
1108 "hsfs: %d-byte logical block size not supported",
1112 return (hs_parsedir(fsp
, HSV_ROOT_DIR(volp
), &hvp
->root_dir
,
1113 (char *)NULL
, (int *)NULL
, HDE_ROOT_DIR_REC_SIZE
));
1119 * Locate the Primary Volume Descriptor
1120 * parse it into an hs_volume structure.
1122 * XXX - Partition not yet done
1124 * Except for fsp->hsfs_vol_type, no fsp member may be modified.
1125 * fsp->hsfs_vol is modified indirectly via the *hvp argument.
1128 hs_findisovol(struct hsfs
*fsp
, struct vnode
*vp
,
1129 struct hs_volume
*hvp
,
1130 struct hs_volume
*svp
,
1131 struct hs_volume
*jvp
)
1144 secno
= hs_findvoldesc(vp
->v_rdev
, ISO_VOLDESC_SEC
);
1145 secbp
= bread(vp
->v_rdev
, secno
* 4, ISO_SECTOR_SIZE
);
1146 error
= geterror(secbp
);
1149 cmn_err(CE_NOTE
, "hs_findisovol: bread: error=(%d)", error
);
1154 volp
= (uchar_t
*)secbp
->b_un
.b_addr
;
1157 * To avoid that we read the whole medium in case that someone prepares
1158 * a malicious "fs image", we read at most 32 blocks.
1160 for (n
= 0; n
< 32 && ISO_DESC_TYPE(volp
) != ISO_VD_EOV
; n
++) {
1161 for (i
= 0; i
< ISO_ID_STRLEN
; i
++)
1162 if (ISO_STD_ID(volp
)[i
] != ISO_ID_STRING
[i
])
1164 switch (ISO_DESC_TYPE(volp
)) {
1166 /* Standard File Structure */
1167 if (ISO_STD_VER(volp
) != ISO_ID_VER
)
1169 if (foundpvd
!= 1) {
1170 fsp
->hsfs_vol_type
= HS_VOL_TYPE_ISO
;
1171 if (error
= hs_parseisovol(fsp
, volp
, hvp
)) {
1176 for (i
= 0; i
< ISO_SECTOR_SIZE
; i
++)
1181 /* Supplementary Volume Descriptor */
1182 if (ISO_STD_VER(volp
) == ISO_ID_VER2
&&
1184 fsp
->hsfs_vol_type
= HS_VOL_TYPE_ISO
;
1185 if (error
= hs_parseisovol(fsp
, volp
, svp
)) {
1191 if (hs_joliet_level(volp
) >= 1 && foundjvd
!= 1) {
1192 fsp
->hsfs_vol_type
= HS_VOL_TYPE_ISO
;
1193 if (error
= hs_parseisovol(fsp
, volp
, jvp
)) {
1203 /* currently cannot handle partition */
1210 secbp
= bread(vp
->v_rdev
, secno
* 4, HS_SECTOR_SIZE
);
1211 error
= geterror(secbp
);
1214 cmn_err(CE_NOTE
, "hs_findisovol: bread: error=(%d)",
1220 volp
= (uchar_t
*)secbp
->b_un
.b_addr
;
1222 for (n
= 0; n
< 16; n
++) {
1225 secbp
= bread(vp
->v_rdev
, secno
* 4, HS_SECTOR_SIZE
);
1226 error
= geterror(secbp
);
1229 cmn_err(CE_NOTE
, "hs_findisovol: bread: error=(%d)",
1236 * Check for the signature from mkisofs that grants that
1237 * the current filesystem allows to use the extent lbn as
1238 * inode number even in pure ISO9660 mode.
1240 volp
= (uchar_t
*)secbp
->b_un
.b_addr
;
1241 if (strncmp((char *)volp
, "MKI ", 4) == 0) {
1250 fsp
->hsfs_flags
|= HSFSMNT_INODE
;
1264 * Return 0 if no Joliet is found
1265 * else return Joliet Level 1..3
1268 hs_joliet_level(uchar_t
*volp
)
1270 if (ISO_std_ver(volp
)[0] == ISO_ID_VER
&&
1271 ISO_svd_esc(volp
)[0] == '%' &&
1272 ISO_svd_esc(volp
)[1] == '/') {
1274 switch (ISO_svd_esc(volp
)[2]) {
1290 * Parse the Primary Volume Descriptor into an hs_volume structure.
1294 hs_parseisovol(struct hsfs
*fsp
, uchar_t
*volp
, struct hs_volume
*hvp
)
1296 hvp
->vol_size
= ISO_VOL_SIZE(volp
);
1297 hvp
->lbn_size
= ISO_BLK_SIZE(volp
);
1298 if (hvp
->lbn_size
== 0) {
1299 cmn_err(CE_NOTE
, "hs_parseisovol: logical block size in the "
1303 hvp
->lbn_shift
= ffs((long)hvp
->lbn_size
) - 1;
1305 ffs((long)howmany(ISO_SECTOR_SIZE
, (int)hvp
->lbn_size
)) - 1;
1306 hvp
->lbn_maxoffset
= hvp
->lbn_size
- 1;
1307 hs_parse_longdate(ISO_cre_date(volp
), &hvp
->cre_date
);
1308 hs_parse_longdate(ISO_mod_date(volp
), &hvp
->mod_date
);
1309 hvp
->file_struct_ver
= ISO_FILE_STRUCT_VER(volp
);
1310 hvp
->ptbl_len
= ISO_PTBL_SIZE(volp
);
1311 hvp
->vol_set_size
= (ushort_t
)ISO_SET_SIZE(volp
);
1312 hvp
->vol_set_seq
= (ushort_t
)ISO_SET_SEQ(volp
);
1313 #if defined(_LITTLE_ENDIAN)
1314 hvp
->ptbl_lbn
= ISO_PTBL_MAN_LS(volp
);
1316 hvp
->ptbl_lbn
= ISO_PTBL_MAN_MS(volp
);
1318 hs_copylabel(hvp
, ISO_VOL_ID(volp
), hs_joliet_level(volp
) >= 1);
1321 * Make sure that lbn_size is a power of two and otherwise valid.
1323 if (hvp
->lbn_size
& ~(1 << hvp
->lbn_shift
)) {
1325 "hsfs: %d-byte logical block size not supported",
1329 return (hs_parsedir(fsp
, ISO_ROOT_DIR(volp
), &hvp
->root_dir
,
1330 (char *)NULL
, (int *)NULL
, IDE_ROOT_DIR_REC_SIZE
));
1334 * Common code for mount and umount.
1335 * Check that the user's argument is a reasonable
1336 * thing on which to mount, and return the device number if so.
1339 hs_getmdev(struct vfs
*vfsp
, char *fspec
, int flags
, dev_t
*pdev
, mode_t
*mode
,
1343 struct vnode
*svp
= NULL
;
1344 struct vnode
*lvp
= NULL
;
1348 enum uio_seg fromspace
= (flags
& MS_SYSSPACE
) ?
1349 UIO_SYSSPACE
: UIO_USERSPACE
;
1352 * Look up the device/file to be mounted.
1354 error
= lookupname(fspec
, fromspace
, FOLLOW
, NULLVPP
, &svp
);
1356 if (error
== ENOENT
)
1361 error
= vfs_get_lofi(vfsp
, &lvp
);
1364 if (error
== ENOENT
)
1367 } else if (error
== 0) {
1372 if (bvp
->v_type
!= VBLK
) {
1377 if ((error
= secpolicy_spec_open(cr
, bvp
, FREAD
)) != 0)
1382 * Can we read from the device/file ?
1384 if ((error
= VOP_ACCESS(svp
, VREAD
, 0, cr
, NULL
)) != 0)
1387 vap
.va_mask
= AT_MODE
; /* get protection mode */
1388 (void) VOP_GETATTR(bvp
, &vap
, 0, CRED(), NULL
);
1389 *mode
= vap
.va_mode
;
1391 dev
= *pdev
= bvp
->v_rdev
;
1396 * Ensure that this device isn't already mounted,
1397 * unless this is a REMOUNT request or we are told to suppress
1400 if ((flags
& MS_NOCHECK
) == 0) {
1401 if (vfs_devmounting(dev
, vfsp
))
1403 if (vfs_devismounted(dev
) && !(flags
& MS_REMOUNT
))
1407 if (getmajor(*pdev
) >= devcnt
) {
1422 hs_copylabel(struct hs_volume
*hvp
, unsigned char *label
, int isjoliet
)
1424 char lbuf
[64]; /* hs_joliet_cp() creates 48 bytes at most */
1428 * hs_joliet_cp() will output 16..48 bytes.
1429 * We need to clear 'lbuf' to avoid junk chars past byte 15.
1431 bzero(lbuf
, sizeof (lbuf
));
1432 (void) hs_joliet_cp((char *)label
, lbuf
, 32);
1433 label
= (unsigned char *)lbuf
;
1435 /* cdrom volid is at most 32 bytes */
1436 bcopy(label
, hvp
->vol_id
, 32);
1437 hvp
->vol_id
[31] = NULL
;
1441 * Mount root file system.
1442 * "why" is ROOT_INIT on initial call, ROOT_REMOUNT if called to
1443 * remount the root file system, and ROOT_UNMOUNT if called to
1444 * unmount the root (e.g., as part of a system shutdown).
1446 * XXX - this may be partially machine-dependent; it, along with the VFS_SWAPVP
1447 * operation, goes along with auto-configuration. A mechanism should be
1448 * provided by which machine-INdependent code in the kernel can say "get me the
1449 * right root file system" and "get me the right initial swap area", and have
1450 * that done in what may well be a machine-dependent fashion.
1451 * Unfortunately, it is also file-system-type dependent (NFS gets it via
1452 * bootparams calls, UFS gets it from various and sundry machine-dependent
1453 * mechanisms, as SPECFS does for swap).
1456 hsfs_mountroot(struct vfs
*vfsp
, enum whymountroot why
)
1460 struct hs_volume
*fvolp
;
1461 static int hsfsrootdone
= 0;
1465 if (why
== ROOT_INIT
) {
1468 rootdev
= getrootdev();
1469 if (rootdev
== (dev_t
)NODEV
)
1471 vfsp
->vfs_dev
= rootdev
;
1472 vfsp
->vfs_flag
|= VFS_RDONLY
;
1473 } else if (why
== ROOT_REMOUNT
) {
1474 cmn_err(CE_NOTE
, "hsfs_mountroot: ROOT_REMOUNT");
1476 } else if (why
== ROOT_UNMOUNT
) {
1479 error
= vfs_lock(vfsp
);
1481 cmn_err(CE_NOTE
, "hsfs_mountroot: couldn't get vfs_lock");
1485 error
= hs_mountfs(vfsp
, rootdev
, "/", mode
, 1, CRED(), 1);
1487 * XXX - assumes root device is not indirect, because we don't set
1488 * rootvp. Is rootvp used for anything? If so, make another arg
1495 rootvp
= (struct vnode
*)0;
1499 if (why
== ROOT_INIT
)
1500 vfs_add((struct vnode
*)0, vfsp
,
1501 (vfsp
->vfs_flag
& VFS_RDONLY
) ? MS_RDONLY
: 0);
1503 fsp
= VFS_TO_HSFS(vfsp
);
1504 fvolp
= &fsp
->hsfs_vol
;
1506 if (fvolp
->cre_date
.tv_sec
== 0) {
1507 cmn_err(CE_NOTE
, "hsfs_mountroot: cre_date.tv_sec == 0");
1508 if (fvolp
->mod_date
.tv_sec
== 0) {
1510 "hsfs_mountroot: mod_date.tv_sec == 0");
1511 cmn_err(CE_NOTE
, "hsfs_mountroot: clkset(-1L)");
1514 clkset(fvolp
->mod_date
.tv_sec
);
1517 clkset(fvolp
->mod_date
.tv_sec
);
1519 #else /* HSFS_CLKSET */
1521 #endif /* HSFS_CLKSET */
1528 * Return the sector where the volume descriptor lives. This is
1529 * a fixed value for "normal" cd-rom's, but can change for
1530 * multisession cd's.
1532 * desc_sec is the same for high-sierra and iso 9660 formats, why
1533 * there are two different #defines used in the code for this is
1534 * beyond me. These are standards, cast in concrete, right?
1535 * To be general, however, this function supports passing in different
1539 hs_findvoldesc(dev_t rdev
, int desc_sec
)
1543 int rval
; /* ignored */
1545 #ifdef CDROMREADOFFSET
1547 * Issue the Read Offset ioctl directly to the
1548 * device. Ignore any errors and set starting
1549 * secno to the default, otherwise add the
1550 * VOLDESC sector number to the offset.
1552 error
= cdev_ioctl(rdev
, CDROMREADOFFSET
, (intptr_t)&secno
,
1553 FNATIVE
|FKIOCTL
|FREAD
, CRED(), &rval
);