diff options
author | joerg <joerg@FreeBSD.org> | 1997-05-04 15:24:23 +0000 |
---|---|---|
committer | joerg <joerg@FreeBSD.org> | 1997-05-04 15:24:23 +0000 |
commit | 8cea5b917d62db9701a7fe2a45c9032aec48325d (patch) | |
tree | a2408a8a297df1fa5ba68bcc7ee4bc36c2fc2521 /sys/isofs | |
parent | 60343a746abd65c1fe9040ea648287d56be4b871 (diff) | |
download | FreeBSD-src-8cea5b917d62db9701a7fe2a45c9032aec48325d.zip FreeBSD-src-8cea5b917d62db9701a7fe2a45c9032aec48325d.tar.gz |
This mega-commit brings the following:
. It makes cd9660 root f/s working again.
. It makes CD9660 a new-style option.
. It adds support to mount an ISO9660 multi-session CD-ROM as the root
filesystem (the last session actually, but that's what is expected
behaviour).
Sigh. The CDIOREADTOCENTRYS did a copyout() of its own, and thus has
been unusable for me for this work. Too bad it didn't simply stuff
the max 100 entries into the struct ioc_read_toc_entry, but relied on
a user supplied data buffer instead. :-( I now had to reinvent the
wheel, and created a CDIOREADTOCENTRY ioctl command that can be used
in a kernel context.
While doing this, i noticed the following bogosities in existing CD-ROM
drivers:
wcd: This driver is likely to be totally bogus when someone tries
two succeeding CDIOREADTOCENTRYS (or now CDIOREADTOCENTRY)
commands with requesting MSF format, since it apparently
operates on an internal table.
scd: This driver apparently returns just a single TOC entry only for
the CDIOREADTOCENTRYS command.
I have only been able to test the CDIOREADTOCENTRY command with the
cd(4) driver. I hereby request the respective maintainers of the
other CD-ROM drivers to verify my code for their driver. When it
comes to merging this CD-ROM multisession stuff into RELENG_2_2 i will
only consider drivers where i've got a confirmation that it actually
works.
Diffstat (limited to 'sys/isofs')
-rw-r--r-- | sys/isofs/cd9660/cd9660_vfsops.c | 76 | ||||
-rw-r--r-- | sys/isofs/cd9660/iso.h | 4 |
2 files changed, 61 insertions, 19 deletions
diff --git a/sys/isofs/cd9660/cd9660_vfsops.c b/sys/isofs/cd9660/cd9660_vfsops.c index a875434..a61ccfc 100644 --- a/sys/isofs/cd9660/cd9660_vfsops.c +++ b/sys/isofs/cd9660/cd9660_vfsops.c @@ -36,7 +36,7 @@ * SUCH DAMAGE. * * @(#)cd9660_vfsops.c 8.18 (Berkeley) 5/22/95 - * $Id: cd9660_vfsops.c,v 1.23 1997/04/29 15:52:53 joerg Exp $ + * $Id: cd9660_vfsops.c,v 1.24 1997/04/29 17:11:51 joerg Exp $ */ #include <sys/param.h> @@ -48,6 +48,8 @@ #include <miscfs/specfs/specdev.h> #include <sys/mount.h> #include <sys/buf.h> +#include <sys/cdio.h> +#include <sys/conf.h> #include <sys/fcntl.h> #include <sys/errno.h> #include <sys/malloc.h> @@ -94,40 +96,77 @@ VFS_SET(cd9660_vfsops, cd9660, MOUNT_CD9660, VFCF_READONLY); * Called by vfs_mountroot when iso is going to be mounted as root. */ +static int iso_get_ssector __P((dev_t dev, struct proc *p)); static int iso_mountfs __P((struct vnode *devvp, struct mount *mp, struct proc *p, struct iso_args *argp)); +static int iso_mountroot __P((struct mount *mp, struct proc *p)); -int -cd9660_mountroot() +/* + * Try to find the start of the last data track on this CD-ROM. This + * is used to mount the last session of a multi-session CD. Bail out + * and return 0 if we fail, this is always a safe bet. + */ +static int +iso_get_ssector(dev, p) + dev_t dev; + struct proc *p; { + struct ioc_toc_header h; + struct ioc_read_toc_single_entry t; + int i; + struct bdevsw *bd; + d_ioctl_t *ioctlp; + + bd = bdevsw[major(dev)]; + ioctlp = bd->d_ioctl; + if (ioctlp == NULL) + return 0; + + if (ioctlp(dev, CDIOREADTOCHEADER, (caddr_t)&h, FREAD, p) == -1) + return 0; + + for (i = h.ending_track; i >= 0; i--) { + t.address_format = CD_LBA_FORMAT; + t.track = i; + if (ioctlp(dev, CDIOREADTOCENTRY, (caddr_t)&t, FREAD, p) == -1) + return 0; + if ((t.entry.control & 4) != 0) + /* found a data track */ + break; + } + + if (i < 0) + return 0; + + return ntohl(t.entry.addr.lba); +} + +static int +iso_mountroot(mp, p) struct mount *mp; - struct proc *p = curproc; /* XXX */ + struct proc *p; +{ struct iso_args args; int error; - + /* * Get vnode for rootdev. */ if ((error = bdevvp(swapdev, &swapdev_vp)) || (error = bdevvp(rootdev, &rootvp))) { - printf("cd9660_mountroot: can't setup bdevvp's"); + printf("iso_mountroot: can't setup bdevvp's"); return (error); } - if (error = vfs_rootmountalloc("cd9660", "root_device", &mp)) - return (error); args.flags = ISOFSMNT_ROOT; - if (error = iso_mountfs(rootvp, mp, p, &args)) { - mp->mnt_vfc->vfc_refcount--; - vfs_unbusy(mp, p); - free(mp, M_MOUNT); + args.ssector = iso_get_ssector(rootdev, p); + if (bootverbose) + printf("iso_mountroot(): using session at block %d\n", + args.ssector); + if (error = iso_mountfs(rootvp, mp, p, &args)) return (error); - } - simple_lock(&mountlist_slock); - CIRCLEQ_INSERT_TAIL(&mountlist, mp, mnt_list); - simple_unlock(&mountlist_slock); + (void)cd9660_statfs(mp, &mp->mnt_stat, p); - vfs_unbusy(mp, p); return (0); } @@ -150,6 +189,9 @@ cd9660_mount(mp, path, data, ndp, p) int error; struct iso_mnt *imp = 0; + if ((mp->mnt_flag & MNT_ROOTFS) != 0) + return (iso_mountroot(mp, p)); + if ((error = copyin(data, (caddr_t)&args, sizeof (struct iso_args)))) return (error); diff --git a/sys/isofs/cd9660/iso.h b/sys/isofs/cd9660/iso.h index d7fc579..2437534 100644 --- a/sys/isofs/cd9660/iso.h +++ b/sys/isofs/cd9660/iso.h @@ -36,7 +36,7 @@ * SUCH DAMAGE. * * @(#)iso.h 8.6 (Berkeley) 5/10/95 - * $Id$ + * $Id: iso.h,v 1.13 1997/02/22 09:38:52 peter Exp $ */ #define ISODCL(from, to) (to - from + 1) @@ -215,7 +215,7 @@ int cd9660_init __P((struct vfsconf *)); #define cd9660_sysctl ((int (*) __P((int *, u_int, void *, size_t *, void *, \ size_t, struct proc *)))eopnotsupp) -int cd9660_mountroot __P((void)); +int cd9660_mountroot __P((int ssector)); extern vop_t **cd9660_vnodeop_p; extern vop_t **cd9660_specop_p; |