Merge commit 'ea01a15a654b9e1c7b37d958f4d1911882ed7781'
[unleashed.git] / kernel / fs / hsfs / hsfs_vfsops.c
blob5133099339c574ab3aff2eab7cc5a7dfe8ff79ec
1 /*
2 * CDDL HEADER START
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]
19 * CDDL HEADER END
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>
38 #include <sys/kmem.h>
39 #include <sys/signal.h>
40 #include <sys/user.h>
41 #include <sys/proc.h>
42 #include <sys/disp.h>
43 #include <sys/buf.h>
44 #include <sys/pathname.h>
45 #include <sys/vfs.h>
46 #include <sys/vnode.h>
47 #include <sys/file.h>
48 #include <sys/uio.h>
49 #include <sys/conf.h>
50 #include <sys/policy.h>
52 #include <vm/page.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>
65 #include <sys/swap.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>
72 #include <sys/sdt.h>
75 * These are needed for the CDROMREADOFFSET Code
77 #include <sys/cdio.h>
78 #include <sys/sunddi.h>
80 #define HSFS_CLKSET
82 #include <sys/modctl.h>
85 * Options for mount.
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"
92 #define HOPT_RR "rr"
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),
130 hsfs_options
134 * Indicates whether to enable the I/O scheduling and readahead logic
135 * 1 - Enable, 0 - Do not Enable.
136 * Debugging purposes.
138 int do_schedio = 1;
139 static int hsfsfstype;
140 static int hsfsinit(int, char *);
142 static vfsdef_t vfw = {
143 VFSDEF_VERSION,
144 "hsfs",
145 hsfsinit,
146 /* We don't suppport remounting */
147 VSW_HASPROTO|VSW_STATS|VSW_CANLOFI|VSW_MOUNTDEV,
148 &hsfs_proto_opttbl
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);
164 _init(void)
166 return (mod_install(&modlinkage));
170 _fini(void)
172 int error;
174 error = mod_remove(&modlinkage);
176 DTRACE_PROBE1(mod_remove, int, error);
178 if (error)
179 return (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();
190 return (0);
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,
251 static int
252 hsfsinit(int fstype, char *name)
254 int error;
256 error = vfs_setfsops(fstype, &hsfs_vfsops);
257 if (error != 0) {
258 cmn_err(CE_WARN, "hsfsinit: bad fstyp");
259 return (error);
262 hsfsfstype = fstype;
263 mutex_init(&hs_mounttab_lock, NULL, MUTEX_DEFAULT, NULL);
264 hs_init_hsnode_cache();
265 hsched_init_caches();
266 return (0);
269 /*ARGSUSED*/
270 static int
271 hsfs_mount(struct vfs *vfsp, struct vnode *mvp,
272 struct mounta *uap, struct cred *cr)
274 int vnode_busy;
275 dev_t dev;
276 struct pathname dpn;
277 int error;
278 mode_t mode;
279 int flags; /* this will hold the mount specific data */
281 if ((error = secpolicy_fs_mount(cr, mvp, vfsp)) != 0)
282 return (error);
284 if (mvp->v_type != VDIR)
285 return (ENOTDIR);
287 /* mount option must be read only, else mount will be rejected */
288 if (!(uap->flags & MS_RDONLY))
289 return (EROFS);
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) {
301 return (EBUSY);
305 * Check for the options that actually affect things
306 * at our level.
308 flags = 0;
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);
324 if (error)
325 return (error);
327 error = hs_getmdev(vfsp, uap->spec, uap->flags, &dev, &mode, cr);
328 if (error != 0) {
329 pn_free(&dpn);
330 return (error);
334 * If the device is a tape, return error
336 if ((BDEVFLAG(dev) & D_TAPE) == D_TAPE) {
337 pn_free(&dpn);
338 return (ENOTBLK);
342 * Mount the filesystem.
344 error = hs_mountfs(vfsp, dev, dpn.pn_path, mode, flags, cr, 0);
345 pn_free(&dpn);
346 return (error);
349 /*ARGSUSED*/
350 static int
351 hsfs_unmount(
352 struct vfs *vfsp,
353 int flag,
354 struct cred *cr)
356 struct hsfs **tspp;
357 struct hsfs *fsp;
359 if (secpolicy_fs_unmount(cr, vfsp) != 0)
360 return (EPERM);
363 * forced unmount is not supported by this file system
364 * and thus, ENOTSUP is being returned.
366 if (flag & MS_FORCE)
367 return (ENOTSUP);
369 fsp = VFS_TO_HSFS(vfsp);
371 if (fsp->hsfs_rootvp->v_count != 1)
372 return (EBUSY);
374 /* destroy all old pages and hsnodes for this vfs */
375 if (hs_synchash(vfsp))
376 return (EBUSY);
378 mutex_enter(&hs_mounttab_lock);
379 for (tspp = &hs_mounttab; *tspp != NULL; tspp = &(*tspp)->hsfs_next) {
380 if (*tspp == fsp)
381 break;
383 if (*tspp == NULL) {
384 mutex_exit(&hs_mounttab_lock);
385 panic("hsfs_unmount: vfs not mounted?");
386 /*NOTREACHED*/
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));
415 return (0);
418 /*ARGSUSED*/
419 static int
420 hsfs_root(struct vfs *vfsp, struct vnode **vpp)
422 *vpp = (VFS_TO_HSFS(vfsp))->hsfs_rootvp;
423 VN_HOLD(*vpp);
424 return (0);
427 /*ARGSUSED*/
428 static int
429 hsfs_statvfs(struct vfs *vfsp, struct statvfs64 *sbp)
431 struct hsfs *fsp;
432 dev32_t d32;
434 fsp = VFS_TO_HSFS(vfsp);
435 if (fsp->hsfs_magic != HSFS_MAGIC)
436 return (EINVAL);
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);
448 sbp->f_fsid = d32;
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);
454 return (0);
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.
466 static int
467 hsfs_vget(struct vfs *vfsp, struct vnode **vpp, struct fid *fidp)
469 struct hsfid *fid;
470 struct hsfs *fsp;
471 ino64_t nodeid;
472 int error;
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,
496 vfsp, vpp);
497 return (error);
499 rw_exit(&fsp->hsfs_hash_lock);
500 return (0);
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.
511 static int
512 compute_cdrom_id(struct hsfs *fsp, vnode_t *devvp)
514 uint_t secno;
515 struct hs_volume *hsvp = &fsp->hsfs_vol;
516 struct buf *bp;
517 int error;
518 int fsid;
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;
532 int i;
534 fsid = 0;
536 for (i = 0; i < CHECKSUM_SIZE / sizeof (int); i++)
537 fsid ^= ibuf[ i ];
538 } else {
540 * Fallback - use creation date
542 fsid = hsvp->cre_date.tv_sec;
545 brelse(bp);
547 return (fsid);
551 /*ARGSUSED*/
552 static int
553 hs_mountfs(
554 struct vfs *vfsp,
555 dev_t dev,
556 char *path,
557 mode_t mode,
558 int mount_flags,
559 struct cred *cr,
560 int isroot)
562 struct vnode *devvp;
563 struct hsfs *tsp;
564 struct hsfs *fsp = NULL;
565 struct vattr vap;
566 struct hsnode *hp;
567 int error;
568 struct timeval tv;
569 int fsid;
570 int use_rrip;
571 int use_vers2;
572 int use_joliet;
573 int has_rrip = 0;
574 int has_vers2 = 0;
575 int has_joliet = 0;
576 int force_rrip_off;
577 int force_vers2_off;
578 int force_joliet_off;
579 size_t pathbufsz = strlen(path) + 1;
580 int redo_rootvp;
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;
605 * Open the device
607 devvp = makespecvp(dev, VBLK);
608 ASSERT(devvp != 0);
611 * Open the target device (file) for read only.
613 if (error = fop_open(&devvp, FREAD, cr, NULL)) {
614 VN_RELE(devvp);
615 return (error);
619 * Refuse to go any further if this
620 * device is being used for swapping
622 if (IS_SWAPVP(common_specvp(devvp))) {
623 error = EBUSY;
624 goto cleanup;
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");
630 goto cleanup;
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) {
639 error = ENXIO;
640 goto cleanup;
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);
675 if (error)
676 goto cleanup;
678 DTRACE_PROBE4(findvol,
679 struct hsfs *, fsp,
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) {
697 uniqtime(&tv);
698 fsid = tv.tv_sec;
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]) {
702 uniqtime(&tv);
703 fsid = tv.tv_sec;
704 break;
708 fsp->hsfs_next = hs_mounttab;
709 hs_mounttab = fsp;
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;
720 vfsp->vfs_dev = dev;
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);
728 error = EINVAL;
729 goto cleanup;
731 DTRACE_PROBE1(rootvp, struct hsfs *, fsp);
734 * Attempt to discover a RR extension.
736 if (use_rrip) {
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,
752 struct hsfs *, fsp,
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.
776 redo_rootvp = 0;
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;
784 redo_rootvp = 1;
785 has_joliet = 0;
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;
791 redo_rootvp = 1;
792 has_vers2 = 0;
796 if (redo_rootvp) {
798 * Make sure not to use Rock Ridge.
800 UNSET_IMPL_BIT(fsp, RRIP_BIT);
801 UNSET_SUSP_BIT(fsp);
802 has_rrip = 0;
804 if (!hs_getrootvp(vfsp, fsp, pathbufsz)) {
805 DTRACE_PROBE1(rootvp__failed, struct hsfs *, fsp);
806 error = EINVAL;
807 goto cleanup;
809 DTRACE_PROBE1(rootvp, struct hsfs *, fsp);
811 if (IS_RRIP_IMPLEMENTED(fsp)) {
812 has_vers2 = 0;
813 has_joliet = 0;
815 if (force_vers2_off)
816 has_vers2 = 0;
817 if (force_joliet_off)
818 has_joliet = 0;
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 */
828 if (isroot) {
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) {
848 case HS_VOL_TYPE_HS:
849 case HS_VOL_TYPE_ISO:
850 default:
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);
860 break;
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);
873 break;
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 */
883 else
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);
889 break;
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
900 if (do_schedio) {
901 fsp->hqueue = kmem_alloc(sizeof (struct hsfs_queue), KM_SLEEP);
902 hsched_init(fsp, fsid, &modlinkage);
906 * Setup kstats
908 hsfs_init_kstats(fsp, fsid);
910 DTRACE_PROBE1(mount__done, struct hsfs *, fsp);
913 * set the magic word
915 fsp->hsfs_magic = HSFS_MAGIC;
916 mutex_exit(&hs_mounttab_lock);
918 kmem_free(svp, sizeof (*svp));
919 kmem_free(jvp, sizeof (*jvp));
921 return (0);
923 cleanup:
924 (void) fop_close(devvp, FREAD, 1, 0, cr, NULL);
925 VN_RELE(devvp);
926 if (fsp)
927 kmem_free(fsp, sizeof (*fsp));
928 if (svp)
929 kmem_free(svp, sizeof (*svp));
930 if (jvp)
931 kmem_free(jvp, sizeof (*jvp));
932 return (error);
936 * Get the rootvp associated with fsp->hsfs_vol
938 static int
939 hs_getrootvp(
940 struct vfs *vfsp,
941 struct hsfs *fsp,
942 size_t pathsize)
944 struct hsnode *hp;
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
952 * in this way.
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);
963 return (0);
965 } else {
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;
975 return (1);
979 * hs_findhsvol()
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.
986 static int
987 hs_findhsvol(struct hsfs *fsp, struct vnode *vp, struct hs_volume *hvp)
989 struct buf *secbp;
990 int i;
991 int n;
992 uchar_t *volp;
993 int error;
994 uint_t secno;
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);
1000 if (error != 0) {
1001 cmn_err(CE_NOTE, "hs_findhsvol: bread: error=(%d)", error);
1002 brelse(secbp);
1003 return (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])
1016 goto cantfind;
1017 if (HSV_STD_VER(volp) != HSV_ID_VER)
1018 goto cantfind;
1019 switch (HSV_DESC_TYPE(volp)) {
1020 case VD_SFS:
1021 /* Standard File Structure */
1022 fsp->hsfs_vol_type = HS_VOL_TYPE_HS;
1023 error = hs_parsehsvol(fsp, volp, hvp);
1024 brelse(secbp);
1025 return (error);
1027 case VD_CCFS:
1028 /* Coded Character File Structure */
1029 case VD_BOOT:
1030 case VD_UNSPEC:
1031 case VD_EOV:
1032 break;
1034 brelse(secbp);
1035 ++secno;
1036 secbp = bread(vp->v_rdev, secno * 4, HS_SECTOR_SIZE);
1038 error = geterror(secbp);
1040 if (error != 0) {
1041 cmn_err(CE_NOTE, "hs_findhsvol: bread: error=(%d)",
1042 error);
1043 brelse(secbp);
1044 return (error);
1047 volp = (uchar_t *)secbp->b_un.b_addr;
1049 cantfind:
1050 brelse(secbp);
1051 return (EINVAL);
1055 * hs_parsehsvol
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.
1062 static int
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 "
1069 "SFSVD is zero");
1070 return (EINVAL);
1072 hvp->lbn_shift = ffs((long)hvp->lbn_size) - 1;
1073 hvp->lbn_secshift =
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);
1084 #else
1085 hvp->ptbl_lbn = HSV_PTBL_MAN_MS(volp);
1086 #endif
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)) {
1093 cmn_err(CE_NOTE,
1094 "hsfs: %d-byte logical block size not supported",
1095 hvp->lbn_size);
1096 return (EINVAL);
1098 return (hs_parsedir(fsp, HSV_ROOT_DIR(volp), &hvp->root_dir,
1099 NULL, NULL, HDE_ROOT_DIR_REC_SIZE));
1103 * hs_findisovol()
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.
1113 static int
1114 hs_findisovol(struct hsfs *fsp, struct vnode *vp,
1115 struct hs_volume *hvp,
1116 struct hs_volume *svp,
1117 struct hs_volume *jvp)
1119 struct buf *secbp;
1120 int i;
1121 int n;
1122 uchar_t *volp;
1123 int error;
1124 uint_t secno;
1125 int foundpvd = 0;
1126 int foundsvd = 0;
1127 int foundjvd = 0;
1128 int pvd_sum = 0;
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);
1134 if (error != 0) {
1135 cmn_err(CE_NOTE, "hs_findisovol: bread: error=(%d)", error);
1136 brelse(secbp);
1137 return (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])
1149 goto cantfind;
1150 switch (ISO_DESC_TYPE(volp)) {
1151 case ISO_VD_PVD:
1152 /* Standard File Structure */
1153 if (ISO_STD_VER(volp) != ISO_ID_VER)
1154 goto cantfind;
1155 if (foundpvd != 1) {
1156 fsp->hsfs_vol_type = HS_VOL_TYPE_ISO;
1157 if (error = hs_parseisovol(fsp, volp, hvp)) {
1158 brelse(secbp);
1159 return (error);
1161 foundpvd = 1;
1162 for (i = 0; i < ISO_SECTOR_SIZE; i++)
1163 pvd_sum += volp[i];
1165 break;
1166 case ISO_VD_SVD:
1167 /* Supplementary Volume Descriptor */
1168 if (ISO_STD_VER(volp) == ISO_ID_VER2 &&
1169 foundsvd != 1) {
1170 fsp->hsfs_vol_type = HS_VOL_TYPE_ISO;
1171 if (error = hs_parseisovol(fsp, volp, svp)) {
1172 brelse(secbp);
1173 return (error);
1175 foundsvd = 1;
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)) {
1180 brelse(secbp);
1181 return (error);
1183 foundjvd = 1;
1185 break;
1186 case ISO_VD_BOOT:
1187 break;
1188 case ISO_VD_VPD:
1189 /* currently cannot handle partition */
1190 break;
1191 case VD_EOV:
1192 break;
1194 brelse(secbp);
1195 ++secno;
1196 secbp = bread(vp->v_rdev, secno * 4, HS_SECTOR_SIZE);
1197 error = geterror(secbp);
1199 if (error != 0) {
1200 cmn_err(CE_NOTE, "hs_findisovol: bread: error=(%d)",
1201 error);
1202 brelse(secbp);
1203 return (error);
1206 volp = (uchar_t *)secbp->b_un.b_addr;
1208 for (n = 0; n < 16; n++) {
1209 brelse(secbp);
1210 ++secno;
1211 secbp = bread(vp->v_rdev, secno * 4, HS_SECTOR_SIZE);
1212 error = geterror(secbp);
1214 if (error != 0) {
1215 cmn_err(CE_NOTE, "hs_findisovol: bread: error=(%d)",
1216 error);
1217 brelse(secbp);
1218 return (error);
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) {
1228 int sum;
1230 sum = volp[2045];
1231 sum *= 256;
1232 sum += volp[2046];
1233 sum *= 256;
1234 sum += volp[2047];
1235 if (sum == pvd_sum)
1236 fsp->hsfs_flags |= HSFSMNT_INODE;
1237 break;
1240 if (foundpvd) {
1241 brelse(secbp);
1242 return (0);
1244 cantfind:
1245 brelse(secbp);
1246 return (EINVAL);
1250 * Return 0 if no Joliet is found
1251 * else return Joliet Level 1..3
1253 static int
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]) {
1262 case '@':
1263 return (1);
1264 case 'C':
1265 return (2);
1266 case 'E':
1267 return (3);
1270 return (0);
1274 * hs_parseisovol
1276 * Parse the Primary Volume Descriptor into an hs_volume structure.
1279 static int
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 "
1286 "PVD is zero");
1287 return (EINVAL);
1289 hvp->lbn_shift = ffs((long)hvp->lbn_size) - 1;
1290 hvp->lbn_secshift =
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);
1301 #else
1302 hvp->ptbl_lbn = ISO_PTBL_MAN_MS(volp);
1303 #endif
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)) {
1310 cmn_err(CE_NOTE,
1311 "hsfs: %d-byte logical block size not supported",
1312 hvp->lbn_size);
1313 return (EINVAL);
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.
1324 static int
1325 hs_getmdev(struct vfs *vfsp, char *fspec, int flags, dev_t *pdev, mode_t *mode,
1326 cred_t *cr)
1328 int error;
1329 struct vnode *svp = NULL;
1330 struct vnode *lvp = NULL;
1331 struct vnode *bvp;
1332 struct vattr vap;
1333 dev_t dev;
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);
1341 if (error) {
1342 if (error == ENOENT)
1343 error = ENODEV;
1344 goto out;
1347 error = vfs_get_lofi(vfsp, &lvp);
1349 if (error > 0) {
1350 if (error == ENOENT)
1351 error = ENODEV;
1352 goto out;
1353 } else if (error == 0) {
1354 bvp = lvp;
1355 } else {
1356 bvp = svp;
1358 if (bvp->v_type != VBLK) {
1359 error = ENOTBLK;
1360 goto out;
1363 if ((error = secpolicy_spec_open(cr, bvp, FREAD)) != 0)
1364 goto out;
1368 * Can we read from the device/file ?
1370 if ((error = fop_access(svp, VREAD, 0, cr, NULL)) != 0)
1371 goto out;
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;
1379 error = EBUSY;
1382 * Ensure that this device isn't already mounted,
1383 * unless this is a REMOUNT request or we are told to suppress
1384 * mount checks.
1386 if ((flags & MS_NOCHECK) == 0) {
1387 if (vfs_devmounting(dev, vfsp))
1388 goto out;
1389 if (vfs_devismounted(dev) && !(flags & MS_REMOUNT))
1390 goto out;
1393 if (getmajor(*pdev) >= devcnt) {
1394 error = ENXIO;
1395 goto out;
1398 error = 0;
1399 out:
1400 if (svp != NULL)
1401 VN_RELE(svp);
1402 if (lvp != NULL)
1403 VN_RELE(lvp);
1404 return (error);
1407 static void
1408 hs_copylabel(struct hs_volume *hvp, unsigned char *label, int isjoliet)
1410 char lbuf[64]; /* hs_joliet_cp() creates 48 bytes at most */
1412 if (isjoliet) {
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).
1441 static int
1442 hsfs_mountroot(struct vfs *vfsp, enum whymountroot why)
1444 int error;
1445 struct hsfs *fsp;
1446 struct hs_volume *fvolp;
1447 static int hsfsrootdone = 0;
1448 dev_t rootdev;
1449 mode_t mode = 0;
1451 if (why == ROOT_INIT) {
1452 if (hsfsrootdone++)
1453 return (EBUSY);
1454 rootdev = getrootdev();
1455 if (rootdev == (dev_t)NODEV)
1456 return (ENODEV);
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");
1461 return (0);
1462 } else if (why == ROOT_UNMOUNT) {
1463 return (0);
1465 error = vfs_lock(vfsp);
1466 if (error) {
1467 cmn_err(CE_NOTE, "hsfs_mountroot: couldn't get vfs_lock");
1468 return (error);
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
1475 * to mountfs.
1477 if (error) {
1478 vfs_unlock(vfsp);
1479 if (rootvp) {
1480 VN_RELE(rootvp);
1481 rootvp = NULL;
1483 return (error);
1485 if (why == ROOT_INIT)
1486 vfs_add(NULL, vfsp,
1487 (vfsp->vfs_flag & VFS_RDONLY) ? MS_RDONLY : 0);
1488 vfs_unlock(vfsp);
1489 fsp = VFS_TO_HSFS(vfsp);
1490 fvolp = &fsp->hsfs_vol;
1491 #ifdef HSFS_CLKSET
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) {
1495 cmn_err(CE_NOTE,
1496 "hsfs_mountroot: mod_date.tv_sec == 0");
1497 cmn_err(CE_NOTE, "hsfs_mountroot: clkset(-1L)");
1498 clkset(-1L);
1499 } else {
1500 clkset(fvolp->mod_date.tv_sec);
1502 } else {
1503 clkset(fvolp->mod_date.tv_sec);
1505 #else /* HSFS_CLKSET */
1506 clkset(-1L);
1507 #endif /* HSFS_CLKSET */
1508 return (0);
1512 * hs_findvoldesc()
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
1522 * values.
1524 static int
1525 hs_findvoldesc(dev_t rdev, int desc_sec)
1527 int secno;
1528 int error;
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);
1540 if (error) {
1541 secno = desc_sec;
1542 } else {
1543 secno += desc_sec;
1545 #else
1546 secno = desc_sec;
1547 #endif
1549 return (secno);