summaryrefslogtreecommitdiffstats
path: root/sys/isofs/cd9660/cd9660_node.c
diff options
context:
space:
mode:
authordyson <dyson@FreeBSD.org>1997-02-10 02:22:35 +0000
committerdyson <dyson@FreeBSD.org>1997-02-10 02:22:35 +0000
commit10f666af84d48e89e4e2960415c9b616fce4077f (patch)
tree88a944de263165091f0a18abeedbaaccec532407 /sys/isofs/cd9660/cd9660_node.c
parent0960d7e91af3428ffba89b42228d82d8afaa0389 (diff)
downloadFreeBSD-src-10f666af84d48e89e4e2960415c9b616fce4077f.zip
FreeBSD-src-10f666af84d48e89e4e2960415c9b616fce4077f.tar.gz
This is the kernel Lite/2 commit. There are some requisite userland
changes, so don't expect to be able to run the kernel as-is (very well) without the appropriate Lite/2 userland changes. The system boots and can mount UFS filesystems. Untested: ext2fs, msdosfs, NFS Known problems: Incorrect Berkeley ID strings in some files. Mount_std mounts will not work until the getfsent library routine is changed. Reviewed by: various people Submitted by: Jeffery Hsu <hsu@freebsd.org>
Diffstat (limited to 'sys/isofs/cd9660/cd9660_node.c')
-rw-r--r--sys/isofs/cd9660/cd9660_node.c462
1 files changed, 144 insertions, 318 deletions
diff --git a/sys/isofs/cd9660/cd9660_node.c b/sys/isofs/cd9660/cd9660_node.c
index c3f0911..c726696 100644
--- a/sys/isofs/cd9660/cd9660_node.c
+++ b/sys/isofs/cd9660/cd9660_node.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 1982, 1986, 1989, 1994
+ * Copyright (c) 1982, 1986, 1989, 1994, 1995
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley
@@ -52,32 +52,21 @@
#include <isofs/cd9660/iso.h>
#include <isofs/cd9660/cd9660_node.h>
+#include <isofs/cd9660/cd9660_mount.h>
#include <isofs/cd9660/iso_rrip.h>
-#define INOHSZ 512
-#if ((INOHSZ&(INOHSZ-1)) == 0)
-#define INOHASH(dev,ino) (((dev)+((ino)>>12))&(INOHSZ-1))
-#else
-#define INOHASH(dev,ino) (((unsigned)((dev)+((ino)>>12)))%INOHSZ)
-#endif
-
-union iso_ihead {
- union iso_ihead *ih_head[2];
- struct iso_node *ih_chain[2];
-} iso_ihead[INOHSZ];
-
-#ifdef ISODEVMAP
-#define DNOHSZ 64
-#if ((DNOHSZ&(DNOHSZ-1)) == 0)
-#define DNOHASH(dev,ino) (((dev)+((ino)>>12))&(DNOHSZ-1))
-#else
-#define DNOHASH(dev,ino) (((unsigned)((dev)+((ino)>>12)))%DNOHSZ)
-#endif
-
-union iso_dhead {
- union iso_dhead *dh_head[2];
- struct iso_dnode *dh_chain[2];
-} iso_dhead[DNOHSZ];
+/*
+ * Structures associated with iso_node caching.
+ */
+struct iso_node **isohashtbl;
+u_long isohash;
+#define INOHASH(device, inum) (((device) + ((inum)>>12)) & isohash)
+struct simplelock cd9660_ihash_slock;
+
+#ifdef ISODEVMAP
+struct iso_node **idvhashtbl;
+u_long idvhash;
+#define DNOHASH(device, inum) (((device) + ((inum)>>12)) & idvhash)
#endif
static unsigned cd9660_chars2ui __P((unsigned char *begin, int len));
@@ -86,73 +75,68 @@ static unsigned cd9660_chars2ui __P((unsigned char *begin, int len));
* Initialize hash links for inodes and dnodes.
*/
int
-cd9660_init()
+cd9660_init(vfsp)
+ struct vfsconf *vfsp;
{
- register int i;
- register union iso_ihead *ih = iso_ihead;
-#ifdef ISODEVMAP
- register union iso_dhead *dh = iso_dhead;
-#endif
- for (i = INOHSZ; --i >= 0; ih++) {
- ih->ih_head[0] = ih;
- ih->ih_head[1] = ih;
- }
-#ifdef ISODEVMAP
- for (i = DNOHSZ; --i >= 0; dh++) {
- dh->dh_head[0] = dh;
- dh->dh_head[1] = dh;
- }
+ isohashtbl = hashinit(desiredvnodes, M_ISOFSMNT, &isohash);
+ simple_lock_init(&cd9660_ihash_slock);
+#ifdef ISODEVMAP
+ idvhashtbl = hashinit(desiredvnodes / 8, M_ISOFSMNT, &idvhash);
#endif
return (0);
}
-#ifdef ISODEVMAP
+#ifdef ISODEVMAP
/*
* Enter a new node into the device hash list
*/
struct iso_dnode *
-iso_dmap(dev,ino,create)
- dev_t dev;
- ino_t ino;
+iso_dmap(device, inum, create)
+ dev_t device;
+ ino_t inum;
int create;
{
- struct iso_dnode *dp;
- union iso_dhead *dh;
+ register struct iso_dnode **dpp, *dp, *dq;
- dh = &iso_dhead[DNOHASH(dev, ino)];
- for (dp = dh->dh_chain[0];
- dp != (struct iso_dnode *)dh;
- dp = dp->d_forw)
- if (ino == dp->i_number && dev == dp->i_dev)
- return dp;
+ dpp = &idvhashtbl[DNOHASH(device, inum)];
+ for (dp = *dpp;; dp = dp->d_next) {
+ if (dp == NULL)
+ return (NULL);
+ if (inum == dp->i_number && device == dp->i_dev)
+ return (dp);
if (!create)
- return (struct iso_dnode *)0;
+ return (NULL);
- MALLOC(dp,struct iso_dnode *,sizeof(struct iso_dnode),M_CACHE,M_WAITOK);
+ MALLOC(dp, struct iso_dnode *, sizeof(struct iso_dnode), M_CACHE,
+ M_WAITOK);
dp->i_dev = dev;
dp->i_number = ino;
- insque(dp,dh);
- return dp;
+ if (dq = *dpp)
+ dq->d_prev = dp->d_next;
+ dp->d_next = dq;
+ dp->d_prev = dpp;
+ *dpp = dp;
+
+ return (dp);
}
void
-iso_dunmap(dev)
- dev_t dev;
+iso_dunmap(device)
+ dev_t device;
{
- struct iso_dnode *dp, *dq;
- union iso_dhead *dh;
-
- for (dh = iso_dhead; dh < iso_dhead + DNOHSZ; dh++) {
- for (dp = dh->dh_chain[0];
- dp != (struct iso_dnode *)dh;
- dp = dq) {
- dq = dp->d_forw;
- if (dev == dp->i_dev) {
- remque(dp);
- FREE(dp,M_CACHE);
+ struct iso_dnode **dpp, *dp, *dq;
+
+ for (dpp = idvhashtbl; dpp <= idvhashtbl + idvhash; dpp++) {
+ for (dp = *dpp; dp != NULL; dp = dq)
+ dq = dp->d_next;
+ if (device == dp->i_dev) {
+ if (dq)
+ dq->d_prev = dp->d_prev;
+ *dp->d_prev = dq;
+ FREE(dp, M_CACHE);
}
}
}
@@ -160,197 +144,74 @@ iso_dunmap(dev)
#endif
/*
- * Look up a ISOFS dinode number to find its incore vnode.
- * If it is not in core, read it in from the specified device.
- * If it is in core, wait for the lock bit to clear, then
- * return the inode locked. Detection and handling of mount
- * points must be done by the calling routine.
+ * Use the device/inum pair to find the incore inode, and return a pointer
+ * to it. If it is in core, but locked, wait for it.
*/
-int
-iso_iget(xp, ino, relocated, ipp, isodir)
- struct iso_node *xp;
- ino_t ino;
- int relocated;
- struct iso_node **ipp;
- struct iso_directory_record *isodir;
+struct vnode *
+cd9660_ihashget(dev, inum)
+ dev_t dev;
+ ino_t inum;
{
- dev_t dev = xp->i_dev;
- struct mount *mntp = ITOV(xp)->v_mount;
- register struct iso_node *ip, *iq;
- register struct vnode *vp;
-#ifdef ISODEVMAP
- register struct iso_dnode *dp;
-#endif
- struct vnode *nvp;
- struct buf *bp = NULL, *bp2 = NULL;
- union iso_ihead *ih;
- int error, result;
- struct iso_mnt *imp;
+ struct proc *p = curproc; /* XXX */
+ struct iso_node *ip;
+ struct vnode *vp;
- ih = &iso_ihead[INOHASH(dev, ino)];
loop:
- for (ip = ih->ih_chain[0];
- ip != (struct iso_node *)ih;
- ip = ip->i_forw) {
- if (ino != ip->i_number || dev != ip->i_dev)
- continue;
- if ((ip->i_flag&ILOCKED) != 0) {
- ip->i_flag |= IWANT;
- (void) tsleep((caddr_t)ip, PINOD, "isoigt", 0);
- goto loop;
- }
- if (vget(ITOV(ip), 1))
- goto loop;
- *ipp = ip;
- return 0;
- }
-
- /*
- * Do the MALLOC before the getnewvnode since doing so afterward
- * might cause a bogus v_data pointer to get dereferenced
- * elsewhere if MALLOC should block.
- */
- MALLOC(ip, struct iso_node *, sizeof(struct iso_node), M_ISOFSNODE, M_WAITOK);
-
- /*
- * Allocate a new vnode/iso_node.
- */
- if ((error = getnewvnode(VT_ISOFS, mntp, cd9660_vnodeop_p, &nvp))) {
- *ipp = NULL;
- FREE(ip, M_ISOFSNODE);
- return error;
- }
- bzero((caddr_t)ip, sizeof(struct iso_node));
- nvp->v_data = ip;
- ip->i_vnode = nvp;
- ip->i_flag = 0;
- ip->i_devvp = 0;
- ip->i_diroff = 0;
- ip->i_lockf = 0;
-
- /*
- * 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.
- */
- ip->i_dev = dev;
- ip->i_number = ino;
- insque(ip, ih);
- ISO_ILOCK(ip);
-
- imp = VFSTOISOFS (mntp);
- 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 ((error = iso_blkatoff(ip,0,&bp))) {
- vrele(ip->i_devvp);
- remque(ip);
- ip->i_forw = ip;
- ip->i_back = ip;
- iso_iput(ip);
- *ipp = 0;
- return error;
- }
- isodir = (struct iso_directory_record *)bp->b_un.b_addr;
- }
-
- 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;
-
- vp = ITOV(ip);
-
- /*
- * Setup time stamp, attribute
- */
- vp->v_type = VNON;
- switch (imp->iso_ftype) {
- default: /* ISO_FTYPE_9660 || ISO_FTYPE_HIGH_SIERRA */
- if ((imp->im_flags&ISOFSMNT_EXTATT)
- && isonum_711(isodir->ext_attr_length))
- iso_blkatoff(ip,-isonum_711(isodir->ext_attr_length),
- &bp2);
- cd9660_defattr(isodir,ip,bp2,imp->iso_ftype );
- cd9660_deftstamp(isodir,ip,bp2,imp->iso_ftype );
- break;
- case ISO_FTYPE_RRIP:
- result = cd9660_rrip_analyze(isodir,ip,imp);
- break;
- }
- if (bp2)
- brelse(bp2);
- if (bp)
- brelse(bp);
-
- /*
- * Initialize the associated vnode
- */
- vp->v_type = IFTOVT(ip->inode.iso_mode);
-
- if ( vp->v_type == VFIFO ) {
- vp->v_op = cd9660_fifoop_p;
- } else if ( vp->v_type == VCHR || vp->v_type == 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, mntp))) {
- /*
- * Reinitialize aliased inode.
- */
- vp = nvp;
- iq = VTOI(vp);
- iq->i_vnode = vp;
- iq->i_flag = 0;
- ISO_ILOCK(iq);
- iq->i_dev = dev;
- iq->i_number = ino;
- iq->i_mnt = ip->i_mnt;
- bcopy(&ip->iso_extent,&iq->iso_extent,
- (char *)(ip + 1) - (char *)&ip->iso_extent);
- insque(iq, ih);
- /*
- * Discard unneeded vnode
- * (This introduces the need of INACTIVE modification)
- */
- ip->inode.iso_mode = 0;
- iso_iput(ip);
- ip = iq;
+ simple_lock(&cd9660_ihash_slock);
+ for (ip = isohashtbl[INOHASH(dev, inum)]; ip; ip = ip->i_next) {
+ if (inum == ip->i_number && dev == ip->i_dev) {
+ vp = ITOV(ip);
+ simple_lock(&vp->v_interlock);
+ simple_unlock(&cd9660_ihash_slock);
+ if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK, p))
+ goto loop;
+ return (vp);
}
}
+ simple_unlock(&cd9660_ihash_slock);
+ return (NULL);
+}
- if (ip->iso_extent == imp->root_extent)
- vp->v_flag |= VROOT;
-
+/*
+ * Insert the inode into the hash table, and return it locked.
+ */
+void
+cd9660_ihashins(ip)
+ struct iso_node *ip;
+{
+ struct proc *p = curproc; /* XXX */
+ struct iso_node **ipp, *iq;
+
+ simple_lock(&cd9660_ihash_slock);
+ ipp = &isohashtbl[INOHASH(ip->i_dev, ip->i_number)];
+ if (iq = *ipp)
+ iq->i_prev = &ip->i_next;
+ ip->i_next = iq;
+ ip->i_prev = ipp;
*ipp = ip;
- return 0;
+ simple_unlock(&cd9660_ihash_slock);
+
+ lockmgr(&ip->i_lock, LK_EXCLUSIVE, (struct simplelock *)0, p);
}
/*
- * Unlock and decrement the reference count of an inode structure.
+ * Remove the inode from the hash table.
*/
-int
-iso_iput(ip)
+void
+cd9660_ihashrem(ip)
register struct iso_node *ip;
{
-
- if ((ip->i_flag & ILOCKED) == 0)
- panic("iso_iput");
- ISO_IUNLOCK(ip);
- vrele(ITOV(ip));
- return (0);
+ register struct iso_node *iq;
+
+ simple_lock(&cd9660_ihash_slock);
+ if (iq = ip->i_next)
+ iq->i_prev = ip->i_prev;
+ *ip->i_prev = iq;
+#ifdef DIAGNOSTIC
+ ip->i_next = NULL;
+ ip->i_prev = NULL;
+#endif
+ simple_unlock(&cd9660_ihash_slock);
}
/*
@@ -361,9 +222,11 @@ int
cd9660_inactive(ap)
struct vop_inactive_args /* {
struct vnode *a_vp;
+ struct proc *a_p;
} */ *ap;
{
struct vnode *vp = ap->a_vp;
+ struct proc *p = ap->a_p;
register struct iso_node *ip = VTOI(vp);
int error = 0;
@@ -371,12 +234,13 @@ cd9660_inactive(ap)
vprint("cd9660_inactive: pushing active", vp);
ip->i_flag = 0;
+ VOP_UNLOCK(vp, 0, p);
/*
* If we are done with the inode, reclaim it
* so that it can be reused immediately.
*/
- if (vp->v_usecount == 0 && ip->inode.iso_mode == 0)
- vgone(vp);
+ if (ip->inode.iso_mode == 0)
+ vrecycle(vp, (struct simplelock *)0, p);
return error;
}
@@ -387,6 +251,7 @@ int
cd9660_reclaim(ap)
struct vop_reclaim_args /* {
struct vnode *a_vp;
+ struct proc *a_p;
} */ *ap;
{
register struct vnode *vp = ap->a_vp;
@@ -397,9 +262,7 @@ cd9660_reclaim(ap)
/*
* Remove the inode from its hash chain.
*/
- remque(ip);
- ip->i_forw = ip;
- ip->i_back = ip;
+ cd9660_ihashrem(ip);
/*
* Purge old data structures associated with the inode.
*/
@@ -410,46 +273,6 @@ cd9660_reclaim(ap)
}
FREE(vp->v_data, M_ISOFSNODE);
vp->v_data = NULL;
- return 0;
-}
-
-/*
- * Lock an inode. If its already locked, set the WANT bit and sleep.
- */
-int
-iso_ilock(ip)
- register struct iso_node *ip;
-{
-
- while (ip->i_flag & ILOCKED) {
- ip->i_flag |= IWANT;
- if (ip->i_spare0 == curproc->p_pid)
- panic("locking against myself");
- ip->i_spare1 = curproc->p_pid;
- (void) tsleep((caddr_t)ip, PINOD, "isoilk", 0);
- }
- ip->i_spare1 = 0;
- ip->i_spare0 = curproc->p_pid;
- ip->i_flag |= ILOCKED;
- return (0);
-}
-
-/*
- * Unlock an inode. If WANT bit is on, wakeup.
- */
-int
-iso_iunlock(ip)
- register struct iso_node *ip;
-{
-
- if ((ip->i_flag & ILOCKED) == 0)
- vprint("iso_iunlock: unlocked inode", ITOV(ip));
- ip->i_spare0 = 0;
- ip->i_flag &= ~ILOCKED;
- if (ip->i_flag&IWANT) {
- ip->i_flag &= ~IWANT;
- wakeup((caddr_t)ip);
- }
return (0);
}
@@ -457,7 +280,7 @@ iso_iunlock(ip)
* File attributes
*/
void
-cd9660_defattr(isodir,inop,bp,ftype)
+cd9660_defattr(isodir, inop, bp, ftype)
struct iso_directory_record *isodir;
struct iso_node *inop;
struct buf *bp;
@@ -482,14 +305,15 @@ cd9660_defattr(isodir,inop,bp,ftype)
inop->inode.iso_links = 1;
}
if (!bp
- && ((imp = inop->i_mnt)->im_flags&ISOFSMNT_EXTATT)
+ && ((imp = inop->i_mnt)->im_flags & ISOFSMNT_EXTATT)
&& (off = isonum_711(isodir->ext_attr_length))) {
- iso_blkatoff(inop,-off * imp->logical_block_size,&bp2);
+ VOP_BLKATOFF(ITOV(inop), (off_t)-(off << imp->im_bshift), NULL,
+ &bp2);
bp = bp2;
}
if (bp) {
- ap = (struct iso_extended_attributes *)bp->b_un.b_addr;
-
+ ap = (struct iso_extended_attributes *)bp->b_data;
+
if (isonum_711(ap->version) == 1) {
if (!(ap->perm[0]&0x40))
inop->inode.iso_mode |= VEXEC >> 6;
@@ -533,16 +357,16 @@ cd9660_deftstamp(isodir,inop,bp,ftype)
int off;
if (!bp
- && ((imp = inop->i_mnt)->im_flags&ISOFSMNT_EXTATT)
+ && ((imp = inop->i_mnt)->im_flags & ISOFSMNT_EXTATT)
&& (off = isonum_711(isodir->ext_attr_length))) {
- iso_blkatoff(inop,-off * imp->logical_block_size,&bp2);
+ VOP_BLKATOFF(ITOV(inop), (off_t)-(off << imp->im_bshift), NULL,
+ &bp2);
bp = bp2;
}
if (bp) {
- ap = (struct iso_extended_attributes *)bp->b_un.b_addr;
-
- if (ftype != ISO_FTYPE_HIGH_SIERRA
- && isonum_711(ap->version) == 1) {
+ ap = (struct iso_extended_attributes *)bp->b_data;
+
+ if (isonum_711(ap->version) == 1) {
if (!cd9660_tstamp_conv17(ap->ftime,&inop->inode.iso_atime))
cd9660_tstamp_conv17(ap->ctime,&inop->inode.iso_atime);
if (!cd9660_tstamp_conv17(ap->ctime,&inop->inode.iso_ctime))
@@ -563,9 +387,9 @@ cd9660_deftstamp(isodir,inop,bp,ftype)
int
cd9660_tstamp_conv7(pi,pu,ftype)
-char *pi;
-struct timespec *pu;
-enum ISO_FTYPE ftype;
+ u_char *pi;
+ struct timespec *pu;
+ enum ISO_FTYPE ftype;
{
int crtime, days;
int y, m, d, hour, minute, second, tz;
@@ -609,13 +433,13 @@ enum ISO_FTYPE ftype;
return 1;
}
-static unsigned
+static u_int
cd9660_chars2ui(begin,len)
- unsigned char *begin;
+ u_char *begin;
int len;
{
- unsigned rc;
-
+ u_int rc;
+
for (rc = 0; --len >= 0;) {
rc *= 10;
rc += *begin++ - '0';
@@ -625,12 +449,12 @@ cd9660_chars2ui(begin,len)
int
cd9660_tstamp_conv17(pi,pu)
- unsigned char *pi;
+ u_char *pi;
struct timespec *pu;
{
- unsigned char buf[7];
-
- /* year:"0001"-"9999" -> -1900 */
+ u_char buf[7];
+
+ /* year:"0001"-"9999" -> -1900 */
buf[0] = cd9660_chars2ui(pi,4) - 1900;
/* month: " 1"-"12" -> 1 - 12 */
@@ -654,12 +478,14 @@ cd9660_tstamp_conv17(pi,pu)
return cd9660_tstamp_conv7(buf, pu, ISO_FTYPE_DEFAULT);
}
-void
-isodirino(inump,isodir,imp)
- ino_t *inump;
+ino_t
+isodirino(isodir, imp)
struct iso_directory_record *isodir;
struct iso_mnt *imp;
{
- *inump = (isonum_733(isodir->extent) + isonum_711(isodir->ext_attr_length))
- * imp->logical_block_size;
+ ino_t ino;
+
+ ino = (isonum_733(isodir->extent) + isonum_711(isodir->ext_attr_length))
+ << imp->im_bshift;
+ return (ino);
}
OpenPOWER on IntegriCloud