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.
25 * Copyright (c) 2017 by Delphix. All rights reserved.
29 * VFS operations for High Sierra filesystem
32 #include <sys/types.h>
33 #include <sys/isa_defs.h>
34 #include <sys/t_lock.h>
35 #include <sys/param.h>
36 #include <sys/systm.h>
37 #include <sys/sysmacros.h>
39 #include <sys/signal.h>
44 #include <sys/pathname.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 "sys/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_MAPLCASE "maplcase"
88 #define HOPT_NOMAPLCASE "nomaplcase"
89 #define HOPT_NOTRAILDOT "notraildot"
90 #define HOPT_TRAILDOT "traildot"
91 #define HOPT_NRR "nrr"
93 #define HOPT_JOLIET "joliet"
94 #define HOPT_NOJOLIET "nojoliet"
95 #define HOPT_JOLIETLONG "jolietlong"
96 #define HOPT_VERS2 "vers2"
97 #define HOPT_NOVERS2 "novers2"
98 #define HOPT_RO MNTOPT_RO
100 static char *mapl_cancel
[] = { HOPT_NOMAPLCASE
, NULL
};
101 static char *nomapl_cancel
[] = { HOPT_MAPLCASE
, NULL
};
102 static char *ro_cancel
[] = { MNTOPT_RW
, NULL
};
103 static char *rr_cancel
[] = { HOPT_NRR
, NULL
};
104 static char *nrr_cancel
[] = { HOPT_RR
, NULL
};
105 static char *joliet_cancel
[] = { HOPT_NOJOLIET
, NULL
};
106 static char *nojoliet_cancel
[] = { HOPT_JOLIET
, NULL
};
107 static char *vers2_cancel
[] = { HOPT_NOVERS2
, NULL
};
108 static char *novers2_cancel
[] = { HOPT_VERS2
, NULL
};
109 static char *trail_cancel
[] = { HOPT_NOTRAILDOT
, NULL
};
110 static char *notrail_cancel
[] = { HOPT_TRAILDOT
, NULL
};
112 static mntopt_t hsfs_options
[] = {
113 { HOPT_MAPLCASE
, mapl_cancel
, NULL
, MO_DEFAULT
, NULL
},
114 { HOPT_NOMAPLCASE
, nomapl_cancel
, NULL
, 0, NULL
},
115 { HOPT_RO
, ro_cancel
, NULL
, MO_DEFAULT
, NULL
},
116 { HOPT_RR
, rr_cancel
, NULL
, MO_DEFAULT
, NULL
},
117 { HOPT_NRR
, nrr_cancel
, NULL
, 0, NULL
},
118 { HOPT_JOLIET
, joliet_cancel
, NULL
, 0, NULL
},
119 { HOPT_NOJOLIET
, nojoliet_cancel
, NULL
, 0, NULL
},
120 { HOPT_JOLIETLONG
, NULL
, NULL
, 0, NULL
},
121 { HOPT_VERS2
, vers2_cancel
, NULL
, 0, NULL
},
122 { HOPT_NOVERS2
, novers2_cancel
, NULL
, 0, NULL
},
123 { HOPT_TRAILDOT
, trail_cancel
, NULL
, MO_DEFAULT
, NULL
},
124 { HOPT_NOTRAILDOT
, notrail_cancel
, NULL
, 0, NULL
},
125 { "sector", NULL
, "0", MO_HASVALUE
, NULL
},
128 static mntopts_t hsfs_proto_opttbl
= {
129 sizeof (hsfs_options
) / sizeof (mntopt_t
),
134 * Indicates whether to enable the I/O scheduling and readahead logic
135 * 1 - Enable, 0 - Do not Enable.
136 * Debugging purposes.
139 static int hsfsfstype
;
140 static int hsfsinit(int, char *);
142 static vfsdef_t vfw
= {
146 /* We don't suppport remounting */
147 VSW_HASPROTO
|VSW_STATS
|VSW_CANLOFI
|VSW_MOUNTDEV
,
151 static struct modlfs modlfs
= {
152 &mod_fsops
, "filesystem for HSFS", &vfw
155 static struct modlinkage modlinkage
= {
156 MODREV_1
, (void *)&modlfs
, NULL
159 extern void hsched_init_caches(void);
160 extern void hsched_fini_caches(void);
166 return (mod_install(&modlinkage
));
174 error
= mod_remove(&modlinkage
);
176 DTRACE_PROBE1(mod_remove
, int, error
);
181 mutex_destroy(&hs_mounttab_lock
);
184 * Tear down the operations vectors
186 (void) vfs_freevfsops_by_type(hsfsfstype
);
188 hs_fini_hsnode_cache();
189 hsched_fini_caches();
194 _info(struct modinfo
*modinfop
)
196 return (mod_info(&modlinkage
, modinfop
));
199 #define BDEVFLAG(dev) ((devopsp[getmajor(dev)])->devo_cb_ops->cb_flag)
201 kmutex_t hs_mounttab_lock
;
202 struct hsfs
*hs_mounttab
= NULL
;
204 /* default mode, uid, gid */
205 mode_t hsfs_default_mode
= 0555;
206 uid_t hsfs_default_uid
= 0;
207 gid_t hsfs_default_gid
= 3;
209 extern void hsched_init(struct hsfs
*fsp
, int fsid
,
210 struct modlinkage
*modlinkage
);
211 extern void hsched_fini(struct hsfs_queue
*hqueue
);
212 extern void hsfs_init_kstats(struct hsfs
*fsp
, int fsid
);
213 extern void hsfs_fini_kstats(struct hsfs
*fsp
);
215 static int hsfs_mount(struct vfs
*vfsp
, struct vnode
*mvp
,
216 struct mounta
*uap
, struct cred
*cr
);
217 static int hsfs_unmount(struct vfs
*vfsp
, int, struct cred
*cr
);
218 static int hsfs_root(struct vfs
*vfsp
, struct vnode
**vpp
);
219 static int hsfs_statvfs(struct vfs
*vfsp
, struct statvfs64
*sbp
);
220 static int hsfs_vget(struct vfs
*vfsp
, struct vnode
**vpp
, struct fid
*fidp
);
221 static int hsfs_mountroot(struct vfs
*, enum whymountroot
);
223 static int hs_mountfs(struct vfs
*vfsp
, dev_t dev
, char *path
,
224 mode_t mode
, int flags
, struct cred
*cr
, int isroot
);
225 static int hs_getrootvp(struct vfs
*vfsp
, struct hsfs
*fsp
, size_t pathsize
);
226 static int hs_findhsvol(struct hsfs
*fsp
, struct vnode
*vp
,
227 struct hs_volume
*hvp
);
228 static int hs_parsehsvol(struct hsfs
*fsp
, uchar_t
*volp
,
229 struct hs_volume
*hvp
);
230 static int hs_findisovol(struct hsfs
*fsp
, struct vnode
*vp
,
231 struct hs_volume
*hvp
,
232 struct hs_volume
*svp
,
233 struct hs_volume
*jvp
);
234 static int hs_joliet_level(uchar_t
*volp
);
235 static int hs_parseisovol(struct hsfs
*fsp
, uchar_t
*volp
,
236 struct hs_volume
*hvp
);
237 static void hs_copylabel(struct hs_volume
*, unsigned char *, int);
238 static int hs_getmdev(struct vfs
*, char *fspec
, int flags
, dev_t
*pdev
,
239 mode_t
*mode
, cred_t
*cr
);
240 static int hs_findvoldesc(dev_t rdev
, int desc_sec
);
242 static const struct vfsops hsfs_vfsops
= {
243 .vfs_mount
= hsfs_mount
,
244 .vfs_unmount
= hsfs_unmount
,
245 .vfs_root
= hsfs_root
,
246 .vfs_statvfs
= hsfs_statvfs
,
247 .vfs_vget
= hsfs_vget
,
248 .vfs_mountroot
= hsfs_mountroot
,
252 hsfsinit(int fstype
, char *name
)
256 error
= vfs_setfsops(fstype
, &hsfs_vfsops
);
258 cmn_err(CE_WARN
, "hsfsinit: bad fstyp");
263 mutex_init(&hs_mounttab_lock
, NULL
, MUTEX_DEFAULT
, NULL
);
264 hs_init_hsnode_cache();
265 hsched_init_caches();
271 hsfs_mount(struct vfs
*vfsp
, struct vnode
*mvp
,
272 struct mounta
*uap
, struct cred
*cr
)
279 int flags
; /* this will hold the mount specific data */
281 if ((error
= secpolicy_fs_mount(cr
, mvp
, vfsp
)) != 0)
284 if (mvp
->v_type
!= VDIR
)
287 /* mount option must be read only, else mount will be rejected */
288 if (!(uap
->flags
& MS_RDONLY
))
292 * We already told the framework that we don't support remounting.
294 ASSERT(!(uap
->flags
& MS_REMOUNT
));
296 mutex_enter(&mvp
->v_lock
);
297 vnode_busy
= (mvp
->v_count
!= 1) || (mvp
->v_flag
& VROOT
);
298 mutex_exit(&mvp
->v_lock
);
300 if ((uap
->flags
& MS_OVERLAY
) == 0 && vnode_busy
) {
305 * Check for the options that actually affect things
309 if (vfs_optionisset(vfsp
, HOPT_NOMAPLCASE
, NULL
))
310 flags
|= HSFSMNT_NOMAPLCASE
;
311 if (vfs_optionisset(vfsp
, HOPT_NOTRAILDOT
, NULL
))
312 flags
|= HSFSMNT_NOTRAILDOT
;
313 if (vfs_optionisset(vfsp
, HOPT_NRR
, NULL
))
314 flags
|= HSFSMNT_NORRIP
;
315 if (vfs_optionisset(vfsp
, HOPT_NOJOLIET
, NULL
))
316 flags
|= HSFSMNT_NOJOLIET
;
317 if (vfs_optionisset(vfsp
, HOPT_JOLIETLONG
, NULL
))
318 flags
|= HSFSMNT_JOLIETLONG
;
319 if (vfs_optionisset(vfsp
, HOPT_NOVERS2
, NULL
))
320 flags
|= HSFSMNT_NOVERS2
;
322 error
= pn_get(uap
->dir
, (uap
->flags
& MS_SYSSPACE
) ?
323 UIO_SYSSPACE
: UIO_USERSPACE
, &dpn
);
327 error
= hs_getmdev(vfsp
, uap
->spec
, uap
->flags
, &dev
, &mode
, cr
);
334 * If the device is a tape, return error
336 if ((BDEVFLAG(dev
) & D_TAPE
) == D_TAPE
) {
342 * Mount the filesystem.
344 error
= hs_mountfs(vfsp
, dev
, dpn
.pn_path
, mode
, flags
, cr
, 0);
359 if (secpolicy_fs_unmount(cr
, vfsp
) != 0)
363 * forced unmount is not supported by this file system
364 * and thus, ENOTSUP is being returned.
369 fsp
= VFS_TO_HSFS(vfsp
);
371 if (fsp
->hsfs_rootvp
->v_count
!= 1)
374 /* destroy all old pages and hsnodes for this vfs */
375 if (hs_synchash(vfsp
))
378 mutex_enter(&hs_mounttab_lock
);
379 for (tspp
= &hs_mounttab
; *tspp
!= NULL
; tspp
= &(*tspp
)->hsfs_next
) {
384 mutex_exit(&hs_mounttab_lock
);
385 panic("hsfs_unmount: vfs not mounted?");
389 *tspp
= fsp
->hsfs_next
;
391 mutex_exit(&hs_mounttab_lock
);
393 hsfs_fini_kstats(fsp
);
394 (void) fop_close(fsp
->hsfs_devvp
, FREAD
, 1, 0, cr
, NULL
);
395 VN_RELE(fsp
->hsfs_devvp
);
396 /* free path table space */
397 if (fsp
->hsfs_ptbl
!= NULL
)
398 kmem_free(fsp
->hsfs_ptbl
, (size_t)fsp
->hsfs_vol
.ptbl_len
);
399 /* free path table index table */
400 if (fsp
->hsfs_ptbl_idx
!= NULL
)
401 kmem_free(fsp
->hsfs_ptbl_idx
, (size_t)
402 (fsp
->hsfs_ptbl_idx_size
* sizeof (struct ptable_idx
)));
404 /* free "mounted on" pathame */
405 if (fsp
->hsfs_fsmnt
!= NULL
)
406 kmem_free(fsp
->hsfs_fsmnt
, strlen(fsp
->hsfs_fsmnt
) + 1);
408 hsched_fini(fsp
->hqueue
);
409 kmem_free(fsp
->hqueue
, sizeof (struct hsfs_queue
));
411 mutex_destroy(&fsp
->hsfs_free_lock
);
412 rw_destroy(&fsp
->hsfs_hash_lock
);
414 kmem_free(fsp
, sizeof (*fsp
));
420 hsfs_root(struct vfs
*vfsp
, struct vnode
**vpp
)
422 *vpp
= (VFS_TO_HSFS(vfsp
))->hsfs_rootvp
;
429 hsfs_statvfs(struct vfs
*vfsp
, struct statvfs64
*sbp
)
434 fsp
= VFS_TO_HSFS(vfsp
);
435 if (fsp
->hsfs_magic
!= HSFS_MAGIC
)
437 bzero(sbp
, sizeof (*sbp
));
438 sbp
->f_bsize
= vfsp
->vfs_bsize
;
439 sbp
->f_frsize
= sbp
->f_bsize
; /* no fragment, same as block size */
440 sbp
->f_blocks
= (fsblkcnt64_t
)fsp
->hsfs_vol
.vol_size
;
442 sbp
->f_bfree
= (fsblkcnt64_t
)0;
443 sbp
->f_bavail
= (fsblkcnt64_t
)0;
444 sbp
->f_files
= (fsfilcnt64_t
)-1;
445 sbp
->f_ffree
= (fsfilcnt64_t
)0;
446 sbp
->f_favail
= (fsfilcnt64_t
)0;
447 (void) cmpldev(&d32
, vfsp
->vfs_dev
);
449 (void) strcpy(sbp
->f_basetype
, vfssw
[vfsp
->vfs_fstype
].vsw_name
);
450 sbp
->f_flag
= vf_to_stf(vfsp
->vfs_flag
);
451 sbp
->f_namemax
= fsp
->hsfs_namemax
;
452 (void) strcpy(sbp
->f_fstr
, fsp
->hsfs_vol
.vol_id
);
458 * Previously nodeid was declared as uint32_t. This has been changed
459 * to conform better with the ISO9660 standard. The standard states that
460 * a LBN can be a 32 bit number, as the MAKE_NODEID macro shifts this
461 * LBN 11 places left (LBN_TO_BYTE) and then shifts the result 5 right
462 * (divide by 32) we are left with the potential of an overflow if
463 * confined to a 32 bit value.
467 hsfs_vget(struct vfs
*vfsp
, struct vnode
**vpp
, struct fid
*fidp
)
474 fsp
= (struct hsfs
*)VFS_TO_HSFS(vfsp
);
475 fid
= (struct hsfid
*)fidp
;
478 * Look for vnode on hashlist.
479 * If found, it's now active and the refcnt was incremented.
482 rw_enter(&fsp
->hsfs_hash_lock
, RW_READER
);
484 nodeid
= fid
->hf_ino
;
486 if ((*vpp
= hs_findhash(nodeid
, fid
->hf_dir_lbn
,
487 (uint_t
)fid
->hf_dir_off
, vfsp
)) == NULL
) {
489 * Not in cache, so we need to remake it.
490 * hs_remakenode() will read the directory entry
491 * and then check again to see if anyone else has
492 * put it in the cache.
494 rw_exit(&fsp
->hsfs_hash_lock
);
495 error
= hs_remakenode(fid
->hf_dir_lbn
, (uint_t
)fid
->hf_dir_off
,
499 rw_exit(&fsp
->hsfs_hash_lock
);
504 #define CHECKSUM_SIZE (64 * 1024)
507 * Compute a CD-ROM fsid by checksumming the first 64K of data on the CD
508 * We use the 'fsp' argument to determine the location of the root
509 * directory entry, and we start reading from there.
512 compute_cdrom_id(struct hsfs
*fsp
, vnode_t
*devvp
)
515 struct hs_volume
*hsvp
= &fsp
->hsfs_vol
;
520 secno
= hsvp
->root_dir
.ext_lbn
>> hsvp
->lbn_secshift
;
521 bp
= bread(devvp
->v_rdev
, secno
* 4, CHECKSUM_SIZE
);
522 error
= geterror(bp
);
525 * An error on read or a partial read means we asked
526 * for a nonexistant/corrupted piece of the device
527 * (including past-the-end of the media). Don't
528 * try to use the checksumming method then.
530 if (!error
&& bp
->b_bcount
== CHECKSUM_SIZE
) {
531 int *ibuf
= (int *)bp
->b_un
.b_addr
;
536 for (i
= 0; i
< CHECKSUM_SIZE
/ sizeof (int); i
++)
540 * Fallback - use creation date
542 fsid
= hsvp
->cre_date
.tv_sec
;
564 struct hsfs
*fsp
= NULL
;
578 int force_joliet_off
;
579 size_t pathbufsz
= strlen(path
) + 1;
582 struct hs_volume
*svp
= NULL
; /* Supplemental VD for ISO-9660:1999 */
583 struct hs_volume
*jvp
= NULL
; /* Joliet VD */
586 * The rules for which extension will be used are:
587 * 1. No specific mount options given:
588 * - use rrip if available
589 * - use ISO9660:1999 if available
590 * - use joliet if available.
591 * 2. rrip/ISO9660:1999/joliet explicitly disabled via mount option:
592 * - use next "lower" extension
593 * 3. joliet/ISO9660:1999/rrip explicitly requested via mount option:
594 * - disable rrip support even if available
595 * - disable IOS9660:1999 support even if available
597 * We need to adjust these flags as we discover the extensions
598 * present. See below. These are just the starting values.
600 use_rrip
= (mount_flags
& HSFSMNT_NORRIP
) == 0;
601 use_vers2
= (mount_flags
& HSFSMNT_NOVERS2
) == 0;
602 use_joliet
= (mount_flags
& HSFSMNT_NOJOLIET
) == 0;
607 devvp
= makespecvp(dev
, VBLK
);
611 * Open the target device (file) for read only.
613 if (error
= fop_open(&devvp
, FREAD
, cr
, NULL
)) {
619 * Refuse to go any further if this
620 * device is being used for swapping
622 if (IS_SWAPVP(common_specvp(devvp
))) {
627 vap
.va_mask
= AT_SIZE
;
628 if ((error
= fop_getattr(devvp
, &vap
, ATTR_COMM
, cr
, NULL
)) != 0) {
629 cmn_err(CE_NOTE
, "Cannot get attributes of the CD-ROM driver");
634 * Make sure we have a nonzero size partition.
635 * The current version of the SD driver will *not* fail the open
636 * of such a partition so we have to check for it here.
638 if (vap
.va_size
== 0) {
644 * Init a new hsfs structure.
646 fsp
= kmem_zalloc(sizeof (*fsp
), KM_SLEEP
);
647 svp
= kmem_zalloc(sizeof (*svp
), KM_SLEEP
);
648 jvp
= kmem_zalloc(sizeof (*jvp
), KM_SLEEP
);
650 /* hardwire perms, uid, gid */
651 fsp
->hsfs_vol
.vol_uid
= hsfs_default_uid
;
652 fsp
->hsfs_vol
.vol_gid
= hsfs_default_gid
;
653 fsp
->hsfs_vol
.vol_prot
= hsfs_default_mode
;
654 svp
->vol_uid
= hsfs_default_uid
;
655 svp
->vol_gid
= hsfs_default_gid
;
656 svp
->vol_prot
= hsfs_default_mode
;
657 jvp
->vol_uid
= hsfs_default_uid
;
658 jvp
->vol_gid
= hsfs_default_gid
;
659 jvp
->vol_prot
= hsfs_default_mode
;
662 * Look for a Standard File Structure Volume Descriptor,
663 * of which there must be at least one.
664 * If found, check for volume size consistency.
666 * If svp->lbn_size is != 0, we did find a ISO-9660:1999 SVD
667 * If jvp->lbn_size is != 0, we did find a Joliet SVD.
669 fsp
->hsfs_namemax
= ISO_FILE_NAMELEN
;
670 fsp
->hsfs_namelen
= ISO_FILE_NAMELEN
;
671 error
= hs_findisovol(fsp
, devvp
, &fsp
->hsfs_vol
, svp
, jvp
);
672 if (error
== EINVAL
) /* no iso 9660 - try high sierra ... */
673 error
= hs_findhsvol(fsp
, devvp
, &fsp
->hsfs_vol
);
678 DTRACE_PROBE4(findvol
,
680 struct hs_volume
*, &fsp
->hsfs_vol
,
681 struct hs_volume
*, svp
,
682 struct hs_volume
*, jvp
);
685 * Generate a file system ID from the CD-ROM,
686 * and check it for uniqueness.
688 * What we are aiming for is some chance of integrity
689 * across disk change. That is, if a client has an fhandle,
690 * it will be valid as long as the same disk is mounted.
692 fsid
= compute_cdrom_id(fsp
, devvp
);
694 mutex_enter(&hs_mounttab_lock
);
696 if (fsid
== 0 || fsid
== -1) {
699 } else /* make sure that the fsid is unique */
700 for (tsp
= hs_mounttab
; tsp
!= NULL
; tsp
= tsp
->hsfs_next
) {
701 if (fsid
== tsp
->hsfs_vfs
->vfs_fsid
.val
[0]) {
708 fsp
->hsfs_next
= hs_mounttab
;
711 fsp
->hsfs_devvp
= devvp
;
712 fsp
->hsfs_vfs
= vfsp
;
713 fsp
->hsfs_fsmnt
= kmem_alloc(pathbufsz
, KM_SLEEP
);
714 (void) strlcpy(fsp
->hsfs_fsmnt
, path
, pathbufsz
);
716 mutex_init(&fsp
->hsfs_free_lock
, NULL
, MUTEX_DEFAULT
, NULL
);
717 rw_init(&fsp
->hsfs_hash_lock
, NULL
, RW_DEFAULT
, NULL
);
719 vfsp
->vfs_data
= (caddr_t
)fsp
;
721 vfsp
->vfs_fstype
= hsfsfstype
;
722 vfsp
->vfs_bsize
= fsp
->hsfs_vol
.lbn_size
; /* %% */
723 vfsp
->vfs_fsid
.val
[0] = fsid
;
724 vfsp
->vfs_fsid
.val
[1] = hsfsfstype
;
726 if (!hs_getrootvp(vfsp
, fsp
, pathbufsz
)) {
727 DTRACE_PROBE1(rootvp__failed
, struct hsfs
*, fsp
);
731 DTRACE_PROBE1(rootvp
, struct hsfs
*, fsp
);
734 * Attempt to discover a RR extension.
737 hp
= VTOH(fsp
->hsfs_rootvp
);
738 hs_check_root_dirent(fsp
->hsfs_rootvp
, &(hp
->hs_dirent
));
741 has_rrip
= IS_RRIP_IMPLEMENTED(fsp
);
742 has_vers2
= (svp
->lbn_size
!= 0);
743 has_joliet
= (jvp
->lbn_size
!= 0);
745 DTRACE_PROBE4(voltype__suggested
, struct hsfs
*, fsp
,
746 int, use_rrip
, int, use_vers2
, int, use_joliet
);
748 DTRACE_PROBE4(voltype__actual
, struct hsfs
*, fsp
,
749 int, has_rrip
, int, has_vers2
, int, has_joliet
);
751 DTRACE_PROBE4(findvol
,
753 struct hs_volume
*, &fsp
->hsfs_vol
,
754 struct hs_volume
*, svp
,
755 struct hs_volume
*, jvp
);
757 force_rrip_off
= !use_rrip
||
758 (vfs_optionisset(vfsp
, HOPT_JOLIET
, NULL
) && has_joliet
) ||
759 (vfs_optionisset(vfsp
, HOPT_VERS2
, NULL
) && has_vers2
);
761 force_vers2_off
= !use_vers2
||
762 (vfs_optionisset(vfsp
, HOPT_JOLIET
, NULL
) && has_joliet
);
764 force_joliet_off
= !use_joliet
;
766 DTRACE_PROBE4(voltype__force_off
, struct hsfs
*, fsp
,
767 int, force_rrip_off
, int, force_vers2_off
, int, force_joliet_off
);
770 * At the moment, we have references of all three possible
771 * extensions (RR, ISO9660:1999/v2 and Joliet) if present.
773 * The "active" volume descriptor is RRIP (or ISO9660:1988).
774 * We now switch to the user-requested one.
778 if (force_rrip_off
|| !has_rrip
) {
779 if (has_vers2
&& !force_vers2_off
) {
780 VN_RELE(fsp
->hsfs_rootvp
);
781 bcopy(svp
, &fsp
->hsfs_vol
, sizeof (struct hs_volume
));
782 fsp
->hsfs_vol_type
= HS_VOL_TYPE_ISO_V2
;
783 vfsp
->vfs_bsize
= fsp
->hsfs_vol
.lbn_size
;
786 } else if (has_joliet
&& !force_joliet_off
) {
787 VN_RELE(fsp
->hsfs_rootvp
);
788 bcopy(jvp
, &fsp
->hsfs_vol
, sizeof (struct hs_volume
));
789 fsp
->hsfs_vol_type
= HS_VOL_TYPE_JOLIET
;
790 vfsp
->vfs_bsize
= fsp
->hsfs_vol
.lbn_size
;
798 * Make sure not to use Rock Ridge.
800 UNSET_IMPL_BIT(fsp
, RRIP_BIT
);
804 if (!hs_getrootvp(vfsp
, fsp
, pathbufsz
)) {
805 DTRACE_PROBE1(rootvp__failed
, struct hsfs
*, fsp
);
809 DTRACE_PROBE1(rootvp
, struct hsfs
*, fsp
);
811 if (IS_RRIP_IMPLEMENTED(fsp
)) {
817 if (force_joliet_off
)
819 DTRACE_PROBE4(voltype__taken
, struct hsfs
*, fsp
,
820 int, has_rrip
, int, has_vers2
, int, has_joliet
);
823 * mark root node as VROOT
825 fsp
->hsfs_rootvp
->v_flag
|= VROOT
;
827 /* Here we take care of some special case stuff for mountroot */
829 fsp
->hsfs_rootvp
->v_rdev
= devvp
->v_rdev
;
830 rootvp
= fsp
->hsfs_rootvp
;
833 if (IS_RRIP_IMPLEMENTED(fsp
)) {
835 * if RRIP, don't copy NOMAPLCASE or NOTRAILDOT to hsfs_flags
837 mount_flags
&= ~(HSFSMNT_NOMAPLCASE
| HSFSMNT_NOTRAILDOT
);
839 fsp
->hsfs_namemax
= RRIP_FILE_NAMELEN
;
840 fsp
->hsfs_namelen
= RRIP_FILE_NAMELEN
;
842 ASSERT(vfs_optionisset(vfsp
, HOPT_RR
, NULL
));
843 vfs_clearmntopt(vfsp
, HOPT_VERS2
);
844 vfs_clearmntopt(vfsp
, HOPT_JOLIET
);
846 } else switch (fsp
->hsfs_vol_type
) {
849 case HS_VOL_TYPE_ISO
:
852 * if iso v1, don't allow trailing spaces in iso file names
854 mount_flags
|= HSFSMNT_NOTRAILSPACE
;
855 fsp
->hsfs_namemax
= ISO_NAMELEN_V2_MAX
;
856 fsp
->hsfs_namelen
= ISO_FILE_NAMELEN
;
857 vfs_clearmntopt(vfsp
, HOPT_RR
);
858 vfs_clearmntopt(vfsp
, HOPT_VERS2
);
859 vfs_clearmntopt(vfsp
, HOPT_JOLIET
);
862 case HS_VOL_TYPE_ISO_V2
:
864 * if iso v2, don't copy NOTRAILDOT to hsfs_flags
866 mount_flags
&= ~HSFSMNT_NOTRAILDOT
;
867 mount_flags
|= HSFSMNT_NOMAPLCASE
| HSFSMNT_NOVERSION
;
868 fsp
->hsfs_namemax
= ISO_NAMELEN_V2_MAX
;
869 fsp
->hsfs_namelen
= ISO_NAMELEN_V2
;
870 vfs_setmntopt(vfsp
, HOPT_VERS2
, NULL
, 0);
871 vfs_clearmntopt(vfsp
, HOPT_RR
);
872 vfs_clearmntopt(vfsp
, HOPT_JOLIET
);
875 case HS_VOL_TYPE_JOLIET
:
877 * if Joliet, don't copy NOMAPLCASE or NOTRAILDOT to hsfs_flags
879 mount_flags
&= ~(HSFSMNT_NOMAPLCASE
| HSFSMNT_NOTRAILDOT
);
880 mount_flags
|= HSFSMNT_NOMAPLCASE
;
881 if (mount_flags
& HSFSMNT_JOLIETLONG
)
882 fsp
->hsfs_namemax
= JOLIET_NAMELEN_MAX
*3; /* UTF-8 */
884 fsp
->hsfs_namemax
= MAXNAMELEN
-1;
885 fsp
->hsfs_namelen
= JOLIET_NAMELEN
*2;
886 vfs_setmntopt(vfsp
, HOPT_JOLIET
, NULL
, 0);
887 vfs_clearmntopt(vfsp
, HOPT_RR
);
888 vfs_clearmntopt(vfsp
, HOPT_VERS2
);
893 * Add the HSFSMNT_INODE pseudo mount flag to the current mount flags.
895 fsp
->hsfs_flags
= mount_flags
| (fsp
->hsfs_flags
& HSFSMNT_INODE
);
898 * Setup I/O Scheduling structures
901 fsp
->hqueue
= kmem_alloc(sizeof (struct hsfs_queue
), KM_SLEEP
);
902 hsched_init(fsp
, fsid
, &modlinkage
);
908 hsfs_init_kstats(fsp
, fsid
);
910 DTRACE_PROBE1(mount__done
, struct hsfs
*, fsp
);
915 fsp
->hsfs_magic
= HSFS_MAGIC
;
916 mutex_exit(&hs_mounttab_lock
);
918 kmem_free(svp
, sizeof (*svp
));
919 kmem_free(jvp
, sizeof (*jvp
));
924 (void) fop_close(devvp
, FREAD
, 1, 0, cr
, NULL
);
927 kmem_free(fsp
, sizeof (*fsp
));
929 kmem_free(svp
, sizeof (*svp
));
931 kmem_free(jvp
, sizeof (*jvp
));
936 * Get the rootvp associated with fsp->hsfs_vol
946 ASSERT(pathsize
== strlen(fsp
->hsfs_fsmnt
) + 1);
949 * If the root directory does not appear to be
950 * valid, use what it points to as "." instead.
951 * Some Defense Mapping Agency disks are non-conformant
954 if (!hsfs_valid_dir(&fsp
->hsfs_vol
.root_dir
)) {
955 hs_log_bogus_disk_warning(fsp
, HSFS_ERR_BAD_ROOT_DIR
, 0);
956 if (hs_remakenode(fsp
->hsfs_vol
.root_dir
.ext_lbn
,
957 0, vfsp
, &fsp
->hsfs_rootvp
)) {
958 hs_mounttab
= hs_mounttab
->hsfs_next
;
959 mutex_destroy(&fsp
->hsfs_free_lock
);
960 rw_destroy(&fsp
->hsfs_hash_lock
);
961 kmem_free(fsp
->hsfs_fsmnt
, pathsize
);
962 mutex_exit(&hs_mounttab_lock
);
966 fsp
->hsfs_rootvp
= hs_makenode(&fsp
->hsfs_vol
.root_dir
,
967 fsp
->hsfs_vol
.root_dir
.ext_lbn
, 0, vfsp
);
970 /* XXX - ignore the path table for now */
971 fsp
->hsfs_ptbl
= NULL
;
972 hp
= VTOH(fsp
->hsfs_rootvp
);
973 hp
->hs_ptbl_idx
= NULL
;
981 * Locate the Standard File Structure Volume Descriptor and
982 * parse it into an hs_volume structure.
984 * XXX - May someday want to look for Coded Character Set FSVD, too.
987 hs_findhsvol(struct hsfs
*fsp
, struct vnode
*vp
, struct hs_volume
*hvp
)
996 secno
= hs_findvoldesc(vp
->v_rdev
, HS_VOLDESC_SEC
);
997 secbp
= bread(vp
->v_rdev
, secno
* 4, HS_SECTOR_SIZE
);
998 error
= geterror(secbp
);
1001 cmn_err(CE_NOTE
, "hs_findhsvol: bread: error=(%d)", error
);
1006 volp
= (uchar_t
*)secbp
->b_un
.b_addr
;
1009 * To avoid that we read the whole medium in case that someone prepares
1010 * a malicious "fs image", we read at most 32 blocks.
1012 for (n
= 0; n
< 32 &&
1013 HSV_DESC_TYPE(volp
) != VD_EOV
; n
++) {
1014 for (i
= 0; i
< HSV_ID_STRLEN
; i
++)
1015 if (HSV_STD_ID(volp
)[i
] != HSV_ID_STRING
[i
])
1017 if (HSV_STD_VER(volp
) != HSV_ID_VER
)
1019 switch (HSV_DESC_TYPE(volp
)) {
1021 /* Standard File Structure */
1022 fsp
->hsfs_vol_type
= HS_VOL_TYPE_HS
;
1023 error
= hs_parsehsvol(fsp
, volp
, hvp
);
1028 /* Coded Character File Structure */
1036 secbp
= bread(vp
->v_rdev
, secno
* 4, HS_SECTOR_SIZE
);
1038 error
= geterror(secbp
);
1041 cmn_err(CE_NOTE
, "hs_findhsvol: bread: error=(%d)",
1047 volp
= (uchar_t
*)secbp
->b_un
.b_addr
;
1057 * Parse the Standard File Structure Volume Descriptor into
1058 * an hs_volume structure. We can't just bcopy it into the
1059 * structure because of byte-ordering problems.
1063 hs_parsehsvol(struct hsfs
*fsp
, uchar_t
*volp
, struct hs_volume
*hvp
)
1065 hvp
->vol_size
= HSV_VOL_SIZE(volp
);
1066 hvp
->lbn_size
= HSV_BLK_SIZE(volp
);
1067 if (hvp
->lbn_size
== 0) {
1068 cmn_err(CE_NOTE
, "hs_parsehsvol: logical block size in the "
1072 hvp
->lbn_shift
= ffs((long)hvp
->lbn_size
) - 1;
1074 ffs((long)howmany(HS_SECTOR_SIZE
, (int)hvp
->lbn_size
)) - 1;
1075 hvp
->lbn_maxoffset
= hvp
->lbn_size
- 1;
1076 hs_parse_longdate(HSV_cre_date(volp
), &hvp
->cre_date
);
1077 hs_parse_longdate(HSV_mod_date(volp
), &hvp
->mod_date
);
1078 hvp
->file_struct_ver
= HSV_FILE_STRUCT_VER(volp
);
1079 hvp
->ptbl_len
= HSV_PTBL_SIZE(volp
);
1080 hvp
->vol_set_size
= (ushort_t
)HSV_SET_SIZE(volp
);
1081 hvp
->vol_set_seq
= (ushort_t
)HSV_SET_SEQ(volp
);
1082 #if defined(_LITTLE_ENDIAN)
1083 hvp
->ptbl_lbn
= HSV_PTBL_MAN_LS(volp
);
1085 hvp
->ptbl_lbn
= HSV_PTBL_MAN_MS(volp
);
1087 hs_copylabel(hvp
, HSV_VOL_ID(volp
), 0);
1090 * Make sure that lbn_size is a power of two and otherwise valid.
1092 if (hvp
->lbn_size
& ~(1 << hvp
->lbn_shift
)) {
1094 "hsfs: %d-byte logical block size not supported",
1098 return (hs_parsedir(fsp
, HSV_ROOT_DIR(volp
), &hvp
->root_dir
,
1099 NULL
, NULL
, HDE_ROOT_DIR_REC_SIZE
));
1105 * Locate the Primary Volume Descriptor
1106 * parse it into an hs_volume structure.
1108 * XXX - Partition not yet done
1110 * Except for fsp->hsfs_vol_type, no fsp member may be modified.
1111 * fsp->hsfs_vol is modified indirectly via the *hvp argument.
1114 hs_findisovol(struct hsfs
*fsp
, struct vnode
*vp
,
1115 struct hs_volume
*hvp
,
1116 struct hs_volume
*svp
,
1117 struct hs_volume
*jvp
)
1130 secno
= hs_findvoldesc(vp
->v_rdev
, ISO_VOLDESC_SEC
);
1131 secbp
= bread(vp
->v_rdev
, secno
* 4, ISO_SECTOR_SIZE
);
1132 error
= geterror(secbp
);
1135 cmn_err(CE_NOTE
, "hs_findisovol: bread: error=(%d)", error
);
1140 volp
= (uchar_t
*)secbp
->b_un
.b_addr
;
1143 * To avoid that we read the whole medium in case that someone prepares
1144 * a malicious "fs image", we read at most 32 blocks.
1146 for (n
= 0; n
< 32 && ISO_DESC_TYPE(volp
) != ISO_VD_EOV
; n
++) {
1147 for (i
= 0; i
< ISO_ID_STRLEN
; i
++)
1148 if (ISO_STD_ID(volp
)[i
] != ISO_ID_STRING
[i
])
1150 switch (ISO_DESC_TYPE(volp
)) {
1152 /* Standard File Structure */
1153 if (ISO_STD_VER(volp
) != ISO_ID_VER
)
1155 if (foundpvd
!= 1) {
1156 fsp
->hsfs_vol_type
= HS_VOL_TYPE_ISO
;
1157 if (error
= hs_parseisovol(fsp
, volp
, hvp
)) {
1162 for (i
= 0; i
< ISO_SECTOR_SIZE
; i
++)
1167 /* Supplementary Volume Descriptor */
1168 if (ISO_STD_VER(volp
) == ISO_ID_VER2
&&
1170 fsp
->hsfs_vol_type
= HS_VOL_TYPE_ISO
;
1171 if (error
= hs_parseisovol(fsp
, volp
, svp
)) {
1177 if (hs_joliet_level(volp
) >= 1 && foundjvd
!= 1) {
1178 fsp
->hsfs_vol_type
= HS_VOL_TYPE_ISO
;
1179 if (error
= hs_parseisovol(fsp
, volp
, jvp
)) {
1189 /* currently cannot handle partition */
1196 secbp
= bread(vp
->v_rdev
, secno
* 4, HS_SECTOR_SIZE
);
1197 error
= geterror(secbp
);
1200 cmn_err(CE_NOTE
, "hs_findisovol: bread: error=(%d)",
1206 volp
= (uchar_t
*)secbp
->b_un
.b_addr
;
1208 for (n
= 0; n
< 16; n
++) {
1211 secbp
= bread(vp
->v_rdev
, secno
* 4, HS_SECTOR_SIZE
);
1212 error
= geterror(secbp
);
1215 cmn_err(CE_NOTE
, "hs_findisovol: bread: error=(%d)",
1222 * Check for the signature from mkisofs that grants that
1223 * the current filesystem allows to use the extent lbn as
1224 * inode number even in pure ISO9660 mode.
1226 volp
= (uchar_t
*)secbp
->b_un
.b_addr
;
1227 if (strncmp((char *)volp
, "MKI ", 4) == 0) {
1236 fsp
->hsfs_flags
|= HSFSMNT_INODE
;
1250 * Return 0 if no Joliet is found
1251 * else return Joliet Level 1..3
1254 hs_joliet_level(uchar_t
*volp
)
1256 if (ISO_std_ver(volp
)[0] == ISO_ID_VER
&&
1257 ISO_svd_esc(volp
)[0] == '%' &&
1258 ISO_svd_esc(volp
)[1] == '/') {
1260 switch (ISO_svd_esc(volp
)[2]) {
1276 * Parse the Primary Volume Descriptor into an hs_volume structure.
1280 hs_parseisovol(struct hsfs
*fsp
, uchar_t
*volp
, struct hs_volume
*hvp
)
1282 hvp
->vol_size
= ISO_VOL_SIZE(volp
);
1283 hvp
->lbn_size
= ISO_BLK_SIZE(volp
);
1284 if (hvp
->lbn_size
== 0) {
1285 cmn_err(CE_NOTE
, "hs_parseisovol: logical block size in the "
1289 hvp
->lbn_shift
= ffs((long)hvp
->lbn_size
) - 1;
1291 ffs((long)howmany(ISO_SECTOR_SIZE
, (int)hvp
->lbn_size
)) - 1;
1292 hvp
->lbn_maxoffset
= hvp
->lbn_size
- 1;
1293 hs_parse_longdate(ISO_cre_date(volp
), &hvp
->cre_date
);
1294 hs_parse_longdate(ISO_mod_date(volp
), &hvp
->mod_date
);
1295 hvp
->file_struct_ver
= ISO_FILE_STRUCT_VER(volp
);
1296 hvp
->ptbl_len
= ISO_PTBL_SIZE(volp
);
1297 hvp
->vol_set_size
= (ushort_t
)ISO_SET_SIZE(volp
);
1298 hvp
->vol_set_seq
= (ushort_t
)ISO_SET_SEQ(volp
);
1299 #if defined(_LITTLE_ENDIAN)
1300 hvp
->ptbl_lbn
= ISO_PTBL_MAN_LS(volp
);
1302 hvp
->ptbl_lbn
= ISO_PTBL_MAN_MS(volp
);
1304 hs_copylabel(hvp
, ISO_VOL_ID(volp
), hs_joliet_level(volp
) >= 1);
1307 * Make sure that lbn_size is a power of two and otherwise valid.
1309 if (hvp
->lbn_size
& ~(1 << hvp
->lbn_shift
)) {
1311 "hsfs: %d-byte logical block size not supported",
1315 return (hs_parsedir(fsp
, ISO_ROOT_DIR(volp
), &hvp
->root_dir
,
1316 NULL
, NULL
, IDE_ROOT_DIR_REC_SIZE
));
1320 * Common code for mount and umount.
1321 * Check that the user's argument is a reasonable
1322 * thing on which to mount, and return the device number if so.
1325 hs_getmdev(struct vfs
*vfsp
, char *fspec
, int flags
, dev_t
*pdev
, mode_t
*mode
,
1329 struct vnode
*svp
= NULL
;
1330 struct vnode
*lvp
= NULL
;
1334 enum uio_seg fromspace
= (flags
& MS_SYSSPACE
) ?
1335 UIO_SYSSPACE
: UIO_USERSPACE
;
1338 * Look up the device/file to be mounted.
1340 error
= lookupname(fspec
, fromspace
, FOLLOW
, NULLVPP
, &svp
);
1342 if (error
== ENOENT
)
1347 error
= vfs_get_lofi(vfsp
, &lvp
);
1350 if (error
== ENOENT
)
1353 } else if (error
== 0) {
1358 if (bvp
->v_type
!= VBLK
) {
1363 if ((error
= secpolicy_spec_open(cr
, bvp
, FREAD
)) != 0)
1368 * Can we read from the device/file ?
1370 if ((error
= fop_access(svp
, VREAD
, 0, cr
, NULL
)) != 0)
1373 vap
.va_mask
= AT_MODE
; /* get protection mode */
1374 (void) fop_getattr(bvp
, &vap
, 0, CRED(), NULL
);
1375 *mode
= vap
.va_mode
;
1377 dev
= *pdev
= bvp
->v_rdev
;
1382 * Ensure that this device isn't already mounted,
1383 * unless this is a REMOUNT request or we are told to suppress
1386 if ((flags
& MS_NOCHECK
) == 0) {
1387 if (vfs_devmounting(dev
, vfsp
))
1389 if (vfs_devismounted(dev
) && !(flags
& MS_REMOUNT
))
1393 if (getmajor(*pdev
) >= devcnt
) {
1408 hs_copylabel(struct hs_volume
*hvp
, unsigned char *label
, int isjoliet
)
1410 char lbuf
[64]; /* hs_joliet_cp() creates 48 bytes at most */
1414 * hs_joliet_cp() will output 16..48 bytes.
1415 * We need to clear 'lbuf' to avoid junk chars past byte 15.
1417 bzero(lbuf
, sizeof (lbuf
));
1418 (void) hs_joliet_cp((char *)label
, lbuf
, 32);
1419 label
= (unsigned char *)lbuf
;
1421 /* cdrom volid is at most 32 bytes */
1422 bcopy(label
, hvp
->vol_id
, 32);
1423 hvp
->vol_id
[31] = '\0';
1427 * Mount root file system.
1428 * "why" is ROOT_INIT on initial call, ROOT_REMOUNT if called to
1429 * remount the root file system, and ROOT_UNMOUNT if called to
1430 * unmount the root (e.g., as part of a system shutdown).
1432 * XXX - this may be partially machine-dependent; it, along with the VFS_SWAPVP
1433 * operation, goes along with auto-configuration. A mechanism should be
1434 * provided by which machine-INdependent code in the kernel can say "get me the
1435 * right root file system" and "get me the right initial swap area", and have
1436 * that done in what may well be a machine-dependent fashion.
1437 * Unfortunately, it is also file-system-type dependent (NFS gets it via
1438 * bootparams calls, UFS gets it from various and sundry machine-dependent
1439 * mechanisms, as SPECFS does for swap).
1442 hsfs_mountroot(struct vfs
*vfsp
, enum whymountroot why
)
1446 struct hs_volume
*fvolp
;
1447 static int hsfsrootdone
= 0;
1451 if (why
== ROOT_INIT
) {
1454 rootdev
= getrootdev();
1455 if (rootdev
== (dev_t
)NODEV
)
1457 vfsp
->vfs_dev
= rootdev
;
1458 vfsp
->vfs_flag
|= VFS_RDONLY
;
1459 } else if (why
== ROOT_REMOUNT
) {
1460 cmn_err(CE_NOTE
, "hsfs_mountroot: ROOT_REMOUNT");
1462 } else if (why
== ROOT_UNMOUNT
) {
1465 error
= vfs_lock(vfsp
);
1467 cmn_err(CE_NOTE
, "hsfs_mountroot: couldn't get vfs_lock");
1471 error
= hs_mountfs(vfsp
, rootdev
, "/", mode
, 1, CRED(), 1);
1473 * XXX - assumes root device is not indirect, because we don't set
1474 * rootvp. Is rootvp used for anything? If so, make another arg
1485 if (why
== ROOT_INIT
)
1487 (vfsp
->vfs_flag
& VFS_RDONLY
) ? MS_RDONLY
: 0);
1489 fsp
= VFS_TO_HSFS(vfsp
);
1490 fvolp
= &fsp
->hsfs_vol
;
1492 if (fvolp
->cre_date
.tv_sec
== 0) {
1493 cmn_err(CE_NOTE
, "hsfs_mountroot: cre_date.tv_sec == 0");
1494 if (fvolp
->mod_date
.tv_sec
== 0) {
1496 "hsfs_mountroot: mod_date.tv_sec == 0");
1497 cmn_err(CE_NOTE
, "hsfs_mountroot: clkset(-1L)");
1500 clkset(fvolp
->mod_date
.tv_sec
);
1503 clkset(fvolp
->mod_date
.tv_sec
);
1505 #else /* HSFS_CLKSET */
1507 #endif /* HSFS_CLKSET */
1514 * Return the sector where the volume descriptor lives. This is
1515 * a fixed value for "normal" cd-rom's, but can change for
1516 * multisession cd's.
1518 * desc_sec is the same for high-sierra and iso 9660 formats, why
1519 * there are two different #defines used in the code for this is
1520 * beyond me. These are standards, cast in concrete, right?
1521 * To be general, however, this function supports passing in different
1525 hs_findvoldesc(dev_t rdev
, int desc_sec
)
1529 int rval
; /* ignored */
1531 #ifdef CDROMREADOFFSET
1533 * Issue the Read Offset ioctl directly to the
1534 * device. Ignore any errors and set starting
1535 * secno to the default, otherwise add the
1536 * VOLDESC sector number to the offset.
1538 error
= cdev_ioctl(rdev
, CDROMREADOFFSET
, (intptr_t)&secno
,
1539 FNATIVE
|FKIOCTL
|FREAD
, CRED(), &rval
);