summaryrefslogtreecommitdiffstats
path: root/sys/fs/cd9660/cd9660_vfsops.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/fs/cd9660/cd9660_vfsops.c')
-rw-r--r--sys/fs/cd9660/cd9660_vfsops.c448
1 files changed, 281 insertions, 167 deletions
diff --git a/sys/fs/cd9660/cd9660_vfsops.c b/sys/fs/cd9660/cd9660_vfsops.c
index 752a7b4..15eade4 100644
--- a/sys/fs/cd9660/cd9660_vfsops.c
+++ b/sys/fs/cd9660/cd9660_vfsops.c
@@ -35,7 +35,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)cd9660_vfsops.c 8.3 (Berkeley) 1/31/94
+ * @(#)cd9660_vfsops.c 8.18 (Berkeley) 5/22/95
* $FreeBSD$
*/
@@ -52,10 +52,12 @@
#include <sys/ioctl.h>
#include <sys/errno.h>
#include <sys/malloc.h>
+#include <sys/stat.h>
#include <isofs/cd9660/iso.h>
-#include <isofs/cd9660/cd9660_node.h>
#include <isofs/cd9660/iso_rrip.h>
+#include <isofs/cd9660/cd9660_node.h>
+#include <isofs/cd9660/cd9660_mount.h>
static int cd9660_mount __P((struct mount *,
@@ -84,17 +86,14 @@ static struct vfsops cd9660_vfsops = {
cd9660_vget,
cd9660_fhtovp,
cd9660_vptofh,
- cd9660_init,
+ cd9660_init
};
VFS_SET(cd9660_vfsops, cd9660, MOUNT_CD9660, VFCF_READONLY);
/*
* Called by vfs_mountroot when iso is going to be mounted as root.
- *
- * Name is updated by mount(8) after booting.
*/
-#define ROOTNAME "root_device"
static int iso_mountfs __P((struct vnode *devvp, struct mount *mp,
struct proc *p, struct iso_args *argp));
@@ -102,55 +101,38 @@ static int iso_mountfs __P((struct vnode *devvp, struct mount *mp,
int
cd9660_mountroot()
{
- register struct mount *mp;
+ struct mount *mp;
struct proc *p = curproc; /* XXX */
- struct iso_mnt *imp;
- u_int size;
- int error;
struct iso_args args;
-
+ int error;
+
/*
* Get vnode for rootdev.
*/
- if (bdevvp(rootdev, &rootvp))
- panic("cd9660_mountroot: can't setup bdevvp for rootdev");
-
- mp = malloc((u_long)sizeof(struct mount), M_MOUNT, M_WAITOK);
- bzero((char *)mp, (u_long)sizeof(struct mount));
- mp->mnt_op = &cd9660_vfsops;
- mp->mnt_flag = MNT_RDONLY;
- args.flags = ISOFSMNT_ROOT;
- if ((error = iso_mountfs(rootvp, mp, p, &args))) {
- free(mp, M_MOUNT);
+ if ((error = bdevvp(swapdev, &swapdev_vp)) ||
+ (error = bdevvp(rootdev, &rootvp))) {
+ printf("cd9660_mountroot: can't setup bdevvp's");
return (error);
}
- if ((error = vfs_lock(mp))) {
- (void)cd9660_unmount(mp, 0, p);
+
+ 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);
return (error);
}
+ simple_lock(&mountlist_slock);
CIRCLEQ_INSERT_TAIL(&mountlist, mp, mnt_list);
- mp->mnt_flag |= MNT_ROOTFS;
- mp->mnt_vnodecovered = NULLVP;
- imp = VFSTOISOFS(mp);
- bzero(imp->im_fsmnt, sizeof(imp->im_fsmnt));
- imp->im_fsmnt[0] = '/';
- bcopy((caddr_t)imp->im_fsmnt, (caddr_t)mp->mnt_stat.f_mntonname,
- MNAMELEN);
- (void) copystr(ROOTNAME, mp->mnt_stat.f_mntfromname, MNAMELEN - 1,
- &size);
- bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
- (void) cd9660_statfs(mp, &mp->mnt_stat, p);
- vfs_unlock(mp);
+ simple_unlock(&mountlist_slock);
+ (void)cd9660_statfs(mp, &mp->mnt_stat, p);
+ vfs_unbusy(mp, p);
return (0);
}
/*
- * Flag to allow forcible unmounting.
- */
-static int iso_doforce = 1;
-
-/*
* VFS Operations.
*
* mount system call
@@ -214,10 +196,8 @@ cd9660_mount(mp, path, data, ndp, p)
return error;
}
imp = VFSTOISOFS(mp);
- (void) copyinstr(path, imp->im_fsmnt, sizeof(imp->im_fsmnt)-1, &size);
- bzero(imp->im_fsmnt + size, sizeof(imp->im_fsmnt) - size);
- bcopy((caddr_t)imp->im_fsmnt, (caddr_t)mp->mnt_stat.f_mntonname,
- MNAMELEN);
+ (void) copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN - 1, &size);
+ bzero(mp->mnt_stat.f_mntonname + size, MNAMELEN - size);
(void) copyinstr(args.fspec, mp->mnt_stat.f_mntfromname, MNAMELEN - 1,
&size);
bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
@@ -277,11 +257,11 @@ iso_mountfs(devvp, mp, p, argp)
iso_bsize = ISO_DEFAULT_BLOCK_SIZE;
for (iso_blknum = 16; iso_blknum < 100; iso_blknum++) {
- if ((error = bread (devvp, btodb(iso_blknum * iso_bsize),
- iso_bsize, NOCRED, &bp)))
+ if (error = bread(devvp, iso_blknum * btodb(iso_bsize),
+ iso_bsize, NOCRED, &bp))
goto out;
-
- vdp = (struct iso_volume_descriptor *)bp->b_un.b_addr;
+
+ vdp = (struct iso_volume_descriptor *)bp->b_data;
if (bcmp (vdp->id, ISO_STANDARD_ID, sizeof vdp->id) != 0) {
if (bcmp (vdp->id_sierra, ISO_SIERRA_ID,
sizeof vdp->id) != 0) {
@@ -347,7 +327,7 @@ iso_mountfs(devvp, mp, p, argp)
mp->mnt_data = (qaddr_t)isomp;
mp->mnt_stat.f_fsid.val[0] = (long)dev;
- mp->mnt_stat.f_fsid.val[1] = MOUNT_CD9660;
+ mp->mnt_stat.f_fsid.val[1] = mp->mnt_vfc->vfc_typenum;
mp->mnt_maxsymlinklen = 0;
mp->mnt_flag |= MNT_LOCAL;
isomp->im_mountp = mp;
@@ -358,14 +338,14 @@ iso_mountfs(devvp, mp, p, argp)
/* Check the Rock Ridge Extention support */
if (!(argp->flags & ISOFSMNT_NORRIP)) {
- if ((error = bread (isomp->im_devvp,
- (isomp->root_extent + isonum_711(rootp->ext_attr_length))
- * isomp->logical_block_size / DEV_BSIZE,
- isomp->logical_block_size,NOCRED,&bp)))
+ if (error = bread(isomp->im_devvp,
+ (isomp->root_extent + isonum_711(rootp->ext_attr_length)) <<
+ (isomp->im_bshift - DEV_BSHIFT),
+ isomp->logical_block_size, NOCRED, &bp))
goto out;
-
- rootp = (struct iso_directory_record *)bp->b_un.b_addr;
-
+
+ rootp = (struct iso_directory_record *)bp->b_data;
+
if ((isomp->rr_skip = cd9660_rrip_offset(rootp,isomp)) < 0) {
argp->flags |= ISOFSMNT_NORRIP;
} else {
@@ -436,12 +416,9 @@ cd9660_unmount(mp, mntflags, p)
{
register struct iso_mnt *isomp;
int error, flags = 0;
-
- if (mntflags & MNT_FORCE) {
- if (!iso_doforce)
- return (EINVAL);
+
+ if (mntflags & MNT_FORCE)
flags |= FORCECLOSE;
- }
#if 0
mntflushbuf(mp, 0);
if (mntinvalbuf(mp))
@@ -474,33 +451,17 @@ cd9660_root(mp, vpp)
struct mount *mp;
struct vnode **vpp;
{
- register struct iso_node *ip;
- struct iso_node tip, *nip;
- struct vnode tvp;
- int error;
- struct iso_mnt *imp = VFSTOISOFS (mp);
- struct iso_directory_record *dp;
-
- tvp.v_mount = mp;
- tvp.v_data = &tip;
- ip = VTOI(&tvp);
- ip->i_vnode = &tvp;
- ip->i_dev = imp->im_dev;
- ip->i_diroff = 0;
- dp = (struct iso_directory_record *)imp->root;
- isodirino(&ip->i_number,dp,imp);
-
+ struct iso_mnt *imp = VFSTOISOFS(mp);
+ struct iso_directory_record *dp =
+ (struct iso_directory_record *)imp->root;
+ ino_t ino = isodirino(dp, imp);
+
/*
* With RRIP we must use the `.' entry of the root directory.
- * Simply tell iget, that it's a relocated directory.
+ * Simply tell vget, that it's a relocated directory.
*/
- error = iso_iget(ip,ip->i_number,
- imp->iso_ftype == ISO_FTYPE_RRIP,
- &nip,dp);
- if (error)
- return error;
- *vpp = ITOV(nip);
- return 0;
+ return (cd9660_vget_internal(mp, ino, vpp,
+ imp->iso_ftype == ISO_FTYPE_RRIP, dp));
}
/*
@@ -541,10 +502,8 @@ cd9660_statfs(mp, sbp, p)
sbp->f_files = 0; /* total files */
sbp->f_ffree = 0; /* free file nodes */
if (sbp != &mp->mnt_stat) {
- bcopy((caddr_t)mp->mnt_stat.f_mntonname,
- (caddr_t)&sbp->f_mntonname[0], MNAMELEN);
- bcopy((caddr_t)mp->mnt_stat.f_mntfromname,
- (caddr_t)&sbp->f_mntfromname[0], MNAMELEN);
+ bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN);
+ bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN);
}
/* Use the first spare for flags: */
sbp->f_spare[0] = isomp->im_flags;
@@ -563,21 +522,6 @@ cd9660_sync(mp, waitfor, cred, p)
}
/*
- * Flat namespace lookup.
- * Currently unsupported.
- */
-/* ARGSUSED */
-static int
-cd9660_vget(mp, ino, vpp)
- struct mount *mp;
- ino_t ino;
- struct vnode **vpp;
-{
-
- return (EOPNOTSUPP);
-}
-
-/*
* File handle to vnode
*
* Have to be really careful about stale file handles:
@@ -604,92 +548,262 @@ cd9660_fhtovp(mp, fhp, nam, vpp, exflagsp, credanonp)
int *exflagsp;
struct ucred **credanonp;
{
- struct vnode tvp;
- int error;
- int lbn, off;
- struct ifid *ifhp;
- struct iso_mnt *imp;
- struct buf *bp;
- struct iso_directory_record *dirp;
- struct iso_node tip, *ip, *nip;
- struct netcred *np;
-
- imp = VFSTOISOFS (mp);
- ifhp = (struct ifid *)fhp;
-
+ struct ifid *ifhp = (struct ifid *)fhp;
+ register struct iso_node *ip;
+ register struct netcred *np;
+ register struct iso_mnt *imp = VFSTOISOFS(mp);
+ struct vnode *nvp;
+ int error;
+
#ifdef ISOFS_DBG
printf("fhtovp: ino %d, start %ld\n",
ifhp->ifid_ino, ifhp->ifid_start);
#endif
-
+
+ /*
+ * Get the export permission structure for this <mp, client> tuple.
+ */
np = vfs_export_lookup(mp, &imp->im_export, nam);
if (np == NULL)
return (EACCES);
- lbn = iso_lblkno(imp, ifhp->ifid_ino);
- if (lbn >= imp->volume_space_size) {
- printf("fhtovp: lbn exceed volume space %d\n", lbn);
- return (ESTALE);
+ if (error = VFS_VGET(mp, ifhp->ifid_ino, &nvp)) {
+ *vpp = NULLVP;
+ return (error);
}
-
- off = iso_blkoff(imp, ifhp->ifid_ino);
- if (off + ISO_DIRECTORY_RECORD_SIZE > imp->logical_block_size) {
- printf("fhtovp: crosses block boundary %d\n",
- off + ISO_DIRECTORY_RECORD_SIZE);
+ ip = VTOI(nvp);
+ if (ip->inode.iso_mode == 0) {
+ vput(nvp);
+ *vpp = NULLVP;
return (ESTALE);
}
+ *vpp = nvp;
+ *exflagsp = np->netc_exflags;
+ *credanonp = &np->netc_anon;
+ return (0);
+}
- error = bread(imp->im_devvp, btodb(lbn * imp->logical_block_size),
- imp->logical_block_size, NOCRED, &bp);
- if (error) {
- printf("fhtovp: bread error %d\n",error);
- brelse(bp);
+int
+cd9660_vget(mp, ino, vpp)
+ struct mount *mp;
+ ino_t ino;
+ struct vnode **vpp;
+{
+
+ /*
+ * XXXX
+ * It would be nice if we didn't always set the `relocated' flag
+ * and force the extra read, but I don't want to think about fixing
+ * that right now.
+ */
+ return (cd9660_vget_internal(mp, ino, vpp,
+#if 0
+ VFSTOISOFS(mp)->iso_ftype == ISO_FTYPE_RRIP,
+#else
+ 0,
+#endif
+ (struct iso_directory_record *)0));
+}
+
+int
+cd9660_vget_internal(mp, ino, vpp, relocated, isodir)
+ struct mount *mp;
+ ino_t ino;
+ struct vnode **vpp;
+ int relocated;
+ struct iso_directory_record *isodir;
+{
+ struct iso_mnt *imp;
+ struct iso_node *ip;
+ struct buf *bp;
+ struct vnode *vp, *nvp;
+ dev_t dev;
+ int error;
+
+ imp = VFSTOISOFS(mp);
+ dev = imp->im_dev;
+ if ((*vpp = cd9660_ihashget(dev, ino)) != NULLVP)
+ return (0);
+
+ /* Allocate a new vnode/iso_node. */
+ if (error = getnewvnode(VT_ISOFS, mp, cd9660_vnodeop_p, &vp)) {
+ *vpp = NULLVP;
return (error);
}
+ MALLOC(ip, struct iso_node *, sizeof(struct iso_node), M_ISOFSNODE,
+ M_WAITOK);
+ bzero((caddr_t)ip, sizeof(struct iso_node));
+ lockinit(&ip->i_lock, PINOD, "isonode", 0, 0);
+ vp->v_data = ip;
+ ip->i_vnode = vp;
+ ip->i_dev = dev;
+ ip->i_number = ino;
- dirp = (struct iso_directory_record *)(bp->b_un.b_addr + off);
- if (off + isonum_711(dirp->length) > imp->logical_block_size) {
- brelse(bp);
- printf("fhtovp: directory crosses block boundary %d[off=%d/len=%d]\n",
- off+isonum_711(dirp->length), off,
- isonum_711(dirp->length));
- return (ESTALE);
+ /*
+ * Put it onto its hash chain and lock it so that other requests for
+ * this inode will block if they arrive while we are sleeping waiting
+ * for old data structures to be purged or for the contents of the
+ * disk portion of this inode to be read.
+ */
+ cd9660_ihashins(ip);
+
+ if (isodir == 0) {
+ int lbn, off;
+
+ lbn = lblkno(imp, ino);
+ if (lbn >= imp->volume_space_size) {
+ vput(vp);
+ printf("fhtovp: lbn exceed volume space %d\n", lbn);
+ return (ESTALE);
+ }
+
+ off = blkoff(imp, ino);
+ if (off + ISO_DIRECTORY_RECORD_SIZE > imp->logical_block_size) {
+ vput(vp);
+ printf("fhtovp: crosses block boundary %d\n",
+ off + ISO_DIRECTORY_RECORD_SIZE);
+ return (ESTALE);
+ }
+
+ error = bread(imp->im_devvp,
+ lbn << (imp->im_bshift - DEV_BSHIFT),
+ imp->logical_block_size, NOCRED, &bp);
+ if (error) {
+ vput(vp);
+ brelse(bp);
+ printf("fhtovp: bread error %d\n",error);
+ return (error);
+ }
+ isodir = (struct iso_directory_record *)(bp->b_data + off);
+
+ if (off + isonum_711(isodir->length) >
+ imp->logical_block_size) {
+ vput(vp);
+ if (bp != 0)
+ brelse(bp);
+ printf("fhtovp: directory crosses block boundary %d[off=%d/len=%d]\n",
+ off +isonum_711(isodir->length), off,
+ isonum_711(isodir->length));
+ return (ESTALE);
+ }
+
+#if 0
+ if (isonum_733(isodir->extent) +
+ isonum_711(isodir->ext_attr_length) != ifhp->ifid_start) {
+ if (bp != 0)
+ brelse(bp);
+ printf("fhtovp: file start miss %d vs %d\n",
+ isonum_733(isodir->extent) + isonum_711(isodir->ext_attr_length),
+ ifhp->ifid_start);
+ return (ESTALE);
+ }
+#endif
+ } else
+ bp = 0;
+
+ ip->i_mnt = imp;
+ ip->i_devvp = imp->im_devvp;
+ VREF(ip->i_devvp);
+
+ if (relocated) {
+ /*
+ * On relocated directories we must
+ * read the `.' entry out of a dir.
+ */
+ ip->iso_start = ino >> imp->im_bshift;
+ if (bp != 0)
+ brelse(bp);
+ if (error = VOP_BLKATOFF(vp, (off_t)0, NULL, &bp)) {
+ vput(vp);
+ return (error);
+ }
+ isodir = (struct iso_directory_record *)bp->b_data;
}
- if (isonum_733(dirp->extent) + isonum_711(dirp->ext_attr_length) !=
- ifhp->ifid_start) {
- brelse(bp);
- printf("fhtovp: file start miss %d vs %ld\n",
- isonum_733(dirp->extent)+isonum_711(dirp->ext_attr_length),
- ifhp->ifid_start);
- return (ESTALE);
+ ip->iso_extent = isonum_733(isodir->extent);
+ ip->i_size = isonum_733(isodir->size);
+ ip->iso_start = isonum_711(isodir->ext_attr_length) + ip->iso_extent;
+
+ /*
+ * Setup time stamp, attribute
+ */
+ vp->v_type = VNON;
+ switch (imp->iso_ftype) {
+ default: /* ISO_FTYPE_9660 */
+ {
+ struct buf *bp2;
+ int off;
+ if ((imp->im_flags & ISOFSMNT_EXTATT)
+ && (off = isonum_711(isodir->ext_attr_length)))
+ VOP_BLKATOFF(vp, (off_t)-(off << imp->im_bshift), NULL,
+ &bp2);
+ else
+ bp2 = NULL;
+ cd9660_defattr(isodir, ip, bp2, ISO_FTYPE_9660);
+ cd9660_deftstamp(isodir, ip, bp2, ISO_FTYPE_9660);
+ if (bp2)
+ brelse(bp2);
+ break;
+ }
+ case ISO_FTYPE_RRIP:
+ cd9660_rrip_analyze(isodir, ip, imp);
+ break;
}
- brelse(bp);
- ip = &tip;
- tvp.v_mount = mp;
- tvp.v_data = ip;
- ip->i_vnode = &tvp;
- ip->i_dev = imp->im_dev;
- if ((error = iso_iget(ip, ifhp->ifid_ino, 0, &nip, dirp))) {
- *vpp = NULLVP;
- printf("fhtovp: failed to get inode\n");
- return (error);
+ if (bp != 0)
+ brelse(bp);
+
+ /*
+ * Initialize the associated vnode
+ */
+ switch (vp->v_type = IFTOVT(ip->inode.iso_mode)) {
+ case VFIFO:
+#ifdef FIFO
+ vp->v_op = cd9660_fifoop_p;
+ break;
+#else
+ vput(vp);
+ return (EOPNOTSUPP);
+#endif /* FIFO */
+ case VCHR:
+ case VBLK:
+ /*
+ * if device, look at device number table for translation
+ */
+#ifdef ISODEVMAP
+ if (dp = iso_dmap(dev, ino, 0))
+ ip->inode.iso_rdev = dp->d_dev;
+#endif
+ vp->v_op = cd9660_specop_p;
+ if (nvp = checkalias(vp, ip->inode.iso_rdev, mp)) {
+ /*
+ * Discard unneeded vnode, but save its iso_node.
+ * Note that the lock is carried over in the iso_node
+ * to the replacement vnode.
+ */
+ nvp->v_data = vp->v_data;
+ vp->v_data = NULL;
+ vp->v_op = spec_vnodeop_p;
+ vrele(vp);
+ vgone(vp);
+ /*
+ * Reinitialize aliased inode.
+ */
+ vp = nvp;
+ ip->i_vnode = vp;
+ }
+ break;
}
- ip = nip;
+
+ if (ip->iso_extent == imp->root_extent)
+ vp->v_flag |= VROOT;
+
/*
* XXX need generation number?
*/
- if (ip->inode.iso_mode == 0) {
- iso_iput(ip);
- *vpp = NULLVP;
- printf("fhtovp: inode mode == 0\n");
- return (ESTALE);
- }
- *vpp = ITOV(ip);
- *exflagsp = np->netc_exflags;
- *credanonp = &np->netc_anon;
- return 0;
+
+ *vpp = vp;
+ return (0);
}
/*
OpenPOWER on IntegriCloud