summaryrefslogtreecommitdiffstats
path: root/sys/fs
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/fs
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/fs')
-rw-r--r--sys/fs/cd9660/TODO30
-rw-r--r--sys/fs/cd9660/cd9660_bmap.c12
-rw-r--r--sys/fs/cd9660/cd9660_lookup.c173
-rw-r--r--sys/fs/cd9660/cd9660_node.c462
-rw-r--r--sys/fs/cd9660/cd9660_node.h36
-rw-r--r--sys/fs/cd9660/cd9660_rrip.c76
-rw-r--r--sys/fs/cd9660/cd9660_rrip.h48
-rw-r--r--sys/fs/cd9660/cd9660_util.c107
-rw-r--r--sys/fs/cd9660/cd9660_vfsops.c448
-rw-r--r--sys/fs/cd9660/cd9660_vnops.c721
-rw-r--r--sys/fs/cd9660/iso.h135
-rw-r--r--sys/fs/deadfs/dead_vnops.c28
-rw-r--r--sys/fs/fdescfs/fdesc.h5
-rw-r--r--sys/fs/fdescfs/fdesc_vfsops.c71
-rw-r--r--sys/fs/fdescfs/fdesc_vnops.c162
-rw-r--r--sys/fs/fifofs/fifo.h10
-rw-r--r--sys/fs/fifofs/fifo_vnops.c177
-rw-r--r--sys/fs/msdosfs/msdosfs_denode.c8
-rw-r--r--sys/fs/msdosfs/msdosfs_lookup.c29
-rw-r--r--sys/fs/msdosfs/msdosfs_vfsops.c6
-rw-r--r--sys/fs/msdosfs/msdosfs_vnops.c28
-rw-r--r--sys/fs/msdosfs/msdosfsmount.h12
-rw-r--r--sys/fs/nullfs/null.h5
-rw-r--r--sys/fs/nullfs/null_subr.c61
-rw-r--r--sys/fs/nullfs/null_vfsops.c19
-rw-r--r--sys/fs/nullfs/null_vnops.c223
-rw-r--r--sys/fs/portalfs/portal_vfsops.c97
-rw-r--r--sys/fs/portalfs/portal_vnops.c57
-rw-r--r--sys/fs/procfs/procfs.h50
-rw-r--r--sys/fs/procfs/procfs_ctl.c24
-rw-r--r--sys/fs/procfs/procfs_fpregs.c3
-rw-r--r--sys/fs/procfs/procfs_map.c2
-rw-r--r--sys/fs/procfs/procfs_mem.c10
-rw-r--r--sys/fs/procfs/procfs_regs.c3
-rw-r--r--sys/fs/procfs/procfs_status.c5
-rw-r--r--sys/fs/procfs/procfs_subr.c55
-rw-r--r--sys/fs/procfs/procfs_vfsops.c109
-rw-r--r--sys/fs/procfs/procfs_vnops.c466
-rw-r--r--sys/fs/specfs/spec_vnops.c91
-rw-r--r--sys/fs/umapfs/umap.h5
-rw-r--r--sys/fs/umapfs/umap_subr.c61
-rw-r--r--sys/fs/umapfs/umap_vfsops.c21
-rw-r--r--sys/fs/umapfs/umap_vnops.c49
-rw-r--r--sys/fs/unionfs/union.h22
-rw-r--r--sys/fs/unionfs/union_subr.c538
-rw-r--r--sys/fs/unionfs/union_vfsops.c238
-rw-r--r--sys/fs/unionfs/union_vnops.c798
47 files changed, 3179 insertions, 2617 deletions
diff --git a/sys/fs/cd9660/TODO b/sys/fs/cd9660/TODO
index eb24a23..71859c7 100644
--- a/sys/fs/cd9660/TODO
+++ b/sys/fs/cd9660/TODO
@@ -25,16 +25,6 @@
There is some preliminary stuff in there that (ab-)uses the mknod
system call, but this needs a writable filesystem
- 3) should be called cdfs, as there are other ISO file system soon possible
-
- Not yet. Probably we should make another file system when the ECMA draft
- is valid and do it. For doing Rock Ridge Support, I can use almost same
- code. So I just use the same file system interface...
-
- 4) should have file handles implemented for use with NFS, etc
-
- Yes. we have already this one, and I based it for this release.
-
5) should have name translation enabled by mount flag
Yes. we can disable the Rock Ridge Extension by follows option;
@@ -57,23 +47,3 @@
clean. As far as I know, if you export the cdrom by NFS, the client
can access the 8 bit clean (ie. Solaris Japanese with EUC code )
- 9) Access checks in isofs_access
-
- Not yet.
-
- 10) Support for generation numbers
-
- Yes. Default is to list only the last file (the one with the highest
- generation number). If you mount with -gen, all files are shown with
- their generation numbers. In both cases you can specify the generation
- number on opening files (if you happen to know it) or leave it off,
- when it will again find the last file.
-
- 11) Support for extended attributes
-
- Yes. Since this requires an extra block buffer for the attributes
- this must be enabled on mounting with the option -extattr.
-
-----------
-Last update July 19, '93 by Atsushi Murai. (amurai@spec.co.jp)
-Last update August 19, '93 by Wolfgang Solfrank. (ws@tools.de)
diff --git a/sys/fs/cd9660/cd9660_bmap.c b/sys/fs/cd9660/cd9660_bmap.c
index 6fffe7a..71dfb9e 100644
--- a/sys/fs/cd9660/cd9660_bmap.c
+++ b/sys/fs/cd9660/cd9660_bmap.c
@@ -67,7 +67,7 @@ cd9660_bmap(ap)
{
struct iso_node *ip = VTOI(ap->a_vp);
daddr_t lblkno = ap->a_bn;
- long bsize;
+ int bshift;
/*
* Check for underlying vnode requests and ensure that logical
@@ -81,8 +81,8 @@ cd9660_bmap(ap)
/*
* Compute the requested block number
*/
- bsize = ip->i_mnt->logical_block_size;
- *ap->a_bnp = (ip->iso_start + lblkno) * btodb(bsize);
+ bshift = ip->i_mnt->im_bshift;
+ *ap->a_bnp = (ip->iso_start + lblkno) << (bshift - DEV_BSHIFT);
/*
* Determine maximum number of readahead blocks following the
@@ -91,11 +91,11 @@ cd9660_bmap(ap)
if (ap->a_runp) {
int nblk;
- nblk = (ip->i_size - (lblkno + 1) * bsize) / bsize;
+ nblk = (ip->i_size >> bshift) - (lblkno + 1);
if (nblk <= 0)
*ap->a_runp = 0;
- else if (nblk >= MAXBSIZE/bsize)
- *ap->a_runp = MAXBSIZE/bsize - 1;
+ else if (nblk >= (MAXBSIZE >> bshift))
+ *ap->a_runp = (MAXBSIZE >> bshift) - 1;
else
*ap->a_runp = nblk;
}
diff --git a/sys/fs/cd9660/cd9660_lookup.c b/sys/fs/cd9660/cd9660_lookup.c
index 6e85a81..a7e38bb 100644
--- a/sys/fs/cd9660/cd9660_lookup.c
+++ b/sys/fs/cd9660/cd9660_lookup.c
@@ -108,8 +108,9 @@ cd9660_lookup(ap)
int saveoffset = 0; /* offset of last directory entry in dir */
int numdirpasses; /* strategy for directory search */
doff_t endsearch; /* offset to end directory search */
- struct iso_node *pdp; /* saved dp during symlink work */
- struct iso_node *tdp; /* returned by iget */
+ struct vnode *pdp; /* saved dp during symlink work */
+ struct vnode *tdp; /* returned by cd9660_vget_internal */
+ u_long bmask; /* block offset mask */
int lockparent; /* 1 => lockparent flag is set */
int wantparent; /* 1 => wantparent or lockparent flag */
int error;
@@ -126,6 +127,7 @@ cd9660_lookup(ap)
struct ucred *cred = cnp->cn_cred;
int flags = cnp->cn_flags;
int nameiop = cnp->cn_nameiop;
+ struct proc *p = cnp->cn_proc;
bp = NULL;
*vpp = NULL;
@@ -139,13 +141,13 @@ cd9660_lookup(ap)
* Check accessiblity of directory.
*/
if (vdp->v_type != VDIR)
- return (ENOTDIR);
- if ((error = VOP_ACCESS(vdp, VEXEC, cred, cnp->cn_proc)))
+ return (ENOTDIR);
+ if (error = VOP_ACCESS(vdp, VEXEC, cred, cnp->cn_proc))
return (error);
if ((flags & ISLASTCN) && (vdp->v_mount->mnt_flag & MNT_RDONLY) &&
(cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME))
return (EROFS);
-
+
/*
* We now have a segment name to search for, and a directory to search.
*
@@ -160,29 +162,29 @@ cd9660_lookup(ap)
return (error);
#ifdef PARANOID
if ((vdp->v_flag & VROOT) && (flags & ISDOTDOT))
- panic("ufs_lookup: .. through root");
+ panic("cd9660_lookup: .. through root");
#endif
/*
* Get the next vnode in the path.
* See comment below starting `Step through' for
* an explaination of the locking protocol.
*/
- pdp = dp;
+ pdp = vdp;
dp = VTOI(*vpp);
vdp = *vpp;
vpid = vdp->v_id;
- if (pdp == dp) {
+ if (pdp == vdp) {
VREF(vdp);
error = 0;
} else if (flags & ISDOTDOT) {
- ISO_IUNLOCK(pdp);
- error = vget(vdp, 1);
+ VOP_UNLOCK(pdp, 0, p);
+ error = vget(vdp, LK_EXCLUSIVE, p);
if (!error && lockparent && (flags & ISLASTCN))
- ISO_ILOCK(pdp);
+ error = vn_lock(pdp, LK_EXCLUSIVE, p);
} else {
- error = vget(vdp, 1);
+ error = vget(vdp, LK_EXCLUSIVE, p);
if (!lockparent || error || !(flags & ISLASTCN))
- ISO_IUNLOCK(pdp);
+ VOP_UNLOCK(pdp, 0, p);
}
/*
* Check that the capability number did not change
@@ -191,13 +193,14 @@ cd9660_lookup(ap)
if (!error) {
if (vpid == vdp->v_id)
return (0);
- iso_iput(dp);
- if (lockparent && pdp != dp && (flags & ISLASTCN))
- ISO_IUNLOCK(pdp);
+ vput(vdp);
+ if (lockparent && pdp != vdp && (flags & ISLASTCN))
+ VOP_UNLOCK(pdp, 0, p);
}
- ISO_ILOCK(pdp);
- dp = pdp;
- vdp = ITOV(dp);
+ if (error = vn_lock(pdp, LK_EXCLUSIVE, p))
+ return (error);
+ vdp = pdp;
+ dp = VTOI(pdp);
*vpp = NULL;
}
@@ -223,6 +226,7 @@ cd9660_lookup(ap)
* profiling time and hence has been removed in the interest
* of simplicity.
*/
+ bmask = imp->im_bmask;
if (nameiop != LOOKUP || dp->i_diroff == 0 ||
dp->i_diroff > dp->i_size) {
entryoffsetinblock = 0;
@@ -230,16 +234,14 @@ cd9660_lookup(ap)
numdirpasses = 1;
} else {
dp->i_offset = dp->i_diroff;
- entryoffsetinblock = iso_blkoff(imp, dp->i_offset);
- if (entryoffsetinblock != 0) {
- if ((error = iso_blkatoff(dp, dp->i_offset, &bp)))
+ if ((entryoffsetinblock = dp->i_offset & bmask) &&
+ (error = VOP_BLKATOFF(vdp, (off_t)dp->i_offset, NULL, &bp)))
return (error);
- }
numdirpasses = 2;
iso_nchstats.ncs_2passes++;
}
- endsearch = roundup(dp->i_size, imp->logical_block_size);
-
+ endsearch = dp->i_size;
+
searchloop:
while (dp->i_offset < endsearch) {
/*
@@ -247,10 +249,11 @@ searchloop:
* read the next directory block.
* Release previous if it exists.
*/
- if (iso_blkoff(imp, dp->i_offset) == 0) {
+ if ((dp->i_offset & bmask) == 0) {
if (bp != NULL)
brelse(bp);
- if ((error = iso_blkatoff(dp, dp->i_offset, &bp)))
+ if (error =
+ VOP_BLKATOFF(vdp, (off_t)dp->i_offset, NULL, &bp))
return (error);
entryoffsetinblock = 0;
}
@@ -258,13 +261,13 @@ searchloop:
* Get pointer to next entry.
*/
ep = (struct iso_directory_record *)
- (bp->b_un.b_addr + entryoffsetinblock);
-
- reclen = isonum_711 (ep->length);
+ ((char *)bp->b_data + entryoffsetinblock);
+
+ reclen = isonum_711(ep->length);
if (reclen == 0) {
/* skip to next block, if any */
dp->i_offset =
- roundup(dp->i_offset, imp->logical_block_size);
+ (dp->i_offset & ~bmask) + imp->logical_block_size;
continue;
}
@@ -275,10 +278,7 @@ searchloop:
if (entryoffsetinblock + reclen > imp->logical_block_size)
/* entries are not allowed to cross boundaries */
break;
-
- /*
- * Check for a name match.
- */
+
namelen = isonum_711(ep->name_len);
isoflags = isonum_711(imp->iso_ftype == ISO_FTYPE_HIGH_SIERRA?
&ep->date[6]: ep->flags);
@@ -286,7 +286,10 @@ searchloop:
if (reclen < ISO_DIRECTORY_RECORD_SIZE + namelen)
/* illegal entry, stop */
break;
-
+
+ /*
+ * Check for a name match.
+ */
switch (imp->iso_ftype) {
default:
if (!(isoflags & 4) == !assoc) {
@@ -297,10 +300,9 @@ searchloop:
&& ep->name[0] == ((flags & ISDOTDOT) ? 1 : 0)) {
/*
* Save directory entry's inode number and
- * reclen in ndp->ni_ufs area, and release
- * directory buffer.
+ * release directory buffer.
*/
- isodirino(&dp->i_ino,ep,imp);
+ dp->i_ino = isodirino(ep, imp);
goto found;
}
if (namelen != 1
@@ -308,8 +310,8 @@ searchloop:
goto notfound;
} else if (!(res = isofncmp(name,len,
ep->name,namelen))) {
- if (isoflags & 2)
- isodirino(&ino,ep,imp);
+ if (isonum_711(ep->flags)&2)
+ ino = isodirino(ep, imp);
else
ino = dbtob(bp->b_blkno)
+ entryoffsetinblock;
@@ -326,7 +328,7 @@ searchloop:
break;
case ISO_FTYPE_RRIP:
if (isonum_711(ep->flags)&2)
- isodirino(&ino,ep,imp);
+ ino = isodirino(ep, imp);
else
ino = dbtob(bp->b_blkno) + entryoffsetinblock;
dp->i_ino = ino;
@@ -344,15 +346,17 @@ searchloop:
foundino:
dp->i_ino = ino;
if (saveoffset != dp->i_offset) {
- if (iso_lblkno(imp,dp->i_offset)
- != iso_lblkno(imp,saveoffset)) {
+ if (lblkno(imp, dp->i_offset) !=
+ lblkno(imp, saveoffset)) {
if (bp != NULL)
brelse(bp);
- if ((error = iso_blkatoff(dp, saveoffset, &bp)))
+ if (error = VOP_BLKATOFF(vdp,
+ (off_t)saveoffset, NULL, &bp))
return (error);
}
- ep = (struct iso_directory_record *)(bp->b_un.b_addr
- + iso_blkoff(imp,saveoffset));
+ entryoffsetinblock = saveoffset & bmask;
+ ep = (struct iso_directory_record *)
+ ((char *)bp->b_data + entryoffsetinblock);
dp->i_offset = saveoffset;
}
goto found;
@@ -370,6 +374,7 @@ notfound:
}
if (bp != NULL)
brelse(bp);
+
/*
* Insert name into cache (as non-existent) if appropriate.
*/
@@ -382,9 +387,7 @@ notfound:
found:
if (numdirpasses == 2)
iso_nchstats.ncs_pass2++;
- if (bp != NULL)
- brelse(bp);
-
+
/*
* Found component in pathname.
* If the final component of path name, save information
@@ -412,31 +415,39 @@ found:
* work if the file system has any hard links other than ".."
* that point backwards in the directory structure.
*/
- pdp = dp;
+ pdp = vdp;
/*
* If ino is different from dp->i_ino,
* it's a relocated directory.
*/
if (flags & ISDOTDOT) {
- ISO_IUNLOCK(pdp); /* race to get the inode */
- if ((error = iso_iget(dp,dp->i_ino,
- dp->i_ino != ino,
- &tdp,ep))) {
- ISO_ILOCK(pdp);
+ VOP_UNLOCK(pdp, 0, p); /* race to get the inode */
+ error = cd9660_vget_internal(vdp->v_mount, dp->i_ino, &tdp,
+ dp->i_ino != ino, ep);
+ brelse(bp);
+ if (error) {
+ vn_lock(pdp, LK_EXCLUSIVE | LK_RETRY, p);
return (error);
}
- if (lockparent && (flags & ISLASTCN))
- ISO_ILOCK(pdp);
- *vpp = ITOV(tdp);
+ if (lockparent && (flags & ISLASTCN) &&
+ (error = vn_lock(pdp, LK_EXCLUSIVE, p))) {
+ vput(tdp);
+ return (error);
+ }
+ *vpp = tdp;
} else if (dp->i_number == dp->i_ino) {
+ brelse(bp);
VREF(vdp); /* we want ourself, ie "." */
*vpp = vdp;
} else {
- if ((error = iso_iget(dp,dp->i_ino,dp->i_ino!=ino,&tdp,ep)))
+ error = cd9660_vget_internal(vdp->v_mount, dp->i_ino, &tdp,
+ dp->i_ino != ino, ep);
+ brelse(bp);
+ if (error)
return (error);
if (!lockparent || !(flags & ISLASTCN))
- ISO_IUNLOCK(pdp);
- *vpp = ITOV(tdp);
+ VOP_UNLOCK(pdp, 0, p);
+ *vpp = tdp;
}
/*
@@ -448,29 +459,37 @@ found:
}
/*
- * Return buffer with contents of block "offset"
- * from the beginning of directory "ip". If "res"
- * is non-zero, fill it in with a pointer to the
+ * Return buffer with the contents of block "offset" from the beginning of
+ * directory "ip". If "res" is non-zero, fill it in with a pointer to the
* remaining space in the directory.
*/
int
-iso_blkatoff(ip, offset, bpp)
- struct iso_node *ip;
- doff_t offset;
- struct buf **bpp;
+cd9660_blkatoff(ap)
+ struct vop_blkatoff_args /* {
+ struct vnode *a_vp;
+ off_t a_offset;
+ char **a_res;
+ struct buf **a_bpp;
+ } */ *ap;
{
- register struct iso_mnt *imp = ip->i_mnt;
- daddr_t lbn = iso_lblkno(imp,offset);
- int bsize = iso_blksize(imp,ip,lbn);
+ struct iso_node *ip;
+ register struct iso_mnt *imp;
struct buf *bp;
- int error;
+ daddr_t lbn;
+ int bsize, error;
- if ((error = bread(ITOV(ip),lbn,bsize,NOCRED,&bp))) {
+ ip = VTOI(ap->a_vp);
+ imp = ip->i_mnt;
+ lbn = lblkno(imp, ap->a_offset);
+ bsize = blksize(imp, ip, lbn);
+
+ if (error = bread(ap->a_vp, lbn, bsize, NOCRED, &bp)) {
brelse(bp);
- *bpp = 0;
+ *ap->a_bpp = NULL;
return (error);
}
- *bpp = bp;
-
+ if (ap->a_res)
+ *ap->a_res = (char *)bp->b_data + blkoff(imp, ap->a_offset);
+ *ap->a_bpp = bp;
return (0);
}
diff --git a/sys/fs/cd9660/cd9660_node.c b/sys/fs/cd9660/cd9660_node.c
index c3f0911..c726696 100644
--- a/sys/fs/cd9660/cd9660_node.c
+++ b/sys/fs/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);
}
diff --git a/sys/fs/cd9660/cd9660_node.h b/sys/fs/cd9660/cd9660_node.h
index 992f9cb..de538fb 100644
--- a/sys/fs/cd9660/cd9660_node.h
+++ b/sys/fs/cd9660/cd9660_node.h
@@ -35,7 +35,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)cd9660_node.h 8.2 (Berkeley) 1/23/94
+ * @(#)cd9660_node.h 8.6 (Berkeley) 5/14/95
* $FreeBSD$
*/
@@ -59,22 +59,20 @@ typedef struct {
dev_t iso_rdev; /* Major/Minor number for special */
} ISO_RRIP_INODE;
-#ifdef ISODEVMAP
+#ifdef ISODEVMAP
/*
* FOr device# (major,minor) translation table
*/
struct iso_dnode {
- struct iso_dnode *d_chain[2]; /* hash chain, MUST be first */
+ struct iso_dnode *d_next, **d_prev; /* hash chain */
dev_t i_dev; /* device where dnode resides */
ino_t i_number; /* the identity of the inode */
dev_t d_dev; /* device # for translation */
};
-#define d_forw d_chain[0]
-#define d_back d_chain[1]
#endif
struct iso_node {
- struct iso_node *i_chain[2]; /* hash chain, MUST be first */
+ struct iso_node *i_next, **i_prev; /* hash chain */
struct vnode *i_vnode; /* vnode associated with this inode */
struct vnode *i_devvp; /* vnode for block I/O */
u_long i_flag; /* see below */
@@ -87,8 +85,7 @@ struct iso_node {
doff_t i_diroff; /* offset in dir, where we found last entry */
doff_t i_offset; /* offset of free space in directory */
ino_t i_ino; /* inode number of found directory */
- long i_spare0;
- long i_spare1;
+ struct lock i_lock; /* node lock */
long iso_extent; /* extent of file */
long i_size;
@@ -101,19 +98,11 @@ struct iso_node {
#define i_back i_chain[1]
/* flags */
-#define ILOCKED 0x0001 /* inode is locked */
-#define IWANT 0x0002 /* some process waiting on lock */
-#define IACC 0x0020 /* inode access time to be updated */
+#define IN_ACCESS 0x0020 /* inode access time to be updated */
#define VTOI(vp) ((struct iso_node *)(vp)->v_data)
#define ITOV(ip) ((ip)->i_vnode)
-#define ISO_ILOCK(ip) iso_ilock(ip)
-#define ISO_IUNLOCK(ip) iso_iunlock(ip)
-
-extern vop_t **cd9660_fifoop_p;
-extern vop_t **cd9660_specop_p;
-
/*
* Prototypes for ISOFS vnode operations
*/
@@ -121,14 +110,19 @@ int cd9660_lookup __P((struct vop_lookup_args *));
int cd9660_inactive __P((struct vop_inactive_args *));
int cd9660_reclaim __P((struct vop_reclaim_args *));
int cd9660_bmap __P((struct vop_bmap_args *));
+int cd9660_pathconf __P((struct vop_pathconf_args *));
+int cd9660_blkatoff __P((struct vop_blkatoff_args *));
+#define cd9660_revoke vop_revoke
+
void cd9660_defattr __P((struct iso_directory_record *,
struct iso_node *, struct buf *, enum ISO_FTYPE));
void cd9660_deftstamp __P((struct iso_directory_record *,
struct iso_node *, struct buf *, enum ISO_FTYPE));
-int cd9660_tstamp_conv7 __P((char *pi, struct timespec *pu, enum ISO_FTYPE));
-int cd9660_tstamp_conv17 __P((unsigned char *pi, struct timespec *pu));
-void isodirino __P((ino_t *inump, struct iso_directory_record *isodir,
- struct iso_mnt *imp));
+struct vnode *cd9660_ihashget __P((dev_t, ino_t));
+void cd9660_ihashins __P((struct iso_node *));
+void cd9660_ihashrem __P((struct iso_node *));
+int cd9660_tstamp_conv7 __P((u_char *, struct timespec *, enum ISO_FTYPE));
+int cd9660_tstamp_conv17 __P((u_char *, struct timespec *));
#ifdef ISODEVMAP
struct iso_dnode *iso_dmap __P((dev_t, ino_t, int));
void iso_dunmap __P((dev_t));
diff --git a/sys/fs/cd9660/cd9660_rrip.c b/sys/fs/cd9660/cd9660_rrip.c
index 44d52eb..521094f 100644
--- a/sys/fs/cd9660/cd9660_rrip.c
+++ b/sys/fs/cd9660/cd9660_rrip.c
@@ -35,7 +35,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)cd9660_rrip.c 8.2 (Berkeley) 1/23/94
+ * @(#)cd9660_rrip.c 8.6 (Berkeley) 12/5/94
* $FreeBSD$
*/
@@ -104,10 +104,10 @@ cd9660_rrip_attr(p,ana)
ISO_RRIP_ATTR *p;
ISO_RRIP_ANALYZE *ana;
{
- ana->inop->inode.iso_mode = isonum_731(p->mode_l);
- ana->inop->inode.iso_uid = (uid_t)isonum_731(p->uid_l);
- ana->inop->inode.iso_gid = (gid_t)isonum_731(p->gid_l);
- ana->inop->inode.iso_links = isonum_731(p->links_l);
+ ana->inop->inode.iso_mode = isonum_733(p->mode);
+ ana->inop->inode.iso_uid = isonum_733(p->uid);
+ ana->inop->inode.iso_gid = isonum_733(p->gid);
+ ana->inop->inode.iso_links = isonum_733(p->links);
ana->fields &= ~ISO_SUSP_ATTR;
return ISO_SUSP_ATTR;
}
@@ -352,8 +352,8 @@ cd9660_rrip_tstamp(p,ana)
ISO_RRIP_TSTAMP *p;
ISO_RRIP_ANALYZE *ana;
{
- unsigned char *ptime;
-
+ u_char *ptime;
+
ptime = p->time;
/* Check a format of time stamp (7bytes/17bytes) */
@@ -367,7 +367,7 @@ cd9660_rrip_tstamp(p,ana)
ptime += 7;
} else
bzero(&ana->inop->inode.iso_mtime,sizeof(struct timespec));
-
+
if (*p->flags&ISO_SUSP_TSTAMP_ACCESS) {
cd9660_tstamp_conv7(ptime,&ana->inop->inode.iso_atime,
ISO_FTYPE_RRIP);
@@ -390,7 +390,7 @@ cd9660_rrip_tstamp(p,ana)
ptime += 17;
} else
bzero(&ana->inop->inode.iso_mtime,sizeof(struct timespec));
-
+
if (*p->flags&ISO_SUSP_TSTAMP_ACCESS) {
cd9660_tstamp_conv17(ptime,&ana->inop->inode.iso_atime);
ptime += 17;
@@ -423,16 +423,15 @@ cd9660_rrip_device(p,ana)
ISO_RRIP_DEVICE *p;
ISO_RRIP_ANALYZE *ana;
{
- unsigned high, low;
-
- high = isonum_733(p->dev_t_high_l);
- low = isonum_733(p->dev_t_low_l);
-
- if ( high == 0 ) {
- ana->inop->inode.iso_rdev = makedev( major(low), minor(low) );
- } else {
- ana->inop->inode.iso_rdev = makedev( high, minor(low) );
- }
+ u_int high, low;
+
+ high = isonum_733(p->dev_t_high);
+ low = isonum_733(p->dev_t_low);
+
+ if (high == 0)
+ ana->inop->inode.iso_rdev = makedev(major(low), minor(low));
+ else
+ ana->inop->inode.iso_rdev = makedev(high, minor(low));
ana->fields &= ~ISO_SUSP_DEVICE;
return ISO_SUSP_DEVICE;
}
@@ -475,8 +474,6 @@ cd9660_rrip_stop(p,ana)
ISO_SUSP_HEADER *p;
ISO_RRIP_ANALYZE *ana;
{
- /* stop analyzing */
- ana->fields = 0;
return ISO_SUSP_STOP;
}
@@ -545,22 +542,30 @@ cd9660_rrip_loop(isodir,ana,table)
if (!ana->fields)
break;
}
+ if (result&ISO_SUSP_STOP) {
+ result &= ~ISO_SUSP_STOP;
+ break;
+ }
+ /* plausibility check */
+ if (isonum_711(phead->length) < sizeof(*phead))
+ break;
/*
* move to next SUSP
* Hopefully this works with newer versions, too
*/
phead = (ISO_SUSP_HEADER *)((char *)phead + isonum_711(phead->length));
}
-
- if ( ana->fields && ana->iso_ce_len ) {
+
+ if (ana->fields && ana->iso_ce_len) {
if (ana->iso_ce_blk >= ana->imp->volume_space_size
|| ana->iso_ce_off + ana->iso_ce_len > ana->imp->logical_block_size
|| bread(ana->imp->im_devvp,
- iso_lblktodaddr(ana->imp, ana->iso_ce_blk),
- ana->imp->logical_block_size,NOCRED,&bp))
+ ana->iso_ce_blk <<
+ (ana->imp->im_bshift - DEV_BSHIFT),
+ ana->imp->logical_block_size, NOCRED, &bp))
/* what to do now? */
break;
- phead = (ISO_SUSP_HEADER *)(bp->b_un.b_addr + ana->iso_ce_off);
+ phead = (ISO_SUSP_HEADER *)(bp->b_data + ana->iso_ce_off);
pend = (ISO_SUSP_HEADER *) ((char *)phead + ana->iso_ce_len);
} else
break;
@@ -569,7 +574,7 @@ cd9660_rrip_loop(isodir,ana,table)
brelse(bp);
/*
* If we don't find the Basic SUSP stuffs, just set default value
- * ( attribute/time stamp )
+ * (attribute/time stamp)
*/
for (ptable = table; ptable->func2; ptable++)
if (!(ptable->result&result))
@@ -579,6 +584,9 @@ cd9660_rrip_loop(isodir,ana,table)
}
/*
+ * Get Attributes.
+ */
+/*
* XXX the casts are bogus but will do for now.
*/
#define BC (rrt_func_t *)
@@ -607,10 +615,8 @@ cd9660_rrip_analyze(isodir,inop,imp)
return cd9660_rrip_loop(isodir,&analyze,rrip_table_analyze);
}
-/*
- * Get Alternate Name from 'AL' record
- * If either no AL record or 0 length,
- * it will be return the translated ISO9660 name,
+/*
+ * Get Alternate Name.
*/
static RRIP_TABLE rrip_table_getname[] = {
{ "NM", BC cd9660_rrip_altname, cd9660_rrip_defname, ISO_SUSP_ALTNAME },
@@ -654,10 +660,8 @@ cd9660_rrip_getname(isodir,outbuf,outlen,inump,imp)
return cd9660_rrip_loop(isodir,&analyze,tab);
}
-/*
- * Get Symbolic Name from 'SL' record
- *
- * Note: isodir should contains SL record!
+/*
+ * Get Symbolic Link.
*/
static RRIP_TABLE rrip_table_getsymname[] = {
{ "SL", BC cd9660_rrip_slink, 0, ISO_SUSP_SLINK },
@@ -696,7 +700,7 @@ static RRIP_TABLE rrip_table_extref[] = {
/*
* Check for Rock Ridge Extension and return offset of its fields.
- * Note: We require the ER field.
+ * Note: We insist on the ER field.
*/
int
cd9660_rrip_offset(isodir,imp)
diff --git a/sys/fs/cd9660/cd9660_rrip.h b/sys/fs/cd9660/cd9660_rrip.h
index e65fb3b..cacee39 100644
--- a/sys/fs/cd9660/cd9660_rrip.h
+++ b/sys/fs/cd9660/cd9660_rrip.h
@@ -35,36 +35,30 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)cd9660_rrip.h 8.1 (Berkeley) 1/21/94
- * $FreeBSD$
+ * @(#)cd9660_rrip.h 8.2 (Berkeley) 12/5/94
+ * $Id: cd9660_rrip.h,v 1.3.2000.1 1996/09/30 12:46:48 dfr Exp $
*/
-
+
typedef struct {
- char type [ISODCL ( 0, 1)];
- unsigned char length [ISODCL ( 2, 2)]; /* 711 */
- unsigned char version [ISODCL ( 3, 3)];
+ char type [ISODCL ( 0, 1)];
+ u_char length [ISODCL ( 2, 2)]; /* 711 */
+ u_char version [ISODCL ( 3, 3)];
} ISO_SUSP_HEADER;
-
+
typedef struct {
ISO_SUSP_HEADER h;
- char mode_l [ISODCL ( 4, 7)]; /* 731 */
- char mode_m [ISODCL ( 8, 11)]; /* 732 */
- char links_l [ISODCL ( 12, 15)]; /* 731 */
- char links_m [ISODCL ( 16, 19)]; /* 732 */
- char uid_l [ISODCL ( 20, 23)]; /* 731 */
- char uid_m [ISODCL ( 24, 27)]; /* 732 */
- char gid_l [ISODCL ( 28, 31)]; /* 731 */
- char gid_m [ISODCL ( 32, 35)]; /* 732 */
+ char mode [ISODCL ( 4, 11)]; /* 733 */
+ char links [ISODCL ( 12, 19)]; /* 733 */
+ char uid [ISODCL ( 20, 27)]; /* 733 */
+ char gid [ISODCL ( 28, 35)]; /* 733 */
} ISO_RRIP_ATTR;
-
+
typedef struct {
ISO_SUSP_HEADER h;
- char dev_t_high_l [ISODCL ( 4, 7)]; /* 731 */
- char dev_t_high_m [ISODCL ( 8, 11)]; /* 732 */
- char dev_t_low_l [ISODCL ( 12, 15)]; /* 731 */
- char dev_t_low_m [ISODCL ( 16, 19)]; /* 732 */
+ char dev_t_high [ISODCL ( 4, 11)]; /* 733 */
+ char dev_t_low [ISODCL ( 12, 19)]; /* 733 */
} ISO_RRIP_DEVICE;
-
+
#define ISO_SUSP_CFLAG_CONTINUE 0x01
#define ISO_SUSP_CFLAG_CURRENT 0x02
#define ISO_SUSP_CFLAG_PARENT 0x04
@@ -73,9 +67,9 @@ typedef struct {
#define ISO_SUSP_CFLAG_HOST 0x20
typedef struct {
- u_char cflag [ISODCL ( 1, 1)];
- u_char clen [ISODCL ( 2, 2)];
- u_char name [0];
+ u_char cflag [ISODCL ( 1, 1)];
+ u_char clen [ISODCL ( 2, 2)];
+ u_char name [1]; /* XXX */
} ISO_RRIP_SLINK_COMPONENT;
#define ISO_RRIP_SLSIZ 2
@@ -116,13 +110,13 @@ typedef struct {
typedef struct {
ISO_SUSP_HEADER h;
- unsigned char flags [ISODCL ( 4, 4)];
- unsigned char time [ISODCL ( 5, 5)];
+ u_char flags [ISODCL ( 4, 4)];
+ u_char time [ISODCL ( 5, 5)];
} ISO_RRIP_TSTAMP;
typedef struct {
ISO_SUSP_HEADER h;
- unsigned char flags [ISODCL ( 4, 4)];
+ u_char flags [ISODCL ( 4, 4)];
} ISO_RRIP_IDFLAG;
typedef struct {
diff --git a/sys/fs/cd9660/cd9660_util.c b/sys/fs/cd9660/cd9660_util.c
index 786d4fd..151d1c3 100644
--- a/sys/fs/cd9660/cd9660_util.c
+++ b/sys/fs/cd9660/cd9660_util.c
@@ -35,7 +35,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)cd9660_util.c 8.1 (Berkeley) 1/21/94
+ * @(#)cd9660_util.c 8.3 (Berkeley) 12/5/94
* $FreeBSD$
*/
@@ -58,104 +58,14 @@
#include <isofs/cd9660/iso.h>
-#ifdef __notanymore__
-int
-isonum_711 (p)
-unsigned char *p;
-{
- return (*p);
-}
-
-int
-isonum_712 (p)
-signed char *p;
-{
- return (*p);
-}
-
-int
-isonum_721 (p)
-unsigned char *p;
-{
- /* little endian short */
-#if BYTE_ORDER != LITTLE_ENDIAN
- printf ("isonum_721 called on non little-endian machine!\n");
-#endif
-
- return *(short *)p;
-}
-
-int
-isonum_722 (p)
-unsigned char *p;
-{
- /* big endian short */
-#if BYTE_ORDER != BIG_ENDIAN
- printf ("isonum_722 called on non big-endian machine!\n");
-#endif
-
- return *(short *)p;
-}
-
-int
-isonum_723 (p)
-unsigned char *p;
-{
-#if BYTE_ORDER == BIG_ENDIAN
- return isonum_722 (p + 2);
-#elif BYTE_ORDER == LITTLE_ENDIAN
- return isonum_721 (p);
-#else
- printf ("isonum_723 unsupported byte order!\n");
- return 0;
-#endif
-}
-
-int
-isonum_731 (p)
-unsigned char *p;
-{
- /* little endian long */
-#if BYTE_ORDER != LITTLE_ENDIAN
- printf ("isonum_731 called on non little-endian machine!\n");
-#endif
-
- return *(long *)p;
-}
-
-int
-isonum_732 (p)
-unsigned char *p;
-{
- /* big endian long */
-#if BYTE_ORDER != BIG_ENDIAN
- printf ("isonum_732 called on non big-endian machine!\n");
-#endif
-
- return *(long *)p;
-}
-
-int
-isonum_733 (p)
-unsigned char *p;
-{
-#if BYTE_ORDER == BIG_ENDIAN
- return isonum_732 (p + 4);
-#elif BYTE_ORDER == LITTLE_ENDIAN
- return isonum_731 (p);
-#else
- printf ("isonum_733 unsupported byte order!\n");
- return 0;
-#endif
-}
-#endif /* __notanymore__ */
-
/*
* translate and compare a filename
* Note: Version number plus ';' may be omitted.
*/
int
-isofncmp(unsigned char *fn,int fnlen,unsigned char *isofn,int isolen)
+isofncmp(fn, fnlen, isofn, isolen)
+ u_char *fn, *isofn;
+ int fnlen, isolen;
{
int i, j;
unsigned char c;
@@ -211,9 +121,12 @@ isofncmp(unsigned char *fn,int fnlen,unsigned char *isofn,int isolen)
* translate a filename
*/
void
-isofntrans(unsigned char *infn,int infnlen,
- unsigned char *outfn,unsigned short *outfnlen,
- int original,int assoc)
+isofntrans(infn, infnlen, outfn, outfnlen, original, assoc)
+ u_char *infn, *outfn;
+ int infnlen;
+ u_short *outfnlen;
+ int original;
+ int assoc;
{
int fnidx = 0;
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);
}
/*
diff --git a/sys/fs/cd9660/cd9660_vnops.c b/sys/fs/cd9660/cd9660_vnops.c
index 88440eb..854d6b5 100644
--- a/sys/fs/cd9660/cd9660_vnops.c
+++ b/sys/fs/cd9660/cd9660_vnops.c
@@ -35,7 +35,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)cd9660_vnops.c 8.3 (Berkeley) 1/23/94
+ * @(#)cd9660_vnops.c 8.19 (Berkeley) 5/27/95
* $FreeBSD$
*/
@@ -55,6 +55,7 @@
#include <miscfs/fifofs/fifo.h>
#include <sys/malloc.h>
#include <sys/dir.h>
+#include <sys/unistd.h>
#include <isofs/cd9660/iso.h>
#include <isofs/cd9660/cd9660_node.h>
@@ -81,7 +82,6 @@ static int cd9660_lock __P((struct vop_lock_args *));
static int cd9660_unlock __P((struct vop_unlock_args *));
static int cd9660_strategy __P((struct vop_strategy_args *));
static int cd9660_print __P((struct vop_print_args *));
-static int cd9660_enotsupp __P((void));
static int cd9660_islocked __P((struct vop_islocked_args *));
#if 0
@@ -100,7 +100,7 @@ cd9660_mknod(ndp, vap, cred, p)
free(ndp->ni_pnbuf, M_NAMEI);
vput(ndp->ni_dvp);
vput(ndp->ni_vp);
- return EINVAL;
+ return (EINVAL);
#else
register struct vnode *vp;
struct iso_node *ip;
@@ -116,7 +116,7 @@ cd9660_mknod(ndp, vap, cred, p)
free(ndp->ni_pnbuf, M_NAMEI);
vput(ndp->ni_dvp);
vput(ndp->ni_vp);
- return EINVAL;
+ return (EINVAL);
}
dp = iso_dmap(ip->i_dev,ip->i_number,1);
@@ -144,7 +144,7 @@ cd9660_mknod(ndp, vap, cred, p)
/*
* Setattr call. Only allowed for block and character special devices.
*/
-static int
+int
cd9660_setattr(ap)
struct vop_setattr_args /* {
struct vnodeop_desc *a_desc;
@@ -175,7 +175,7 @@ cd9660_setattr(ap)
return (0);
}
}
- return (EOPNOTSUPP);
+ return (0);
}
/*
@@ -229,23 +229,65 @@ cd9660_access(ap)
struct proc *a_p;
} */ *ap;
{
+ struct vnode *vp = ap->a_vp;
+ struct iso_node *ip = VTOI(vp);
+ struct ucred *cred = ap->a_cred;
+ mode_t mask, mode = ap->a_mode;
+ gid_t *gp;
+ int i;
+
/*
- * Disallow write attempts on read-only file systems;
- * unless the file is a socket, fifo, or a block or
- * character device resident on the file system.
+ * Disallow write attempts unless the file is a socket,
+ * fifo, or a block or character device resident on the
+ * file system.
*/
- if (ap->a_mode & VWRITE) {
- switch (ap->a_vp->v_type) {
+ if (mode & VWRITE) {
+ switch (vp->v_type) {
case VDIR:
case VLNK:
case VREG:
- if (ap->a_vp->v_mount->mnt_flag & MNT_RDONLY)
- return (EROFS);
- break;
+ return (EROFS);
}
}
- return (0);
+ /* User id 0 always gets access. */
+ if (cred->cr_uid == 0)
+ return (0);
+
+ mask = 0;
+
+ /* Otherwise, check the owner. */
+ if (cred->cr_uid == ip->inode.iso_uid) {
+ if (mode & VEXEC)
+ mask |= S_IXUSR;
+ if (mode & VREAD)
+ mask |= S_IRUSR;
+ if (mode & VWRITE)
+ mask |= S_IWUSR;
+ return ((ip->inode.iso_mode & mask) == mask ? 0 : EACCES);
+ }
+
+ /* Otherwise, check the groups. */
+ for (i = 0, gp = cred->cr_groups; i < cred->cr_ngroups; i++, gp++)
+ if (ip->inode.iso_gid == *gp) {
+ if (mode & VEXEC)
+ mask |= S_IXGRP;
+ if (mode & VREAD)
+ mask |= S_IRGRP;
+ if (mode & VWRITE)
+ mask |= S_IWGRP;
+ return ((ip->inode.iso_mode & mask) == mask ?
+ 0 : EACCES);
+ }
+
+ /* Otherwise, check everyone else. */
+ if (mode & VEXEC)
+ mask |= S_IXOTH;
+ if (mode & VREAD)
+ mask |= S_IROTH;
+ if (mode & VWRITE)
+ mask |= S_IWOTH;
+ return ((ip->inode.iso_mode & mask) == mask ? 0 : EACCES);
}
static int
@@ -275,6 +317,29 @@ cd9660_getattr(ap)
vap->va_rdev = ip->inode.iso_rdev;
vap->va_size = (u_quad_t) ip->i_size;
+ if (ip->i_size == 0 && (vap->va_mode & S_IFMT) == S_IFLNK) {
+ struct vop_readlink_args rdlnk;
+ struct iovec aiov;
+ struct uio auio;
+ char *cp;
+
+ MALLOC(cp, char *, MAXPATHLEN, M_TEMP, M_WAITOK);
+ aiov.iov_base = cp;
+ aiov.iov_len = MAXPATHLEN;
+ auio.uio_iov = &aiov;
+ auio.uio_iovcnt = 1;
+ auio.uio_offset = 0;
+ auio.uio_rw = UIO_READ;
+ auio.uio_segflg = UIO_SYSSPACE;
+ auio.uio_procp = ap->a_p;
+ auio.uio_resid = MAXPATHLEN;
+ rdlnk.a_uio = &auio;
+ rdlnk.a_vp = ap->a_vp;
+ rdlnk.a_cred = ap->a_cred;
+ if (cd9660_readlink(&rdlnk) == 0)
+ vap->va_size = MAXPATHLEN - auio.uio_resid;
+ FREE(cp, M_TEMP);
+ }
vap->va_flags = 0;
vap->va_gen = 1;
vap->va_blocksize = ip->i_mnt->logical_block_size;
@@ -325,31 +390,31 @@ cd9660_read(ap)
return (0);
if (uio->uio_offset < 0)
return (EINVAL);
- ip->i_flag |= IACC;
+ ip->i_flag |= IN_ACCESS;
imp = ip->i_mnt;
do {
- lbn = iso_lblkno(imp, uio->uio_offset);
- on = iso_blkoff(imp, uio->uio_offset);
- n = min((unsigned)(imp->logical_block_size - on),
+ lbn = lblkno(imp, uio->uio_offset);
+ on = blkoff(imp, uio->uio_offset);
+ n = min((u_int)(imp->logical_block_size - on),
uio->uio_resid);
diff = (off_t)ip->i_size - uio->uio_offset;
if (diff <= 0)
return (0);
if (diff < n)
n = diff;
- size = iso_blksize(imp, ip, lbn);
+ size = blksize(imp, ip, lbn);
rablock = lbn + 1;
if (doclusterread) {
- if (iso_lblktosize(imp, rablock) <= ip->i_size)
- error = cluster_read(vp, ip->i_size,
+ if (lblktosize(imp, rablock) <= ip->i_size)
+ error = cluster_read(vp, (off_t)ip->i_size,
lbn, size, NOCRED, uio->uio_resid,
(ap->a_ioflag >> 16), &bp);
else
error = bread(vp, lbn, size, NOCRED, &bp);
} else {
if (vp->v_lastr + 1 == lbn &&
- iso_lblktosize(imp, rablock) < ip->i_size) {
- rasize = iso_blksize(imp, ip, rablock);
+ lblktosize(imp, rablock) < ip->i_size) {
+ rasize = blksize(imp, ip, rablock);
error = breadn(vp, lbn, size, &rablock,
&rasize, 1, NOCRED, &bp);
} else
@@ -362,7 +427,10 @@ cd9660_read(ap)
return (error);
}
- error = uiomove(bp->b_un.b_addr + on, (int)n, uio);
+ error = uiomove(bp->b_data + on, (int)n, uio);
+ if (n + on == imp->logical_block_size ||
+ uio->uio_offset == (off_t)ip->i_size)
+ bp->b_flags |= B_AGE;
brelse(bp);
} while (error == 0 && uio->uio_resid > 0 && n != 0);
return (error);
@@ -373,8 +441,8 @@ static int
cd9660_ioctl(ap)
struct vop_ioctl_args /* {
struct vnode *a_vp;
- int a_command;
- caddr_t a_data;
+ u_long a_command;
+ caddr_t a_data;
int a_fflag;
struct ucred *a_cred;
struct proc *a_p;
@@ -452,12 +520,12 @@ struct isoreaddir {
off_t curroff;
struct uio *uio;
off_t uio_off;
- u_int *cookiep;
+ int eofflag;
+ u_long *cookies;
int ncookies;
- int eof;
};
-static int
+int
iso_uiodir(idp,dp,off)
struct isoreaddir *idp;
struct dirent *dp;
@@ -469,27 +537,27 @@ iso_uiodir(idp,dp,off)
dp->d_reclen = DIRSIZ(dp);
if (idp->uio->uio_resid < dp->d_reclen) {
- idp->eof = 0;
- return -1;
+ idp->eofflag = 0;
+ return (-1);
}
- if (idp->cookiep) {
+ if (idp->cookies) {
if (idp->ncookies <= 0) {
- idp->eof = 0;
- return -1;
+ idp->eofflag = 0;
+ return (-1);
}
- *idp->cookiep++ = off;
+ *idp->cookies++ = off;
--idp->ncookies;
}
- if ((error = uiomove((caddr_t)dp,dp->d_reclen,idp->uio)))
- return error;
+ if (error = uiomove((caddr_t) dp,dp->d_reclen,idp->uio))
+ return (error);
idp->uio_off = off;
- return 0;
+ return (0);
}
-static int
+int
iso_shipdir(idp)
struct isoreaddir *idp;
{
@@ -517,13 +585,13 @@ assoc = (cl > 1) && (*cname == ASSOCCHAR);
if (sl != cl
|| bcmp(sname,cname,sl)) {
if (idp->assocent.d_namlen) {
- if ((error = iso_uiodir(idp,&idp->assocent,idp->assocoff)))
- return error;
+ if (error = iso_uiodir(idp,&idp->assocent,idp->assocoff))
+ return (error);
idp->assocent.d_namlen = 0;
}
if (idp->saveent.d_namlen) {
- if ((error = iso_uiodir(idp,&idp->saveent,idp->saveoff)))
- return error;
+ if (error = iso_uiodir(idp,&idp->saveent,idp->saveoff))
+ return (error);
idp->saveent.d_namlen = 0;
}
}
@@ -536,13 +604,11 @@ assoc = (cl > 1) && (*cname == ASSOCCHAR);
idp->saveoff = idp->curroff;
bcopy(&idp->current,&idp->saveent,idp->current.d_reclen);
}
- return 0;
+ return (0);
}
/*
* Vnode op for readdir
- * XXX make sure everything still works now that eofflagp and cookiep
- * are no longer args.
*/
static int
cd9660_readdir(ap)
@@ -550,54 +616,61 @@ cd9660_readdir(ap)
struct vnode *a_vp;
struct uio *a_uio;
struct ucred *a_cred;
+ int *a_eofflag;
+ int *a_ncookies;
+ u_long *a_cookies;
} */ *ap;
{
register struct uio *uio = ap->a_uio;
struct isoreaddir *idp;
+ struct vnode *vdp = ap->a_vp;
+ struct iso_node *dp;
+ struct iso_mnt *imp;
+ struct buf *bp = NULL;
+ struct iso_directory_record *ep;
int entryoffsetinblock;
+ doff_t endsearch;
+ u_long bmask;
int error = 0;
- int endsearch;
- struct iso_directory_record *ep;
- u_short elen;
- int namlen;
int reclen;
- int isoflags;
- struct iso_mnt *imp;
- struct iso_node *ip;
- struct buf *bp = NULL;
- u_short tmplen;
+ u_short namelen;
int ncookies = 0;
- u_int *cookies = NULL;
+ u_long *cookies = NULL;
- ip = VTOI(ap->a_vp);
- imp = ip->i_mnt;
+ dp = VTOI(vdp);
+ imp = dp->i_mnt;
+ bmask = imp->im_bmask;
- MALLOC(idp,struct isoreaddir *,sizeof(*idp),M_TEMP,M_WAITOK);
- idp->saveent.d_namlen = 0;
- idp->assocent.d_namlen = 0;
+ MALLOC(idp, struct isoreaddir *, sizeof(*idp), M_TEMP, M_WAITOK);
+ idp->saveent.d_namlen = idp->assocent.d_namlen = 0;
+ /*
+ * XXX
+ * Is it worth trying to figure out the type?
+ */
+ idp->saveent.d_type = idp->assocent.d_type = idp->current.d_type =
+ DT_UNKNOWN;
idp->uio = uio;
- if (ap->a_ncookies != NULL) {
+ if (ap->a_ncookies == NULL) {
+ idp->cookies = NULL;
+ } else {
/*
* Guess the number of cookies needed.
*/
ncookies = uio->uio_resid / 16;
- MALLOC(cookies, u_int *, ncookies * sizeof(u_int), M_TEMP, M_WAITOK);
- idp->cookiep = cookies;
+ MALLOC(cookies, u_long *, ncookies * sizeof(u_int), M_TEMP,
+ M_WAITOK);
+ idp->cookies = cookies;
idp->ncookies = ncookies;
- } else
- idp->cookiep = 0;
- idp->eof = 0;
+ }
+ idp->eofflag = 1;
idp->curroff = uio->uio_offset;
- entryoffsetinblock = iso_blkoff(imp, idp->curroff);
- if (entryoffsetinblock != 0) {
- if ((error = iso_blkatoff(ip, idp->curroff, &bp))) {
- FREE(idp,M_TEMP);
- return (error);
- }
+ if ((entryoffsetinblock = idp->curroff & bmask) &&
+ (error = VOP_BLKATOFF(vdp, (off_t)idp->curroff, NULL, &bp))) {
+ FREE(idp, M_TEMP);
+ return (error);
}
-
- endsearch = ip->i_size;
+ endsearch = dp->i_size;
while (idp->curroff < endsearch) {
/*
@@ -605,26 +678,25 @@ cd9660_readdir(ap)
* read the next directory block.
* Release previous if it exists.
*/
-
- if (iso_blkoff(imp, idp->curroff) == 0) {
+ if ((idp->curroff & bmask) == 0) {
if (bp != NULL)
brelse(bp);
- if ((error = iso_blkatoff(ip, idp->curroff, &bp)))
+ if (error =
+ VOP_BLKATOFF(vdp, (off_t)idp->curroff, NULL, &bp))
break;
entryoffsetinblock = 0;
}
/*
* Get pointer to next entry.
*/
-
ep = (struct iso_directory_record *)
- (bp->b_un.b_addr + entryoffsetinblock);
+ ((char *)bp->b_data + entryoffsetinblock);
- reclen = isonum_711 (ep->length);
+ reclen = isonum_711(ep->length);
if (reclen == 0) {
/* skip to next block, if any */
- idp->curroff = roundup (idp->curroff,
- imp->logical_block_size);
+ idp->curroff =
+ (idp->curroff & ~bmask) + imp->logical_block_size;
continue;
}
@@ -640,35 +712,27 @@ cd9660_readdir(ap)
break;
}
- namlen = isonum_711 (ep->name_len);
- if (reclen < ISO_DIRECTORY_RECORD_SIZE + namlen) {
+ idp->current.d_namlen = isonum_711(ep->name_len);
+
+ if (reclen < ISO_DIRECTORY_RECORD_SIZE + idp->current.d_namlen) {
error = EINVAL;
/* illegal entry, stop */
break;
}
- /* XXX: be more intelligent if we can */
- idp->current.d_type = DT_UNKNOWN;
-
- idp->current.d_namlen = namlen;
- isoflags = isonum_711(imp->iso_ftype == ISO_FTYPE_HIGH_SIERRA?
- &ep->date[6]: ep->flags);
- if (isoflags & 2)
- isodirino(&idp->current.d_fileno,ep,imp);
+ if (isonum_711(ep->flags)&2)
+ idp->current.d_fileno = isodirino(ep, imp);
else
idp->current.d_fileno = dbtob(bp->b_blkno) +
- idp->curroff;
+ entryoffsetinblock;
idp->curroff += reclen;
- /*
- *
- */
+
switch (imp->iso_ftype) {
case ISO_FTYPE_RRIP:
- cd9660_rrip_getname(ep,idp->current.d_name,
- &tmplen,
+ cd9660_rrip_getname(ep,idp->current.d_name, &namelen,
&idp->current.d_fileno,imp);
- idp->current.d_namlen = tmplen;
+ idp->current.d_namlen = (u_char)namelen;
if (idp->current.d_namlen)
error = iso_uiodir(idp,&idp->current,idp->curroff);
break;
@@ -685,10 +749,10 @@ cd9660_readdir(ap)
break;
default:
isofntrans(ep->name,idp->current.d_namlen,
- idp->current.d_name, &elen,
+ idp->current.d_name, &namelen,
imp->iso_ftype == ISO_FTYPE_9660,
- isoflags & 4);
- idp->current.d_namlen = (u_char)elen;
+ isonum_711(ep->flags)&4);
+ idp->current.d_namlen = (u_char)namelen;
if (imp->iso_ftype == ISO_FTYPE_DEFAULT)
error = iso_shipdir(idp);
else
@@ -711,7 +775,7 @@ cd9660_readdir(ap)
if (ap->a_ncookies != NULL) {
if (error)
- FREE(cookies, M_TEMP);
+ free(cookies, M_TEMP);
else {
/*
* Work out the number of cookies actually used.
@@ -725,10 +789,9 @@ cd9660_readdir(ap)
brelse (bp);
uio->uio_offset = idp->uio_off;
- if (ap->a_eofflag)
- *ap->a_eofflag = idp->eof;
+ *ap->a_eofflag = idp->eofflag;
- FREE(idp,M_TEMP);
+ FREE(idp, M_TEMP);
return (error);
}
@@ -754,44 +817,34 @@ cd9660_readlink(ap)
ISODIR *dirp;
ISOMNT *imp;
struct buf *bp;
+ struct uio *uio;
u_short symlen;
int error;
char *symname;
ip = VTOI(ap->a_vp);
imp = ip->i_mnt;
+ uio = ap->a_uio;
if (imp->iso_ftype != ISO_FTYPE_RRIP)
- return EINVAL;
+ return (EINVAL);
/*
* Get parents directory record block that this inode included.
*/
error = bread(imp->im_devvp,
- iso_dblkno(imp, ip->i_number),
- imp->logical_block_size,
- NOCRED,
- &bp);
+ (ip->i_number >> imp->im_bshift) <<
+ (imp->im_bshift - DEV_BSHIFT),
+ imp->logical_block_size, NOCRED, &bp);
if (error) {
brelse(bp);
- return EINVAL;
+ return (EINVAL);
}
/*
* Setup the directory pointer for this inode
*/
- dirp = (ISODIR *)(bp->b_un.b_addr + (ip->i_number & imp->im_bmask));
-#ifdef DEBUG
- printf("lbn=%d,off=%d,bsize=%d,DEV_BSIZE=%d, dirp= %08x, b_addr=%08x, offset=%08x(%08x)\n",
- (daddr_t)(ip->i_number >> imp->im_bshift),
- ip->i_number & imp->im_bmask,
- imp->logical_block_size,
- DEV_BSIZE,
- dirp,
- bp->b_un.b_addr,
- ip->i_number,
- ip->i_number & imp->im_bmask );
-#endif
+ dirp = (ISODIR *)(bp->b_data + (ip->i_number & imp->im_bmask));
/*
* Just make sure, we have a right one....
@@ -800,22 +853,26 @@ cd9660_readlink(ap)
if ((ip->i_number & imp->im_bmask) + isonum_711(dirp->length)
> (unsigned)imp->logical_block_size) {
brelse(bp);
- return EINVAL;
+ return (EINVAL);
}
/*
* Now get a buffer
* Abuse a namei buffer for now.
*/
- MALLOC(symname,char *,MAXPATHLEN,M_NAMEI,M_WAITOK);
-
+ if (uio->uio_segflg == UIO_SYSSPACE)
+ symname = uio->uio_iov->iov_base;
+ else
+ MALLOC(symname, char *, MAXPATHLEN, M_NAMEI, M_WAITOK);
+
/*
* Ok, we just gathering a symbolic name in SL record.
*/
- if (cd9660_rrip_getsymname(dirp,symname,&symlen,imp) == 0) {
- FREE(symname,M_NAMEI);
+ if (cd9660_rrip_getsymname(dirp, symname, &symlen, imp) == 0) {
+ if (uio->uio_segflg != UIO_SYSSPACE)
+ FREE(symname, M_NAMEI);
brelse(bp);
- return EINVAL;
+ return (EINVAL);
}
/*
* Don't forget before you leave from home ;-)
@@ -825,11 +882,15 @@ cd9660_readlink(ap)
/*
* return with the symbolic name to caller's.
*/
- error = uiomove(symname,symlen,ap->a_uio);
-
- FREE(symname,M_NAMEI);
-
- return error;
+ if (uio->uio_segflg != UIO_SYSSPACE) {
+ error = uiomove(symname, symlen, uio);
+ FREE(symname, M_NAMEI);
+ return (error);
+ }
+ uio->uio_resid -= symlen;
+ uio->uio_iov->iov_base += symlen;
+ uio->uio_iov->iov_len -= symlen;
+ return (0);
}
/*
@@ -845,7 +906,7 @@ cd9660_abortop(ap)
{
if ((ap->a_cnp->cn_flags & (HASBUF | SAVESTART)) == HASBUF)
FREE(ap->a_cnp->cn_pnbuf, M_NAMEI);
- return 0;
+ return (0);
}
/*
@@ -855,12 +916,14 @@ static int
cd9660_lock(ap)
struct vop_lock_args /* {
struct vnode *a_vp;
+ int a_flags;
+ struct proc *a_p;
} */ *ap;
{
- register struct iso_node *ip = VTOI(ap->a_vp);
+ struct vnode *vp = ap->a_vp;
- ISO_ILOCK(ip);
- return 0;
+ return (lockmgr(&VTOI(vp)->i_lock, ap->a_flags, &vp->v_interlock,
+ ap->a_p));
}
/*
@@ -870,29 +933,14 @@ static int
cd9660_unlock(ap)
struct vop_unlock_args /* {
struct vnode *a_vp;
+ int a_flags;
+ struct proc *a_p;
} */ *ap;
{
- register struct iso_node *ip = VTOI(ap->a_vp);
-
- if (!(ip->i_flag & ILOCKED))
- panic("cd9660_unlock NOT LOCKED");
- ISO_IUNLOCK(ip);
- return 0;
-}
-
-/*
- * Check for a locked inode.
- */
-static int
-cd9660_islocked(ap)
- struct vop_islocked_args /* {
- struct vnode *a_vp;
- } */ *ap;
-{
+ struct vnode *vp = ap->a_vp;
- if (VTOI(ap->a_vp)->i_flag & ILOCKED)
- return 1;
- return 0;
+ return (lockmgr(&VTOI(vp)->i_lock, ap->a_flags | LK_RELEASE,
+ &vp->v_interlock, ap->a_p));
}
/*
@@ -943,102 +991,150 @@ cd9660_print(ap)
struct vnode *a_vp;
} */ *ap;
{
+
printf("tag VT_ISOFS, isofs vnode\n");
- return 0;
+ return (0);
+}
+
+/*
+ * Check for a locked inode.
+ */
+int
+cd9660_islocked(ap)
+ struct vop_islocked_args /* {
+ struct vnode *a_vp;
+ } */ *ap;
+{
+
+ return (lockstatus(&VTOI(ap->a_vp)->i_lock));
}
/*
- * Unsupported operation
+ * Return POSIX pathconf information applicable to cd9660 filesystems.
*/
-static int
-cd9660_enotsupp()
+int
+cd9660_pathconf(ap)
+ struct vop_pathconf_args /* {
+ struct vnode *a_vp;
+ int a_name;
+ register_t *a_retval;
+ } */ *ap;
{
- return (EOPNOTSUPP);
+ switch (ap->a_name) {
+ case _PC_LINK_MAX:
+ *ap->a_retval = 1;
+ return (0);
+ case _PC_NAME_MAX:
+ if (VTOI(ap->a_vp)->i_mnt->iso_ftype == ISO_FTYPE_RRIP)
+ *ap->a_retval = NAME_MAX;
+ else
+ *ap->a_retval = 37;
+ return (0);
+ case _PC_PATH_MAX:
+ *ap->a_retval = PATH_MAX;
+ return (0);
+ case _PC_PIPE_BUF:
+ *ap->a_retval = PIPE_BUF;
+ return (0);
+ case _PC_CHOWN_RESTRICTED:
+ *ap->a_retval = 1;
+ return (0);
+ case _PC_NO_TRUNC:
+ *ap->a_retval = 1;
+ return (0);
+ default:
+ return (EINVAL);
+ }
+ /* NOTREACHED */
}
/*
* Global vfs data structures for isofs
*/
#define cd9660_create \
- ((int (*) __P((struct vop_create_args *)))cd9660_enotsupp)
-#define cd9660_mknod ((int (*) __P((struct vop_mknod_args *)))cd9660_enotsupp)
-#define cd9660_write ((int (*) __P((struct vop_write_args *)))cd9660_enotsupp)
+ ((int (*) __P((struct vop_create_args *)))eopnotsupp)
+#define cd9660_mknod ((int (*) __P((struct vop_mknod_args *)))eopnotsupp)
+#define cd9660_write ((int (*) __P((struct vop_write_args *)))eopnotsupp)
+#ifdef NFS
+#define cd9660_lease_check lease_check
+#else
+#define cd9660_lease_check ((int (*) __P((struct vop_lease_args *)))nullop)
+#endif
#define cd9660_fsync ((int (*) __P((struct vop_fsync_args *)))nullop)
#define cd9660_remove \
- ((int (*) __P((struct vop_remove_args *)))cd9660_enotsupp)
-#define cd9660_link ((int (*) __P((struct vop_link_args *)))cd9660_enotsupp)
+ ((int (*) __P((struct vop_remove_args *)))eopnotsupp)
+#define cd9660_link ((int (*) __P((struct vop_link_args *)))eopnotsupp)
#define cd9660_rename \
- ((int (*) __P((struct vop_rename_args *)))cd9660_enotsupp)
-#define cd9660_mkdir ((int (*) __P((struct vop_mkdir_args *)))cd9660_enotsupp)
-#define cd9660_rmdir ((int (*) __P((struct vop_rmdir_args *)))cd9660_enotsupp)
+ ((int (*) __P((struct vop_rename_args *)))eopnotsupp)
+#define cd9660_mkdir ((int (*) __P((struct vop_mkdir_args *)))eopnotsupp)
+#define cd9660_rmdir ((int (*) __P((struct vop_rmdir_args *)))eopnotsupp)
#define cd9660_symlink \
- ((int (*) __P((struct vop_symlink_args *)))cd9660_enotsupp)
-#define cd9660_pathconf \
- ((int (*) __P((struct vop_pathconf_args *)))cd9660_enotsupp)
+ ((int (*) __P((struct vop_symlink_args *)))eopnotsupp)
#define cd9660_advlock \
- ((int (*) __P((struct vop_advlock_args *)))cd9660_enotsupp)
-#define cd9660_blkatoff \
- ((int (*) __P((struct vop_blkatoff_args *)))cd9660_enotsupp)
+ ((int (*) __P((struct vop_advlock_args *)))eopnotsupp)
#define cd9660_valloc ((int(*) __P(( \
struct vnode *pvp, \
int mode, \
struct ucred *cred, \
- struct vnode **vpp))) cd9660_enotsupp)
-#define cd9660_vfree ((int (*) __P((struct vop_vfree_args *)))cd9660_enotsupp)
+ struct vnode **vpp))) eopnotsupp)
+#define cd9660_vfree ((int (*) __P((struct vop_vfree_args *)))eopnotsupp)
#define cd9660_truncate \
- ((int (*) __P((struct vop_truncate_args *)))cd9660_enotsupp)
+ ((int (*) __P((struct vop_truncate_args *)))eopnotsupp)
#define cd9660_update \
- ((int (*) __P((struct vop_update_args *)))cd9660_enotsupp)
+ ((int (*) __P((struct vop_update_args *)))eopnotsupp)
#define cd9660_bwrite \
- ((int (*) __P((struct vop_bwrite_args *)))cd9660_enotsupp)
+ ((int (*) __P((struct vop_bwrite_args *)))eopnotsupp)
/*
- * Global vfs data structures for nfs
+ * Global vfs data structures for cd9660
*/
vop_t **cd9660_vnodeop_p;
-static struct vnodeopv_entry_desc cd9660_vnodeop_entries[] = {
+struct vnodeopv_entry_desc cd9660_vnodeop_entries[] = {
+
{ &vop_default_desc, (vop_t *)vn_default_error },
- { &vop_lookup_desc, (vop_t *)cd9660_lookup }, /* lookup */
- { &vop_create_desc, (vop_t *)cd9660_create }, /* create */
- { &vop_mknod_desc, (vop_t *)cd9660_mknod }, /* mknod */
- { &vop_open_desc, (vop_t *)cd9660_open }, /* open */
- { &vop_close_desc, (vop_t *)cd9660_close }, /* close */
- { &vop_access_desc, (vop_t *)cd9660_access }, /* access */
- { &vop_getattr_desc, (vop_t *)cd9660_getattr }, /* getattr */
- { &vop_setattr_desc, (vop_t *)cd9660_setattr }, /* setattr */
- { &vop_read_desc, (vop_t *)cd9660_read }, /* read */
- { &vop_write_desc, (vop_t *)cd9660_write }, /* write */
- { &vop_ioctl_desc, (vop_t *)cd9660_ioctl }, /* ioctl */
- { &vop_select_desc, (vop_t *)cd9660_select }, /* select */
- { &vop_mmap_desc, (vop_t *)cd9660_mmap }, /* mmap */
- { &vop_fsync_desc, (vop_t *)cd9660_fsync }, /* fsync */
- { &vop_seek_desc, (vop_t *)cd9660_seek }, /* seek */
- { &vop_remove_desc, (vop_t *)cd9660_remove }, /* remove */
- { &vop_link_desc, (vop_t *)cd9660_link }, /* link */
- { &vop_rename_desc, (vop_t *)cd9660_rename }, /* rename */
- { &vop_mkdir_desc, (vop_t *)cd9660_mkdir }, /* mkdir */
- { &vop_rmdir_desc, (vop_t *)cd9660_rmdir }, /* rmdir */
- { &vop_symlink_desc, (vop_t *)cd9660_symlink }, /* symlink */
- { &vop_readdir_desc, (vop_t *)cd9660_readdir }, /* readdir */
- { &vop_readlink_desc, (vop_t *)cd9660_readlink }, /* readlink */
- { &vop_abortop_desc, (vop_t *)cd9660_abortop }, /* abortop */
- { &vop_inactive_desc, (vop_t *)cd9660_inactive }, /* inactive */
- { &vop_reclaim_desc, (vop_t *)cd9660_reclaim }, /* reclaim */
- { &vop_lock_desc, (vop_t *)cd9660_lock }, /* lock */
- { &vop_unlock_desc, (vop_t *)cd9660_unlock }, /* unlock */
- { &vop_bmap_desc, (vop_t *)cd9660_bmap }, /* bmap */
- { &vop_strategy_desc, (vop_t *)cd9660_strategy }, /* strategy */
- { &vop_print_desc, (vop_t *)cd9660_print }, /* print */
- { &vop_islocked_desc, (vop_t *)cd9660_islocked }, /* islocked */
- { &vop_pathconf_desc, (vop_t *)cd9660_pathconf }, /* pathconf */
- { &vop_advlock_desc, (vop_t *)cd9660_advlock }, /* advlock */
- { &vop_blkatoff_desc, (vop_t *)cd9660_blkatoff }, /* blkatoff */
- { &vop_valloc_desc, (vop_t *)cd9660_valloc }, /* valloc */
- { &vop_vfree_desc, (vop_t *)cd9660_vfree }, /* vfree */
- { &vop_truncate_desc, (vop_t *)cd9660_truncate }, /* truncate */
- { &vop_update_desc, (vop_t *)cd9660_update }, /* update */
- { &vop_bwrite_desc, (vop_t *)vn_bwrite }, /* bwrite */
+ { &vop_lookup_desc, (vop_t *)cd9660_lookup }, /* lookup */
+ { &vop_create_desc, (vop_t *)cd9660_create }, /* create */
+ { &vop_mknod_desc, (vop_t *)cd9660_mknod }, /* mknod */
+ { &vop_open_desc, (vop_t *)cd9660_open }, /* open */
+ { &vop_close_desc, (vop_t *)cd9660_close }, /* close */
+ { &vop_access_desc, (vop_t *)cd9660_access }, /* access */
+ { &vop_getattr_desc, (vop_t *)cd9660_getattr }, /* getattr */
+ { &vop_setattr_desc, (vop_t *)cd9660_setattr }, /* setattr */
+ { &vop_read_desc, (vop_t *)cd9660_read }, /* read */
+ { &vop_write_desc, (vop_t *)cd9660_write }, /* write */
+ { &vop_lease_desc, (vop_t *)cd9660_lease_check },/* lease */
+ { &vop_ioctl_desc, (vop_t *)cd9660_ioctl }, /* ioctl */
+ { &vop_select_desc, (vop_t *)cd9660_select }, /* select */
+ { &vop_revoke_desc, (vop_t *)cd9660_revoke }, /* revoke */
+ { &vop_mmap_desc, (vop_t *)cd9660_mmap }, /* mmap */
+ { &vop_fsync_desc, (vop_t *)cd9660_fsync }, /* fsync */
+ { &vop_seek_desc, (vop_t *)cd9660_seek }, /* seek */
+ { &vop_remove_desc, (vop_t *)cd9660_remove }, /* remove */
+ { &vop_link_desc, (vop_t *)cd9660_link }, /* link */
+ { &vop_rename_desc, (vop_t *)cd9660_rename }, /* rename */
+ { &vop_mkdir_desc, (vop_t *)cd9660_mkdir }, /* mkdir */
+ { &vop_rmdir_desc, (vop_t *)cd9660_rmdir }, /* rmdir */
+ { &vop_symlink_desc, (vop_t *)cd9660_symlink }, /* symlink */
+ { &vop_readdir_desc, (vop_t *)cd9660_readdir }, /* readdir */
+ { &vop_readlink_desc, (vop_t *)cd9660_readlink },/* readlink */
+ { &vop_abortop_desc, (vop_t *)cd9660_abortop }, /* abortop */
+ { &vop_inactive_desc, (vop_t *)cd9660_inactive },/* inactive */
+ { &vop_reclaim_desc, (vop_t *)cd9660_reclaim }, /* reclaim */
+ { &vop_lock_desc, (vop_t *)cd9660_lock }, /* lock */
+ { &vop_unlock_desc, (vop_t *)cd9660_unlock }, /* unlock */
+ { &vop_bmap_desc, (vop_t *)cd9660_bmap }, /* bmap */
+ { &vop_strategy_desc, (vop_t *)cd9660_strategy },/* strategy */
+ { &vop_print_desc, (vop_t *)cd9660_print }, /* print */
+ { &vop_islocked_desc, (vop_t *)cd9660_islocked },/* islocked */
+ { &vop_pathconf_desc, (vop_t *)cd9660_pathconf },/* pathconf */
+ { &vop_advlock_desc, (vop_t *)cd9660_advlock }, /* advlock */
+ { &vop_blkatoff_desc, (vop_t *)cd9660_blkatoff },/* blkatoff */
+ { &vop_valloc_desc, (vop_t *)cd9660_valloc }, /* valloc */
+ { &vop_vfree_desc, (vop_t *)cd9660_vfree }, /* vfree */
+ { &vop_truncate_desc, (vop_t *)cd9660_truncate },/* truncate */
+ { &vop_update_desc, (vop_t *)cd9660_update }, /* update */
+ { &vop_bwrite_desc, (vop_t *)vn_bwrite },
{ NULL, NULL }
};
static struct vnodeopv_desc cd9660_vnodeop_opv_desc =
@@ -1049,101 +1145,106 @@ VNODEOP_SET(cd9660_vnodeop_opv_desc);
* Special device vnode ops
*/
vop_t **cd9660_specop_p;
-static struct vnodeopv_entry_desc cd9660_specop_entries[] = {
+struct vnodeopv_entry_desc cd9660_specop_entries[] = {
{ &vop_default_desc, (vop_t *)vn_default_error },
- { &vop_lookup_desc, (vop_t *)spec_lookup }, /* lookup */
- { &vop_create_desc, (vop_t *)cd9660_create }, /* create */
- { &vop_mknod_desc, (vop_t *)cd9660_mknod }, /* mknod */
- { &vop_open_desc, (vop_t *)spec_open }, /* open */
- { &vop_close_desc, (vop_t *)spec_close }, /* close */
- { &vop_access_desc, (vop_t *)cd9660_access }, /* access */
- { &vop_getattr_desc, (vop_t *)cd9660_getattr }, /* getattr */
- { &vop_setattr_desc, (vop_t *)cd9660_setattr }, /* setattr */
- { &vop_read_desc, (vop_t *)spec_read }, /* read */
- { &vop_write_desc, (vop_t *)spec_write }, /* write */
- { &vop_ioctl_desc, (vop_t *)spec_ioctl }, /* ioctl */
- { &vop_select_desc, (vop_t *)spec_select }, /* select */
- { &vop_mmap_desc, (vop_t *)spec_mmap }, /* mmap */
- { &vop_fsync_desc, (vop_t *)spec_fsync }, /* fsync */
- { &vop_seek_desc, (vop_t *)spec_seek }, /* seek */
- { &vop_remove_desc, (vop_t *)cd9660_remove }, /* remove */
- { &vop_link_desc, (vop_t *)cd9660_link }, /* link */
- { &vop_rename_desc, (vop_t *)cd9660_rename }, /* rename */
- { &vop_mkdir_desc, (vop_t *)cd9660_mkdir }, /* mkdir */
- { &vop_rmdir_desc, (vop_t *)cd9660_rmdir }, /* rmdir */
- { &vop_symlink_desc, (vop_t *)cd9660_symlink }, /* symlink */
- { &vop_readdir_desc, (vop_t *)spec_readdir }, /* readdir */
- { &vop_readlink_desc, (vop_t *)spec_readlink }, /* readlink */
- { &vop_abortop_desc, (vop_t *)spec_abortop }, /* abortop */
- { &vop_inactive_desc, (vop_t *)cd9660_inactive }, /* inactive */
- { &vop_reclaim_desc, (vop_t *)cd9660_reclaim }, /* reclaim */
- { &vop_lock_desc, (vop_t *)cd9660_lock }, /* lock */
- { &vop_unlock_desc, (vop_t *)cd9660_unlock }, /* unlock */
- { &vop_bmap_desc, (vop_t *)spec_bmap }, /* bmap */
- { &vop_strategy_desc, (vop_t *)spec_strategy }, /* strategy */
- { &vop_print_desc, (vop_t *)cd9660_print }, /* print */
- { &vop_islocked_desc, (vop_t *)cd9660_islocked }, /* islocked */
- { &vop_pathconf_desc, (vop_t *)spec_pathconf }, /* pathconf */
- { &vop_advlock_desc, (vop_t *)spec_advlock }, /* advlock */
- { &vop_blkatoff_desc, (vop_t *)spec_blkatoff }, /* blkatoff */
- { &vop_valloc_desc, (vop_t *)spec_valloc }, /* valloc */
- { &vop_vfree_desc, (vop_t *)spec_vfree }, /* vfree */
- { &vop_truncate_desc, (vop_t *)spec_truncate }, /* truncate */
- { &vop_update_desc, (vop_t *)cd9660_update }, /* update */
- { &vop_getpages_desc, (vop_t *)spec_getpages}, /* getpages */
- { &vop_bwrite_desc, (vop_t *)vn_bwrite }, /* bwrite */
+ { &vop_lookup_desc, (vop_t *)spec_lookup }, /* lookup */
+ { &vop_create_desc, (vop_t *)spec_create }, /* create */
+ { &vop_mknod_desc, (vop_t *)spec_mknod }, /* mknod */
+ { &vop_open_desc, (vop_t *)spec_open }, /* open */
+ { &vop_close_desc, (vop_t *)spec_close }, /* close */
+ { &vop_access_desc, (vop_t *)cd9660_access }, /* access */
+ { &vop_getattr_desc, (vop_t *)cd9660_getattr }, /* getattr */
+ { &vop_setattr_desc, (vop_t *)cd9660_setattr }, /* setattr */
+ { &vop_read_desc, (vop_t *)spec_read }, /* read */
+ { &vop_write_desc, (vop_t *)spec_write }, /* write */
+ { &vop_lease_desc, (vop_t *)spec_lease_check }, /* lease */
+ { &vop_ioctl_desc, (vop_t *)spec_ioctl }, /* ioctl */
+ { &vop_select_desc, (vop_t *)spec_select }, /* select */
+ { &vop_revoke_desc, (vop_t *)spec_revoke }, /* revoke */
+ { &vop_mmap_desc, (vop_t *)spec_mmap }, /* mmap */
+ { &vop_fsync_desc, (vop_t *)spec_fsync }, /* fsync */
+ { &vop_seek_desc, (vop_t *)spec_seek }, /* seek */
+ { &vop_remove_desc, (vop_t *)spec_remove }, /* remove */
+ { &vop_link_desc, (vop_t *)spec_link }, /* link */
+ { &vop_rename_desc, (vop_t *)spec_rename }, /* rename */
+ { &vop_mkdir_desc, (vop_t *)spec_mkdir }, /* mkdir */
+ { &vop_rmdir_desc, (vop_t *)spec_rmdir }, /* rmdir */
+ { &vop_symlink_desc, (vop_t *)spec_symlink }, /* symlink */
+ { &vop_readdir_desc, (vop_t *)spec_readdir }, /* readdir */
+ { &vop_readlink_desc, (vop_t *)spec_readlink }, /* readlink */
+ { &vop_abortop_desc, (vop_t *)spec_abortop }, /* abortop */
+ { &vop_inactive_desc, (vop_t *)cd9660_inactive },/* inactive */
+ { &vop_reclaim_desc, (vop_t *)cd9660_reclaim }, /* reclaim */
+ { &vop_lock_desc, (vop_t *)cd9660_lock }, /* lock */
+ { &vop_unlock_desc, (vop_t *)cd9660_unlock }, /* unlock */
+ { &vop_bmap_desc, (vop_t *)spec_bmap }, /* bmap */
+ { &vop_strategy_desc, (vop_t *)spec_strategy }, /* strategy */
+ { &vop_print_desc, (vop_t *)cd9660_print }, /* print */
+ { &vop_islocked_desc, (vop_t *)cd9660_islocked },/* islocked */
+ { &vop_pathconf_desc, (vop_t *)spec_pathconf }, /* pathconf */
+ { &vop_advlock_desc, (vop_t *)spec_advlock }, /* advlock */
+ { &vop_blkatoff_desc, (vop_t *)spec_blkatoff }, /* blkatoff */
+ { &vop_valloc_desc, (vop_t *)spec_valloc }, /* valloc */
+ { &vop_vfree_desc, (vop_t *)spec_vfree }, /* vfree */
+ { &vop_truncate_desc, (vop_t *)spec_truncate }, /* truncate */
+ { &vop_update_desc, (vop_t *)cd9660_update }, /* update */
+ { &vop_bwrite_desc, (vop_t *)vn_bwrite },
{ NULL, NULL }
};
static struct vnodeopv_desc cd9660_specop_opv_desc =
{ &cd9660_specop_p, cd9660_specop_entries };
VNODEOP_SET(cd9660_specop_opv_desc);
+#ifdef FIFO
vop_t **cd9660_fifoop_p;
-static struct vnodeopv_entry_desc cd9660_fifoop_entries[] = {
+struct vnodeopv_entry_desc cd9660_fifoop_entries[] = {
{ &vop_default_desc, (vop_t *)vn_default_error },
- { &vop_lookup_desc, (vop_t *)fifo_lookup }, /* lookup */
- { &vop_create_desc, (vop_t *)cd9660_create }, /* create */
- { &vop_mknod_desc, (vop_t *)cd9660_mknod }, /* mknod */
- { &vop_open_desc, (vop_t *)fifo_open }, /* open */
- { &vop_close_desc, (vop_t *)fifo_close }, /* close */
- { &vop_access_desc, (vop_t *)cd9660_access }, /* access */
- { &vop_getattr_desc, (vop_t *)cd9660_getattr }, /* getattr */
- { &vop_setattr_desc, (vop_t *)cd9660_setattr }, /* setattr */
- { &vop_read_desc, (vop_t *)fifo_read }, /* read */
- { &vop_write_desc, (vop_t *)fifo_write }, /* write */
- { &vop_ioctl_desc, (vop_t *)fifo_ioctl }, /* ioctl */
- { &vop_select_desc, (vop_t *)fifo_select }, /* select */
- { &vop_mmap_desc, (vop_t *)fifo_mmap }, /* mmap */
- { &vop_fsync_desc, (vop_t *)fifo_fsync }, /* fsync */
- { &vop_seek_desc, (vop_t *)fifo_seek }, /* seek */
- { &vop_remove_desc, (vop_t *)cd9660_remove }, /* remove */
- { &vop_link_desc, (vop_t *)cd9660_link }, /* link */
- { &vop_rename_desc, (vop_t *)cd9660_rename }, /* rename */
- { &vop_mkdir_desc, (vop_t *)cd9660_mkdir }, /* mkdir */
- { &vop_rmdir_desc, (vop_t *)cd9660_rmdir }, /* rmdir */
- { &vop_symlink_desc, (vop_t *)cd9660_symlink }, /* symlink */
- { &vop_readdir_desc, (vop_t *)fifo_readdir }, /* readdir */
- { &vop_readlink_desc, (vop_t *)fifo_readlink }, /* readlink */
- { &vop_abortop_desc, (vop_t *)fifo_abortop }, /* abortop */
- { &vop_inactive_desc, (vop_t *)cd9660_inactive }, /* inactive */
- { &vop_reclaim_desc, (vop_t *)cd9660_reclaim }, /* reclaim */
- { &vop_lock_desc, (vop_t *)cd9660_lock }, /* lock */
- { &vop_unlock_desc, (vop_t *)cd9660_unlock }, /* unlock */
- { &vop_bmap_desc, (vop_t *)fifo_bmap }, /* bmap */
- { &vop_strategy_desc, (vop_t *)fifo_badop }, /* strategy */
- { &vop_print_desc, (vop_t *)cd9660_print }, /* print */
- { &vop_islocked_desc, (vop_t *)cd9660_islocked }, /* islocked */
- { &vop_pathconf_desc, (vop_t *)fifo_pathconf }, /* pathconf */
- { &vop_advlock_desc, (vop_t *)fifo_advlock }, /* advlock */
- { &vop_blkatoff_desc, (vop_t *)fifo_blkatoff }, /* blkatoff */
- { &vop_valloc_desc, (vop_t *)fifo_valloc }, /* valloc */
- { &vop_vfree_desc, (vop_t *)fifo_vfree }, /* vfree */
- { &vop_truncate_desc, (vop_t *)fifo_truncate }, /* truncate */
- { &vop_update_desc, (vop_t *)cd9660_update }, /* update */
- { &vop_bwrite_desc, (vop_t *)vn_bwrite }, /* bwrite */
+ { &vop_lookup_desc, (vop_t *)fifo_lookup }, /* lookup */
+ { &vop_create_desc, (vop_t *)fifo_create }, /* create */
+ { &vop_mknod_desc, (vop_t *)fifo_mknod }, /* mknod */
+ { &vop_open_desc, (vop_t *)fifo_open }, /* open */
+ { &vop_close_desc, (vop_t *)fifo_close }, /* close */
+ { &vop_access_desc, (vop_t *)cd9660_access }, /* access */
+ { &vop_getattr_desc, (vop_t *)cd9660_getattr }, /* getattr */
+ { &vop_setattr_desc, (vop_t *)cd9660_setattr }, /* setattr */
+ { &vop_read_desc, (vop_t *)fifo_read }, /* read */
+ { &vop_write_desc, (vop_t *)fifo_write }, /* write */
+ { &vop_lease_desc, (vop_t *)fifo_lease_check }, /* lease */
+ { &vop_ioctl_desc, (vop_t *)fifo_ioctl }, /* ioctl */
+ { &vop_select_desc, (vop_t *)fifo_select }, /* select */
+ { &vop_revoke_desc, (vop_t *)fifo_revoke }, /* revoke */
+ { &vop_mmap_desc, (vop_t *)fifo_mmap }, /* mmap */
+ { &vop_fsync_desc, (vop_t *)fifo_fsync }, /* fsync */
+ { &vop_seek_desc, (vop_t *)fifo_seek }, /* seek */
+ { &vop_remove_desc, (vop_t *)fifo_remove }, /* remove */
+ { &vop_link_desc, (vop_t *)fifo_link } , /* link */
+ { &vop_rename_desc, (vop_t *)fifo_rename }, /* rename */
+ { &vop_mkdir_desc, (vop_t *)fifo_mkdir }, /* mkdir */
+ { &vop_rmdir_desc, (vop_t *)fifo_rmdir }, /* rmdir */
+ { &vop_symlink_desc, (vop_t *)fifo_symlink }, /* symlink */
+ { &vop_readdir_desc, (vop_t *)fifo_readdir }, /* readdir */
+ { &vop_readlink_desc, (vop_t *)fifo_readlink }, /* readlink */
+ { &vop_abortop_desc, (vop_t *)fifo_abortop }, /* abortop */
+ { &vop_inactive_desc, (vop_t *)cd9660_inactive },/* inactive */
+ { &vop_reclaim_desc, (vop_t *)cd9660_reclaim }, /* reclaim */
+ { &vop_lock_desc, (vop_t *)cd9660_lock }, /* lock */
+ { &vop_unlock_desc, (vop_t *)cd9660_unlock }, /* unlock */
+ { &vop_bmap_desc, (vop_t *)fifo_bmap }, /* bmap */
+ { &vop_strategy_desc, (vop_t *)fifo_strategy }, /* strategy */
+ { &vop_print_desc, (vop_t *)cd9660_print }, /* print */
+ { &vop_islocked_desc, (vop_t *)cd9660_islocked },/* islocked */
+ { &vop_pathconf_desc, (vop_t *)fifo_pathconf }, /* pathconf */
+ { &vop_advlock_desc, (vop_t *)fifo_advlock }, /* advlock */
+ { &vop_blkatoff_desc, (vop_t *)fifo_blkatoff }, /* blkatoff */
+ { &vop_valloc_desc, (vop_t *)fifo_valloc }, /* valloc */
+ { &vop_vfree_desc, (vop_t *)fifo_vfree }, /* vfree */
+ { &vop_truncate_desc, (vop_t *)fifo_truncate }, /* truncate */
+ { &vop_update_desc, (vop_t *)cd9660_update }, /* update */
+ { &vop_bwrite_desc, (vop_t *)vn_bwrite },
{ NULL, NULL }
};
static struct vnodeopv_desc cd9660_fifoop_opv_desc =
{ &cd9660_fifoop_p, cd9660_fifoop_entries };
VNODEOP_SET(cd9660_fifoop_opv_desc);
+#endif /* FIFO */
diff --git a/sys/fs/cd9660/iso.h b/sys/fs/cd9660/iso.h
index 1656c23..e2a7779 100644
--- a/sys/fs/cd9660/iso.h
+++ b/sys/fs/cd9660/iso.h
@@ -35,7 +35,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)iso.h 8.2 (Berkeley) 1/23/94
+ * @(#)iso.h 8.6 (Berkeley) 5/10/95
* $FreeBSD$
*/
@@ -138,37 +138,37 @@ struct iso_sierra_primary_descriptor {
struct iso_directory_record {
char length [ISODCL (1, 1)]; /* 711 */
char ext_attr_length [ISODCL (2, 2)]; /* 711 */
- unsigned char extent [ISODCL (3, 10)]; /* 733 */
- unsigned char size [ISODCL (11, 18)]; /* 733 */
+ u_char extent [ISODCL (3, 10)]; /* 733 */
+ u_char size [ISODCL (11, 18)]; /* 733 */
char date [ISODCL (19, 25)]; /* 7 by 711 */
char flags [ISODCL (26, 26)];
char file_unit_size [ISODCL (27, 27)]; /* 711 */
char interleave [ISODCL (28, 28)]; /* 711 */
char volume_sequence_number [ISODCL (29, 32)]; /* 723 */
char name_len [ISODCL (33, 33)]; /* 711 */
- char name [0];
+ char name [1]; /* XXX */
};
/* can't take sizeof(iso_directory_record), because of possible alignment
of the last entry (34 instead of 33) */
#define ISO_DIRECTORY_RECORD_SIZE 33
struct iso_extended_attributes {
- unsigned char owner [ISODCL (1, 4)]; /* 723 */
- unsigned char group [ISODCL (5, 8)]; /* 723 */
- unsigned char perm [ISODCL (9, 10)]; /* 9.5.3 */
+ u_char owner [ISODCL (1, 4)]; /* 723 */
+ u_char group [ISODCL (5, 8)]; /* 723 */
+ u_char perm [ISODCL (9, 10)]; /* 9.5.3 */
char ctime [ISODCL (11, 27)]; /* 8.4.26.1 */
char mtime [ISODCL (28, 44)]; /* 8.4.26.1 */
char xtime [ISODCL (45, 61)]; /* 8.4.26.1 */
char ftime [ISODCL (62, 78)]; /* 8.4.26.1 */
char recfmt [ISODCL (79, 79)]; /* 711 */
char recattr [ISODCL (80, 80)]; /* 711 */
- unsigned char reclen [ISODCL (81, 84)]; /* 723 */
+ u_char reclen [ISODCL (81, 84)]; /* 723 */
char system_id [ISODCL (85, 116)]; /* achars */
char system_use [ISODCL (117, 180)];
char version [ISODCL (181, 181)]; /* 711 */
char len_esc [ISODCL (182, 182)]; /* 711 */
char reserved [ISODCL (183, 246)];
- unsigned char len_au [ISODCL (247, 250)]; /* 723 */
+ u_char len_au [ISODCL (247, 250)]; /* 723 */
};
/* CD-ROM Format type */
@@ -191,7 +191,6 @@ struct iso_mnt {
int im_bmask;
int volume_space_size;
- char im_fsmnt[50];
struct netexport im_export;
char root[ISODCL (157, 190)];
@@ -205,94 +204,102 @@ struct iso_mnt {
#define VFSTOISOFS(mp) ((struct iso_mnt *)((mp)->mnt_data))
-#define iso_blkoff(imp, loc) ((loc) & (imp)->im_bmask)
-#define iso_lblkno(imp, loc) ((loc) >> (imp)->im_bshift)
-#define iso_blksize(imp, ip, lbn) ((imp)->logical_block_size)
-#define iso_lblktosize(imp, blk) ((blk) << (imp)->im_bshift)
-#define iso_lblktodaddr(imp, lbn) btodb(iso_lblktosize(imp, lbn))
-#define iso_dblkinc(imp, lbn) ((lbn) + iso_lblktodaddr(imp, 1))
-#define iso_dblkno(imp, loc) iso_lblktodaddr(imp, iso_lblkno(imp, loc))
-int cd9660_init __P((void));
-
-struct iso_node;
-int iso_blkatoff __P((struct iso_node *ip, long offset, struct buf **bpp));
-int iso_iget __P((struct iso_node *xp, ino_t ino, int relocated,
- struct iso_node **ipp, struct iso_directory_record *isodir));
-int iso_iput __P((struct iso_node *ip));
-int iso_ilock __P((struct iso_node *ip));
-int iso_iunlock __P((struct iso_node *ip));
-int cd9660_mountroot __P((void));
+#define blkoff(imp, loc) ((loc) & (imp)->im_bmask)
+#define lblktosize(imp, blk) ((blk) << (imp)->im_bshift)
+#define lblkno(imp, loc) ((loc) >> (imp)->im_bshift)
+#define blksize(imp, ip, lbn) ((imp)->logical_block_size)
+
+int cd9660_vget_internal __P((struct mount *, ino_t, struct vnode **, int,
+ struct iso_directory_record *));
+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));
extern vop_t **cd9660_vnodeop_p;
+extern vop_t **cd9660_specop_p;
+#ifdef FIFO
+extern vop_t **cd9660_fifoop_p;
+#endif
-static int isonum_711 __P((unsigned char *p));
-static int isonum_712 __P((char *p));
-static int isonum_721 __P((unsigned char *p));
-static int isonum_722 __P((unsigned char *p));
-static int isonum_723 __P((unsigned char *p));
-static int isonum_731 __P((unsigned char *p));
-static int isonum_732 __P((unsigned char *p));
-static int isonum_733 __P((unsigned char *p));
-
-static inline int
+static __inline int isonum_711 __P((u_char *));
+static __inline int
isonum_711(p)
- unsigned char *p;
+ u_char *p;
{
return *p;
}
-static inline int
+static __inline int isonum_712 __P((char *));
+static __inline int
isonum_712(p)
char *p;
{
return *p;
}
-static inline int
-isonum_721(p)
- unsigned char *p;
+#ifndef UNALIGNED_ACCESS
+
+static __inline int isonum_723 __P((u_char *));
+static __inline int
+isonum_723(p)
+ u_char *p;
{
- return *p|((char)p[1] << 8);
+ return *p|(p[1] << 8);
}
-static inline int
-isonum_722(p)
- unsigned char *p;
+static __inline int isonum_733 __P((u_char *));
+static __inline int
+isonum_733(p)
+ u_char *p;
{
- return ((char)*p << 8)|p[1];
+ return *p|(p[1] << 8)|(p[2] << 16)|(p[3] << 24);
}
-static inline int
+#else /* UNALIGNED_ACCESS */
+
+#if BYTE_ORDER == LITTLE_ENDIAN
+
+static __inline int
isonum_723(p)
- unsigned char *p;
+ u_char *p
{
- return isonum_721(p);
+ return *(u_int16t *)p;
}
-static inline int
-isonum_731(p)
- unsigned char *p;
+static __inline int
+isonum_733(p)
+ u_char *p;
{
- return *p|(p[1] << 8)|(p[2] << 16)|(p[3] << 24);
+ return *(u_int32t *)p;
}
-static inline int
-isonum_732(p)
- unsigned char *p;
+#endif
+
+#if BYTE_ORDER == BIG_ENDIAN
+
+static __inline int
+isonum_723(p)
+ u_char *p
{
- return (*p << 24)|(p[1] << 16)|(p[2] << 8)|p[3];
+ return *(u_int16t *)(p + 2);
}
-static inline int
+static __inline int
isonum_733(p)
- unsigned char *p;
+ u_char *p;
{
- return isonum_731(p);
+ return *(u_int32t *)(p + 4);
}
-int isofncmp __P((unsigned char *, int, unsigned char *, int));
-void isofntrans __P((unsigned char *, int, unsigned char *, unsigned short *,
- int, int));
+#endif
+
+#endif /* UNALIGNED_ACCESS */
+
+int isofncmp __P((u_char *, int, u_char *, int));
+void isofntrans __P((u_char *, int, u_char *, u_short *, int, int));
+ino_t isodirino __P((struct iso_directory_record *, struct iso_mnt *));
/*
* Associated files have a leading '='.
diff --git a/sys/fs/deadfs/dead_vnops.c b/sys/fs/deadfs/dead_vnops.c
index f22425c..6d83c61 100644
--- a/sys/fs/deadfs/dead_vnops.c
+++ b/sys/fs/deadfs/dead_vnops.c
@@ -77,11 +77,11 @@ static int dead_select __P((struct vop_select_args *));
#define dead_inactive ((int (*) __P((struct vop_inactive_args *)))nullop)
#define dead_reclaim ((int (*) __P((struct vop_reclaim_args *)))nullop)
static int dead_lock __P((struct vop_lock_args *));
-#define dead_unlock ((int (*) __P((struct vop_unlock_args *)))nullop)
+#define dead_unlock ((int (*) __P((struct vop_unlock_args *)))vop_nounlock)
static int dead_bmap __P((struct vop_bmap_args *));
static int dead_strategy __P((struct vop_strategy_args *));
static int dead_print __P((struct vop_print_args *));
-#define dead_islocked ((int (*) __P((struct vop_islocked_args *)))nullop)
+#define dead_islocked ((int(*) __P((struct vop_islocked_args *)))vop_noislocked)
#define dead_pathconf ((int (*) __P((struct vop_pathconf_args *)))dead_ebadf)
#define dead_advlock ((int (*) __P((struct vop_advlock_args *)))dead_ebadf)
#define dead_blkatoff ((int (*) __P((struct vop_blkatoff_args *)))dead_badop)
@@ -191,11 +191,20 @@ dead_read(ap)
if (chkvnlock(ap->a_vp))
panic("dead_read: lock");
+#if 0
+ /* Lite2 behaviour */
+ /*
+ * Return EOF for tty devices, EIO for others
+ */
+ if ((ap->a_vp->v_flag & VISTTY) == 0)
+ return (EIO);
+#else
/*
* Return EOF for character devices, EIO for others
*/
if (ap->a_vp->v_type != VCHR)
return (EIO);
+#endif
return (0);
}
@@ -282,12 +291,23 @@ static int
dead_lock(ap)
struct vop_lock_args /* {
struct vnode *a_vp;
+ int a_flags;
+ struct proc *a_p;
} */ *ap;
{
+ struct vnode *vp = ap->a_vp;
- if (!chkvnlock(ap->a_vp))
+ /*
+ * Since we are not using the lock manager, we must clear
+ * the interlock here.
+ */
+ if (ap->a_flags & LK_INTERLOCK) {
+ simple_unlock(&vp->v_interlock);
+ ap->a_flags &= ~LK_INTERLOCK;
+ }
+ if (!chkvnlock(vp))
return (0);
- return (VCALL(ap->a_vp, VOFFSET(vop_lock), ap));
+ return (VCALL(vp, VOFFSET(vop_lock), ap));
}
/*
diff --git a/sys/fs/fdescfs/fdesc.h b/sys/fs/fdescfs/fdesc.h
index d754655..b4eff1f 100644
--- a/sys/fs/fdescfs/fdesc.h
+++ b/sys/fs/fdescfs/fdesc.h
@@ -61,8 +61,7 @@ typedef enum {
} fdntype;
struct fdescnode {
- struct fdescnode *fd_forw; /* Hash chain */
- struct fdescnode *fd_back;
+ LIST_ENTRY(fdescnode) fd_hash; /* Hash list */
struct vnode *fd_vnode; /* Back ptr to vnode */
fdntype fd_type; /* Type of this node */
unsigned fd_fd; /* Fd to be dup'ed */
@@ -74,7 +73,7 @@ struct fdescnode {
#define VTOFDESC(vp) ((struct fdescnode *)(vp)->v_data)
extern dev_t devctty;
-extern int fdesc_init __P((void));
+extern int fdesc_init __P((struct vfsconf *));
extern int fdesc_root __P((struct mount *, struct vnode **));
extern int fdesc_allocvp __P((fdntype, int, struct mount *, struct vnode **));
extern vop_t **fdesc_vnodeop_p;
diff --git a/sys/fs/fdescfs/fdesc_vfsops.c b/sys/fs/fdescfs/fdesc_vfsops.c
index 5f6703b..135052e 100644
--- a/sys/fs/fdescfs/fdesc_vfsops.c
+++ b/sys/fs/fdescfs/fdesc_vfsops.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1992, 1993
+ * Copyright (c) 1992, 1993, 1995
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software donated to Berkeley by
@@ -108,7 +108,7 @@ fdesc_mount(mp, path, data, ndp, p)
/* XXX -- don't mark as local to work around fts() problems */
/*mp->mnt_flag |= MNT_LOCAL;*/
mp->mnt_data = (qaddr_t) fmp;
- getnewfsid(mp, MOUNT_FDESC);
+ vfs_getnewfsid(mp);
(void) copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN - 1, &size);
bzero(mp->mnt_stat.f_mntonname + size, MNAMELEN - size);
@@ -137,12 +137,8 @@ fdesc_unmount(mp, mntflags, p)
int flags = 0;
struct vnode *rootvp = VFSTOFDESC(mp)->f_root;
- if (mntflags & MNT_FORCE) {
- /* fdesc can never be rootfs so don't check for it */
- if (!doforce)
- return (EINVAL);
+ if (mntflags & MNT_FORCE)
flags |= FORCECLOSE;
- }
/*
* Clear out buffer cache. I don't think we
@@ -176,6 +172,7 @@ fdesc_root(mp, vpp)
struct mount *mp;
struct vnode **vpp;
{
+ struct proc *p = curproc; /* XXX */
struct vnode *vp;
/*
@@ -183,24 +180,12 @@ fdesc_root(mp, vpp)
*/
vp = VFSTOFDESC(mp)->f_root;
VREF(vp);
- VOP_LOCK(vp);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
*vpp = vp;
return (0);
}
static int
-fdesc_quotactl(mp, cmd, uid, arg, p)
- struct mount *mp;
- int cmd;
- uid_t uid;
- caddr_t arg;
- struct proc *p;
-{
-
- return (EOPNOTSUPP);
-}
-
-static int
fdesc_statfs(mp, sbp, p)
struct mount *mp;
struct statfs *sbp;
@@ -233,7 +218,6 @@ fdesc_statfs(mp, sbp, p)
if (fdp->fd_nfiles < lim)
freefd += (lim - fdp->fd_nfiles);
- sbp->f_type = MOUNT_FDESC;
sbp->f_flags = 0;
sbp->f_bsize = DEV_BSIZE;
sbp->f_iosize = DEV_BSIZE;
@@ -243,6 +227,7 @@ fdesc_statfs(mp, sbp, p)
sbp->f_files = lim + 1; /* Allow for "." */
sbp->f_ffree = freefd; /* See comments above */
if (sbp != &mp->mnt_stat) {
+ sbp->f_type = mp->mnt_vfc->vfc_typenum;
bcopy(&mp->mnt_stat.f_fsid, &sbp->f_fsid, sizeof(sbp->f_fsid));
bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN);
bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN);
@@ -261,41 +246,15 @@ fdesc_sync(mp, waitfor, cred, p)
return (0);
}
-/*
- * Fdesc flat namespace lookup.
- * Currently unsupported.
- */
-static int
-fdesc_vget(mp, ino, vpp)
- struct mount *mp;
- ino_t ino;
- struct vnode **vpp;
-{
-
- return (EOPNOTSUPP);
-}
-
-static int
-fdesc_fhtovp(mp, fhp, nam, vpp, exflagsp, credanonp)
- struct mount *mp;
- struct fid *fhp;
- struct mbuf *nam;
- struct vnode **vpp;
- int *exflagsp;
- struct ucred **credanonp;
-{
-
- return (EOPNOTSUPP);
-}
-
-static int
-fdesc_vptofh(vp, fhp)
- struct vnode *vp;
- struct fid *fhp;
-{
-
- return (EOPNOTSUPP);
-}
+#define fdesc_fhtovp ((int (*) __P((struct mount *, struct fid *, \
+ struct mbuf *, struct vnode **, int *, struct ucred **)))eopnotsupp)
+#define fdesc_quotactl ((int (*) __P((struct mount *, int, uid_t, caddr_t, \
+ struct proc *)))eopnotsupp)
+#define fdesc_sysctl ((int (*) __P((int *, u_int, void *, size_t *, void *, \
+ size_t, struct proc *)))eopnotsupp)
+#define fdesc_vget ((int (*) __P((struct mount *, ino_t, struct vnode **))) \
+ eopnotsupp)
+#define fdesc_vptofh ((int (*) __P((struct vnode *, struct fid *)))eopnotsupp)
static struct vfsops fdesc_vfsops = {
fdesc_mount,
diff --git a/sys/fs/fdescfs/fdesc_vnops.c b/sys/fs/fdescfs/fdesc_vnops.c
index 1fe511b..795dfd8 100644
--- a/sys/fs/fdescfs/fdesc_vnops.c
+++ b/sys/fs/fdescfs/fdesc_vnops.c
@@ -77,22 +77,14 @@ FD_STDIN, FD_STDOUT, FD_STDERR must be a sequence n, n+1, n+2
#endif
#define NFDCACHE 4
-#define FD_NHASH(ix) ((ix) & NFDCACHE-1)
-
-/*
- * Cache head
- */
-struct fdcache {
- struct fdescnode *fc_forw;
- struct fdescnode *fc_back;
-};
-
-static struct fdcache fdcache[NFDCACHE];
+#define FD_NHASH(ix) \
+ (&fdhashtbl[(ix) & fdhash])
+LIST_HEAD(fdhashhead, fdescnode) *fdhashtbl;
+u_long fdhash;
static int fdesc_attr __P((int fd, struct vattr *vap, struct ucred *cred,
struct proc *p));
static int fdesc_badop __P((void));
-static int fdesc_enotsupp __P((void));
static int fdesc_getattr __P((struct vop_getattr_args *ap));
static struct fdcache *
fdesc_hash __P((int ix));
@@ -115,28 +107,15 @@ static int fdesc_write __P((struct vop_write_args *ap));
* Initialise cache headers
*/
int
-fdesc_init()
+fdesc_init(vfsp)
+ struct vfsconf *vfsp;
{
- struct fdcache *fc;
devctty = makedev(nchrdev, 0);
-
- for (fc = fdcache; fc < fdcache + NFDCACHE; fc++)
- fc->fc_forw = fc->fc_back = (struct fdescnode *) fc;
+ fdhashtbl = hashinit(NFDCACHE, M_CACHE, &fdhash);
return (0);
}
-/*
- * Compute hash list for given target vnode
- */
-static struct fdcache *
-fdesc_hash(ix)
- int ix;
-{
-
- return (&fdcache[FD_NHASH(ix)]);
-}
-
int
fdesc_allocvp(ftype, ix, mp, vpp)
fdntype ftype;
@@ -144,15 +123,16 @@ fdesc_allocvp(ftype, ix, mp, vpp)
struct mount *mp;
struct vnode **vpp;
{
- struct fdcache *fc;
+ struct proc *p = curproc; /* XXX */
+ struct fdhashhead *fc;
struct fdescnode *fd;
int error = 0;
+ fc = FD_NHASH(ix);
loop:
- fc = fdesc_hash(ix);
- for (fd = fc->fc_forw; fd != (struct fdescnode *) fc; fd = fd->fd_forw) {
+ for (fd = fc->lh_first; fd != 0; fd = fd->fd_hash.le_next) {
if (fd->fd_ix == ix && fd->fd_vnode->v_mount == mp) {
- if (vget(fd->fd_vnode, 0))
+ if (vget(fd->fd_vnode, 0, p))
goto loop;
*vpp = fd->fd_vnode;
return (error);
@@ -188,8 +168,7 @@ loop:
fd->fd_fd = -1;
fd->fd_link = 0;
fd->fd_ix = ix;
- fc = fdesc_hash(ix);
- insque(fd, fc);
+ LIST_INSERT_HEAD(fc, fd, fd_hash);
out:;
fdcache_lock &= ~FDL_LOCKED;
@@ -216,31 +195,28 @@ fdesc_lookup(ap)
{
struct vnode **vpp = ap->a_vpp;
struct vnode *dvp = ap->a_dvp;
- char *pname;
- struct proc *p;
- int nfiles;
- unsigned fd = 0;
+ struct componentname *cnp = ap->a_cnp;
+ char *pname = cnp->cn_nameptr;
+ struct proc *p = cnp->cn_proc;
+ int nfiles = p->p_fd->fd_nfiles;
+ unsigned fd;
int error;
struct vnode *fvp;
char *ln;
- if (ap->a_cnp->cn_nameiop == DELETE ||
- ap->a_cnp->cn_nameiop == RENAME) {
+ if (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME) {
error = EROFS;
goto bad;
}
- pname = ap->a_cnp->cn_nameptr;
- if (ap->a_cnp->cn_namelen == 1 && *pname == '.') {
+ VOP_UNLOCK(dvp, 0, p);
+ if (cnp->cn_namelen == 1 && *pname == '.') {
*vpp = dvp;
- VREF(dvp);
- VOP_LOCK(dvp);
+ VREF(dvp);
+ vn_lock(dvp, LK_SHARED | LK_RETRY, p);
return (0);
}
- p = ap->a_cnp->cn_proc;
- nfiles = p->p_fd->fd_nfiles;
-
switch (VTOFDESC(dvp)->fd_type) {
default:
case Flink:
@@ -250,17 +226,17 @@ fdesc_lookup(ap)
goto bad;
case Froot:
- if (ap->a_cnp->cn_namelen == 2 && bcmp(pname, "fd", 2) == 0) {
+ if (cnp->cn_namelen == 2 && bcmp(pname, "fd", 2) == 0) {
error = fdesc_allocvp(Fdevfd, FD_DEVFD, dvp->v_mount, &fvp);
if (error)
goto bad;
*vpp = fvp;
fvp->v_type = VDIR;
- VOP_LOCK(fvp);
+ vn_lock(fvp, LK_SHARED | LK_RETRY, p);
return (0);
}
- if (ap->a_cnp->cn_namelen == 3 && bcmp(pname, "tty", 3) == 0) {
+ if (cnp->cn_namelen == 3 && bcmp(pname, "tty", 3) == 0) {
struct vnode *ttyvp = cttyvp(p);
if (ttyvp == NULL) {
error = ENXIO;
@@ -271,12 +247,12 @@ fdesc_lookup(ap)
goto bad;
*vpp = fvp;
fvp->v_type = VFIFO;
- VOP_LOCK(fvp);
+ vn_lock(fvp, LK_SHARED | LK_RETRY, p);
return (0);
}
ln = 0;
- switch (ap->a_cnp->cn_namelen) {
+ switch (cnp->cn_namelen) {
case 5:
if (bcmp(pname, "stdin", 5) == 0) {
ln = "fd/0";
@@ -302,7 +278,7 @@ fdesc_lookup(ap)
VTOFDESC(fvp)->fd_link = ln;
*vpp = fvp;
fvp->v_type = VLNK;
- VOP_LOCK(fvp);
+ vn_lock(fvp, LK_SHARED | LK_RETRY, p);
return (0);
} else {
error = ENOENT;
@@ -312,9 +288,10 @@ fdesc_lookup(ap)
/* FALL THROUGH */
case Fdevfd:
- if (ap->a_cnp->cn_namelen == 2 && bcmp(pname, "..", 2) == 0) {
- error = fdesc_root(dvp->v_mount, vpp);
- return (error);
+ if (cnp->cn_namelen == 2 && bcmp(pname, "..", 2) == 0) {
+ if (error = fdesc_root(dvp->v_mount, vpp))
+ goto bad;
+ return (0);
}
fd = 0;
@@ -338,11 +315,13 @@ fdesc_lookup(ap)
if (error)
goto bad;
VTOFDESC(fvp)->fd_fd = fd;
+ vn_lock(fvp, LK_SHARED | LK_RETRY, p);
*vpp = fvp;
return (0);
}
bad:;
+ vn_lock(dvp, LK_SHARED | LK_RETRY, p);
*vpp = NULL;
return (error);
}
@@ -402,10 +381,10 @@ fdesc_attr(fd, vap, cred, p)
error = VOP_GETATTR((struct vnode *) fp->f_data, vap, cred, p);
if (error == 0 && vap->va_type == VDIR) {
/*
- * don't allow directories to show up because
- * that causes loops in the namespace.
+ * directories can cause loops in the namespace,
+ * so turn off the 'x' bits to avoid trouble.
*/
- vap->va_type = VFIFO;
+ vap->va_mode &= ~((VEXEC)|(VEXEC>>3)|(VEXEC>>6));
}
break;
@@ -591,6 +570,9 @@ fdesc_readdir(ap)
struct vnode *a_vp;
struct uio *a_uio;
struct ucred *a_cred;
+ int *a_eofflag;
+ u_long *a_cookies;
+ int a_ncookies;
} */ *ap;
{
struct uio *uio = ap->a_uio;
@@ -598,6 +580,13 @@ fdesc_readdir(ap)
int i;
int error;
+ /*
+ * We don't allow exporting fdesc mounts, and currently local
+ * requests do not need cookies.
+ */
+ if (ap->a_ncookies)
+ panic("fdesc_readdir: not hungry");
+
switch (VTOFDESC(ap->a_vp)->fd_type) {
case Fctty:
return (0);
@@ -814,6 +803,7 @@ static int
fdesc_inactive(ap)
struct vop_inactive_args /* {
struct vnode *a_vp;
+ struct proc *a_p;
} */ *ap;
{
struct vnode *vp = ap->a_vp;
@@ -822,6 +812,7 @@ fdesc_inactive(ap)
* Clear out the v_type field to avoid
* nasty things happening in vgone().
*/
+ VOP_UNLOCK(vp, 0, ap->a_p);
vp->v_type = VNON;
return (0);
}
@@ -833,8 +824,9 @@ fdesc_reclaim(ap)
} */ *ap;
{
struct vnode *vp = ap->a_vp;
+ struct fdescnode *fd = VTOFDESC(vp);
- remque(VTOFDESC(vp));
+ LIST_REMOVE(fd, fd_hash);
FREE(vp->v_data, M_TEMP);
vp->v_data = 0;
@@ -907,16 +899,6 @@ fdesc_vfree(ap)
}
/*
- * /dev/fd vnode unsupported operation
- */
-static int
-fdesc_enotsupp()
-{
-
- return (EOPNOTSUPP);
-}
-
-/*
* /dev/fd "should never get here" operation
*/
static int
@@ -927,38 +909,39 @@ fdesc_badop()
/* NOTREACHED */
}
-#define fdesc_create ((int (*) __P((struct vop_create_args *)))fdesc_enotsupp)
-#define fdesc_mknod ((int (*) __P((struct vop_mknod_args *)))fdesc_enotsupp)
+#define fdesc_create ((int (*) __P((struct vop_create_args *)))eopnotsupp)
+#define fdesc_mknod ((int (*) __P((struct vop_mknod_args *)))eopnotsupp)
#define fdesc_close ((int (*) __P((struct vop_close_args *)))nullop)
#define fdesc_access ((int (*) __P((struct vop_access_args *)))nullop)
-#define fdesc_mmap ((int (*) __P((struct vop_mmap_args *)))fdesc_enotsupp)
+#define fdesc_mmap ((int (*) __P((struct vop_mmap_args *)))eopnotsupp)
+#define fdesc_revoke vop_revoke
#define fdesc_fsync ((int (*) __P((struct vop_fsync_args *)))nullop)
#define fdesc_seek ((int (*) __P((struct vop_seek_args *)))nullop)
-#define fdesc_remove ((int (*) __P((struct vop_remove_args *)))fdesc_enotsupp)
-#define fdesc_link ((int (*) __P((struct vop_link_args *)))fdesc_enotsupp)
-#define fdesc_rename ((int (*) __P((struct vop_rename_args *)))fdesc_enotsupp)
-#define fdesc_mkdir ((int (*) __P((struct vop_mkdir_args *)))fdesc_enotsupp)
-#define fdesc_rmdir ((int (*) __P((struct vop_rmdir_args *)))fdesc_enotsupp)
-#define fdesc_symlink ((int (*) __P((struct vop_symlink_args *)))fdesc_enotsupp)
+#define fdesc_remove ((int (*) __P((struct vop_remove_args *)))eopnotsupp)
+#define fdesc_link ((int (*) __P((struct vop_link_args *)))eopnotsupp)
+#define fdesc_rename ((int (*) __P((struct vop_rename_args *)))eopnotsupp)
+#define fdesc_mkdir ((int (*) __P((struct vop_mkdir_args *)))eopnotsupp)
+#define fdesc_rmdir ((int (*) __P((struct vop_rmdir_args *)))eopnotsupp)
+#define fdesc_symlink ((int (*) __P((struct vop_symlink_args *)))eopnotsupp)
#define fdesc_abortop ((int (*) __P((struct vop_abortop_args *)))nullop)
-#define fdesc_lock ((int (*) __P((struct vop_lock_args *)))nullop)
-#define fdesc_unlock ((int (*) __P((struct vop_unlock_args *)))nullop)
+#define fdesc_lock ((int (*) __P((struct vop_lock_args *)))vop_nolock)
+#define fdesc_unlock ((int (*) __P((struct vop_unlock_args *)))vop_nounlock)
#define fdesc_bmap ((int (*) __P((struct vop_bmap_args *)))fdesc_badop)
#define fdesc_strategy ((int (*) __P((struct vop_strategy_args *)))fdesc_badop)
-#define fdesc_islocked ((int (*) __P((struct vop_islocked_args *)))nullop)
-#define fdesc_advlock ((int (*) __P((struct vop_advlock_args *)))fdesc_enotsupp)
+#define fdesc_islocked \
+ ((int (*) __P((struct vop_islocked_args *)))vop_noislocked)
+#define fdesc_advlock ((int (*) __P((struct vop_advlock_args *)))eopnotsupp)
#define fdesc_blkatoff \
- ((int (*) __P((struct vop_blkatoff_args *)))fdesc_enotsupp)
-#define fdesc_vget ((int (*) __P((struct vop_vget_args *)))fdesc_enotsupp)
+ ((int (*) __P((struct vop_blkatoff_args *)))eopnotsupp)
#define fdesc_valloc ((int(*) __P(( \
struct vnode *pvp, \
int mode, \
struct ucred *cred, \
- struct vnode **vpp))) fdesc_enotsupp)
+ struct vnode **vpp))) eopnotsupp)
#define fdesc_truncate \
- ((int (*) __P((struct vop_truncate_args *)))fdesc_enotsupp)
-#define fdesc_update ((int (*) __P((struct vop_update_args *)))fdesc_enotsupp)
-#define fdesc_bwrite ((int (*) __P((struct vop_bwrite_args *)))fdesc_enotsupp)
+ ((int (*) __P((struct vop_truncate_args *)))eopnotsupp)
+#define fdesc_update ((int (*) __P((struct vop_update_args *)))eopnotsupp)
+#define fdesc_bwrite ((int (*) __P((struct vop_bwrite_args *)))eopnotsupp)
static vop_t **fdesc_vnodeop_p;
static struct vnodeopv_entry_desc fdesc_vnodeop_entries[] = {
@@ -975,6 +958,7 @@ static struct vnodeopv_entry_desc fdesc_vnodeop_entries[] = {
{ &vop_write_desc, (vop_t *)fdesc_write }, /* write */
{ &vop_ioctl_desc, (vop_t *)fdesc_ioctl }, /* ioctl */
{ &vop_select_desc, (vop_t *)fdesc_select }, /* select */
+ { &vop_revoke_desc, (vop_t *)fdesc_revoke }, /* revoke */
{ &vop_mmap_desc, (vop_t *)fdesc_mmap }, /* mmap */
{ &vop_fsync_desc, (vop_t *)fdesc_fsync }, /* fsync */
{ &vop_seek_desc, (vop_t *)fdesc_seek }, /* seek */
diff --git a/sys/fs/fifofs/fifo.h b/sys/fs/fifofs/fifo.h
index efeaf85..6562159 100644
--- a/sys/fs/fifofs/fifo.h
+++ b/sys/fs/fifofs/fifo.h
@@ -30,7 +30,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)fifo.h 8.2 (Berkeley) 2/2/94
+ * @(#)fifo.h 8.6 (Berkeley) 5/21/95
* $FreeBSD$
*/
@@ -51,8 +51,10 @@ int fifo_close __P((struct vop_close_args *));
#define fifo_setattr ((int (*) __P((struct vop_setattr_args *)))fifo_ebadf)
int fifo_read __P((struct vop_read_args *));
int fifo_write __P((struct vop_write_args *));
+#define fifo_lease_check ((int (*) __P((struct vop_lease_args *)))nullop)
int fifo_ioctl __P((struct vop_ioctl_args *));
int fifo_select __P((struct vop_select_args *));
+#define fifo_revoke vop_revoke
#define fifo_mmap ((int (*) __P((struct vop_mmap_args *)))fifo_badop)
#define fifo_fsync ((int (*) __P((struct vop_fsync_args *)))nullop)
#define fifo_seek ((int (*) __P((struct vop_seek_args *)))fifo_badop)
@@ -65,11 +67,13 @@ int fifo_select __P((struct vop_select_args *));
#define fifo_readdir ((int (*) __P((struct vop_readdir_args *)))fifo_badop)
#define fifo_readlink ((int (*) __P((struct vop_readlink_args *)))fifo_badop)
#define fifo_abortop ((int (*) __P((struct vop_abortop_args *)))fifo_badop)
-#define fifo_inactive ((int (*) __P((struct vop_inactive_args *)))nullop)
+int fifo_inactive __P((struct vop_inactive_args *));
#define fifo_reclaim ((int (*) __P((struct vop_reclaim_args *)))nullop)
+#define fifo_lock ((int (*) __P((struct vop_lock_args *)))vop_nolock)
+#define fifo_unlock ((int (*) __P((struct vop_unlock_args *)))vop_nounlock)
int fifo_bmap __P((struct vop_bmap_args *));
#define fifo_strategy ((int (*) __P((struct vop_strategy_args *)))fifo_badop)
-#define fifo_islocked ((int (*) __P((struct vop_islocked_args *)))nullop)
+#define fifo_islocked ((int(*) __P((struct vop_islocked_args *)))vop_noislocked)
int fifo_pathconf __P((struct vop_pathconf_args *));
int fifo_advlock __P((struct vop_advlock_args *));
#define fifo_blkatoff ((int (*) __P((struct vop_blkatoff_args *)))fifo_badop)
diff --git a/sys/fs/fifofs/fifo_vnops.c b/sys/fs/fifofs/fifo_vnops.c
index 240354f..8f915ec 100644
--- a/sys/fs/fifofs/fifo_vnops.c
+++ b/sys/fs/fifofs/fifo_vnops.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1990, 1993
+ * Copyright (c) 1990, 1993, 1995
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -30,12 +30,12 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)fifo_vnops.c 8.2 (Berkeley) 1/4/94
+ * @(#)fifo_vnops.c 8.10 (Berkeley) 5/27/95
* $FreeBSD$
*/
#include <sys/param.h>
-#include <sys/kernel.h>
+#include <sys/systm.h>
#include <sys/proc.h>
#include <sys/time.h>
#include <sys/namei.h>
@@ -44,7 +44,6 @@
#include <sys/socket.h>
#include <sys/socketvar.h>
#include <sys/stat.h>
-#include <sys/systm.h>
#include <sys/ioctl.h>
#include <sys/file.h>
#include <sys/errno.h>
@@ -64,8 +63,6 @@ struct fifoinfo {
};
static int fifo_ebadf __P((void));
-static int fifo_unlock __P((struct vop_unlock_args *));
-static int fifo_lock __P((struct vop_lock_args *));
static int fifo_print __P((struct vop_print_args *));
vop_t **fifo_vnodeop_p;
@@ -81,8 +78,10 @@ static struct vnodeopv_entry_desc fifo_vnodeop_entries[] = {
{ &vop_setattr_desc, (vop_t *)fifo_setattr }, /* setattr */
{ &vop_read_desc, (vop_t *)fifo_read }, /* read */
{ &vop_write_desc, (vop_t *)fifo_write }, /* write */
+ { &vop_lease_desc, (vop_t *)fifo_lease_check }, /* lease */
{ &vop_ioctl_desc, (vop_t *)fifo_ioctl }, /* ioctl */
{ &vop_select_desc, (vop_t *)fifo_select }, /* select */
+ { &vop_revoke_desc, (vop_t *)fifo_revoke }, /* revoke */
{ &vop_mmap_desc, (vop_t *)fifo_mmap }, /* mmap */
{ &vop_fsync_desc, (vop_t *)fifo_fsync }, /* fsync */
{ &vop_seek_desc, (vop_t *)fifo_seek }, /* seek */
@@ -149,8 +148,9 @@ fifo_open(ap)
struct proc *a_p;
} */ *ap;
{
- register struct vnode *vp = ap->a_vp;
- register struct fifoinfo *fip;
+ struct vnode *vp = ap->a_vp;
+ struct fifoinfo *fip;
+ struct proc *p = ap->a_p;
struct socket *rso, *wso;
int error;
static char openstr[] = "fifo";
@@ -158,14 +158,14 @@ fifo_open(ap)
if ((fip = vp->v_fifoinfo) == NULL) {
MALLOC(fip, struct fifoinfo *, sizeof(*fip), M_VNODE, M_WAITOK);
vp->v_fifoinfo = fip;
- error = socreate(AF_UNIX, &rso, SOCK_STREAM, 0, ap->a_p);
+ error = socreate(AF_LOCAL, &rso, SOCK_STREAM, 0, ap->a_p);
if (error) {
free(fip, M_VNODE);
vp->v_fifoinfo = NULL;
return (error);
}
fip->fi_readsock = rso;
- error = socreate(AF_UNIX, &wso, SOCK_STREAM, 0, ap->a_p);
+ error = socreate(AF_LOCAL, &wso, SOCK_STREAM, 0, ap->a_p);
if (error) {
(void)soclose(rso);
free(fip, M_VNODE);
@@ -185,60 +185,52 @@ fifo_open(ap)
wso->so_state |= SS_CANTRCVMORE;
rso->so_state |= SS_CANTSENDMORE;
}
- error = 0;
- if ((ap->a_mode & (FREAD|FWRITE)) == (FREAD|FWRITE)) {
- if (fip->fi_readers == 0) {
+ if (ap->a_mode & FREAD) {
+ fip->fi_readers++;
+ if (fip->fi_readers == 1) {
fip->fi_writesock->so_state &= ~SS_CANTSENDMORE;
if (fip->fi_writers > 0)
wakeup((caddr_t)&fip->fi_writers);
}
- if (fip->fi_writers == 0) {
+ }
+ if (ap->a_mode & FWRITE) {
+ fip->fi_writers++;
+ if (fip->fi_writers == 1) {
fip->fi_readsock->so_state &= ~SS_CANTRCVMORE;
if (fip->fi_readers > 0)
wakeup((caddr_t)&fip->fi_readers);
}
- fip->fi_readers++;
- fip->fi_writers++;
}
- else if (ap->a_mode & FREAD) {
- fip->fi_readers++;
- if (fip->fi_readers == 1) {
- fip->fi_writesock->so_state &= ~SS_CANTSENDMORE;
- if (fip->fi_writers > 0)
- wakeup((caddr_t)&fip->fi_writers);
+ if ((ap->a_mode & FREAD) && (ap->a_mode & O_NONBLOCK) == 0) {
+ while (fip->fi_writers == 0) {
+ VOP_UNLOCK(vp, 0, p);
+ error = tsleep((caddr_t)&fip->fi_readers,
+ PCATCH | PSOCK, openstr, 0);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
+ if (error)
+ goto bad;
}
- if (!(ap->a_mode & O_NONBLOCK))
- while (fip->fi_writers == 0) {
- VOP_UNLOCK(vp);
- error = tsleep((caddr_t)&fip->fi_readers,
- PCATCH | PSOCK, openstr, 0);
- VOP_LOCK(vp);
- if (error)
- break;
- }
}
- else {
- fip->fi_writers++;
- if (fip->fi_readers == 0 && (ap->a_mode & O_NONBLOCK)) {
- error = ENXIO;
- } else {
- if (fip->fi_writers == 1) {
- fip->fi_readsock->so_state &= ~SS_CANTRCVMORE;
- if (fip->fi_readers > 0)
- wakeup((caddr_t)&fip->fi_readers);
+ if (ap->a_mode & FWRITE) {
+ if (ap->a_mode & O_NONBLOCK) {
+ if (fip->fi_readers == 0) {
+ error = ENXIO;
+ goto bad;
}
+ } else {
while (fip->fi_readers == 0) {
- VOP_UNLOCK(vp);
+ VOP_UNLOCK(vp, 0, p);
error = tsleep((caddr_t)&fip->fi_writers,
PCATCH | PSOCK, openstr, 0);
- VOP_LOCK(vp);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
if (error)
- break;
+ goto bad;
}
}
}
- if (error)
- VOP_CLOSE(vp, ap->a_mode, ap->a_cred, ap->a_p);
+ return (0);
+bad:
+ VOP_CLOSE(vp, ap->a_mode, ap->a_cred, p);
return (error);
}
@@ -255,8 +247,9 @@ fifo_read(ap)
struct ucred *a_cred;
} */ *ap;
{
- register struct uio *uio = ap->a_uio;
- register struct socket *rso = ap->a_vp->v_fifoinfo->fi_readsock;
+ struct uio *uio = ap->a_uio;
+ struct socket *rso = ap->a_vp->v_fifoinfo->fi_readsock;
+ struct proc *p = uio->uio_procp;
int error, startresid;
#ifdef DIAGNOSTIC
@@ -268,10 +261,10 @@ fifo_read(ap)
if (ap->a_ioflag & IO_NDELAY)
rso->so_state |= SS_NBIO;
startresid = uio->uio_resid;
- VOP_UNLOCK(ap->a_vp);
- error = soreceive(rso, (struct mbuf **)0, uio,
- (struct mbuf **)0, (struct mbuf **)0, (int*)0);
- VOP_LOCK(ap->a_vp);
+ VOP_UNLOCK(ap->a_vp, 0, p);
+ error = soreceive(rso, (struct mbuf **)0, uio, (struct mbuf **)0,
+ (struct mbuf **)0, (int *)0);
+ vn_lock(ap->a_vp, LK_EXCLUSIVE | LK_RETRY, p);
/*
* Clear EOF indication after first such return.
*/
@@ -296,6 +289,7 @@ fifo_write(ap)
} */ *ap;
{
struct socket *wso = ap->a_vp->v_fifoinfo->fi_writesock;
+ struct proc *p = ap->a_uio->uio_procp;
int error;
#ifdef DIAGNOSTIC
@@ -304,9 +298,9 @@ fifo_write(ap)
#endif
if (ap->a_ioflag & IO_NDELAY)
wso->so_state |= SS_NBIO;
- VOP_UNLOCK(ap->a_vp);
+ VOP_UNLOCK(ap->a_vp, 0, p);
error = sosend(wso, (struct mbuf *)0, ap->a_uio, 0, (struct mbuf *)0, 0);
- VOP_LOCK(ap->a_vp);
+ vn_lock(ap->a_vp, LK_EXCLUSIVE | LK_RETRY, p);
if (ap->a_ioflag & IO_NDELAY)
wso->so_state &= ~SS_NBIO;
return (error);
@@ -328,14 +322,23 @@ fifo_ioctl(ap)
} */ *ap;
{
struct file filetmp;
+ int error;
if (ap->a_command == FIONBIO)
return (0);
- if (ap->a_fflag & FREAD)
+ if (ap->a_fflag & FREAD) {
filetmp.f_data = (caddr_t)ap->a_vp->v_fifoinfo->fi_readsock;
- else
+ error = soo_ioctl(&filetmp, ap->a_command, ap->a_data, ap->a_p);
+ if (error)
+ return (error);
+ }
+ if (ap->a_fflag & FWRITE) {
filetmp.f_data = (caddr_t)ap->a_vp->v_fifoinfo->fi_writesock;
- return (soo_ioctl(&filetmp, ap->a_command, ap->a_data, ap->a_p));
+ error = soo_ioctl(&filetmp, ap->a_command, ap->a_data, ap->a_p);
+ if (error)
+ return (error);
+ }
+ return (0);
}
/* ARGSUSED */
@@ -350,12 +353,33 @@ fifo_select(ap)
} */ *ap;
{
struct file filetmp;
+ int ready;
- if (ap->a_fflags & FREAD)
+ if (ap->a_fflags & FREAD) {
filetmp.f_data = (caddr_t)ap->a_vp->v_fifoinfo->fi_readsock;
- else
+ ready = soo_select(&filetmp, ap->a_which, ap->a_p);
+ if (ready)
+ return (ready);
+ }
+ if (ap->a_fflags & FWRITE) {
filetmp.f_data = (caddr_t)ap->a_vp->v_fifoinfo->fi_writesock;
- return (soo_select(&filetmp, ap->a_which, ap->a_p));
+ ready = soo_select(&filetmp, ap->a_which, ap->a_p);
+ if (ready)
+ return (ready);
+ }
+ return (0);
+}
+
+int
+fifo_inactive(ap)
+ struct vop_inactive_args /* {
+ struct vnode *a_vp;
+ struct proc *a_p;
+ } */ *ap;
+{
+
+ VOP_UNLOCK(ap->a_vp, 0, ap->a_p);
+ return (0);
}
/*
@@ -385,31 +409,6 @@ fifo_bmap(ap)
}
/*
- * At the moment we do not do any locking.
- */
-/* ARGSUSED */
-static int
-fifo_lock(ap)
- struct vop_lock_args /* {
- struct vnode *a_vp;
- } */ *ap;
-{
-
- return (0);
-}
-
-/* ARGSUSED */
-static int
-fifo_unlock(ap)
- struct vop_unlock_args /* {
- struct vnode *a_vp;
- } */ *ap;
-{
-
- return (0);
-}
-
-/*
* Device close routine
*/
/* ARGSUSED */
@@ -426,16 +425,16 @@ fifo_close(ap)
register struct fifoinfo *fip = vp->v_fifoinfo;
int error1, error2;
- if (ap->a_fflag & FWRITE) {
- fip->fi_writers--;
- if (fip->fi_writers == 0)
- socantrcvmore(fip->fi_readsock);
- }
if (ap->a_fflag & FREAD) {
fip->fi_readers--;
if (fip->fi_readers == 0)
socantsendmore(fip->fi_writesock);
}
+ if (ap->a_fflag & FWRITE) {
+ fip->fi_writers--;
+ if (fip->fi_writers == 0)
+ socantrcvmore(fip->fi_readsock);
+ }
if (vp->v_usecount > 1)
return (0);
error1 = soclose(fip->fi_readsock);
diff --git a/sys/fs/msdosfs/msdosfs_denode.c b/sys/fs/msdosfs/msdosfs_denode.c
index de4bf5e..a891ddc 100644
--- a/sys/fs/msdosfs/msdosfs_denode.c
+++ b/sys/fs/msdosfs/msdosfs_denode.c
@@ -124,7 +124,7 @@ msdosfs_hashget(dev, dirclust, diroff)
(void) tsleep((caddr_t)dep, PINOD, "msdhgt", 0);
break;
}
- if (!vget(DETOV(dep), 1))
+ if (!vget(DETOV(dep), LK_EXCLUSIVE | LK_INTERLOCK, curproc))
return dep;
break;
}
@@ -259,7 +259,7 @@ deget(pmp, dirclust, diroffset, direntptr, depp)
* can't be accessed until we've read it in and have done what we
* need to it.
*/
- VOP_LOCK(nvp);
+ vn_lock(nvp, LK_EXCLUSIVE | LK_RETRY, curproc);
msdosfs_hashins(ldep);
/*
@@ -716,7 +716,7 @@ msdosfs_inactive(ap)
printf("msdosfs_inactive(): dep %p, refcnt %ld, mntflag %x, MNT_RDONLY %x\n",
dep, dep->de_refcnt, vp->v_mount->mnt_flag, MNT_RDONLY);
#endif
- VOP_LOCK(vp);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, curproc);
if (dep->de_refcnt <= 0 && (vp->v_mount->mnt_flag & MNT_RDONLY) == 0) {
error = detrunc(dep, (u_long) 0, 0, NOCRED, NULL);
dep->de_flag |= DE_UPDATE;
@@ -726,7 +726,7 @@ msdosfs_inactive(ap)
TIMEVAL_TO_TIMESPEC(&time, &ts);
deupdat(dep, &ts, 0);
}
- VOP_UNLOCK(vp);
+ VOP_UNLOCK(vp, 0, curproc);
dep->de_flag = 0;
/*
diff --git a/sys/fs/msdosfs/msdosfs_lookup.c b/sys/fs/msdosfs/msdosfs_lookup.c
index 60236b8..6617f9e 100644
--- a/sys/fs/msdosfs/msdosfs_lookup.c
+++ b/sys/fs/msdosfs/msdosfs_lookup.c
@@ -54,6 +54,7 @@
#include <sys/vnode.h>
#include <sys/mount.h>
#include <sys/systm.h>
+#include <sys/proc.h>
#include <msdosfs/bpb.h>
#include <msdosfs/direntry.h>
@@ -156,14 +157,14 @@ msdosfs_lookup(ap)
VREF(vdp);
error = 0;
} else if (flags & ISDOTDOT) {
- VOP_UNLOCK(pdp);
- error = vget(vdp, 1);
+ VOP_UNLOCK(pdp, 0, curproc);
+ error = vget(vdp, LK_EXCLUSIVE | LK_INTERLOCK, curproc);
if (!error && lockparent && (flags & ISLASTCN))
- error = VOP_LOCK(pdp);
+ error = vn_lock(pdp, LK_EXCLUSIVE | LK_RETRY, curproc);
} else {
- error = vget(vdp, 1);
+ error = vget(vdp, LK_EXCLUSIVE | LK_INTERLOCK, curproc);
if (!lockparent || error || !(flags & ISLASTCN))
- VOP_UNLOCK(pdp);
+ VOP_UNLOCK(pdp, 0, curproc);
}
if (!error) {
@@ -183,9 +184,9 @@ msdosfs_lookup(ap)
}
vput(vdp);
if (lockparent && pdp != vdp && (flags & ISLASTCN))
- VOP_UNLOCK(pdp);
+ VOP_UNLOCK(pdp, 0, curproc);
}
- error = VOP_LOCK(pdp);
+ error = vn_lock(pdp, LK_EXCLUSIVE | LK_RETRY, curproc);
if (error)
return error;
vdp = pdp;
@@ -345,7 +346,7 @@ notfound:;
/* dp->de_flag |= DE_UPDATE; never update dos directories */
cnp->cn_flags |= SAVENAME;
if (!lockparent)/* leave searched dir locked? */
- VOP_UNLOCK(vdp);
+ VOP_UNLOCK(vdp, 0, curproc);
return EJUSTRETURN;
}
/*
@@ -398,7 +399,7 @@ foundroot:;
}
*vpp = DETOV(tdp);
if (!lockparent)
- VOP_UNLOCK(vdp);
+ VOP_UNLOCK(vdp, 0, curproc);
if (bp)
brelse(bp);
return 0;
@@ -428,7 +429,7 @@ foundroot:;
*vpp = DETOV(tdp);
cnp->cn_flags |= SAVENAME;
if (!lockparent)
- VOP_UNLOCK(vdp);
+ VOP_UNLOCK(vdp, 0, curproc);
if (bp)
brelse(bp);
return 0;
@@ -439,16 +440,16 @@ foundroot:;
*/
pdp = vdp;
if (flags & ISDOTDOT) {
- VOP_UNLOCK(pdp);
+ VOP_UNLOCK(pdp, 0, curproc);
error = deget(pmp, cluster, diroff, dep, &tdp);
if (error) {
- VOP_LOCK(pdp);
+ vn_lock(pdp, LK_EXCLUSIVE | LK_RETRY, curproc);
if (bp)
brelse(bp);
return error;
}
if (lockparent && (flags & ISLASTCN)
- && (error = VOP_LOCK(pdp))) {
+ && (error = vn_lock(pdp, LK_EXCLUSIVE | LK_RETRY, curproc))) {
vput(DETOV(tdp));
return error;
}
@@ -464,7 +465,7 @@ foundroot:;
return error;
}
if (!lockparent || !(flags & ISLASTCN))
- VOP_UNLOCK(pdp);
+ VOP_UNLOCK(pdp, 0, curproc);
*vpp = DETOV(tdp);
}
if (bp)
diff --git a/sys/fs/msdosfs/msdosfs_vfsops.c b/sys/fs/msdosfs/msdosfs_vfsops.c
index 5669c63..d0c8cdb 100644
--- a/sys/fs/msdosfs/msdosfs_vfsops.c
+++ b/sys/fs/msdosfs/msdosfs_vfsops.c
@@ -130,10 +130,10 @@ msdosfs_mount(mp, path, data, ndp, p)
flags = WRITECLOSE;
if (mp->mnt_flag & MNT_FORCE)
flags |= FORCECLOSE;
- if (vfs_busy(mp))
+ if (vfs_busy(mp, LK_NOWAIT, 0, p))
return EBUSY;
error = vflush(mp, NULLVP, flags);
- vfs_unbusy(mp);
+ vfs_unbusy(mp, p);
}
if (!error && (mp->mnt_flag & MNT_RELOAD))
/* not yet implemented */
@@ -707,7 +707,7 @@ loop:
if ((dep->de_flag & (DE_MODIFIED | DE_UPDATE)) == 0 &&
vp->v_dirtyblkhd.lh_first == NULL)
continue;
- if (vget(vp, 1)) /* not there anymore? */
+ if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK, p)) /* not there anymore? */
goto loop;
error = VOP_FSYNC(vp, cred, waitfor, p);
if (error)
diff --git a/sys/fs/msdosfs/msdosfs_vnops.c b/sys/fs/msdosfs/msdosfs_vnops.c
index bc4e12e..0f4deae 100644
--- a/sys/fs/msdosfs/msdosfs_vnops.c
+++ b/sys/fs/msdosfs/msdosfs_vnops.c
@@ -1172,17 +1172,17 @@ msdosfs_rename(ap)
*/
if (newparent == 0) {
/* tddep and fddep point to the same denode here */
- VOP_LOCK(ap->a_fvp); /* ap->a_fdvp is already locked */
+ vn_lock(ap->a_fvp, LK_EXCLUSIVE | LK_RETRY, curproc); /* ap->a_fdvp is already locked */
error = readep(fddep->de_pmp, fdep->de_dirclust,
fdep->de_diroffset, &bp, &ep);
if (error) {
- VOP_UNLOCK(ap->a_fvp);
+ VOP_UNLOCK(ap->a_fvp, 0, curproc);
goto bad;
}
bcopy(toname, ep->deName, 11);
error = bwrite(bp);
if (error) {
- VOP_UNLOCK(ap->a_fvp);
+ VOP_UNLOCK(ap->a_fvp, 0, curproc);
goto bad;
}
bcopy(toname, fdep->de_Name, 11); /* update denode */
@@ -1204,7 +1204,7 @@ msdosfs_rename(ap)
* will also insure that the directory entry on disk has a
* filesize of zero.
*/
- VOP_LOCK(ap->a_fvp);
+ vn_lock(ap->a_fvp, LK_EXCLUSIVE | LK_RETRY, curproc);
bcopy(toname, fdep->de_Name, 11); /* update denode */
if (fdep->de_Attributes & ATTR_DIRECTORY) {
dirsize = fdep->de_FileSize;
@@ -1216,22 +1216,22 @@ msdosfs_rename(ap)
}
if (error) {
/* should put back filename */
- VOP_UNLOCK(ap->a_fvp);
+ VOP_UNLOCK(ap->a_fvp, 0, curproc);
goto bad;
}
- VOP_LOCK(ap->a_fdvp);
+ vn_lock(ap->a_fdvp, LK_EXCLUSIVE | LK_RETRY, curproc);
error = readep(fddep->de_pmp, fddep->de_fndclust,
fddep->de_fndoffset, &bp, &ep);
if (error) {
- VOP_UNLOCK(ap->a_fvp);
- VOP_UNLOCK(ap->a_fdvp);
+ VOP_UNLOCK(ap->a_fvp, 0, curproc);
+ VOP_UNLOCK(ap->a_fdvp, 0, curproc);
goto bad;
}
ep->deName[0] = SLOT_DELETED;
error = bwrite(bp);
if (error) {
- VOP_UNLOCK(ap->a_fvp);
- VOP_UNLOCK(ap->a_fdvp);
+ VOP_UNLOCK(ap->a_fvp, 0, curproc);
+ VOP_UNLOCK(ap->a_fdvp, 0, curproc);
goto bad;
}
if (!sourceisadirectory) {
@@ -1239,7 +1239,7 @@ msdosfs_rename(ap)
fdep->de_diroffset = tddep->de_fndoffset;
reinsert(fdep);
}
- VOP_UNLOCK(ap->a_fdvp);
+ VOP_UNLOCK(ap->a_fdvp, 0, curproc);
}
/* fdep is still locked here */
@@ -1259,19 +1259,19 @@ msdosfs_rename(ap)
NOCRED, &bp);
if (error) {
/* should really panic here, fs is corrupt */
- VOP_UNLOCK(ap->a_fvp);
+ VOP_UNLOCK(ap->a_fvp, 0, curproc);
goto bad;
}
dotdotp = (struct direntry *) bp->b_data + 1;
putushort(dotdotp->deStartCluster, tddep->de_StartCluster);
error = bwrite(bp);
- VOP_UNLOCK(ap->a_fvp);
+ VOP_UNLOCK(ap->a_fvp, 0, curproc);
if (error) {
/* should really panic here, fs is corrupt */
goto bad;
}
} else
- VOP_UNLOCK(ap->a_fvp);
+ VOP_UNLOCK(ap->a_fvp, 0, curproc);
bad: ;
vrele(DETOV(fdep));
vrele(DETOV(fddep));
diff --git a/sys/fs/msdosfs/msdosfsmount.h b/sys/fs/msdosfs/msdosfsmount.h
index 7b0a22e..77c6add 100644
--- a/sys/fs/msdosfs/msdosfsmount.h
+++ b/sys/fs/msdosfs/msdosfsmount.h
@@ -169,3 +169,15 @@ struct msdosfsmount {
(((size) + (pmp)->pm_bpcluster - 1) >> (pmp)->pm_cnshift)
int msdosfs_init __P((void));
+
+/*
+ * Arguments to mount MSDOS filesystems.
+ */
+struct msdosfs_args {
+ char *fspec; /* blocks special holding the fs to mount */
+ struct export_args export; /* network export information */
+ uid_t uid; /* uid that owns msdosfs files */
+ gid_t gid; /* gid that owns msdosfs files */
+ mode_t mask; /* mask to be applied for msdosfs perms */
+};
+
diff --git a/sys/fs/nullfs/null.h b/sys/fs/nullfs/null.h
index beadb42..70a81b2 100644
--- a/sys/fs/nullfs/null.h
+++ b/sys/fs/nullfs/null.h
@@ -33,7 +33,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)null.h 8.2 (Berkeley) 1/21/94
+ * @(#)null.h 8.3 (Berkeley) 8/20/94
*
* $FreeBSD$
*/
@@ -52,8 +52,7 @@ struct null_mount {
* A cache of vnode references
*/
struct null_node {
- struct null_node *null_forw; /* Hash chain */
- struct null_node *null_back;
+ LIST_ENTRY(null_node) null_hash; /* Hash list */
struct vnode *null_lowervp; /* VREFed once */
struct vnode *null_vnode; /* Back pointer */
};
diff --git a/sys/fs/nullfs/null_subr.c b/sys/fs/nullfs/null_subr.c
index a14a7e4..4418631 100644
--- a/sys/fs/nullfs/null_subr.c
+++ b/sys/fs/nullfs/null_subr.c
@@ -33,13 +33,14 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)null_subr.c 8.4 (Berkeley) 1/21/94
+ * @(#)null_subr.c 8.7 (Berkeley) 5/14/95
*
* $FreeBSD$
*/
#include <sys/param.h>
#include <sys/systm.h>
+#include <sys/proc.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/vnode.h>
@@ -48,11 +49,8 @@
#include <sys/malloc.h>
#include <miscfs/nullfs/null.h>
-extern int nullfs_init __P((void));
-
#define LOG2_SIZEVNODE 7 /* log2(sizeof struct vnode) */
#define NNULLNODECACHE 16
-#define NULL_NHASH(vp) ((((u_long)vp)>>LOG2_SIZEVNODE) & (NNULLNODECACHE-1))
/*
* Null layer cache:
@@ -62,51 +60,32 @@ extern int nullfs_init __P((void));
* alias is removed the lower vnode is vrele'd.
*/
-/*
- * Cache head
- */
-struct null_node_cache {
- struct null_node *ac_forw;
- struct null_node *ac_back;
-};
-
-static struct null_node_cache null_node_cache[NNULLNODECACHE];
+#define NULL_NHASH(vp) \
+ (&null_node_hashtbl[(((u_long)vp)>>LOG2_SIZEVNODE) & null_node_hash])
+LIST_HEAD(null_node_hashhead, null_node) *null_node_hashtbl;
+u_long null_node_hash;
static int null_node_alloc __P((struct mount *mp, struct vnode *lowervp,
struct vnode **vpp));
static struct vnode *
null_node_find __P((struct mount *mp, struct vnode *lowervp));
-static struct null_node_cache *
- null_node_hash __P((struct vnode *lowervp));
/*
* Initialise cache headers
*/
int
-nullfs_init()
+nullfs_init(vfsp)
+ struct vfsconf *vfsp;
{
- struct null_node_cache *ac;
+
#ifdef NULLFS_DIAGNOSTIC
printf("nullfs_init\n"); /* printed during system boot */
#endif
-
- for (ac = null_node_cache; ac < null_node_cache + NNULLNODECACHE; ac++)
- ac->ac_forw = ac->ac_back = (struct null_node *) ac;
+ null_node_hashtbl = hashinit(NNULLNODECACHE, M_CACHE, &null_node_hash);
return (0);
}
/*
- * Compute hash list for given lower vnode
- */
-static struct null_node_cache *
-null_node_hash(lowervp)
-struct vnode *lowervp;
-{
-
- return (&null_node_cache[NULL_NHASH(lowervp)]);
-}
-
-/*
* Return a VREF'ed alias for lower vnode if already exists, else 0.
*/
static struct vnode *
@@ -114,7 +93,8 @@ null_node_find(mp, lowervp)
struct mount *mp;
struct vnode *lowervp;
{
- struct null_node_cache *hd;
+ struct proc *p = curproc; /* XXX */
+ struct null_node_hashhead *hd;
struct null_node *a;
struct vnode *vp;
@@ -124,9 +104,9 @@ null_node_find(mp, lowervp)
* the lower vnode. If found, the increment the null_node
* reference count (but NOT the lower vnode's VREF counter).
*/
- hd = null_node_hash(lowervp);
+ hd = NULL_NHASH(lowervp);
loop:
- for (a = hd->ac_forw; a != (struct null_node *) hd; a = a->null_forw) {
+ for (a = hd->lh_first; a != 0; a = a->null_hash.le_next) {
if (a->null_lowervp == lowervp && NULLTOV(a)->v_mount == mp) {
vp = NULLTOV(a);
/*
@@ -134,7 +114,7 @@ loop:
* stuff, but we don't want to lock
* the lower node.
*/
- if (vget(vp, 0)) {
+ if (vget(vp, 0, p)) {
printf ("null_node_find: vget failed.\n");
goto loop;
};
@@ -157,7 +137,7 @@ null_node_alloc(mp, lowervp, vpp)
struct vnode *lowervp;
struct vnode **vpp;
{
- struct null_node_cache *hd;
+ struct null_node_hashhead *hd;
struct null_node *xp;
struct vnode *othervp, *vp;
int error;
@@ -194,8 +174,8 @@ null_node_alloc(mp, lowervp, vpp)
return 0;
};
VREF(lowervp); /* Extra VREF will be vrele'd in null_node_create */
- hd = null_node_hash(lowervp);
- insque(xp, hd);
+ hd = NULL_NHASH(lowervp);
+ LIST_INSERT_HEAD(hd, xp, null_hash);
return 0;
}
@@ -250,9 +230,8 @@ null_node_create(mp, lowervp, newvpp)
#ifdef DIAGNOSTIC
if (lowervp->v_usecount < 1) {
/* Should never happen... */
- vprint ("null_node_create: alias ",aliasvp);
- vprint ("null_node_create: lower ",lowervp);
- printf ("null_node_create: lower has 0 usecount.\n");
+ vprint ("null_node_create: alias ", aliasvp);
+ vprint ("null_node_create: lower ", lowervp);
panic ("null_node_create: lower has 0 usecount.");
};
#endif
diff --git a/sys/fs/nullfs/null_vfsops.c b/sys/fs/nullfs/null_vfsops.c
index e2aeeba..339b7c1 100644
--- a/sys/fs/nullfs/null_vfsops.c
+++ b/sys/fs/nullfs/null_vfsops.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1992, 1993
+ * Copyright (c) 1992, 1993, 1995
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software donated to Berkeley by
@@ -46,7 +46,7 @@
#include <sys/param.h>
#include <sys/systm.h>
-#include <sys/kernel.h>
+#include <sys/proc.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/vnode.h>
@@ -55,7 +55,7 @@
#include <sys/malloc.h>
#include <miscfs/nullfs/null.h>
-extern int nullfs_init __P((void));
+extern int nullfs_init __P((struct vfsconf *));
static int nullfs_fhtovp __P((struct mount *mp, struct fid *fidp,
struct mbuf *nam, struct vnode **vpp,
@@ -146,7 +146,7 @@ nullfs_mount(mp, path, data, ndp, p)
/*
* Unlock the node (either the lower or the alias)
*/
- VOP_UNLOCK(vp);
+ VOP_UNLOCK(vp, 0, p);
/*
* Make sure the node alias worked
*/
@@ -166,7 +166,7 @@ nullfs_mount(mp, path, data, ndp, p)
if (NULLVPTOLOWERVP(nullm_rootvp)->v_mount->mnt_flag & MNT_LOCAL)
mp->mnt_flag |= MNT_LOCAL;
mp->mnt_data = (qaddr_t) xmp;
- getnewfsid(mp, MOUNT_LOFS);
+ vfs_getnewfsid(mp);
(void) copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN - 1, &size);
bzero(mp->mnt_stat.f_mntonname + size, MNAMELEN - size);
@@ -212,12 +212,8 @@ nullfs_unmount(mp, mntflags, p)
printf("nullfs_unmount(mp = %x)\n", mp);
#endif
- if (mntflags & MNT_FORCE) {
- /* lofs can never be rootfs so don't check for it */
- if (!doforce)
- return (EINVAL);
+ if (mntflags & MNT_FORCE)
flags |= FORCECLOSE;
- }
/*
* Clear out buffer cache. I don't think we
@@ -259,6 +255,7 @@ nullfs_root(mp, vpp)
struct mount *mp;
struct vnode **vpp;
{
+ struct proc *p = curproc; /* XXX */
struct vnode *vp;
#ifdef NULLFS_DIAGNOSTIC
@@ -273,7 +270,7 @@ nullfs_root(mp, vpp)
*/
vp = MOUNTTONULLMOUNT(mp)->nullm_rootvp;
VREF(vp);
- VOP_LOCK(vp);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
*vpp = vp;
return 0;
}
diff --git a/sys/fs/nullfs/null_vnops.c b/sys/fs/nullfs/null_vnops.c
index ec279bc..c1af96f 100644
--- a/sys/fs/nullfs/null_vnops.c
+++ b/sys/fs/nullfs/null_vnops.c
@@ -33,7 +33,13 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)null_vnops.c 8.1 (Berkeley) 6/10/93
+ * @(#)null_vnops.c 8.6 (Berkeley) 5/27/95
+ *
+ * Ancestors:
+ * @(#)lofs_vnops.c 1.2 (Berkeley) 6/18/92
+ * $Id: null_vnops.c,v 1.11.2000.1 1996/09/17 14:32:31 peter Exp $
+ * ...and...
+ * @(#)null_vnodeops.c 1.20 92/07/07 UCLA Ficus project
*
* $FreeBSD$
*/
@@ -88,13 +94,21 @@
* in the arguments and, if a vnode is return by the operation,
* stacks a null-node on top of the returned vnode.
*
- * Although bypass handles most operations,
- * vop_getattr, _inactive, _reclaim, and _print are not bypassed.
- * Vop_getattr must change the fsid being returned.
+ * Although bypass handles most operations, vop_getattr, vop_lock,
+ * vop_unlock, vop_inactive, vop_reclaim, and vop_print are not
+ * bypassed. Vop_getattr must change the fsid being returned.
+ * Vop_lock and vop_unlock must handle any locking for the
+ * current vnode as well as pass the lock request down.
* Vop_inactive and vop_reclaim are not bypassed so that
- * they can handle freeing null-layer specific data.
- * Vop_print is not bypassed to avoid excessive debugging
- * information.
+ * they can handle freeing null-layer specific data. Vop_print
+ * is not bypassed to avoid excessive debugging information.
+ * Also, certain vnode operations change the locking state within
+ * the operation (create, mknod, remove, link, rename, mkdir, rmdir,
+ * and symlink). Ideally these operations should not change the
+ * lock state, but should be changed to let the caller of the
+ * function unlock them. Otherwise all intermediate vnode layers
+ * (such as union, umapfs, etc) must catch these functions to do
+ * the necessary locking at their layer.
*
*
* INSTANTIATING VNODE STACKS
@@ -178,7 +192,7 @@ static int null_bug_bypass = 0; /* for debugging: enables bypass printf'ing */
SYSCTL_INT(_debug, OID_AUTO, nullfs_bug_bypass, CTLFLAG_RW,
&null_bug_bypass, 0, "");
-static int null_bypass __P((struct vop_generic_args *ap));
+int null_bypass __P((struct vop_generic_args *ap));
static int null_bwrite __P((struct vop_bwrite_args *ap));
static int null_getattr __P((struct vop_getattr_args *ap));
static int null_inactive __P((struct vop_inactive_args *ap));
@@ -211,7 +225,7 @@ static int null_strategy __P((struct vop_strategy_args *ap));
* - all mapped vnodes are of our vnode-type (NEEDSWORK:
* problems on rmdir'ing mount points and renaming?)
*/
-static int
+int
null_bypass(ap)
struct vop_generic_args /* {
struct vnodeop_desc *a_desc;
@@ -254,7 +268,8 @@ null_bypass(ap)
* are of our type. Check for and don't map any
* that aren't. (We must always map first vp or vclean fails.)
*/
- if (i && (*this_vp_p)->v_op != null_vnodeop_p) {
+ if (i && (*this_vp_p == NULL ||
+ (*this_vp_p)->v_op != null_vnodeop_p)) {
old_vps[i] = NULL;
} else {
old_vps[i] = *this_vp_p;
@@ -317,6 +332,105 @@ null_bypass(ap)
return (error);
}
+/*
+ * We have to carry on the locking protocol on the null layer vnodes
+ * as we progress through the tree. We also have to enforce read-only
+ * if this layer is mounted read-only.
+ */
+static int
+null_lookup(ap)
+ struct vop_lookup_args /* {
+ struct vnode * a_dvp;
+ struct vnode ** a_vpp;
+ struct componentname * a_cnp;
+ } */ *ap;
+{
+ struct componentname *cnp = ap->a_cnp;
+ struct proc *p = cnp->cn_proc;
+ int flags = cnp->cn_flags;
+ struct vop_lock_args lockargs;
+ struct vop_unlock_args unlockargs;
+ struct vnode *dvp, *vp;
+ int error;
+
+ if ((flags & ISLASTCN) && (ap->a_dvp->v_mount->mnt_flag & MNT_RDONLY) &&
+ (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME))
+ return (EROFS);
+ error = null_bypass(ap);
+ if (error == EJUSTRETURN && (flags & ISLASTCN) &&
+ (ap->a_dvp->v_mount->mnt_flag & MNT_RDONLY) &&
+ (cnp->cn_nameiop == CREATE || cnp->cn_nameiop == RENAME))
+ error = EROFS;
+ /*
+ * We must do the same locking and unlocking at this layer as
+ * is done in the layers below us. We could figure this out
+ * based on the error return and the LASTCN, LOCKPARENT, and
+ * LOCKLEAF flags. However, it is more expidient to just find
+ * out the state of the lower level vnodes and set ours to the
+ * same state.
+ */
+ dvp = ap->a_dvp;
+ vp = *ap->a_vpp;
+ if (dvp == vp)
+ return (error);
+ if (!VOP_ISLOCKED(dvp)) {
+ unlockargs.a_vp = dvp;
+ unlockargs.a_flags = 0;
+ unlockargs.a_p = p;
+ vop_nounlock(&unlockargs);
+ }
+ if (vp != NULL && VOP_ISLOCKED(vp)) {
+ lockargs.a_vp = vp;
+ lockargs.a_flags = LK_SHARED;
+ lockargs.a_p = p;
+ vop_nolock(&lockargs);
+ }
+ return (error);
+}
+
+/*
+ * Setattr call. Disallow write attempts if the layer is mounted read-only.
+ */
+int
+null_setattr(ap)
+ struct vop_setattr_args /* {
+ struct vnodeop_desc *a_desc;
+ struct vnode *a_vp;
+ struct vattr *a_vap;
+ struct ucred *a_cred;
+ struct proc *a_p;
+ } */ *ap;
+{
+ struct vnode *vp = ap->a_vp;
+ struct vattr *vap = ap->a_vap;
+
+ if ((vap->va_flags != VNOVAL || vap->va_uid != (uid_t)VNOVAL ||
+ vap->va_gid != (gid_t)VNOVAL || vap->va_atime.ts_sec != VNOVAL ||
+ vap->va_mtime.ts_sec != VNOVAL || vap->va_mode != (mode_t)VNOVAL) &&
+ (vp->v_mount->mnt_flag & MNT_RDONLY))
+ return (EROFS);
+ if (vap->va_size != VNOVAL) {
+ switch (vp->v_type) {
+ case VDIR:
+ return (EISDIR);
+ case VCHR:
+ case VBLK:
+ case VSOCK:
+ case VFIFO:
+ return (0);
+ case VREG:
+ case VLNK:
+ default:
+ /*
+ * Disallow write attempts if the filesystem is
+ * mounted read-only.
+ */
+ if (vp->v_mount->mnt_flag & MNT_RDONLY)
+ return (EROFS);
+ }
+ }
+ return (null_bypass(ap));
+}
/*
* We handle getattr only to change the fsid.
@@ -331,19 +445,90 @@ null_getattr(ap)
} */ *ap;
{
int error;
- error = null_bypass(ap);
- if (error)
+
+ if (error = null_bypass(ap))
return (error);
/* Requires that arguments be restored. */
ap->a_vap->va_fsid = ap->a_vp->v_mount->mnt_stat.f_fsid.val[0];
return (0);
}
-
static int
+null_access(ap)
+ struct vop_access_args /* {
+ struct vnode *a_vp;
+ int a_mode;
+ struct ucred *a_cred;
+ struct proc *a_p;
+ } */ *ap;
+{
+ struct vnode *vp = ap->a_vp;
+ mode_t mode = ap->a_mode;
+
+ /*
+ * Disallow write attempts on read-only layers;
+ * unless the file is a socket, fifo, or a block or
+ * character device resident on the file system.
+ */
+ if (mode & VWRITE) {
+ switch (vp->v_type) {
+ case VDIR:
+ case VLNK:
+ case VREG:
+ if (vp->v_mount->mnt_flag & MNT_RDONLY)
+ return (EROFS);
+ break;
+ }
+ }
+ return (null_bypass(ap));
+}
+
+/*
+ * We need to process our own vnode lock and then clear the
+ * interlock flag as it applies only to our vnode, not the
+ * vnodes below us on the stack.
+ */
+int
+null_lock(ap)
+ struct vop_lock_args /* {
+ struct vnode *a_vp;
+ int a_flags;
+ struct proc *a_p;
+ } */ *ap;
+{
+
+ vop_nolock(ap);
+ if ((ap->a_flags & LK_TYPE_MASK) == LK_DRAIN)
+ return (0);
+ ap->a_flags &= ~LK_INTERLOCK;
+ return (null_bypass(ap));
+}
+
+/*
+ * We need to process our own vnode unlock and then clear the
+ * interlock flag as it applies only to our vnode, not the
+ * vnodes below us on the stack.
+ */
+int
+null_unlock(ap)
+ struct vop_unlock_args /* {
+ struct vnode *a_vp;
+ int a_flags;
+ struct proc *a_p;
+ } */ *ap;
+{
+ struct vnode *vp = ap->a_vp;
+
+ vop_nounlock(ap);
+ ap->a_flags &= ~LK_INTERLOCK;
+ return (null_bypass(ap));
+}
+
+int
null_inactive(ap)
struct vop_inactive_args /* {
struct vnode *a_vp;
+ struct proc *a_p;
} */ *ap;
{
/*
@@ -358,6 +543,7 @@ null_inactive(ap)
* like they do in the name lookup cache code.
* That's too much work for now.
*/
+ VOP_UNLOCK(ap->a_vp, 0, ap->a_p);
return (0);
}
@@ -365,6 +551,7 @@ static int
null_reclaim(ap)
struct vop_reclaim_args /* {
struct vnode *a_vp;
+ struct proc *a_p;
} */ *ap;
{
struct vnode *vp = ap->a_vp;
@@ -377,14 +564,13 @@ null_reclaim(ap)
*/
/* After this assignment, this node will not be re-used. */
xp->null_lowervp = NULL;
- remque(xp);
+ LIST_REMOVE(xp, null_hash);
FREE(vp->v_data, M_TEMP);
vp->v_data = NULL;
vrele (lowervp);
return (0);
}
-
static int
null_print(ap)
struct vop_print_args /* {
@@ -396,7 +582,6 @@ null_print(ap)
return (0);
}
-
/*
* XXX - vop_strategy must be hand coded because it has no
* vnode in its arguments.
@@ -422,7 +607,6 @@ null_strategy(ap)
return (error);
}
-
/*
* XXX - like vop_strategy, vop_bwrite must be hand coded because it has no
* vnode in its arguments.
@@ -455,7 +639,12 @@ vop_t **null_vnodeop_p;
static struct vnodeopv_entry_desc null_vnodeop_entries[] = {
{ &vop_default_desc, (vop_t *)null_bypass },
+ { &vop_lookup_desc, (vop_t *)null_lookup },
+ { &vop_setattr_desc, (vop_t *)null_setattr },
{ &vop_getattr_desc, (vop_t *)null_getattr },
+ { &vop_access_desc, (vop_t *)null_access },
+ { &vop_lock_desc, (vop_t *)null_lock },
+ { &vop_unlock_desc, (vop_t *)null_unlock },
{ &vop_inactive_desc, (vop_t *)null_inactive },
{ &vop_reclaim_desc, (vop_t *)null_reclaim },
{ &vop_print_desc, (vop_t *)null_print },
diff --git a/sys/fs/portalfs/portal_vfsops.c b/sys/fs/portalfs/portal_vfsops.c
index a980f65..74e1542 100644
--- a/sys/fs/portalfs/portal_vfsops.c
+++ b/sys/fs/portalfs/portal_vfsops.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1992, 1993
+ * Copyright (c) 1992, 1993, 1995
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software donated to Berkeley by
@@ -33,7 +33,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)portal_vfsops.c 8.6 (Berkeley) 1/21/94
+ * @(#)portal_vfsops.c 8.11 (Berkeley) 5/14/95
*
* $FreeBSD$
*/
@@ -62,28 +62,18 @@
#include <sys/un.h>
#include <miscfs/portal/portal.h>
-static int portal_init __P((void));
static int portal_mount __P((struct mount *mp, char *path, caddr_t data,
struct nameidata *ndp, struct proc *p));
static int portal_start __P((struct mount *mp, int flags, struct proc *p));
static int portal_unmount __P((struct mount *mp, int mntflags,
struct proc *p));
static int portal_root __P((struct mount *mp, struct vnode **vpp));
-static int portal_quotactl __P((struct mount *mp, int cmd, uid_t uid,
- caddr_t arg, struct proc *p));
static int portal_statfs __P((struct mount *mp, struct statfs *sbp,
struct proc *p));
-static int portal_sync __P((struct mount *mp, int waitfor,
- struct ucred *cred, struct proc *p));
-static int portal_vget __P((struct mount *mp, ino_t ino,
- struct vnode **vpp));
-static int portal_fhtovp __P((struct mount *mp, struct fid *fhp,
- struct mbuf *nam, struct vnode **vpp,
- int *exflagsp, struct ucred **credanonp));
-static int portal_vptofh __P((struct vnode *vp, struct fid *fhp));
static int
-portal_init()
+portal_init(vfsp)
+ struct vfsconf *vfsp;
{
return (0);
@@ -150,7 +140,7 @@ portal_mount(mp, path, data, ndp, p)
mp->mnt_flag |= MNT_LOCAL;
mp->mnt_data = (qaddr_t) fmp;
- getnewfsid(mp, MOUNT_PORTAL);
+ vfs_getnewfsid(mp);
(void)copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN - 1, &size);
bzero(mp->mnt_stat.f_mntonname + size, MNAMELEN - size);
@@ -186,12 +176,8 @@ portal_unmount(mp, mntflags, p)
int error, flags = 0;
- if (mntflags & MNT_FORCE) {
- /* portal can never be rootfs so don't check for it */
- if (!doforce)
- return (EINVAL);
+ if (mntflags & MNT_FORCE)
flags |= FORCECLOSE;
- }
/*
* Clear out buffer cache. I don't think we
@@ -241,39 +227,26 @@ portal_root(mp, vpp)
struct mount *mp;
struct vnode **vpp;
{
+ struct proc *p = curproc; /* XXX */
struct vnode *vp;
-
/*
* Return locked reference to root.
*/
vp = VFSTOPORTAL(mp)->pm_root;
VREF(vp);
- VOP_LOCK(vp);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
*vpp = vp;
return (0);
}
static int
-portal_quotactl(mp, cmd, uid, arg, p)
- struct mount *mp;
- int cmd;
- uid_t uid;
- caddr_t arg;
- struct proc *p;
-{
-
- return (EOPNOTSUPP);
-}
-
-static int
portal_statfs(mp, sbp, p)
struct mount *mp;
struct statfs *sbp;
struct proc *p;
{
- sbp->f_type = MOUNT_PORTAL;
sbp->f_flags = 0;
sbp->f_bsize = DEV_BSIZE;
sbp->f_iosize = DEV_BSIZE;
@@ -283,6 +256,7 @@ portal_statfs(mp, sbp, p)
sbp->f_files = 1; /* Allow for "." */
sbp->f_ffree = 0; /* See comments above */
if (sbp != &mp->mnt_stat) {
+ sbp->f_type = mp->mnt_vfc->vfc_typenum;
bcopy(&mp->mnt_stat.f_fsid, &sbp->f_fsid, sizeof(sbp->f_fsid));
bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN);
bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN);
@@ -290,48 +264,17 @@ portal_statfs(mp, sbp, p)
return (0);
}
-static int
-portal_sync(mp, waitfor, cred, p)
- struct mount *mp;
- int waitfor;
- struct ucred *cred;
- struct proc *p;
-{
-
- return (0);
-}
-
-static int
-portal_vget(mp, ino, vpp)
- struct mount *mp;
- ino_t ino;
- struct vnode **vpp;
-{
-
- return (EOPNOTSUPP);
-}
-
-static int
-portal_fhtovp(mp, fhp, nam, vpp, exflagsp, credanonp)
- struct mount *mp;
- struct fid *fhp;
- struct mbuf *nam;
- struct vnode **vpp;
- int *exflagsp;
- struct ucred **credanonp;
-{
-
- return (EOPNOTSUPP);
-}
-
-static int
-portal_vptofh(vp, fhp)
- struct vnode *vp;
- struct fid *fhp;
-{
-
- return (EOPNOTSUPP);
-}
+#define portal_fhtovp ((int (*) __P((struct mount *, struct fid *, \
+ struct mbuf *, struct vnode **, int *, struct ucred **)))eopnotsupp)
+#define portal_quotactl ((int (*) __P((struct mount *, int, uid_t, caddr_t, \
+ struct proc *)))eopnotsupp)
+#define portal_sync ((int (*) __P((struct mount *, int, struct ucred *, \
+ struct proc *)))nullop)
+#define portal_sysctl ((int (*) __P((int *, u_int, void *, size_t *, void *, \
+ size_t, struct proc *)))eopnotsupp)
+#define portal_vget ((int (*) __P((struct mount *, ino_t, struct vnode **))) \
+ eopnotsupp)
+#define portal_vptofh ((int (*) __P((struct vnode *, struct fid *)))eopnotsupp)
static struct vfsops portal_vfsops = {
portal_mount,
diff --git a/sys/fs/portalfs/portal_vnops.c b/sys/fs/portalfs/portal_vnops.c
index 8135a5e..19b439c 100644
--- a/sys/fs/portalfs/portal_vnops.c
+++ b/sys/fs/portalfs/portal_vnops.c
@@ -33,7 +33,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)portal_vnops.c 8.8 (Berkeley) 1/21/94
+ * @(#)portal_vnops.c 8.14 (Berkeley) 5/21/95
*
* $FreeBSD$
*/
@@ -112,17 +112,25 @@ portal_lookup(ap)
struct componentname * a_cnp;
} */ *ap;
{
- char *pname = ap->a_cnp->cn_nameptr;
+ struct componentname *cnp = ap->a_cnp;
+ struct vnode **vpp = ap->a_vpp;
+ struct vnode *dvp = ap->a_dvp;
+ char *pname = cnp->cn_nameptr;
struct portalnode *pt;
int error;
struct vnode *fvp = 0;
char *path;
int size;
- if (ap->a_cnp->cn_namelen == 1 && *pname == '.') {
- *ap->a_vpp = ap->a_dvp;
- VREF(ap->a_dvp);
- /*VOP_LOCK(ap->a_dvp);*/
+ *vpp = NULLVP;
+
+ if (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME)
+ return (EROFS);
+
+ if (cnp->cn_namelen == 1 && *pname == '.') {
+ *vpp = dvp;
+ VREF(dvp);
+ /*VOP_LOCK(dvp);*/
return (0);
}
@@ -134,7 +142,7 @@ portal_lookup(ap)
MALLOC(pt, struct portalnode *, sizeof(struct portalnode),
M_TEMP, M_WAITOK);
- error = getnewvnode(VT_PORTAL, ap->a_dvp->v_mount, portal_vnodeop_p, &fvp);
+ error = getnewvnode(VT_PORTAL, dvp->v_mount, portal_vnodeop_p, &fvp);
if (error) {
FREE(pt, M_TEMP);
goto bad;
@@ -148,22 +156,20 @@ portal_lookup(ap)
*/
for (size = 0, path = pname; *path; path++)
size++;
- ap->a_cnp->cn_consume = size - ap->a_cnp->cn_namelen;
+ cnp->cn_consume = size - cnp->cn_namelen;
pt->pt_arg = malloc(size+1, M_TEMP, M_WAITOK);
pt->pt_size = size+1;
bcopy(pname, pt->pt_arg, pt->pt_size);
pt->pt_fileid = portal_fileid++;
- *ap->a_vpp = fvp;
+ *vpp = fvp;
/*VOP_LOCK(fvp);*/
return (0);
bad:;
- if (fvp) {
+ if (fvp)
vrele(fvp);
- }
- *ap->a_vpp = NULL;
return (error);
}
@@ -444,6 +450,7 @@ portal_getattr(ap)
{
struct vnode *vp = ap->a_vp;
struct vattr *vap = ap->a_vap;
+ struct timeval tv;
bzero(vap, sizeof(*vap));
vattr_null(vap);
@@ -452,8 +459,8 @@ portal_getattr(ap)
vap->va_fsid = vp->v_mount->mnt_stat.f_fsid.val[0];
vap->va_size = DEV_BSIZE;
vap->va_blocksize = DEV_BSIZE;
- microtime((struct timeval *)&vap->va_atime);
- TIMEVAL_TO_TIMESPEC((struct timeval *)&vap->va_atime, (struct timespec *)&vap->va_atime);
+ microtime(&tv);
+ TIMEVAL_TO_TIMESPEC(&tv, &vap->va_atime);
vap->va_mtime = vap->va_atime;
vap->va_ctime = vap->va_ctime;
vap->va_gen = 0;
@@ -509,9 +516,19 @@ portal_readdir(ap)
struct vnode *a_vp;
struct uio *a_uio;
struct ucred *a_cred;
+ int *a_eofflag;
+ u_long *a_cookies;
+ int a_ncookies;
} */ *ap;
{
+ /*
+ * We don't allow exporting portal mounts, and currently local
+ * requests do not need cookies.
+ */
+ if (ap->a_ncookies)
+ panic("portal_readdir: not hungry");
+
return (0);
}
@@ -519,9 +536,11 @@ static int
portal_inactive(ap)
struct vop_inactive_args /* {
struct vnode *a_vp;
+ struct proc *a_p;
} */ *ap;
{
+ VOP_UNLOCK(ap->a_vp, 0, ap->a_p);
return (0);
}
@@ -639,6 +658,7 @@ portal_badop()
#define portal_ioctl ((int (*) __P((struct vop_ioctl_args *)))portal_enotsupp)
#define portal_select ((int (*) __P((struct vop_select_args *)))portal_enotsupp)
#define portal_mmap ((int (*) __P((struct vop_mmap_args *)))portal_enotsupp)
+#define portal_revoke vop_revoke
#define portal_fsync ((int (*) __P((struct vop_fsync_args *)))nullop)
#define portal_seek ((int (*) __P((struct vop_seek_args *)))nullop)
#define portal_remove ((int (*) __P((struct vop_remove_args *)))portal_enotsupp)
@@ -651,12 +671,14 @@ portal_badop()
#define portal_readlink \
((int (*) __P((struct vop_readlink_args *)))portal_enotsupp)
#define portal_abortop ((int (*) __P((struct vop_abortop_args *)))nullop)
-#define portal_lock ((int (*) __P((struct vop_lock_args *)))nullop)
-#define portal_unlock ((int (*) __P((struct vop_unlock_args *)))nullop)
+#define portal_lock ((int (*) __P((struct vop_lock_args *)))vop_nolock)
+#define portal_unlock ((int (*) __P((struct vop_unlock_args *)))vop_nounlock)
#define portal_bmap ((int (*) __P((struct vop_bmap_args *)))portal_badop)
#define portal_strategy \
((int (*) __P((struct vop_strategy_args *)))portal_badop)
-#define portal_islocked ((int (*) __P((struct vop_islocked_args *)))nullop)
+#define portal_islocked \
+ ((int (*) __P((struct vop_islocked_args *)))vop_noislocked)
+#define fifo_islocked ((int(*) __P((struct vop_islocked_args *)))vop_noislocked)
#define portal_advlock \
((int (*) __P((struct vop_advlock_args *)))portal_enotsupp)
#define portal_blkatoff \
@@ -687,6 +709,7 @@ static struct vnodeopv_entry_desc portal_vnodeop_entries[] = {
{ &vop_ioctl_desc, (vop_t *)portal_ioctl }, /* ioctl */
{ &vop_select_desc, (vop_t *)portal_select }, /* select */
{ &vop_mmap_desc, (vop_t *)portal_mmap }, /* mmap */
+ { &vop_revoke_desc, (vop_t *)portal_revoke }, /* revoke */
{ &vop_fsync_desc, (vop_t *)portal_fsync }, /* fsync */
{ &vop_seek_desc, (vop_t *)portal_seek }, /* seek */
{ &vop_remove_desc, (vop_t *)portal_remove }, /* remove */
diff --git a/sys/fs/procfs/procfs.h b/sys/fs/procfs/procfs.h
index df01a39..ef0d7eb 100644
--- a/sys/fs/procfs/procfs.h
+++ b/sys/fs/procfs/procfs.h
@@ -34,8 +34,9 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)procfs.h 8.6 (Berkeley) 2/3/94
+ * @(#)procfs.h 8.9 (Berkeley) 5/14/95
*
+ * From:
* $FreeBSD$
*/
@@ -44,6 +45,7 @@
*/
typedef enum {
Proot, /* the filesystem root */
+ Pcurproc, /* symbolic link for curproc */
Pproc, /* a process-specific sub-directory */
Pfile, /* the executable file */
Pmem, /* the process's memory image */
@@ -97,9 +99,9 @@ struct pfsdent {
};
#define UIO_MX sizeof(struct pfsdent)
#define PROCFS_FILENO(pid, type) \
- (((type) == Proot) ? \
- 2 : \
- ((((pid)+1) << 3) + ((int) (type))))
+ (((type) < Pproc) ? \
+ ((type) + 2) : \
+ ((((pid)+1) << 4) + ((int) (type))))
/*
* Convert between pfsnode vnode
@@ -113,33 +115,33 @@ struct vfs_namemap {
int nm_val;
};
-extern int vfs_getuserstr __P((struct uio *, char *, int *));
-extern vfs_namemap_t *vfs_findname __P((vfs_namemap_t *, char *, int));
+int vfs_getuserstr __P((struct uio *, char *, int *));
+vfs_namemap_t *vfs_findname __P((vfs_namemap_t *, char *, int));
/* <machine/reg.h> */
struct reg;
struct fpreg;
#define PFIND(pid) ((pid) ? pfind(pid) : &proc0)
-extern int procfs_freevp __P((struct vnode *));
-extern int procfs_allocvp __P((struct mount *, struct vnode **, long, pfstype));
-extern struct vnode *procfs_findtextvp __P((struct proc *));
-extern int procfs_sstep __P((struct proc *));
-extern void procfs_fix_sstep __P((struct proc *));
-extern int procfs_read_regs __P((struct proc *, struct reg *));
-extern int procfs_write_regs __P((struct proc *, struct reg *));
-extern int procfs_read_fpregs __P((struct proc *, struct fpreg *));
-extern int procfs_write_fpregs __P((struct proc *, struct fpreg *));
-extern int procfs_donote __P((struct proc *, struct proc *, struct pfsnode *pfsp, struct uio *uio));
-extern int procfs_doregs __P((struct proc *, struct proc *, struct pfsnode *pfsp, struct uio *uio));
-extern int procfs_dofpregs __P((struct proc *, struct proc *, struct pfsnode *pfsp, struct uio *uio));
-extern int procfs_domem __P((struct proc *, struct proc *, struct pfsnode *pfsp, struct uio *uio));
-extern int procfs_doctl __P((struct proc *, struct proc *, struct pfsnode *pfsp, struct uio *uio));
-extern int procfs_dostatus __P((struct proc *, struct proc *, struct pfsnode *pfsp, struct uio *uio));
-extern int procfs_domap __P((struct proc *, struct proc *, struct pfsnode *pfsp, struct uio *uio));
-extern int procfs_dotype __P((struct proc *, struct proc *, struct pfsnode *pfsp, struct uio *uio));
+int procfs_freevp __P((struct vnode *));
+int procfs_allocvp __P((struct mount *, struct vnode **, long, pfstype));
+struct vnode *procfs_findtextvp __P((struct proc *));
+int procfs_sstep __P((struct proc *));
+void procfs_fix_sstep __P((struct proc *));
+int procfs_read_regs __P((struct proc *, struct reg *));
+int procfs_write_regs __P((struct proc *, struct reg *));
+int procfs_read_fpregs __P((struct proc *, struct fpreg *));
+int procfs_write_fpregs __P((struct proc *, struct fpreg *));
+int procfs_donote __P((struct proc *, struct proc *, struct pfsnode *pfsp, struct uio *uio));
+int procfs_doregs __P((struct proc *, struct proc *, struct pfsnode *pfsp, struct uio *uio));
+int procfs_dofpregs __P((struct proc *, struct proc *, struct pfsnode *pfsp, struct uio *uio));
+int procfs_domem __P((struct proc *, struct proc *, struct pfsnode *pfsp, struct uio *uio));
+int procfs_doctl __P((struct proc *, struct proc *, struct pfsnode *pfsp, struct uio *uio));
+int procfs_dostatus __P((struct proc *, struct proc *, struct pfsnode *pfsp, struct uio *uio));
+int procfs_domap __P((struct proc *, struct proc *, struct pfsnode *pfsp, struct uio *uio));
+int procfs_dotype __P((struct proc *, struct proc *, struct pfsnode *pfsp, struct uio *uio));
-/* check to see if the process has the "items" (regs/file) */
+/* functions to check whether or not files should be displayed */
int procfs_validfile __P((struct proc *));
int procfs_validfpregs __P((struct proc *));
int procfs_validregs __P((struct proc *));
diff --git a/sys/fs/procfs/procfs_ctl.c b/sys/fs/procfs/procfs_ctl.c
index 4ddf7a7..68b93dd 100644
--- a/sys/fs/procfs/procfs_ctl.c
+++ b/sys/fs/procfs/procfs_ctl.c
@@ -34,8 +34,9 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)procfs_ctl.c 8.3 (Berkeley) 1/21/94
+ * @(#)procfs_ctl.c 8.4 (Berkeley) 6/15/94
*
+ * From:
* $FreeBSD$
*/
@@ -51,13 +52,13 @@
#include <sys/resourcevar.h>
#include <sys/signal.h>
#include <sys/signalvar.h>
-
-#include <vm/vm.h>
-#include <vm/vm_param.h>
-#include <vm/vm_extern.h>
-
+#include <sys/ptrace.h>
#include <miscfs/procfs/procfs.h>
+#ifndef FIX_SSTEP
+#define FIX_SSTEP(p)
+#endif
+
/*
* True iff process (p) is in trace wait state
* relative to process (curp)
@@ -67,13 +68,6 @@
(p)->p_pptr == (curp) && \
((p)->p_flag & P_TRACED))
-#ifdef notdef
-#define FIX_SSTEP(p) { \
- procfs_fix_sstep(p); \
- } \
-}
-#endif
-
#define PROCFS_CTL_ATTACH 1
#define PROCFS_CTL_DETACH 2
#define PROCFS_CTL_STEP 3
@@ -220,8 +214,10 @@ procfs_control(curp, p, op)
*/
case PROCFS_CTL_STEP:
PHOLD(p);
- procfs_sstep(p);
+ error = procfs_sstep(p);
PRELE(p);
+ if (error)
+ return (error);
break;
/*
diff --git a/sys/fs/procfs/procfs_fpregs.c b/sys/fs/procfs/procfs_fpregs.c
index a3cad5f..841cf76 100644
--- a/sys/fs/procfs/procfs_fpregs.c
+++ b/sys/fs/procfs/procfs_fpregs.c
@@ -34,8 +34,9 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)procfs_fpregs.c 8.1 (Berkeley) 1/27/94
+ * @(#)procfs_fpregs.c 8.2 (Berkeley) 6/15/94
*
+ * From:
* $FreeBSD$
*/
diff --git a/sys/fs/procfs/procfs_map.c b/sys/fs/procfs/procfs_map.c
index 27c44fa..40c40d8 100644
--- a/sys/fs/procfs/procfs_map.c
+++ b/sys/fs/procfs/procfs_map.c
@@ -59,7 +59,7 @@
#include <vm/vm_param.h>
#include <vm/vm_prot.h>
#include <vm/vm_inherit.h>
-#include <vm/lock.h>
+#include <sys/lock.h>
#include <vm/pmap.h>
#include <vm/vm_map.h>
#include <vm/vm_page.h>
diff --git a/sys/fs/procfs/procfs_mem.c b/sys/fs/procfs/procfs_mem.c
index 4e8fac6..06364e5 100644
--- a/sys/fs/procfs/procfs_mem.c
+++ b/sys/fs/procfs/procfs_mem.c
@@ -35,7 +35,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)procfs_mem.c 8.4 (Berkeley) 1/21/94
+ * @(#)procfs_mem.c 8.5 (Berkeley) 6/15/94
*
* $FreeBSD$
*/
@@ -55,7 +55,7 @@
#include <vm/vm.h>
#include <vm/vm_param.h>
#include <vm/vm_prot.h>
-#include <vm/lock.h>
+#include <sys/lock.h>
#include <vm/pmap.h>
#include <vm/vm_map.h>
#include <vm/vm_kern.h>
@@ -295,14 +295,11 @@ procfs_domem(curp, p, pfs, uio)
struct pfsnode *pfs;
struct uio *uio;
{
- int error;
if (uio->uio_resid == 0)
return (0);
- error = procfs_rwmem(p, uio);
-
- return (error);
+ return (procfs_rwmem(p, uio));
}
/*
@@ -320,5 +317,6 @@ struct vnode *
procfs_findtextvp(p)
struct proc *p;
{
+
return (p->p_textvp);
}
diff --git a/sys/fs/procfs/procfs_regs.c b/sys/fs/procfs/procfs_regs.c
index 9282a3a..56ef233 100644
--- a/sys/fs/procfs/procfs_regs.c
+++ b/sys/fs/procfs/procfs_regs.c
@@ -34,8 +34,9 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)procfs_regs.c 8.3 (Berkeley) 1/27/94
+ * @(#)procfs_regs.c 8.4 (Berkeley) 6/15/94
*
+ * From:
* $FreeBSD$
*/
diff --git a/sys/fs/procfs/procfs_status.c b/sys/fs/procfs/procfs_status.c
index 432918d..76974b5 100644
--- a/sys/fs/procfs/procfs_status.c
+++ b/sys/fs/procfs/procfs_status.c
@@ -34,8 +34,9 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)procfs_status.c 8.3 (Berkeley) 2/17/94
+ * @(#)procfs_status.c 8.4 (Berkeley) 6/15/94
*
+ * From:
* $FreeBSD$
*/
@@ -142,7 +143,7 @@ procfs_dostatus(curp, p, pfs, uio)
xlen = ps - psbuf;
xlen -= uio->uio_offset;
ps = psbuf + uio->uio_offset;
- xlen = min(xlen, uio->uio_resid);
+ xlen = imin(xlen, uio->uio_resid);
if (xlen <= 0)
error = 0;
else
diff --git a/sys/fs/procfs/procfs_subr.c b/sys/fs/procfs/procfs_subr.c
index d9b3d2f..5ee78f0 100644
--- a/sys/fs/procfs/procfs_subr.c
+++ b/sys/fs/procfs/procfs_subr.c
@@ -34,7 +34,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)procfs_subr.c 8.4 (Berkeley) 1/27/94
+ * @(#)procfs_subr.c 8.6 (Berkeley) 5/14/95
*
* $FreeBSD$
*/
@@ -84,18 +84,21 @@ procfs_allocvp(mp, vpp, pid, pfs_type)
long pid;
pfstype pfs_type;
{
- int error;
+ struct proc *p = curproc; /* XXX */
struct pfsnode *pfs;
+ struct vnode *vp;
struct pfsnode **pp;
+ int error;
loop:
for (pfs = pfshead; pfs != 0; pfs = pfs->pfs_next) {
+ vp = PFSTOV(pfs);
if (pfs->pfs_pid == pid &&
pfs->pfs_type == pfs_type &&
- PFSTOV(pfs)->v_mount == mp) {
- if (vget(pfs->pfs_vnode, 0))
+ vp->v_mount == mp) {
+ if (vget(vp, 0, p))
goto loop;
- *vpp = pfs->pfs_vnode;
+ *vpp = vp;
return (0);
}
}
@@ -118,17 +121,18 @@ loop:
*/
MALLOC(pfs, struct pfsnode *, sizeof(struct pfsnode), M_TEMP, M_WAITOK);
- error = getnewvnode(VT_PROCFS, mp, procfs_vnodeop_p, vpp);
- if (error) {
+ if (error = getnewvnode(VT_PROCFS, mp, procfs_vnodeop_p, vpp)) {
FREE(pfs, M_TEMP);
goto out;
}
+ vp = *vpp;
+
+ vp->v_data = pfs;
- (*vpp)->v_data = pfs;
pfs->pfs_next = 0;
pfs->pfs_pid = (pid_t) pid;
pfs->pfs_type = pfs_type;
- pfs->pfs_vnode = *vpp;
+ pfs->pfs_vnode = vp;
pfs->pfs_flags = 0;
pfs->pfs_lockowner = 0;
pfs->pfs_fileno = PROCFS_FILENO(pid, pfs_type);
@@ -138,33 +142,41 @@ loop:
pfs->pfs_mode = (VREAD|VEXEC) |
(VREAD|VEXEC) >> 3 |
(VREAD|VEXEC) >> 6;
+ vp->v_type = VDIR;
+ vp->v_flag = VROOT;
+ break;
+
+ case Pcurproc: /* /proc/curproc = lr--r--r-- */
+ pfs->pfs_mode = (VREAD) |
+ (VREAD >> 3) |
+ (VREAD >> 6);
+ vp->v_type = VLNK;
break;
case Pproc:
pfs->pfs_mode = (VREAD|VEXEC) |
(VREAD|VEXEC) >> 3 |
(VREAD|VEXEC) >> 6;
+ vp->v_type = VDIR;
break;
case Pfile:
- pfs->pfs_mode = (VREAD|VWRITE);
- break;
-
case Pmem:
pfs->pfs_mode = (VREAD|VWRITE) |
(VREAD) >> 3;;
break;
case Pregs:
- pfs->pfs_mode = (VREAD|VWRITE);
- break;
-
case Pfpregs:
pfs->pfs_mode = (VREAD|VWRITE);
+ vp->v_type = VREG;
break;
case Pctl:
+ case Pnote:
+ case Pnotepg:
pfs->pfs_mode = (VWRITE);
+ vp->v_type = VREG;
break;
case Ptype:
@@ -173,14 +185,7 @@ loop:
pfs->pfs_mode = (VREAD) |
(VREAD >> 3) |
(VREAD >> 6);
- break;
-
- case Pnote:
- pfs->pfs_mode = (VWRITE);
- break;
-
- case Pnotepg:
- pfs->pfs_mode = (VWRITE);
+ vp->v_type = VREG;
break;
default:
@@ -316,8 +321,7 @@ vfs_getuserstr(uio, buf, buflenp)
return (EMSGSIZE);
xlen = uio->uio_resid;
- error = uiomove(buf, xlen, uio);
- if (error)
+ if (error = uiomove(buf, xlen, uio))
return (error);
/* allow multiple writes without seeks */
@@ -339,6 +343,7 @@ vfs_findname(nm, buf, buflen)
char *buf;
int buflen;
{
+
for (; nm->nm_name; nm++)
if (bcmp(buf, nm->nm_name, buflen+1) == 0)
return (nm);
diff --git a/sys/fs/procfs/procfs_vfsops.c b/sys/fs/procfs/procfs_vfsops.c
index 433b391..5387126 100644
--- a/sys/fs/procfs/procfs_vfsops.c
+++ b/sys/fs/procfs/procfs_vfsops.c
@@ -34,7 +34,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)procfs_vfsops.c 8.4 (Berkeley) 1/21/94
+ * @(#)procfs_vfsops.c 8.7 (Berkeley) 5/10/95
*
* $FreeBSD$
*/
@@ -56,24 +56,14 @@
#include <miscfs/procfs/procfs.h>
#include <vm/vm.h> /* for PAGE_SIZE */
-static int procfs_fhtovp __P((struct mount *mp, struct fid *fhp,
- struct mbuf *nam, struct vnode **vpp,
- int *exflagsp, struct ucred **credanonp));
-static int procfs_init __P((void));
+static int procfs_init __P((struct vfsconf *vfsp));
static int procfs_mount __P((struct mount *mp, char *path, caddr_t data,
struct nameidata *ndp, struct proc *p));
-static int procfs_quotactl __P((struct mount *mp, int cmds, uid_t uid,
- caddr_t arg, struct proc *p));
static int procfs_start __P((struct mount *mp, int flags, struct proc *p));
static int procfs_statfs __P((struct mount *mp, struct statfs *sbp,
struct proc *p));
-static int procfs_sync __P((struct mount *mp, int waitfor,
- struct ucred *cred, struct proc *p));
static int procfs_unmount __P((struct mount *mp, int mntflags,
struct proc *p));
-static int procfs_vget __P((struct mount *mp, ino_t ino,
- struct vnode **vpp));
-static int procfs_vptofh __P((struct vnode *vp, struct fid *fhp));
/*
* VFS Operations.
@@ -101,7 +91,7 @@ procfs_mount(mp, path, data, ndp, p)
mp->mnt_flag |= MNT_LOCAL;
mp->mnt_data = 0;
- getnewfsid(mp, MOUNT_PROCFS);
+ vfs_getnewfsid(mp);
(void) copyinstr(path, (caddr_t)mp->mnt_stat.f_mntonname, MNAMELEN, &size);
bzero(mp->mnt_stat.f_mntonname + size, MNAMELEN - size);
@@ -125,12 +115,8 @@ procfs_unmount(mp, mntflags, p)
int error;
int flags = 0;
- if (mntflags & MNT_FORCE) {
- /* procfs can never be rootfs so don't check for it */
- if (!doforce)
- return (EINVAL);
+ if (mntflags & MNT_FORCE)
flags |= FORCECLOSE;
- }
error = vflush(mp, 0, flags);
if (error)
@@ -144,24 +130,10 @@ procfs_root(mp, vpp)
struct mount *mp;
struct vnode **vpp;
{
- struct pfsnode *pfs;
- struct vnode *vp;
- int error;
-
- error = procfs_allocvp(mp, &vp, (pid_t) 0, Proot);
- if (error)
- return (error);
-
- vp->v_type = VDIR;
- vp->v_flag = VROOT;
- pfs = VTOPFS(vp);
- *vpp = vp;
- return (0);
+ return (procfs_allocvp(mp, vpp, 0, Proot));
}
-/*
- */
/* ARGSUSED */
static int
procfs_start(mp, flags, p)
@@ -182,7 +154,6 @@ procfs_statfs(mp, sbp, p)
struct statfs *sbp;
struct proc *p;
{
- sbp->f_type = MOUNT_PROCFS;
sbp->f_bsize = PAGE_SIZE;
sbp->f_iosize = PAGE_SIZE;
sbp->f_blocks = 1; /* avoid divide by zero in some df's */
@@ -192,6 +163,7 @@ procfs_statfs(mp, sbp, p)
sbp->f_ffree = maxproc - nprocs; /* approx */
if (sbp != &mp->mnt_stat) {
+ sbp->f_type = mp->mnt_vfc->vfc_typenum;
bcopy(&mp->mnt_stat.f_fsid, &sbp->f_fsid, sizeof(sbp->f_fsid));
bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN);
bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN);
@@ -200,68 +172,25 @@ procfs_statfs(mp, sbp, p)
return (0);
}
-
-static int
-procfs_quotactl(mp, cmds, uid, arg, p)
- struct mount *mp;
- int cmds;
- uid_t uid;
- caddr_t arg;
- struct proc *p;
-{
-
- return (EOPNOTSUPP);
-}
-
static int
-procfs_sync(mp, waitfor, cred, p)
- struct mount *mp;
- int waitfor;
- struct ucred *cred;
- struct proc *p;
+procfs_init(vfsp)
+ struct vfsconf *vfsp;
{
return (0);
}
-static int
-procfs_vget(mp, ino, vpp)
- struct mount *mp;
- ino_t ino;
- struct vnode **vpp;
-{
-
- return (EOPNOTSUPP);
-}
-
-static int
-procfs_fhtovp(mp, fhp, nam, vpp, exflagsp, credanonp)
- struct mount *mp;
- struct fid *fhp;
- struct mbuf *nam;
- struct vnode **vpp;
- int *exflagsp;
- struct ucred **credanonp;
-{
-
- return (EINVAL);
-}
-
-static int
-procfs_vptofh(vp, fhp)
- struct vnode *vp;
- struct fid *fhp;
-{
-
- return EINVAL;
-}
-
-static int
-procfs_init()
-{
-
- return (0);
-}
+#define procfs_fhtovp ((int (*) __P((struct mount *, struct fid *, \
+ struct mbuf *, struct vnode **, int *, struct ucred **)))einval)
+#define procfs_quotactl ((int (*) __P((struct mount *, int, uid_t, caddr_t, \
+ struct proc *)))eopnotsupp)
+#define procfs_sync ((int (*) __P((struct mount *, int, struct ucred *, \
+ struct proc *)))nullop)
+#define procfs_sysctl ((int (*) __P((int *, u_int, void *, size_t *, void *, \
+ size_t, struct proc *)))eopnotsupp)
+#define procfs_vget ((int (*) __P((struct mount *, ino_t, struct vnode **))) \
+ eopnotsupp)
+#define procfs_vptofh ((int (*) __P((struct vnode *, struct fid *)))einval)
static struct vfsops procfs_vfsops = {
procfs_mount,
diff --git a/sys/fs/procfs/procfs_vnops.c b/sys/fs/procfs/procfs_vnops.c
index f497563..85be3ea 100644
--- a/sys/fs/procfs/procfs_vnops.c
+++ b/sys/fs/procfs/procfs_vnops.c
@@ -1,6 +1,6 @@
/*
- * Copyright (c) 1993 Jan-Simon Pendry
- * Copyright (c) 1993
+ * Copyright (c) 1993, 1995 Jan-Simon Pendry
+ * Copyright (c) 1993, 1995
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
@@ -34,7 +34,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)procfs_vnops.c 8.6 (Berkeley) 2/7/94
+ * @(#)procfs_vnops.c 8.18 (Berkeley) 5/21/95
*
* $FreeBSD$
*/
@@ -55,8 +55,9 @@
#include <sys/malloc.h>
#include <sys/dirent.h>
#include <sys/resourcevar.h>
-#include <miscfs/procfs/procfs.h>
#include <vm/vm.h> /* for PAGE_SIZE */
+#include <machine/reg.h>
+#include <miscfs/procfs/procfs.h>
static int procfs_abortop __P((struct vop_abortop_args *));
static int procfs_access __P((struct vop_access_args *));
@@ -78,29 +79,30 @@ static int procfs_setattr __P((struct vop_setattr_args *));
* process-specific sub-directories. It is
* used in procfs_lookup and procfs_readdir
*/
-static struct pfsnames {
- u_short d_namlen;
- char d_name[PROCFS_NAMELEN];
- pfstype d_pfstype;
- int (*d_valid) __P((struct proc *));
-} procent[] = {
+struct proc_target {
+ u_char pt_type;
+ u_char pt_namlen;
+ char *pt_name;
+ pfstype pt_pfstype;
+ int (*pt_valid) __P((struct proc *p));
+} proc_targets[] = {
#define N(s) sizeof(s)-1, s
- /* namlen, nam, type validp */
- { N("."), Pproc, NULL },
- { N(".."), Proot, NULL },
- { N("file"), Pfile, procfs_validfile },
- { N("mem"), Pmem, NULL },
- { N("regs"), Pregs, procfs_validregs },
- { N("fpregs"), Pfpregs, procfs_validfpregs },
- { N("ctl"), Pctl, NULL },
- { N("status"), Pstatus, NULL },
- { N("note"), Pnote, NULL },
- { N("notepg"), Pnotepg, NULL },
- { N("map"), Pmap, procfs_validmap },
- { N("etype"), Ptype, procfs_validtype },
+ /* name type validp */
+ { DT_DIR, N("."), Pproc, NULL },
+ { DT_DIR, N(".."), Proot, NULL },
+ { DT_REG, N("file"), Pfile, procfs_validfile },
+ { DT_REG, N("mem"), Pmem, NULL },
+ { DT_REG, N("regs"), Pregs, procfs_validregs },
+ { DT_REG, N("fpregs"), Pfpregs, procfs_validfpregs },
+ { DT_REG, N("ctl"), Pctl, NULL },
+ { DT_REG, N("status"), Pstatus, NULL },
+ { DT_REG, N("note"), Pnote, NULL },
+ { DT_REG, N("notepg"), Pnotepg, NULL },
+ { DT_REG, N("map"), Pmap, procfs_validmap },
+ { DT_REG, N("etype"), Ptype, procfs_validtype },
#undef N
};
-#define Nprocent (sizeof(procent)/sizeof(procent[0]))
+static const int nproc_targets = sizeof(proc_targets) / sizeof(proc_targets[0]);
static pid_t atopid __P((const char *, u_int));
@@ -117,7 +119,12 @@ static pid_t atopid __P((const char *, u_int));
*/
static int
procfs_open(ap)
- struct vop_open_args *ap;
+ struct vop_open_args /* {
+ struct vnode *a_vp;
+ int a_mode;
+ struct ucred *a_cred;
+ struct proc *a_p;
+ } */ *ap;
{
struct pfsnode *pfs = VTOPFS(ap->a_vp);
@@ -126,11 +133,10 @@ procfs_open(ap)
if (PFIND(pfs->pfs_pid) == 0)
return (ENOENT); /* was ESRCH, jsp */
- if (((pfs->pfs_flags & FWRITE) && (ap->a_mode & O_EXCL)) ||
- ((pfs->pfs_flags & O_EXCL) && (ap->a_mode & FWRITE)))
+ if ((pfs->pfs_flags & FWRITE) && (ap->a_mode & O_EXCL) ||
+ (pfs->pfs_flags & O_EXCL) && (ap->a_mode & FWRITE))
return (EBUSY);
-
if (ap->a_mode & FWRITE)
pfs->pfs_flags = ap->a_mode & (FWRITE|O_EXCL);
@@ -152,7 +158,12 @@ procfs_open(ap)
*/
static int
procfs_close(ap)
- struct vop_close_args *ap;
+ struct vop_close_args /* {
+ struct vnode *a_vp;
+ int a_fflag;
+ struct ucred *a_cred;
+ struct proc *a_p;
+ } */ *ap;
{
struct pfsnode *pfs = VTOPFS(ap->a_vp);
@@ -174,14 +185,51 @@ procfs_close(ap)
*/
static int
procfs_ioctl(ap)
- struct vop_ioctl_args *ap;
+ struct vop_ioctl_args /* {
+ struct vnode *a_vp;
+ int a_command;
+ caddr_t a_data;
+ int a_fflag;
+ struct ucred *a_cred;
+ struct proc *a_p;
+ } */ *ap;
{
return (ENOTTY);
}
/*
- * _inactive is called when the pfsnode
+ * do block mapping for pfsnode (vp).
+ * since we don't use the buffer cache
+ * for procfs this function should never
+ * be called. in any case, it's not clear
+ * what part of the kernel ever makes use
+ * of this function. for sanity, this is the
+ * usual no-op bmap, although returning
+ * (EIO) would be a reasonable alternative.
+ */
+int
+procfs_bmap(ap)
+ struct vop_bmap_args /* {
+ struct vnode *a_vp;
+ daddr_t a_bn;
+ struct vnode **a_vpp;
+ daddr_t *a_bnp;
+ int *a_runp;
+ } */ *ap;
+{
+
+ if (ap->a_vpp != NULL)
+ *ap->a_vpp = ap->a_vp;
+ if (ap->a_bnp != NULL)
+ *ap->a_bnp = ap->a_bn;
+ if (ap->a_runp != NULL)
+ *ap->a_runp = 0;
+ return (0);
+}
+
+/*
+ * procfs_inactive is called when the pfsnode
* is vrele'd and the reference count goes
* to zero. (vp) will be on the vnode free
* list, so to get it back vget() must be
@@ -194,16 +242,20 @@ procfs_ioctl(ap)
* chances are that the process will still be
* there and PFIND is not free.
*
- * (vp) is not locked on entry or exit.
+ * (vp) is locked on entry, but must be unlocked on exit.
*/
static int
procfs_inactive(ap)
- struct vop_inactive_args *ap;
+ struct vop_inactive_args /* {
+ struct vnode *a_vp;
+ } */ *ap;
{
- struct pfsnode *pfs = VTOPFS(ap->a_vp);
+ struct vnode *vp = ap->a_vp;
+ struct pfsnode *pfs = VTOPFS(vp);
+ VOP_UNLOCK(vp, 0, ap->a_p);
if (PFIND(pfs->pfs_pid) == 0)
- vgone(ap->a_vp);
+ vgone(vp);
return (0);
}
@@ -217,12 +269,12 @@ procfs_inactive(ap)
*/
static int
procfs_reclaim(ap)
- struct vop_reclaim_args *ap;
+ struct vop_reclaim_args /* {
+ struct vnode *a_vp;
+ } */ *ap;
{
- int error;
- error = procfs_freevp(ap->a_vp);
- return (error);
+ return (procfs_freevp(ap->a_vp));
}
/*
@@ -269,13 +321,14 @@ procfs_pathconf(ap)
*/
static int
procfs_print(ap)
- struct vop_print_args *ap;
+ struct vop_print_args /* {
+ struct vnode *a_vp;
+ } */ *ap;
{
struct pfsnode *pfs = VTOPFS(ap->a_vp);
- printf("tag VT_PROCFS, pid %lu, mode %x, flags %lx\n",
- pfs->pfs_pid,
- pfs->pfs_mode, pfs->pfs_flags);
+ printf("tag VT_PROCFS, type %s, pid %d, mode %x, flags %x\n",
+ pfs->pfs_type, pfs->pfs_pid, pfs->pfs_mode, pfs->pfs_flags);
return (0);
}
@@ -287,7 +340,10 @@ procfs_print(ap)
*/
static int
procfs_abortop(ap)
- struct vop_abortop_args *ap;
+ struct vop_abortop_args /* {
+ struct vnode *a_dvp;
+ struct componentname *a_cnp;
+ } */ *ap;
{
if ((ap->a_cnp->cn_flags & (HASBUF | SAVESTART)) == HASBUF)
@@ -316,7 +372,12 @@ procfs_badop()
*/
static int
procfs_getattr(ap)
- struct vop_getattr_args *ap;
+ struct vop_getattr_args /* {
+ struct vnode *a_vp;
+ struct vattr *a_vap;
+ struct ucred *a_cred;
+ struct proc *a_p;
+ } */ *ap;
{
struct pfsnode *pfs = VTOPFS(ap->a_vp);
struct vattr *vap = ap->a_vap;
@@ -329,6 +390,7 @@ procfs_getattr(ap)
*/
switch (pfs->pfs_type) {
case Proot:
+ case Pcurproc:
procp = 0;
break;
@@ -353,6 +415,21 @@ procfs_getattr(ap)
vap->va_bytes = vap->va_size = 0;
/*
+ * Make all times be current TOD.
+ * It would be possible to get the process start
+ * time from the p_stat structure, but there's
+ * no "file creation" time stamp anyway, and the
+ * p_stat structure is not addressible if u. gets
+ * swapped out for that process.
+ */
+ {
+ struct timeval tv;
+ microtime(&tv);
+ TIMEVAL_TO_TIMESPEC(&tv, &vap->va_ctime);
+ }
+ vap->va_atime = vap->va_mtime = vap->va_ctime;
+
+ /*
* If the process has exercised some setuid or setgid
* privilege, then rip away read/write permission so
* that only root can gain access.
@@ -376,21 +453,6 @@ procfs_getattr(ap)
}
/*
- * Make all times be current TOD.
- * It would be possible to get the process start
- * time from the p_stat structure, but there's
- * no "file creation" time stamp anyway, and the
- * p_stat structure is not addressible if u. gets
- * swapped out for that process.
- */
- {
- struct timeval tv;
- microtime(&tv);
- TIMEVAL_TO_TIMESPEC(&tv, &vap->va_ctime);
- }
- vap->va_atime = vap->va_mtime = vap->va_ctime;
-
- /*
* now do the object specific fields
*
* The size could be set from struct reg, but it's hardly
@@ -402,17 +464,30 @@ procfs_getattr(ap)
switch (pfs->pfs_type) {
case Proot:
- vap->va_nlink = nprocs + 3;
+ /*
+ * Set nlink to 1 to tell fts(3) we don't actually know.
+ */
+ vap->va_nlink = 1;
+ vap->va_uid = 0;
+ vap->va_gid = 0;
+ vap->va_size = vap->va_bytes = DEV_BSIZE;
+ break;
+
+ case Pcurproc: {
+ char buf[16]; /* should be enough */
+ vap->va_nlink = 1;
vap->va_uid = 0;
vap->va_gid = 0;
- vap->va_bytes = vap->va_size = DEV_BSIZE;
+ vap->va_size = vap->va_bytes =
+ sprintf(buf, "%ld", (long)curproc->p_pid);
break;
+ }
case Pproc:
- vap->va_nlink = Nprocent;
+ vap->va_nlink = nproc_targets;
vap->va_uid = procp->p_ucred->cr_uid;
vap->va_gid = procp->p_ucred->cr_gid;
- vap->va_bytes = vap->va_size = DEV_BSIZE;
+ vap->va_size = vap->va_bytes = DEV_BSIZE;
break;
case Pfile:
@@ -436,7 +511,15 @@ procfs_getattr(ap)
case Ptype:
case Pmap:
case Pregs:
+ vap->va_bytes = vap->va_size = sizeof(struct reg);
+ vap->va_nlink = 1;
+ vap->va_uid = procp->p_ucred->cr_uid;
+ vap->va_gid = procp->p_ucred->cr_gid;
+ break;
+
case Pfpregs:
+ vap->va_bytes = vap->va_size = sizeof(struct fpreg);
+
case Pctl:
case Pstatus:
case Pnote:
@@ -455,7 +538,12 @@ procfs_getattr(ap)
static int
procfs_setattr(ap)
- struct vop_setattr_args *ap;
+ struct vop_setattr_args /* {
+ struct vnode *a_vp;
+ struct vattr *a_vap;
+ struct ucred *a_cred;
+ struct proc *a_p;
+ } */ *ap;
{
/*
* just fake out attribute setting
@@ -484,7 +572,12 @@ procfs_setattr(ap)
*/
static int
procfs_access(ap)
- struct vop_access_args *ap;
+ struct vop_access_args /* {
+ struct vnode *a_vp;
+ int a_mode;
+ struct ucred *a_cred;
+ struct proc *a_p;
+ } */ *ap;
{
struct vattr *vap;
struct vattr vattr;
@@ -494,8 +587,9 @@ procfs_access(ap)
* If you're the super-user,
* you always get access.
*/
- if (ap->a_cred->cr_uid == (uid_t) 0)
+ if (ap->a_cred->cr_uid == 0)
return (0);
+
vap = &vattr;
error = VOP_GETATTR(ap->a_vp, vap, ap->a_cred, ap->a_p);
if (error)
@@ -510,7 +604,7 @@ procfs_access(ap)
gid_t *gp;
int i;
- (ap->a_mode) >>= 3;
+ ap->a_mode >>= 3;
gp = ap->a_cred->cr_groups;
for (i = 0; i < ap->a_cred->cr_ngroups; i++, gp++)
if (vap->va_gid == *gp)
@@ -537,18 +631,23 @@ found:
*/
static int
procfs_lookup(ap)
- struct vop_lookup_args *ap;
+ struct vop_lookup_args /* {
+ struct vnode * a_dvp;
+ struct vnode ** a_vpp;
+ struct componentname * a_cnp;
+ } */ *ap;
{
struct componentname *cnp = ap->a_cnp;
struct vnode **vpp = ap->a_vpp;
struct vnode *dvp = ap->a_dvp;
char *pname = cnp->cn_nameptr;
+ struct proc *curp = cnp->cn_proc;
int error = 0;
+ struct proc_target *pt;
+ struct vnode *fvp;
pid_t pid;
- struct vnode *nvp;
struct pfsnode *pfs;
- struct proc *procp;
- pfstype pfs_type;
+ struct proc *p;
int i;
*vpp = NULL;
@@ -559,7 +658,7 @@ procfs_lookup(ap)
if (cnp->cn_namelen == 1 && *pname == '.') {
*vpp = dvp;
VREF(dvp);
- /*VOP_LOCK(dvp);*/
+ /* vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY, curp); */
return (0);
}
@@ -570,72 +669,52 @@ procfs_lookup(ap)
return (EIO);
if (CNEQ(cnp, "curproc", 7))
- pid = cnp->cn_proc->p_pid;
- else
- pid = atopid(pname, cnp->cn_namelen);
- if (pid == NO_PID)
- return (ENOENT);
+ return (procfs_allocvp(dvp->v_mount, vpp, 0, Pcurproc));
- procp = PFIND(pid);
- if (procp == 0)
- return (ENOENT);
-
- error = procfs_allocvp(dvp->v_mount, &nvp, pid, Pproc);
- if (error)
- return (error);
+ pid = atopid(pname, cnp->cn_namelen);
+ if (pid == NO_PID)
+ break;
- nvp->v_type = VDIR;
- pfs = VTOPFS(nvp);
+ p = PFIND(pid);
+ if (p == 0)
+ break;
- *vpp = nvp;
- return (0);
+ return (procfs_allocvp(dvp->v_mount, vpp, pid, Pproc));
case Pproc:
- if (cnp->cn_flags & ISDOTDOT) {
- error = procfs_root(dvp->v_mount, vpp);
- return (error);
- }
-
- procp = PFIND(pfs->pfs_pid);
- if (procp == 0)
- return (ENOENT);
+ if (cnp->cn_flags & ISDOTDOT)
+ return (procfs_root(dvp->v_mount, vpp));
- for (i = 0; i < Nprocent; i++) {
- struct pfsnames *dp = &procent[i];
+ p = PFIND(pfs->pfs_pid);
+ if (p == 0)
+ break;
- if (cnp->cn_namelen == dp->d_namlen &&
- bcmp(pname, dp->d_name, dp->d_namlen) == 0 &&
- (dp->d_valid == NULL || (*dp->d_valid)(procp))) {
- pfs_type = dp->d_pfstype;
+ for (pt = proc_targets, i = 0; i < nproc_targets; pt++, i++) {
+ if (cnp->cn_namelen == pt->pt_namlen &&
+ bcmp(pt->pt_name, pname, cnp->cn_namelen) == 0 &&
+ (pt->pt_valid == NULL || (*pt->pt_valid)(p)))
goto found;
- }
}
- return (ENOENT);
+ break;
found:
- if (pfs_type == Pfile) {
- nvp = procfs_findtextvp(procp);
- if (nvp) {
- VREF(nvp);
- VOP_LOCK(nvp);
- } else {
- error = ENXIO;
- }
- } else {
- error = procfs_allocvp(dvp->v_mount, &nvp,
- pfs->pfs_pid, pfs_type);
- if (error)
- return (error);
-
- nvp->v_type = VREG;
- pfs = VTOPFS(nvp);
+ if (pt->pt_pfstype == Pfile) {
+ fvp = procfs_findtextvp(p);
+ /* We already checked that it exists. */
+ VREF(fvp);
+ vn_lock(fvp, LK_EXCLUSIVE | LK_RETRY, curp);
+ *vpp = fvp;
+ return (0);
}
- *vpp = nvp;
- return (error);
+
+ return (procfs_allocvp(dvp->v_mount, vpp, pfs->pfs_pid,
+ pt->pt_pfstype));
default:
return (ENOTDIR);
}
+
+ return (cnp->cn_nameiop == LOOKUP ? ENOENT : EROFS);
}
/*
@@ -645,6 +724,7 @@ int
procfs_validfile(p)
struct proc *p;
{
+
return (procfs_findtextvp(p) != NULLVP);
}
@@ -662,7 +742,14 @@ procfs_validfile(p)
*/
static int
procfs_readdir(ap)
- struct vop_readdir_args *ap;
+ struct vop_readdir_args /* {
+ struct vnode *a_vp;
+ struct uio *a_uio;
+ struct ucred *a_cred;
+ int *a_eofflag;
+ u_long *a_cookies;
+ int a_ncookies;
+ } */ *ap;
{
struct uio *uio = ap->a_uio;
struct pfsdent d;
@@ -672,6 +759,13 @@ procfs_readdir(ap)
int count;
int i;
+ /*
+ * We don't allow exporting procfs mounts, and currently local
+ * requests do not need cookies.
+ */
+ if (ap->a_ncookies)
+ panic("procfs_readdir: not hungry");
+
pfs = VTOPFS(ap->a_vp);
if (uio->uio_resid < UIO_MX)
@@ -693,39 +787,28 @@ procfs_readdir(ap)
*/
case Pproc: {
struct proc *p;
+ struct proc_target *pt;
p = PFIND(pfs->pfs_pid);
if (p == NULL)
break;
- while (uio->uio_resid >= UIO_MX) {
- struct pfsnames *dt;
-
- if (i >= Nprocent)
- break;
-
- dt = &procent[i];
-
- /* see if we should show this one. */
- if (dt->d_valid && (*dt->d_valid)(p) == 0) {
- i++;
+ for (pt = &proc_targets[i];
+ uio->uio_resid >= UIO_MX && i < nproc_targets; pt++, i++) {
+ if (pt->pt_valid && (*pt->pt_valid)(p) == 0)
continue;
- }
dp->d_reclen = UIO_MX;
- dp->d_fileno = PROCFS_FILENO(pfs->pfs_pid, dt->d_pfstype);
- dp->d_type = DT_REG;
- dp->d_namlen = dt->d_namlen;
- bcopy(dt->d_name, dp->d_name, sizeof(dt->d_name)-1);
- error = uiomove((caddr_t) dp, UIO_MX, uio);
- if (error)
+ dp->d_fileno = PROCFS_FILENO(pfs->pfs_pid, pt->pt_pfstype);
+ dp->d_namlen = pt->pt_namlen;
+ bcopy(pt->pt_name, dp->d_name, pt->pt_namlen + 1);
+ dp->d_type = pt->pt_type;
+
+ if (error = uiomove((caddr_t)dp, UIO_MX, uio))
break;
- count += UIO_MX;
- i++;
}
break;
-
}
/*
@@ -738,63 +821,61 @@ procfs_readdir(ap)
*/
case Proot: {
- int pcnt;
#ifdef PROCFS_ZOMBIE
int doingzomb = 0;
#endif
+ int pcnt = 0;
volatile struct proc *p = allproc.lh_first;
-#define PROCFS_XFILES 3 /* number of other entries, like "curproc" */
- pcnt = PROCFS_XFILES;
-
- while (p && uio->uio_resid >= UIO_MX) {
+ again:
+ for (; p && uio->uio_resid >= UIO_MX; i++, pcnt++) {
bzero((char *) dp, UIO_MX);
- dp->d_type = DT_DIR;
dp->d_reclen = UIO_MX;
switch (i) {
- case 0:
+ case 0: /* `.' */
+ case 1: /* `..' */
dp->d_fileno = PROCFS_FILENO(0, Proot);
- dp->d_namlen = sprintf(dp->d_name, ".");
- break;
-
- case 1:
- dp->d_fileno = PROCFS_FILENO(0, Proot);
- dp->d_namlen = sprintf(dp->d_name, "..");
+ dp->d_namlen = i + 1;
+ bcopy("..", dp->d_name, dp->d_namlen);
+ dp->d_name[i + 1] = '\0';
+ dp->d_type = DT_DIR;
break;
case 2:
- /* ship out entry for "curproc" */
- dp->d_fileno = PROCFS_FILENO(PID_MAX+1, Pproc);
- dp->d_namlen = sprintf(dp->d_name, "curproc");
+ dp->d_fileno = PROCFS_FILENO(0, Pcurproc);
+ dp->d_namlen = 7;
+ bcopy("curproc", dp->d_name, 8);
+ dp->d_type = DT_LNK;
break;
default:
- if (pcnt >= i) {
- dp->d_fileno = PROCFS_FILENO(p->p_pid, Pproc);
- dp->d_namlen = sprintf(dp->d_name, "%ld", (long) p->p_pid);
+ while (pcnt < i) {
+ pcnt++;
+ p = p->p_list.le_next;
+ if (!p)
+ goto done;
}
-
+ dp->d_fileno = PROCFS_FILENO(p->p_pid, Pproc);
+ dp->d_namlen = sprintf(dp->d_name, "%ld",
+ (long)p->p_pid);
+ dp->d_type = DT_REG;
p = p->p_list.le_next;
-
-#ifdef PROCFS_ZOMBIE
- if (p == 0 && doingzomb == 0) {
- doingzomb = 1;
- p = zombproc.lh_first;
- }
-#endif
-
- if (pcnt++ < i)
- continue;
-
break;
}
- error = uiomove((caddr_t) dp, UIO_MX, uio);
- if (error)
+
+ if (error = uiomove((caddr_t)dp, UIO_MX, uio))
break;
- count += UIO_MX;
- i++;
}
+ done:
+
+#ifdef PROCFS_ZOMBIE
+ if (p == 0 && doingzomb == 0) {
+ doingzomb = 1;
+ p = zombproc.lh_first;
+ goto again;
+ }
+#endif
break;
@@ -811,6 +892,25 @@ procfs_readdir(ap)
}
/*
+ * readlink reads the link of `curproc'
+ */
+int
+procfs_readlink(ap)
+ struct vop_readlink_args *ap;
+{
+ struct uio *uio = ap->a_uio;
+ char buf[16]; /* should be enough */
+ int len;
+
+ if (VTOPFS(ap->a_vp)->pfs_fileno != PROCFS_FILENO(0, Pcurproc))
+ return (EINVAL);
+
+ len = sprintf(buf, "%ld", (long)curproc->p_pid);
+
+ return (uiomove((caddr_t)buf, len, ap->a_uio));
+}
+
+/*
* convert decimal ascii to pid_t
*/
static pid_t
@@ -838,6 +938,7 @@ atopid(b, len)
#define procfs_write procfs_rw
#define procfs_select ((int (*) __P((struct vop_select_args *))) procfs_badop)
#define procfs_mmap ((int (*) __P((struct vop_mmap_args *))) procfs_badop)
+#define procfs_revoke vop_revoke
#define procfs_fsync ((int (*) __P((struct vop_fsync_args *))) procfs_badop)
#define procfs_seek ((int (*) __P((struct vop_seek_args *))) procfs_badop)
#define procfs_remove ((int (*) __P((struct vop_remove_args *))) procfs_badop)
@@ -849,7 +950,6 @@ atopid(b, len)
#define procfs_readlink ((int (*) __P((struct vop_readlink_args *))) procfs_badop)
#define procfs_lock ((int (*) __P((struct vop_lock_args *))) nullop)
#define procfs_unlock ((int (*) __P((struct vop_unlock_args *))) nullop)
-#define procfs_bmap ((int (*) __P((struct vop_bmap_args *))) procfs_badop)
#define procfs_strategy ((int (*) __P((struct vop_strategy_args *))) procfs_badop)
#define procfs_islocked ((int (*) __P((struct vop_islocked_args *))) nullop)
#define procfs_advlock ((int (*) __P((struct vop_advlock_args *))) procfs_badop)
@@ -859,6 +959,9 @@ atopid(b, len)
#define procfs_truncate ((int (*) __P((struct vop_truncate_args *))) procfs_badop)
#define procfs_update ((int (*) __P((struct vop_update_args *))) nullop)
+/*
+ * procfs vnode operations.
+ */
vop_t **procfs_vnodeop_p;
static struct vnodeopv_entry_desc procfs_vnodeop_entries[] = {
{ &vop_default_desc, (vop_t *)vn_default_error },
@@ -875,6 +978,7 @@ static struct vnodeopv_entry_desc procfs_vnodeop_entries[] = {
{ &vop_ioctl_desc, (vop_t *)procfs_ioctl }, /* ioctl */
{ &vop_select_desc, (vop_t *)procfs_select }, /* select */
{ &vop_mmap_desc, (vop_t *)procfs_mmap }, /* mmap */
+ { &vop_revoke_desc, (vop_t *)procfs_revoke }, /* revoke */
{ &vop_fsync_desc, (vop_t *)procfs_fsync }, /* fsync */
{ &vop_seek_desc, (vop_t *)procfs_seek }, /* seek */
{ &vop_remove_desc, (vop_t *)procfs_remove }, /* remove */
diff --git a/sys/fs/specfs/spec_vnops.c b/sys/fs/specfs/spec_vnops.c
index 049f41e..2e8cc04 100644
--- a/sys/fs/specfs/spec_vnops.c
+++ b/sys/fs/specfs/spec_vnops.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1989, 1993
+ * Copyright (c) 1989, 1993, 1995
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -30,7 +30,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)spec_vnops.c 8.6 (Berkeley) 4/9/94
+ * @(#)spec_vnops.c 8.14 (Berkeley) 5/21/95
* $FreeBSD$
*/
@@ -79,8 +79,10 @@ static struct vnodeopv_entry_desc spec_vnodeop_entries[] = {
{ &vop_setattr_desc, (vop_t *)spec_setattr }, /* setattr */
{ &vop_read_desc, (vop_t *)spec_read }, /* read */
{ &vop_write_desc, (vop_t *)spec_write }, /* write */
+ { &vop_lease_desc, (vop_t *)spec_lease_check }, /* lease */
{ &vop_ioctl_desc, (vop_t *)spec_ioctl }, /* ioctl */
{ &vop_select_desc, (vop_t *)spec_select }, /* select */
+ { &vop_revoke_desc, (vop_t *)spec_revoke }, /* revoke */
{ &vop_mmap_desc, (vop_t *)spec_mmap }, /* mmap */
{ &vop_fsync_desc, (vop_t *)spec_fsync }, /* fsync */
{ &vop_seek_desc, (vop_t *)spec_seek }, /* seek */
@@ -148,9 +150,10 @@ spec_open(ap)
struct proc *a_p;
} */ *ap;
{
+ struct proc *p = ap->a_p;
struct vnode *bvp, *vp = ap->a_vp;
dev_t bdev, dev = (dev_t)vp->v_rdev;
- register int maj = major(dev);
+ int maj = major(dev);
int error;
/*
@@ -171,7 +174,9 @@ spec_open(ap)
* When running in very secure mode, do not allow
* opens for writing of any disk character devices.
*/
- if (securelevel >= 2 && isdisk(dev, VCHR))
+ if (securelevel >= 2
+ && cdevsw[maj]->d_bdev
+ && cdevsw[maj]->d_bdev->d_flags == D_DISK)
return (EPERM);
/*
* When running in secure mode, do not allow opens
@@ -189,9 +194,20 @@ spec_open(ap)
return (EPERM);
}
}
- VOP_UNLOCK(vp);
- error = (*cdevsw[maj]->d_open)(dev, ap->a_mode, S_IFCHR, ap->a_p);
- VOP_LOCK(vp);
+#if 0
+ /*
+ * Lite2 stuff. We will almost certainly do this
+ * differently with devfs. The only use of this flag
+ * is in dead_read to make ttys return EOF instead of
+ * EIO when they are dead. Pre-lite2 FreeBSD returns
+ * EOF for all character devices.
+ */
+ if (cdevsw[maj]->d_type == D_TTY)
+ vp->v_flag |= VISTTY;
+#endif
+ VOP_UNLOCK(vp, 0, p);
+ error = (*cdevsw[maj]->d_open)(dev, ap->a_mode, S_IFCHR, p);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
return (error);
case VBLK:
@@ -204,7 +220,7 @@ spec_open(ap)
* opens for writing of any disk block devices.
*/
if (securelevel >= 2 && ap->a_cred != FSCRED &&
- (ap->a_mode & FWRITE) && isdisk(dev, VBLK))
+ (ap->a_mode & FWRITE) && bdevsw[maj]->d_flags == D_DISK)
return (EPERM);
/*
* Do not allow opens of block devices that are
@@ -213,9 +229,7 @@ spec_open(ap)
error = vfs_mountedon(vp);
if (error)
return (error);
- return ((*bdevsw[maj]->d_open)(dev, ap->a_mode, S_IFBLK, ap->a_p));
- default:
- break;
+ return ((*bdevsw[maj]->d_open)(dev, ap->a_mode, S_IFBLK, p));
}
return (0);
}
@@ -257,10 +271,10 @@ spec_read(ap)
switch (vp->v_type) {
case VCHR:
- VOP_UNLOCK(vp);
+ VOP_UNLOCK(vp, 0, p);
error = (*cdevsw[major(vp->v_rdev)]->d_read)
(vp->v_rdev, uio, ap->a_ioflag);
- VOP_LOCK(vp);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
return (error);
case VBLK:
@@ -335,10 +349,10 @@ spec_write(ap)
switch (vp->v_type) {
case VCHR:
- VOP_UNLOCK(vp);
+ VOP_UNLOCK(vp, 0, p);
error = (*cdevsw[major(vp->v_rdev)]->d_write)
(vp->v_rdev, uio, ap->a_ioflag);
- VOP_LOCK(vp);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
return (error);
case VBLK:
@@ -408,7 +422,7 @@ spec_ioctl(ap)
case VBLK:
if (ap->a_command == 0 && (int)ap->a_data == B_TAPE)
- if (bdevsw[major(dev)]->d_flags & B_TAPE)
+ if (bdevsw[major(dev)]->d_flags == D_TAPE)
return (0);
else
return (1);
@@ -498,6 +512,18 @@ loop:
return (0);
}
+int
+spec_inactive(ap)
+ struct vop_inactive_args /* {
+ struct vnode *a_vp;
+ struct proc *a_p;
+ } */ *ap;
+{
+
+ VOP_UNLOCK(ap->a_vp, 0, ap->a_p);
+ return (0);
+}
+
/*
* Just call the device strategy routine
*/
@@ -539,31 +565,6 @@ spec_bmap(ap)
}
/*
- * At the moment we do not do any locking.
- */
-/* ARGSUSED */
-int
-spec_lock(ap)
- struct vop_lock_args /* {
- struct vnode *a_vp;
- } */ *ap;
-{
-
- return (0);
-}
-
-/* ARGSUSED */
-int
-spec_unlock(ap)
- struct vop_unlock_args /* {
- struct vnode *a_vp;
- } */ *ap;
-{
-
- return (0);
-}
-
-/*
* Device close routine
*/
/* ARGSUSED */
@@ -577,6 +578,7 @@ spec_close(ap)
} */ *ap;
{
register struct vnode *vp = ap->a_vp;
+ struct proc *p = ap->a_p;
dev_t dev = vp->v_rdev;
d_close_t *devclose;
int mode, error;
@@ -631,8 +633,11 @@ spec_close(ap)
(vp->v_flag & VXLOCK) == 0)
return (0);
- if (vp->v_object)
- vnode_pager_uncache(vp);
+ if (vp->v_object) {
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
+ vnode_pager_uncache(vp, p);
+ VOP_UNLOCK(vp, 0, p);
+ }
devclose = bdevsw[major(dev)]->d_close;
mode = S_IFBLK;
diff --git a/sys/fs/umapfs/umap.h b/sys/fs/umapfs/umap.h
index db1efd4..54ae097 100644
--- a/sys/fs/umapfs/umap.h
+++ b/sys/fs/umapfs/umap.h
@@ -33,7 +33,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)umap.h 8.3 (Berkeley) 1/21/94
+ * @(#)umap.h 8.4 (Berkeley) 8/20/94
*
* $FreeBSD$
*/
@@ -67,8 +67,7 @@ struct umap_mount {
* A cache of vnode references
*/
struct umap_node {
- struct umap_node *umap_forw; /* Hash chain */
- struct umap_node *umap_back;
+ LIST_ENTRY(umap_node) umap_hash; /* Hash list */
struct vnode *umap_lowervp; /* Aliased vnode - VREFed once */
struct vnode *umap_vnode; /* Back pointer to vnode/umap_node */
};
diff --git a/sys/fs/umapfs/umap_subr.c b/sys/fs/umapfs/umap_subr.c
index 8333943..3b3629d 100644
--- a/sys/fs/umapfs/umap_subr.c
+++ b/sys/fs/umapfs/umap_subr.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1992, 1993
+ * Copyright (c) 1992, 1993, 1995
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software donated to Berkeley by
@@ -33,13 +33,14 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)umap_subr.c 8.6 (Berkeley) 1/26/94
+ * @(#)umap_subr.c 8.9 (Berkeley) 5/14/95
*
* $FreeBSD$
*/
#include <sys/param.h>
#include <sys/systm.h>
+#include <sys/proc.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/vnode.h>
@@ -48,11 +49,8 @@
#include <sys/malloc.h>
#include <miscfs/umapfs/umap.h>
-extern int umapfs_init __P((void));
-
#define LOG2_SIZEVNODE 7 /* log2(sizeof struct vnode) */
#define NUMAPNODECACHE 16
-#define UMAP_NHASH(vp) ((((u_long) vp)>>LOG2_SIZEVNODE) & (NUMAPNODECACHE-1))
/*
* Null layer cache:
@@ -62,52 +60,33 @@ extern int umapfs_init __P((void));
* alias is removed the target vnode is vrele'd.
*/
-/*
- * Cache head
- */
-struct umap_node_cache {
- struct umap_node *ac_forw;
- struct umap_node *ac_back;
-};
-
-static struct umap_node_cache umap_node_cache[NUMAPNODECACHE];
+#define UMAP_NHASH(vp) \
+ (&umap_node_hashtbl[(((u_long)vp)>>LOG2_SIZEVNODE) & umap_node_hash])
+LIST_HEAD(umap_node_hashhead, umap_node) *umap_node_hashtbl;
+u_long umap_node_hash;
static u_long umap_findid __P((u_long id, u_long map[][2], int nentries));
static int umap_node_alloc __P((struct mount *mp, struct vnode *lowervp,
struct vnode **vpp));
static struct vnode *
umap_node_find __P((struct mount *mp, struct vnode *targetvp));
-static struct umap_node_cache *
- umap_node_hash __P((struct vnode *targetvp));
/*
* Initialise cache headers
*/
int
-umapfs_init()
+umapfs_init(vfsp)
+ struct vfsconf *vfsp;
{
- struct umap_node_cache *ac;
+
#ifdef UMAPFS_DIAGNOSTIC
printf("umapfs_init\n"); /* printed during system boot */
#endif
-
- for (ac = umap_node_cache; ac < umap_node_cache + NUMAPNODECACHE; ac++)
- ac->ac_forw = ac->ac_back = (struct umap_node *) ac;
+ umap_node_hashtbl = hashinit(NUMAPNODECACHE, M_CACHE, &umap_node_hash);
return (0);
}
/*
- * Compute hash list for given target vnode
- */
-static struct umap_node_cache *
-umap_node_hash(targetvp)
- struct vnode *targetvp;
-{
-
- return (&umap_node_cache[UMAP_NHASH(targetvp)]);
-}
-
-/*
* umap_findid is called by various routines in umap_vnodeops.c to
* find a user or group id in a map.
*/
@@ -163,7 +142,8 @@ umap_node_find(mp, targetvp)
struct mount *mp;
struct vnode *targetvp;
{
- struct umap_node_cache *hd;
+ struct proc *p = curproc; /* XXX */
+ struct umap_node_hashhead *hd;
struct umap_node *a;
struct vnode *vp;
@@ -177,10 +157,9 @@ umap_node_find(mp, targetvp)
* the target vnode. If found, the increment the umap_node
* reference count (but NOT the target vnode's VREF counter).
*/
- hd = umap_node_hash(targetvp);
-
- loop:
- for (a = hd->ac_forw; a != (struct umap_node *) hd; a = a->umap_forw) {
+ hd = UMAP_NHASH(targetvp);
+loop:
+ for (a = hd->lh_first; a != 0; a = a->umap_hash.le_next) {
if (a->umap_lowervp == targetvp &&
a->umap_vnode->v_mount == mp) {
vp = UMAPTOV(a);
@@ -189,7 +168,7 @@ umap_node_find(mp, targetvp)
* stuff, but we don't want to lock
* the lower node.
*/
- if (vget(vp, 0)) {
+ if (vget(vp, 0, p)) {
#ifdef UMAPFS_DIAGNOSTIC
printf ("umap_node_find: vget failed.\n");
#endif
@@ -217,7 +196,7 @@ umap_node_alloc(mp, lowervp, vpp)
struct vnode *lowervp;
struct vnode **vpp;
{
- struct umap_node_cache *hd;
+ struct umap_node_hashhead *hd;
struct umap_node *xp;
struct vnode *othervp, *vp;
int error;
@@ -257,8 +236,8 @@ umap_node_alloc(mp, lowervp, vpp)
return (0);
}
VREF(lowervp); /* Extra VREF will be vrele'd in umap_node_create */
- hd = umap_node_hash(lowervp);
- insque(xp, hd);
+ hd = UMAP_NHASH(lowervp);
+ LIST_INSERT_HEAD(hd, xp, umap_hash);
return (0);
}
diff --git a/sys/fs/umapfs/umap_vfsops.c b/sys/fs/umapfs/umap_vfsops.c
index 517c291..897e2ce 100644
--- a/sys/fs/umapfs/umap_vfsops.c
+++ b/sys/fs/umapfs/umap_vfsops.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1992, 1993
+ * Copyright (c) 1992, 1993, 1995
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software donated to Berkeley by
@@ -33,7 +33,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)umap_vfsops.c 8.3 (Berkeley) 1/21/94
+ * @(#)umap_vfsops.c 8.8 (Berkeley) 5/14/95
*
* $FreeBSD$
*/
@@ -46,6 +46,7 @@
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
+#include <sys/proc.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/vnode.h>
@@ -54,7 +55,7 @@
#include <sys/malloc.h>
#include <miscfs/umapfs/umap.h>
-extern int umapfs_init __P((void));
+extern int umapfs_init __P((struct vfsconf *));
static int umapfs_fhtovp __P((struct mount *mp, struct fid *fidp,
struct mbuf *nam, struct vnode **vpp,
@@ -187,7 +188,7 @@ umapfs_mount(mp, path, data, ndp, p)
/*
* Unlock the node (either the lower or the alias)
*/
- VOP_UNLOCK(vp);
+ VOP_UNLOCK(vp, 0, p);
/*
* Make sure the node alias worked
*/
@@ -207,7 +208,7 @@ umapfs_mount(mp, path, data, ndp, p)
if (UMAPVPTOLOWERVP(umapm_rootvp)->v_mount->mnt_flag & MNT_LOCAL)
mp->mnt_flag |= MNT_LOCAL;
mp->mnt_data = (qaddr_t) amp;
- getnewfsid(mp, MOUNT_LOFS);
+ vfs_getnewfsid(mp);
(void) copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN - 1, &size);
bzero(mp->mnt_stat.f_mntonname + size, MNAMELEN - size);
@@ -253,12 +254,8 @@ umapfs_unmount(mp, mntflags, p)
printf("umapfs_unmount(mp = %x)\n", mp);
#endif
- if (mntflags & MNT_FORCE) {
- /* lofs can never be rootfs so don't check for it */
- if (!doforce)
- return (EINVAL);
+ if (mntflags & MNT_FORCE)
flags |= FORCECLOSE;
- }
/*
* Clear out buffer cache. I don't think we
@@ -300,6 +297,7 @@ umapfs_root(mp, vpp)
struct mount *mp;
struct vnode **vpp;
{
+ struct proc *p = curproc; /* XXX */
struct vnode *vp;
#ifdef UMAPFS_DIAGNOSTIC
@@ -314,7 +312,7 @@ umapfs_root(mp, vpp)
*/
vp = MOUNTTOUMAPMOUNT(mp)->umapm_rootvp;
VREF(vp);
- VOP_LOCK(vp);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
*vpp = vp;
return (0);
}
@@ -429,4 +427,3 @@ static struct vfsops umap_vfsops = {
};
VFS_SET(umap_vfsops, umap, MOUNT_UMAP, VFCF_LOOPBACK);
-
diff --git a/sys/fs/umapfs/umap_vnops.c b/sys/fs/umapfs/umap_vnops.c
index 7c14cda..17064f4 100644
--- a/sys/fs/umapfs/umap_vnops.c
+++ b/sys/fs/umapfs/umap_vnops.c
@@ -33,7 +33,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)umap_vnops.c 8.3 (Berkeley) 1/5/94
+ * @(#)umap_vnops.c 8.6 (Berkeley) 5/22/95
* $FreeBSD$
*/
@@ -336,10 +336,52 @@ umap_getattr(ap)
return (0);
}
+/*
+ * We need to process our own vnode lock and then clear the
+ * interlock flag as it applies only to our vnode, not the
+ * vnodes below us on the stack.
+ */
+int
+umap_lock(ap)
+ struct vop_lock_args /* {
+ struct vnode *a_vp;
+ int a_flags;
+ struct proc *a_p;
+ } */ *ap;
+{
+
+ vop_nolock(ap);
+ if ((ap->a_flags & LK_TYPE_MASK) == LK_DRAIN)
+ return (0);
+ ap->a_flags &= ~LK_INTERLOCK;
+ return (null_bypass(ap));
+}
+
+/*
+ * We need to process our own vnode unlock and then clear the
+ * interlock flag as it applies only to our vnode, not the
+ * vnodes below us on the stack.
+ */
+int
+umap_unlock(ap)
+ struct vop_unlock_args /* {
+ struct vnode *a_vp;
+ int a_flags;
+ struct proc *a_p;
+ } */ *ap;
+{
+ struct vnode *vp = ap->a_vp;
+
+ vop_nounlock(ap);
+ ap->a_flags &= ~LK_INTERLOCK;
+ return (null_bypass(ap));
+}
+
static int
umap_inactive(ap)
struct vop_inactive_args /* {
struct vnode *a_vp;
+ struct proc *a_p;
} */ *ap;
{
/*
@@ -349,6 +391,7 @@ umap_inactive(ap)
* cache and reusable.
*
*/
+ VOP_UNLOCK(ap->a_vp, 0, ap->a_p);
return (0);
}
@@ -364,7 +407,7 @@ umap_reclaim(ap)
/* After this assignment, this node will not be re-used. */
xp->umap_lowervp = NULL;
- remque(xp);
+ LIST_REMOVE(xp, umap_hash);
FREE(vp->v_data, M_TEMP);
vp->v_data = NULL;
vrele(lowervp);
@@ -487,6 +530,8 @@ static struct vnodeopv_entry_desc umap_vnodeop_entries[] = {
{ &vop_default_desc, (vop_t *)umap_bypass },
{ &vop_getattr_desc, (vop_t *)umap_getattr },
+ { &vop_lock_desc, (vop_t *)umap_lock },
+ { &vop_unlock_desc, (vop_t *)umap_unlock },
{ &vop_inactive_desc, (vop_t *)umap_inactive },
{ &vop_reclaim_desc, (vop_t *)umap_reclaim },
{ &vop_print_desc, (vop_t *)umap_print },
diff --git a/sys/fs/unionfs/union.h b/sys/fs/unionfs/union.h
index 9c740d3..c956921 100644
--- a/sys/fs/unionfs/union.h
+++ b/sys/fs/unionfs/union.h
@@ -34,7 +34,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)union.h 8.2 (Berkeley) 2/17/94
+ * @(#)union.h 8.9 (Berkeley) 12/10/94
* $FreeBSD$
*/
@@ -75,10 +75,14 @@ struct union_node {
struct vnode *un_uppervp; /* overlaying object */
struct vnode *un_lowervp; /* underlying object */
struct vnode *un_dirvp; /* Parent dir of uppervp */
+ struct vnode *un_pvp; /* Parent vnode */
char *un_path; /* saved component name */
int un_hash; /* saved un_path hash value */
int un_openl; /* # of opens on lowervp */
- int un_flags;
+ unsigned int un_flags;
+ struct vnode **un_dircache; /* cached union stack */
+ off_t un_uppersz; /* size of upper object */
+ off_t un_lowersz; /* size of lower object */
#ifdef DIAGNOSTIC
pid_t un_pid;
#endif
@@ -88,16 +92,23 @@ struct union_node {
#define UN_LOCKED 0x02
#define UN_ULOCK 0x04 /* Upper node is locked */
#define UN_KLOCK 0x08 /* Keep upper node locked on vput */
+#define UN_CACHED 0x10 /* In union cache */
extern int union_allocvp __P((struct vnode **, struct mount *,
struct vnode *, struct vnode *,
struct componentname *, struct vnode *,
- struct vnode *));
+ struct vnode *, int));
extern int union_freevp __P((struct vnode *));
-extern int union_copyfile __P((struct proc *, struct ucred *,
- struct vnode *, struct vnode *));
+extern int union_copyfile __P((struct vnode *, struct vnode *,
+ struct ucred *, struct proc *));
+extern int union_copyup __P((struct union_node *, int, struct ucred *,
+ struct proc *));
+extern int union_dowhiteout __P((struct union_node *, struct ucred *,
+ struct proc *));
extern int union_mkshadow __P((struct union_mount *, struct vnode *,
struct componentname *, struct vnode **));
+extern int union_mkwhiteout __P((struct union_mount *, struct vnode *,
+ struct componentname *, char *));
extern int union_vn_create __P((struct vnode **, struct union_node *,
struct proc *));
extern int union_vn_close __P((struct vnode *, int, struct ucred *,
@@ -108,6 +119,7 @@ extern void union_removed_upper __P((struct union_node *un));
extern struct vnode *union_lowervp __P((struct vnode *));
extern void union_newlower __P((struct union_node *, struct vnode *));
extern void union_newupper __P((struct union_node *, struct vnode *));
+extern void union_newsize __P((struct vnode *, off_t, off_t));
#define MOUNTTOUNIONMOUNT(mp) ((struct union_mount *)((mp)->mnt_data))
#define VTOUNION(vp) ((struct union_node *)(vp)->v_data)
diff --git a/sys/fs/unionfs/union_subr.c b/sys/fs/unionfs/union_subr.c
index 6549f7d..63e25e6 100644
--- a/sys/fs/unionfs/union_subr.c
+++ b/sys/fs/unionfs/union_subr.c
@@ -34,7 +34,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)union_subr.c 8.4 (Berkeley) 2/17/94
+ * @(#)union_subr.c 8.20 (Berkeley) 5/20/95
* $FreeBSD$
*/
@@ -48,6 +48,9 @@
#include <sys/file.h>
#include <sys/filedesc.h>
#include <sys/queue.h>
+#include <sys/mount.h>
+#include <sys/stat.h>
+#include <vm/vm.h> /* for vnode_pager_setsize */
#include <miscfs/union/union.h>
#include <sys/proc.h>
@@ -118,31 +121,38 @@ union_updatevp(un, uppervp, lowervp)
{
int ohash = UNION_HASH(un->un_uppervp, un->un_lowervp);
int nhash = UNION_HASH(uppervp, lowervp);
+ int docache = (lowervp != NULLVP || uppervp != NULLVP);
+ int lhash, hhash, uhash;
- if (ohash != nhash) {
- /*
- * Ensure locking is ordered from lower to higher
- * to avoid deadlocks.
- */
- if (nhash < ohash) {
- int t = ohash;
- ohash = nhash;
- nhash = t;
- }
+ /*
+ * Ensure locking is ordered from lower to higher
+ * to avoid deadlocks.
+ */
+ if (nhash < ohash) {
+ lhash = nhash;
+ uhash = ohash;
+ } else {
+ lhash = ohash;
+ uhash = nhash;
+ }
- while (union_list_lock(ohash))
+ if (lhash != uhash)
+ while (union_list_lock(lhash))
continue;
- while (union_list_lock(nhash))
- continue;
+ while (union_list_lock(uhash))
+ continue;
- LIST_REMOVE(un, un_cache);
- union_list_unlock(ohash);
- } else {
- while (union_list_lock(nhash))
- continue;
+ if (ohash != nhash || !docache) {
+ if (un->un_flags & UN_CACHED) {
+ un->un_flags &= ~UN_CACHED;
+ LIST_REMOVE(un, un_cache);
+ }
}
+ if (ohash != nhash)
+ union_list_unlock(ohash);
+
if (un->un_lowervp != lowervp) {
if (un->un_lowervp) {
vrele(un->un_lowervp);
@@ -156,6 +166,7 @@ union_updatevp(un, uppervp, lowervp)
}
}
un->un_lowervp = lowervp;
+ un->un_lowersz = VNOVAL;
}
if (un->un_uppervp != uppervp) {
@@ -163,10 +174,13 @@ union_updatevp(un, uppervp, lowervp)
vrele(un->un_uppervp);
un->un_uppervp = uppervp;
+ un->un_uppersz = VNOVAL;
}
- if (ohash != nhash)
+ if (docache && (ohash != nhash)) {
LIST_INSERT_HEAD(&unhead[nhash], un, un_cache);
+ un->un_flags |= UN_CACHED;
+ }
union_list_unlock(nhash);
}
@@ -190,6 +204,47 @@ union_newupper(un, uppervp)
}
/*
+ * Keep track of size changes in the underlying vnodes.
+ * If the size changes, then callback to the vm layer
+ * giving priority to the upper layer size.
+ */
+void
+union_newsize(vp, uppersz, lowersz)
+ struct vnode *vp;
+ off_t uppersz, lowersz;
+{
+ struct union_node *un;
+ off_t sz;
+
+ /* only interested in regular files */
+ if (vp->v_type != VREG)
+ return;
+
+ un = VTOUNION(vp);
+ sz = VNOVAL;
+
+ if ((uppersz != VNOVAL) && (un->un_uppersz != uppersz)) {
+ un->un_uppersz = uppersz;
+ if (sz == VNOVAL)
+ sz = un->un_uppersz;
+ }
+
+ if ((lowersz != VNOVAL) && (un->un_lowersz != lowersz)) {
+ un->un_lowersz = lowersz;
+ if (sz == VNOVAL)
+ sz = un->un_lowersz;
+ }
+
+ if (sz != VNOVAL) {
+#ifdef UNION_DIAGNOSTIC
+ printf("union: %s size now %ld\n",
+ uppersz != VNOVAL ? "upper" : "lower", (long) sz);
+#endif
+ vnode_pager_setsize(vp, sz);
+ }
+}
+
+/*
* allocate a union_node/vnode pair. the vnode is
* referenced and locked. the new vnode is returned
* via (vpp). (mp) is the mountpoint of the union filesystem,
@@ -221,19 +276,22 @@ union_newupper(un, uppervp)
* the vnode free list.
*/
int
-union_allocvp(vpp, mp, undvp, dvp, cnp, uppervp, lowervp)
+union_allocvp(vpp, mp, undvp, dvp, cnp, uppervp, lowervp, docache)
struct vnode **vpp;
struct mount *mp;
- struct vnode *undvp;
+ struct vnode *undvp; /* parent union vnode */
struct vnode *dvp; /* may be null */
struct componentname *cnp; /* may be null */
struct vnode *uppervp; /* may be null */
struct vnode *lowervp; /* may be null */
+ int docache;
{
int error;
struct union_node *un = 0;
struct vnode *xlowervp = NULLVP;
- int hash = 0;
+ struct union_mount *um = MOUNTTOUNIONMOUNT(mp);
+ int hash;
+ int vflag;
int try;
if (uppervp == NULLVP && lowervp == NULLVP)
@@ -244,8 +302,22 @@ union_allocvp(vpp, mp, undvp, dvp, cnp, uppervp, lowervp)
lowervp = NULLVP;
}
+ /* detect the root vnode (and aliases) */
+ vflag = 0;
+ if ((uppervp == um->um_uppervp) &&
+ ((lowervp == NULLVP) || lowervp == um->um_lowervp)) {
+ if (lowervp == NULLVP) {
+ lowervp = um->um_lowervp;
+ if (lowervp != NULLVP)
+ VREF(lowervp);
+ }
+ vflag = VROOT;
+ }
+
loop:
- for (try = 0; try < 3; try++) {
+ if (!docache) {
+ un = 0;
+ } else for (try = 0; try < 3; try++) {
switch (try) {
case 0:
if (lowervp == NULLVP)
@@ -276,7 +348,8 @@ loop:
(un->un_uppervp == uppervp ||
un->un_uppervp == NULLVP) &&
(UNIONTOV(un)->v_mount == mp)) {
- if (vget(UNIONTOV(un), 0)) {
+ if (vget(UNIONTOV(un), 0,
+ cnp ? cnp->cn_proc : NULL)) {
union_list_unlock(hash);
goto loop;
}
@@ -359,8 +432,7 @@ loop:
*/
if (lowervp != un->un_lowervp) {
union_newlower(un, lowervp);
- if (cnp && (lowervp != NULLVP) &&
- (lowervp->v_type == VREG)) {
+ if (cnp && (lowervp != NULLVP)) {
un->un_hash = cnp->cn_hash;
un->un_path = malloc(cnp->cn_namelen+1,
M_TEMP, M_WAITOK);
@@ -377,14 +449,16 @@ loop:
return (0);
}
- /*
- * otherwise lock the vp list while we call getnewvnode
- * since that can block.
- */
- hash = UNION_HASH(uppervp, lowervp);
+ if (docache) {
+ /*
+ * otherwise lock the vp list while we call getnewvnode
+ * since that can block.
+ */
+ hash = UNION_HASH(uppervp, lowervp);
- if (union_list_lock(hash))
- goto loop;
+ if (union_list_lock(hash))
+ goto loop;
+ }
error = getnewvnode(VT_UNION, mp, union_vnodeop_p, vpp);
if (error) {
@@ -403,6 +477,7 @@ loop:
MALLOC((*vpp)->v_data, void *, sizeof(struct union_node),
M_TEMP, M_WAITOK);
+ (*vpp)->v_flag |= vflag;
if (uppervp)
(*vpp)->v_type = uppervp->v_type;
else
@@ -410,7 +485,13 @@ loop:
un = VTOUNION(*vpp);
un->un_vnode = *vpp;
un->un_uppervp = uppervp;
+ un->un_uppersz = VNOVAL;
un->un_lowervp = lowervp;
+ un->un_lowersz = VNOVAL;
+ un->un_pvp = undvp;
+ if (undvp != NULLVP)
+ VREF(undvp);
+ un->un_dircache = 0;
un->un_openl = 0;
un->un_flags = UN_LOCKED;
if (un->un_uppervp)
@@ -421,7 +502,7 @@ loop:
else
un->un_pid = -1;
#endif
- if (cnp && (lowervp != NULLVP) && (lowervp->v_type == VREG)) {
+ if (cnp && (lowervp != NULLVP)) {
un->un_hash = cnp->cn_hash;
un->un_path = malloc(cnp->cn_namelen+1, M_TEMP, M_WAITOK);
bcopy(cnp->cn_nameptr, un->un_path, cnp->cn_namelen);
@@ -434,13 +515,17 @@ loop:
un->un_dirvp = 0;
}
- LIST_INSERT_HEAD(&unhead[hash], un, un_cache);
+ if (docache) {
+ LIST_INSERT_HEAD(&unhead[hash], un, un_cache);
+ un->un_flags |= UN_CACHED;
+ }
if (xlowervp)
vrele(xlowervp);
out:
- union_list_unlock(hash);
+ if (docache)
+ union_list_unlock(hash);
return (error);
}
@@ -451,13 +536,18 @@ union_freevp(vp)
{
struct union_node *un = VTOUNION(vp);
- LIST_REMOVE(un, un_cache);
+ if (un->un_flags & UN_CACHED) {
+ un->un_flags &= ~UN_CACHED;
+ LIST_REMOVE(un, un_cache);
+ }
- if (un->un_uppervp)
+ if (un->un_pvp != NULLVP)
+ vrele(un->un_pvp);
+ if (un->un_uppervp != NULLVP)
vrele(un->un_uppervp);
- if (un->un_lowervp)
+ if (un->un_lowervp != NULLVP)
vrele(un->un_lowervp);
- if (un->un_dirvp)
+ if (un->un_dirvp != NULLVP)
vrele(un->un_dirvp);
if (un->un_path)
free(un->un_path, M_TEMP);
@@ -474,11 +564,11 @@ union_freevp(vp)
* and (tvp) are locked on entry and exit.
*/
int
-union_copyfile(p, cred, fvp, tvp)
- struct proc *p;
- struct ucred *cred;
+union_copyfile(fvp, tvp, cred, p)
struct vnode *fvp;
struct vnode *tvp;
+ struct ucred *cred;
+ struct proc *p;
{
char *buf;
struct uio uio;
@@ -497,12 +587,12 @@ union_copyfile(p, cred, fvp, tvp)
uio.uio_segflg = UIO_SYSSPACE;
uio.uio_offset = 0;
- VOP_UNLOCK(fvp); /* XXX */
- LEASE_CHECK(fvp, p, cred, LEASE_READ);
- VOP_LOCK(fvp); /* XXX */
- VOP_UNLOCK(tvp); /* XXX */
- LEASE_CHECK(tvp, p, cred, LEASE_WRITE);
- VOP_LOCK(tvp); /* XXX */
+ VOP_UNLOCK(fvp, 0, p); /* XXX */
+ VOP_LEASE(fvp, p, cred, LEASE_READ);
+ vn_lock(fvp, LK_EXCLUSIVE | LK_RETRY, p); /* XXX */
+ VOP_UNLOCK(tvp, 0, p); /* XXX */
+ VOP_LEASE(tvp, p, cred, LEASE_WRITE);
+ vn_lock(tvp, LK_EXCLUSIVE | LK_RETRY, p); /* XXX */
buf = malloc(MAXBSIZE, M_TEMP, M_WAITOK);
@@ -542,6 +632,123 @@ union_copyfile(p, cred, fvp, tvp)
}
/*
+ * (un) is assumed to be locked on entry and remains
+ * locked on exit.
+ */
+int
+union_copyup(un, docopy, cred, p)
+ struct union_node *un;
+ int docopy;
+ struct ucred *cred;
+ struct proc *p;
+{
+ int error;
+ struct vnode *lvp, *uvp;
+
+ error = union_vn_create(&uvp, un, p);
+ if (error)
+ return (error);
+
+ /* at this point, uppervp is locked */
+ union_newupper(un, uvp);
+ un->un_flags |= UN_ULOCK;
+
+ lvp = un->un_lowervp;
+
+ if (docopy) {
+ /*
+ * XX - should not ignore errors
+ * from VOP_CLOSE
+ */
+ vn_lock(lvp, LK_EXCLUSIVE | LK_RETRY, p);
+ error = VOP_OPEN(lvp, FREAD, cred, p);
+ if (error == 0) {
+ error = union_copyfile(lvp, uvp, cred, p);
+ VOP_UNLOCK(lvp, 0, p);
+ (void) VOP_CLOSE(lvp, FREAD, cred, p);
+ }
+#ifdef UNION_DIAGNOSTIC
+ if (error == 0)
+ uprintf("union: copied up %s\n", un->un_path);
+#endif
+
+ }
+ un->un_flags &= ~UN_ULOCK;
+ VOP_UNLOCK(uvp, 0, p);
+ union_vn_close(uvp, FWRITE, cred, p);
+ vn_lock(uvp, LK_EXCLUSIVE | LK_RETRY, p);
+ un->un_flags |= UN_ULOCK;
+
+ /*
+ * Subsequent IOs will go to the top layer, so
+ * call close on the lower vnode and open on the
+ * upper vnode to ensure that the filesystem keeps
+ * its references counts right. This doesn't do
+ * the right thing with (cred) and (FREAD) though.
+ * Ignoring error returns is not right, either.
+ */
+ if (error == 0) {
+ int i;
+
+ for (i = 0; i < un->un_openl; i++) {
+ (void) VOP_CLOSE(lvp, FREAD, cred, p);
+ (void) VOP_OPEN(uvp, FREAD, cred, p);
+ }
+ un->un_openl = 0;
+ }
+
+ return (error);
+
+}
+
+static int
+union_relookup(um, dvp, vpp, cnp, cn, path, pathlen)
+ struct union_mount *um;
+ struct vnode *dvp;
+ struct vnode **vpp;
+ struct componentname *cnp;
+ struct componentname *cn;
+ char *path;
+ int pathlen;
+{
+ int error;
+
+ /*
+ * A new componentname structure must be faked up because
+ * there is no way to know where the upper level cnp came
+ * from or what it is being used for. This must duplicate
+ * some of the work done by NDINIT, some of the work done
+ * by namei, some of the work done by lookup and some of
+ * the work done by VOP_LOOKUP when given a CREATE flag.
+ * Conclusion: Horrible.
+ *
+ * The pathname buffer will be FREEed by VOP_MKDIR.
+ */
+ cn->cn_namelen = pathlen;
+ cn->cn_pnbuf = malloc(cn->cn_namelen+1, M_NAMEI, M_WAITOK);
+ bcopy(path, cn->cn_pnbuf, cn->cn_namelen);
+ cn->cn_pnbuf[cn->cn_namelen] = '\0';
+
+ cn->cn_nameiop = CREATE;
+ cn->cn_flags = (LOCKPARENT|HASBUF|SAVENAME|SAVESTART|ISLASTCN);
+ cn->cn_proc = cnp->cn_proc;
+ if (um->um_op == UNMNT_ABOVE)
+ cn->cn_cred = cnp->cn_cred;
+ else
+ cn->cn_cred = um->um_cred;
+ cn->cn_nameptr = cn->cn_pnbuf;
+ cn->cn_hash = cnp->cn_hash;
+ cn->cn_consume = cnp->cn_consume;
+
+ VREF(dvp);
+ error = relookup(dvp, vpp, cn);
+ if (!error)
+ vrele(dvp);
+
+ return (error);
+}
+
+/*
* Create a shadow directory in the upper layer.
* The new vnode is returned locked.
*
@@ -565,6 +772,19 @@ union_mkshadow(um, dvp, cnp, vpp)
struct proc *p = cnp->cn_proc;
struct componentname cn;
+ error = union_relookup(um, dvp, vpp, cnp, &cn,
+ cnp->cn_nameptr, cnp->cn_namelen);
+ if (error)
+ return (error);
+
+ if (*vpp) {
+ VOP_ABORTOP(dvp, &cn);
+ VOP_UNLOCK(dvp, 0, p);
+ vrele(*vpp);
+ *vpp = NULLVP;
+ return (EEXIST);
+ }
+
/*
* policy: when creating the shadow directory in the
* upper layer, create it owned by the user who did
@@ -573,55 +793,62 @@ union_mkshadow(um, dvp, cnp, vpp)
* mkdir syscall). (jsp, kb)
*/
- /*
- * A new componentname structure must be faked up because
- * there is no way to know where the upper level cnp came
- * from or what it is being used for. This must duplicate
- * some of the work done by NDINIT, some of the work done
- * by namei, some of the work done by lookup and some of
- * the work done by VOP_LOOKUP when given a CREATE flag.
- * Conclusion: Horrible.
- *
- * The pathname buffer will be FREEed by VOP_MKDIR.
- */
- cn.cn_pnbuf = malloc(cnp->cn_namelen+1, M_NAMEI, M_WAITOK);
- bcopy(cnp->cn_nameptr, cn.cn_pnbuf, cnp->cn_namelen);
- cn.cn_pnbuf[cnp->cn_namelen] = '\0';
+ VATTR_NULL(&va);
+ va.va_type = VDIR;
+ va.va_mode = um->um_cmode;
- cn.cn_nameiop = CREATE;
- cn.cn_flags = (LOCKPARENT|HASBUF|SAVENAME|SAVESTART|ISLASTCN);
- cn.cn_proc = cnp->cn_proc;
- if (um->um_op == UNMNT_ABOVE)
- cn.cn_cred = cnp->cn_cred;
- else
- cn.cn_cred = um->um_cred;
- cn.cn_nameptr = cn.cn_pnbuf;
- cn.cn_namelen = cnp->cn_namelen;
- cn.cn_hash = cnp->cn_hash;
- cn.cn_consume = cnp->cn_consume;
+ /* VOP_LEASE: dvp is locked */
+ VOP_LEASE(dvp, p, cn.cn_cred, LEASE_WRITE);
- VREF(dvp);
- error = relookup(dvp, vpp, &cn);
- if (error)
+ error = VOP_MKDIR(dvp, vpp, &cn, &va);
+ return (error);
+}
+
+/*
+ * Create a whiteout entry in the upper layer.
+ *
+ * (um) points to the union mount structure for access to the
+ * the mounting process's credentials.
+ * (dvp) is the directory in which to create the whiteout.
+ * it is locked on entry and exit.
+ * (cnp) is the componentname to be created.
+ */
+int
+union_mkwhiteout(um, dvp, cnp, path)
+ struct union_mount *um;
+ struct vnode *dvp;
+ struct componentname *cnp;
+ char *path;
+{
+ int error;
+ struct vattr va;
+ struct proc *p = cnp->cn_proc;
+ struct vnode *wvp;
+ struct componentname cn;
+
+ VOP_UNLOCK(dvp, 0, p);
+ error = union_relookup(um, dvp, &wvp, cnp, &cn, path, strlen(path));
+ if (error) {
+ vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY, p);
return (error);
- vrele(dvp);
+ }
- if (*vpp) {
+ if (wvp) {
VOP_ABORTOP(dvp, &cn);
- VOP_UNLOCK(dvp);
- vrele(*vpp);
- *vpp = NULLVP;
+ vrele(dvp);
+ vrele(wvp);
return (EEXIST);
}
- VATTR_NULL(&va);
- va.va_type = VDIR;
- va.va_mode = um->um_cmode;
+ /* VOP_LEASE: dvp is locked */
+ VOP_LEASE(dvp, p, p->p_ucred, LEASE_WRITE);
+
+ error = VOP_WHITEOUT(dvp, &cn, CREATE);
+ if (error)
+ VOP_ABORTOP(dvp, &cn);
- /* LEASE_CHECK: dvp is locked */
- LEASE_CHECK(dvp, p, p->p_ucred, LEASE_WRITE);
+ vrele(dvp);
- error = VOP_MKDIR(dvp, vpp, &cn, &va);
return (error);
}
@@ -699,9 +926,8 @@ union_vn_create(vpp, un, p)
VATTR_NULL(vap);
vap->va_type = VREG;
vap->va_mode = cmode;
- LEASE_CHECK(un->un_dirvp, p, cred, LEASE_WRITE);
- error = VOP_CREATE(un->un_dirvp, &vp, &cn, vap);
- if (error)
+ VOP_LEASE(un->un_dirvp, p, cred, LEASE_WRITE);
+ if (error = VOP_CREATE(un->un_dirvp, &vp, &cn, vap))
return (error);
error = VOP_OPEN(vp, fmode, cred, p);
@@ -722,6 +948,7 @@ union_vn_close(vp, fmode, cred, p)
struct ucred *cred;
struct proc *p;
{
+
if (fmode & FWRITE)
--vp->v_writecount;
return (VOP_CLOSE(vp, fmode, cred, p));
@@ -731,24 +958,137 @@ void
union_removed_upper(un)
struct union_node *un;
{
+ struct proc *p = curproc; /* XXX */
+
+ union_newupper(un, NULLVP);
+ if (un->un_flags & UN_CACHED) {
+ un->un_flags &= ~UN_CACHED;
+ LIST_REMOVE(un, un_cache);
+ }
+
if (un->un_flags & UN_ULOCK) {
un->un_flags &= ~UN_ULOCK;
- VOP_UNLOCK(un->un_uppervp);
+ VOP_UNLOCK(un->un_uppervp, 0, p);
}
-
- union_newupper(un, NULLVP);
}
+#if 0
struct vnode *
union_lowervp(vp)
struct vnode *vp;
{
struct union_node *un = VTOUNION(vp);
- if (un->un_lowervp && (vp->v_type == un->un_lowervp->v_type)) {
- if (vget(un->un_lowervp, 0))
- return (NULLVP);
+ if ((un->un_lowervp != NULLVP) &&
+ (vp->v_type == un->un_lowervp->v_type)) {
+ if (vget(un->un_lowervp, 0) == 0)
+ return (un->un_lowervp);
}
- return (un->un_lowervp);
+ return (NULLVP);
+}
+#endif
+
+/*
+ * determine whether a whiteout is needed
+ * during a remove/rmdir operation.
+ */
+int
+union_dowhiteout(un, cred, p)
+ struct union_node *un;
+ struct ucred *cred;
+ struct proc *p;
+{
+ struct vattr va;
+
+ if (un->un_lowervp != NULLVP)
+ return (1);
+
+ if (VOP_GETATTR(un->un_uppervp, &va, cred, p) == 0 &&
+ (va.va_flags & OPAQUE))
+ return (1);
+
+ return (0);
+}
+
+static void
+union_dircache_r(vp, vppp, cntp)
+ struct vnode *vp;
+ struct vnode ***vppp;
+ int *cntp;
+{
+ struct union_node *un;
+
+ if (vp->v_op != union_vnodeop_p) {
+ if (vppp) {
+ VREF(vp);
+ *(*vppp)++ = vp;
+ if (--(*cntp) == 0)
+ panic("union: dircache table too small");
+ } else {
+ (*cntp)++;
+ }
+
+ return;
+ }
+
+ un = VTOUNION(vp);
+ if (un->un_uppervp != NULLVP)
+ union_dircache_r(un->un_uppervp, vppp, cntp);
+ if (un->un_lowervp != NULLVP)
+ union_dircache_r(un->un_lowervp, vppp, cntp);
+}
+
+struct vnode *
+union_dircache(vp, p)
+ struct vnode *vp;
+ struct proc *p;
+{
+ int cnt;
+ struct vnode *nvp;
+ struct vnode **vpp;
+ struct vnode **dircache;
+ struct union_node *un;
+ int error;
+
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
+ dircache = VTOUNION(vp)->un_dircache;
+
+ nvp = NULLVP;
+
+ if (dircache == 0) {
+ cnt = 0;
+ union_dircache_r(vp, 0, &cnt);
+ cnt++;
+ dircache = (struct vnode **)
+ malloc(cnt * sizeof(struct vnode *),
+ M_TEMP, M_WAITOK);
+ vpp = dircache;
+ union_dircache_r(vp, &vpp, &cnt);
+ *vpp = NULLVP;
+ vpp = dircache + 1;
+ } else {
+ vpp = dircache;
+ do {
+ if (*vpp++ == VTOUNION(vp)->un_uppervp)
+ break;
+ } while (*vpp != NULLVP);
+ }
+
+ if (*vpp == NULLVP)
+ goto out;
+
+ vn_lock(*vpp, LK_EXCLUSIVE | LK_RETRY, p);
+ VREF(*vpp);
+ error = union_allocvp(&nvp, vp->v_mount, NULLVP, NULLVP, 0, *vpp, NULLVP, 0);
+ if (error)
+ goto out;
+
+ VTOUNION(vp)->un_dircache = 0;
+ un = VTOUNION(nvp);
+ un->un_dircache = dircache;
+
+out:
+ VOP_UNLOCK(vp, 0, p);
+ return (nvp);
}
diff --git a/sys/fs/unionfs/union_vfsops.c b/sys/fs/unionfs/union_vfsops.c
index a1a6a0d..0295961 100644
--- a/sys/fs/unionfs/union_vfsops.c
+++ b/sys/fs/unionfs/union_vfsops.c
@@ -1,6 +1,6 @@
/*
- * Copyright (c) 1994 The Regents of the University of California.
- * Copyright (c) 1994 Jan-Simon Pendry.
+ * Copyright (c) 1994, 1995 The Regents of the University of California.
+ * Copyright (c) 1994, 1995 Jan-Simon Pendry.
* All rights reserved.
*
* This code is derived from software donated to Berkeley by
@@ -34,7 +34,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)union_vfsops.c 8.7 (Berkeley) 3/5/94
+ * @(#)union_vfsops.c 8.20 (Berkeley) 5/20/95
* $FreeBSD$
*/
@@ -56,7 +56,7 @@
#include <sys/queue.h>
#include <miscfs/union/union.h>
-extern int union_init __P((void));
+extern int union_init __P((struct vfsconf *));
extern int union_fhtovp __P((struct mount *mp, struct fid *fidp,
struct mbuf *nam, struct vnode **vpp,
@@ -92,7 +92,7 @@ union_mount(mp, path, data, ndp, p)
struct union_args args;
struct vnode *lowerrootvp = NULLVP;
struct vnode *upperrootvp = NULLVP;
- struct union_mount *um;
+ struct union_mount *um = 0;
struct ucred *cred = 0;
struct ucred *scred;
struct vattr va;
@@ -118,34 +118,6 @@ union_mount(mp, path, data, ndp, p)
}
/*
- * Take a copy of the process's credentials. This isn't
- * quite right since the euid will always be zero and we
- * want to get the "real" users credentials. So fix up
- * the uid field after taking the copy.
- */
- cred = crdup(p->p_ucred);
- cred->cr_uid = p->p_cred->p_ruid;
-
- /*
- * Ensure the *real* user has write permission on the
- * mounted-on directory. This allows the mount_union
- * command to be made setuid root so allowing anyone
- * to do union mounts onto any directory on which they
- * have write permission and which they also own.
- */
- error = VOP_GETATTR(mp->mnt_vnodecovered, &va, cred, p);
- if (error)
- goto bad;
- if ((va.va_uid != cred->cr_uid) &&
- (cred->cr_uid != 0)) {
- error = EACCES;
- goto bad;
- }
- error = VOP_ACCESS(mp->mnt_vnodecovered, VWRITE, cred, p);
- if (error)
- goto bad;
-
- /*
* Get argument
*/
error = copyin(data, (caddr_t)&args, sizeof(struct union_args));
@@ -156,18 +128,10 @@ union_mount(mp, path, data, ndp, p)
VREF(lowerrootvp);
/*
- * Find upper node. Use the real process credentials,
- * not the effective ones since this will have come
- * through a setuid process (mount_union). All this
- * messing around with permissions is entirely bogus
- * and should be removed by allowing any user straight
- * past the mount system call.
+ * Find upper node.
*/
- scred = p->p_ucred;
- p->p_ucred = cred;
NDINIT(ndp, LOOKUP, FOLLOW|WANTPARENT,
UIO_USERSPACE, args.target, p);
- p->p_ucred = scred;
error = namei(ndp);
if (error)
@@ -218,7 +182,18 @@ union_mount(mp, path, data, ndp, p)
goto bad;
}
- um->um_cred = cred;
+ /*
+ * Unless the mount is readonly, ensure that the top layer
+ * supports whiteout operations
+ */
+ if ((mp->mnt_flag & MNT_RDONLY) == 0) {
+ error = VOP_WHITEOUT(um->um_uppervp, (struct componentname *) 0, LOOKUP);
+ if (error)
+ goto bad;
+ }
+
+ um->um_cred = p->p_ucred;
+ crhold(um->um_cred);
um->um_cmode = UN_DIRMODE &~ p->p_fd->fd_cmask;
/*
@@ -246,24 +221,18 @@ union_mount(mp, path, data, ndp, p)
*/
mp->mnt_flag |= (um->um_uppervp->v_mount->mnt_flag & MNT_RDONLY);
- /*
- * This is a user mount. Privilege check for unmount
- * will be done in union_unmount.
- */
- mp->mnt_flag |= MNT_USER;
-
mp->mnt_data = (qaddr_t) um;
- getnewfsid(mp, MOUNT_UNION);
+ vfs_getnewfsid(mp);
(void) copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN - 1, &size);
bzero(mp->mnt_stat.f_mntonname + size, MNAMELEN - size);
switch (um->um_op) {
case UNMNT_ABOVE:
- cp = "<above>";
+ cp = "<above>:";
break;
case UNMNT_BELOW:
- cp = "<below>";
+ cp = "<below>:";
break;
case UNMNT_REPLACE:
cp = "";
@@ -287,6 +256,8 @@ union_mount(mp, path, data, ndp, p)
return (0);
bad:
+ if (um)
+ free(um, M_UFSMNT);
if (cred)
crfree(cred);
if (upperrootvp)
@@ -323,40 +294,55 @@ union_unmount(mp, mntflags, p)
struct union_mount *um = MOUNTTOUNIONMOUNT(mp);
struct vnode *um_rootvp;
int error;
+ int freeing;
int flags = 0;
#ifdef UNION_DIAGNOSTIC
printf("union_unmount(mp = %x)\n", mp);
#endif
- /* only the mounter, or superuser can unmount */
- if ((p->p_cred->p_ruid != um->um_cred->cr_uid) &&
- (error = suser(p->p_ucred, &p->p_acflag)))
+ if (mntflags & MNT_FORCE)
+ flags |= FORCECLOSE;
+
+ if (error = union_root(mp, &um_rootvp))
return (error);
- if (mntflags & MNT_FORCE) {
- /* union can never be rootfs so don't check for it */
- if (!doforce)
- return (EINVAL);
- flags |= FORCECLOSE;
+ /*
+ * Keep flushing vnodes from the mount list.
+ * This is needed because of the un_pvp held
+ * reference to the parent vnode.
+ * If more vnodes have been freed on a given pass,
+ * the try again. The loop will iterate at most
+ * (d) times, where (d) is the maximum tree depth
+ * in the filesystem.
+ */
+ for (freeing = 0; vflush(mp, um_rootvp, flags) != 0;) {
+ struct vnode *vp;
+ int n;
+
+ /* count #vnodes held on mount list */
+ for (n = 0, vp = mp->mnt_vnodelist.lh_first;
+ vp != NULLVP;
+ vp = vp->v_mntvnodes.le_next)
+ n++;
+
+ /* if this is unchanged then stop */
+ if (n == freeing)
+ break;
+
+ /* otherwise try once more time */
+ freeing = n;
}
- error = union_root(mp, &um_rootvp);
- if (error)
- return (error);
+ /* At this point the root vnode should have a single reference */
if (um_rootvp->v_usecount > 1) {
vput(um_rootvp);
return (EBUSY);
}
- error = vflush(mp, um_rootvp, flags);
- if (error) {
- vput(um_rootvp);
- return (error);
- }
#ifdef UNION_DIAGNOSTIC
- vprint("alias root of lower", um_rootvp);
-#endif
+ vprint("union root", um_rootvp);
+#endif
/*
* Discard references to upper and lower target vnodes.
*/
@@ -385,16 +371,11 @@ union_root(mp, vpp)
struct mount *mp;
struct vnode **vpp;
{
+ struct proc *p = curproc; /* XXX */
struct union_mount *um = MOUNTTOUNIONMOUNT(mp);
int error;
int loselock;
-#ifdef UNION_DIAGNOSTIC
- printf("union_root(mp = %x, lvp = %x, uvp = %x)\n", mp,
- um->um_lowervp,
- um->um_uppervp);
-#endif
-
/*
* Return locked reference to root.
*/
@@ -403,7 +384,7 @@ union_root(mp, vpp)
VOP_ISLOCKED(um->um_uppervp)) {
loselock = 1;
} else {
- VOP_LOCK(um->um_uppervp);
+ vn_lock(um->um_uppervp, LK_EXCLUSIVE | LK_RETRY, p);
loselock = 0;
}
if (um->um_lowervp)
@@ -413,16 +394,17 @@ union_root(mp, vpp)
(struct vnode *) 0,
(struct componentname *) 0,
um->um_uppervp,
- um->um_lowervp);
+ um->um_lowervp,
+ 1);
if (error) {
- if (!loselock)
- VOP_UNLOCK(um->um_uppervp);
- vrele(um->um_uppervp);
+ if (loselock)
+ vrele(um->um_uppervp);
+ else
+ vput(um->um_uppervp);
if (um->um_lowervp)
vrele(um->um_lowervp);
} else {
- (*vpp)->v_flag |= VROOT;
if (loselock)
VTOUNION(*vpp)->un_flags &= ~UN_ULOCK;
}
@@ -431,18 +413,6 @@ union_root(mp, vpp)
}
int
-union_quotactl(mp, cmd, uid, arg, p)
- struct mount *mp;
- int cmd;
- uid_t uid;
- caddr_t arg;
- struct proc *p;
-{
-
- return (EOPNOTSUPP);
-}
-
-int
union_statfs(mp, sbp, p)
struct mount *mp;
struct statfs *sbp;
@@ -485,7 +455,6 @@ union_statfs(mp, sbp, p)
if (error)
return (error);
- sbp->f_type = MOUNT_UNION;
sbp->f_flags = mstat.f_flags;
sbp->f_bsize = mstat.f_bsize;
sbp->f_iosize = mstat.f_iosize;
@@ -496,18 +465,23 @@ union_statfs(mp, sbp, p)
* kind of sense. none of this makes sense though.
*/
- if (mstat.f_bsize != lbsize) {
+ if (mstat.f_bsize != lbsize)
sbp->f_blocks = sbp->f_blocks * lbsize / mstat.f_bsize;
- sbp->f_bfree = sbp->f_bfree * lbsize / mstat.f_bsize;
- sbp->f_bavail = sbp->f_bavail * lbsize / mstat.f_bsize;
- }
+
+ /*
+ * The "total" fields count total resources in all layers,
+ * the "free" fields count only those resources which are
+ * free in the upper layer (since only the upper layer
+ * is writeable).
+ */
sbp->f_blocks += mstat.f_blocks;
- sbp->f_bfree += mstat.f_bfree;
- sbp->f_bavail += mstat.f_bavail;
+ sbp->f_bfree = mstat.f_bfree;
+ sbp->f_bavail = mstat.f_bavail;
sbp->f_files += mstat.f_files;
- sbp->f_ffree += mstat.f_ffree;
+ sbp->f_ffree = mstat.f_ffree;
if (sbp != &mp->mnt_stat) {
+ sbp->f_type = mp->mnt_vfc->vfc_typenum;
bcopy(&mp->mnt_stat.f_fsid, &sbp->f_fsid, sizeof(sbp->f_fsid));
bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN);
bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN);
@@ -515,51 +489,21 @@ union_statfs(mp, sbp, p)
return (0);
}
-int
-union_sync(mp, waitfor, cred, p)
- struct mount *mp;
- int waitfor;
- struct ucred *cred;
- struct proc *p;
-{
-
- /*
- * XXX - Assumes no data cached at union layer.
- */
- return (0);
-}
-
-int
-union_vget(mp, ino, vpp)
- struct mount *mp;
- ino_t ino;
- struct vnode **vpp;
-{
-
- return (EOPNOTSUPP);
-}
-
-int
-union_fhtovp(mp, fidp, nam, vpp, exflagsp, credanonp)
- struct mount *mp;
- struct fid *fidp;
- struct mbuf *nam;
- struct vnode **vpp;
- int *exflagsp;
- struct ucred **credanonp;
-{
-
- return (EOPNOTSUPP);
-}
-
-int
-union_vptofh(vp, fhp)
- struct vnode *vp;
- struct fid *fhp;
-{
-
- return (EOPNOTSUPP);
-}
+/*
+ * XXX - Assumes no data cached at union layer.
+ */
+#define union_sync ((int (*) __P((struct mount *, int, struct ucred *, \
+ struct proc *)))nullop)
+
+#define union_fhtovp ((int (*) __P((struct mount *, struct fid *, \
+ struct mbuf *, struct vnode **, int *, struct ucred **)))eopnotsupp)
+#define union_quotactl ((int (*) __P((struct mount *, int, uid_t, caddr_t, \
+ struct proc *)))eopnotsupp)
+#define union_sysctl ((int (*) __P((int *, u_int, void *, size_t *, void *, \
+ size_t, struct proc *)))eopnotsupp)
+#define union_vget ((int (*) __P((struct mount *, ino_t, struct vnode **))) \
+ eopnotsupp)
+#define union_vptofh ((int (*) __P((struct vnode *, struct fid *)))eopnotsupp)
struct vfsops union_vfsops = {
union_mount,
diff --git a/sys/fs/unionfs/union_vnops.c b/sys/fs/unionfs/union_vnops.c
index 5940243..4a66dc0 100644
--- a/sys/fs/unionfs/union_vnops.c
+++ b/sys/fs/unionfs/union_vnops.c
@@ -1,7 +1,7 @@
/*
- * Copyright (c) 1992, 1993, 1994 The Regents of the University of California.
- * Copyright (c) 1992, 1993, 1994 Jan-Simon Pendry.
- * All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995 Jan-Simon Pendry.
+ * Copyright (c) 1992, 1993, 1994, 1995
+ * The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Jan-Simon Pendry.
@@ -34,7 +34,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)union_vnops.c 8.6 (Berkeley) 2/17/94
+ * @(#)union_vnops.c 8.32 (Berkeley) 6/23/95
* $FreeBSD$
*/
@@ -43,7 +43,7 @@
#include <sys/proc.h>
#include <sys/file.h>
#include <sys/time.h>
-#include <sys/kernel.h>
+#include <sys/stat.h>
#include <sys/types.h>
#include <sys/vnode.h>
#include <sys/mount.h>
@@ -51,16 +51,12 @@
#include <sys/malloc.h>
#include <sys/buf.h>
#include <sys/queue.h>
+#include <sys/lock.h>
#include <miscfs/union/union.h>
-/* FIXUP throws the lock on the uppervp vnode if the union_node is already
- * locked and the uppervp vnode is not. Before, this was thrown regardless
- * of the state of the union_node which resulted in locked vnodes which
- * were never unlocked (since the union would never be unlocked).
- */
-#define FIXUP(un) { \
- if (((un)->un_flags & (UN_LOCKED|UN_ULOCK)) == UN_LOCKED) { \
- union_fixup(un); \
+#define FIXUP(un, p) { \
+ if (((un)->un_flags & UN_ULOCK) == 0) { \
+ union_fixup(un, p); \
} \
}
@@ -70,7 +66,7 @@ extern int union_advlock __P((struct vop_advlock_args *ap));
extern int union_bmap __P((struct vop_bmap_args *ap));
extern int union_close __P((struct vop_close_args *ap));
extern int union_create __P((struct vop_create_args *ap));
-static void union_fixup __P((struct union_node *un));
+static void union_fixup __P((struct union_node *un, struct proc *p));
extern int union_fsync __P((struct vop_fsync_args *ap));
extern int union_getattr __P((struct vop_getattr_args *ap));
extern int union_inactive __P((struct vop_inactive_args *ap));
@@ -79,7 +75,7 @@ extern int union_islocked __P((struct vop_islocked_args *ap));
extern int union_link __P((struct vop_link_args *ap));
extern int union_lock __P((struct vop_lock_args *ap));
extern int union_lookup __P((struct vop_lookup_args *ap));
-static int union_lookup1 __P((struct vnode *udvp, struct vnode *dvp,
+static int union_lookup1 __P((struct vnode *udvp, struct vnode **dvpp,
struct vnode **vpp,
struct componentname *cnp));
extern int union_mkdir __P((struct vop_mkdir_args *ap));
@@ -100,29 +96,34 @@ extern int union_select __P((struct vop_select_args *ap));
extern int union_setattr __P((struct vop_setattr_args *ap));
extern int union_strategy __P((struct vop_strategy_args *ap));
extern int union_symlink __P((struct vop_symlink_args *ap));
-extern int union_unlock __P((struct vop_lock_args *ap));
+extern int union_unlock __P((struct vop_unlock_args *ap));
extern int union_write __P((struct vop_read_args *ap));
static void
-union_fixup(un)
+union_fixup(un, p)
struct union_node *un;
+ struct proc *p;
{
- VOP_LOCK(un->un_uppervp);
+ vn_lock(un->un_uppervp, LK_EXCLUSIVE | LK_RETRY, p);
un->un_flags |= UN_ULOCK;
}
static int
-union_lookup1(udvp, dvp, vpp, cnp)
+union_lookup1(udvp, dvpp, vpp, cnp)
struct vnode *udvp;
- struct vnode *dvp;
+ struct vnode **dvpp;
struct vnode **vpp;
struct componentname *cnp;
{
int error;
+ struct proc *p = cnp->cn_proc;
struct vnode *tdvp;
+ struct vnode *dvp;
struct mount *mp;
+ dvp = *dvpp;
+
/*
* If stepping up the directory tree, check for going
* back across the mount point, in which case do what
@@ -130,21 +131,18 @@ union_lookup1(udvp, dvp, vpp, cnp)
* hierarchy.
*/
if (cnp->cn_flags & ISDOTDOT) {
- for (;;) {
+ while ((dvp != udvp) && (dvp->v_flag & VROOT)) {
/*
* Don't do the NOCROSSMOUNT check
* at this level. By definition,
* union fs deals with namespaces, not
* filesystems.
*/
- if ((dvp->v_flag & VROOT) == 0)
- break;
-
tdvp = dvp;
- dvp = dvp->v_mount->mnt_vnodecovered;
+ *dvpp = dvp = dvp->v_mount->mnt_vnodecovered;
vput(tdvp);
VREF(dvp);
- VOP_LOCK(dvp);
+ vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY, p);
}
}
@@ -158,7 +156,7 @@ union_lookup1(udvp, dvp, vpp, cnp)
* here to allow it to be unlocked again (phew) in union_lookup.
*/
if (dvp != tdvp && !(cnp->cn_flags & ISLASTCN))
- VOP_LOCK(dvp);
+ vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY, p);
dvp = tdvp;
@@ -170,13 +168,11 @@ union_lookup1(udvp, dvp, vpp, cnp)
while (dvp != udvp && (dvp->v_type == VDIR) &&
(mp = dvp->v_mountedhere)) {
- if (mp->mnt_flag & MNT_MLOCK) {
- mp->mnt_flag |= MNT_MWAIT;
- (void) tsleep((caddr_t) mp, PVFS, "unlkup", 0);
+ if (vfs_busy(mp, 0, 0, p))
continue;
- }
error = VFS_ROOT(mp, &tdvp);
+ vfs_unbusy(mp, p);
if (error) {
vput(dvp);
return (error);
@@ -206,9 +202,28 @@ union_lookup(ap)
struct vnode *dvp = ap->a_dvp;
struct union_node *dun = VTOUNION(dvp);
struct componentname *cnp = ap->a_cnp;
+ struct proc *p = cnp->cn_proc;
int lockparent = cnp->cn_flags & LOCKPARENT;
struct union_mount *um = MOUNTTOUNIONMOUNT(dvp->v_mount);
- struct ucred *saved_cred = 0;
+ struct ucred *saved_cred;
+ int iswhiteout;
+ struct vattr va;
+
+#ifdef notyet
+ if (cnp->cn_namelen == 3 &&
+ cnp->cn_nameptr[2] == '.' &&
+ cnp->cn_nameptr[1] == '.' &&
+ cnp->cn_nameptr[0] == '.') {
+ dvp = *ap->a_vpp = LOWERVP(ap->a_dvp);
+ if (dvp == NULLVP)
+ return (ENOENT);
+ VREF(dvp);
+ vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY, p);
+ if (!lockparent || !(cnp->cn_flags & ISLASTCN))
+ VOP_UNLOCK(ap->a_dvp, 0, p);
+ return (0);
+ }
+#endif
cnp->cn_flags |= LOCKPARENT;
@@ -216,6 +231,7 @@ union_lookup(ap)
lowerdvp = dun->un_lowervp;
uppervp = NULLVP;
lowervp = NULLVP;
+ iswhiteout = 0;
/*
* do the lookup in the upper level.
@@ -223,9 +239,9 @@ union_lookup(ap)
* then assume that something special is going
* on and just return that vnode.
*/
- if (upperdvp) {
- FIXUP(dun);
- uerror = union_lookup1(um->um_uppervp, upperdvp,
+ if (upperdvp != NULLVP) {
+ FIXUP(dun, p);
+ uerror = union_lookup1(um->um_uppervp, &upperdvp,
&uppervp, cnp);
/*if (uppervp == upperdvp)
dun->un_flags |= UN_KLOCK;*/
@@ -236,6 +252,16 @@ union_lookup(ap)
cnp->cn_flags &= ~LOCKPARENT;
return (uerror);
}
+ if (uerror == ENOENT || uerror == EJUSTRETURN) {
+ if (cnp->cn_flags & ISWHITEOUT) {
+ iswhiteout = 1;
+ } else if (lowerdvp != NULLVP) {
+ lerror = VOP_GETATTR(upperdvp, &va,
+ cnp->cn_cred, cnp->cn_proc);
+ if (lerror == 0 && (va.va_flags & OPAQUE))
+ iswhiteout = 1;
+ }
+ }
} else {
uerror = ENOENT;
}
@@ -247,10 +273,10 @@ union_lookup(ap)
* back from the upper layer and return the lower vnode
* instead.
*/
- if (lowerdvp) {
+ if (lowerdvp != NULLVP && !iswhiteout) {
int nameiop;
- VOP_LOCK(lowerdvp);
+ vn_lock(lowerdvp, LK_EXCLUSIVE | LK_RETRY, p);
/*
* Only do a LOOKUP on the bottom node, since
@@ -262,17 +288,17 @@ union_lookup(ap)
saved_cred = cnp->cn_cred;
cnp->cn_cred = um->um_cred;
}
- lerror = union_lookup1(um->um_lowervp, lowerdvp,
+ lerror = union_lookup1(um->um_lowervp, &lowerdvp,
&lowervp, cnp);
if (um->um_op == UNMNT_BELOW)
cnp->cn_cred = saved_cred;
cnp->cn_nameiop = nameiop;
if (lowervp != lowerdvp)
- VOP_UNLOCK(lowerdvp);
+ VOP_UNLOCK(lowerdvp, 0, p);
if (cnp->cn_consume != 0) {
- if (uppervp) {
+ if (uppervp != NULLVP) {
if (uppervp == upperdvp)
vrele(uppervp);
else
@@ -286,6 +312,14 @@ union_lookup(ap)
}
} else {
lerror = ENOENT;
+ if ((cnp->cn_flags & ISDOTDOT) && dun->un_pvp != NULLVP) {
+ lowervp = LOWERVP(dun->un_pvp);
+ if (lowervp != NULLVP) {
+ VREF(lowervp);
+ vn_lock(lowervp, LK_EXCLUSIVE | LK_RETRY, p);
+ lerror = 0;
+ }
+ }
}
if (!lockparent)
@@ -326,13 +360,13 @@ union_lookup(ap)
if (uerror != 0 /* && (lerror == 0) */ ) {
if (lowervp->v_type == VDIR) { /* case 2b. */
dun->un_flags &= ~UN_ULOCK;
- VOP_UNLOCK(upperdvp);
+ VOP_UNLOCK(upperdvp, 0, p);
uerror = union_mkshadow(um, upperdvp, cnp, &uppervp);
- VOP_LOCK(upperdvp);
+ vn_lock(upperdvp, LK_EXCLUSIVE | LK_RETRY, p);
dun->un_flags |= UN_ULOCK;
if (uerror) {
- if (lowervp) {
+ if (lowervp != NULLVP) {
vput(lowervp);
lowervp = NULLVP;
}
@@ -341,21 +375,21 @@ union_lookup(ap)
}
}
- if (lowervp)
- VOP_UNLOCK(lowervp);
+ if (lowervp != NULLVP)
+ VOP_UNLOCK(lowervp, 0, p);
error = union_allocvp(ap->a_vpp, dvp->v_mount, dvp, upperdvp, cnp,
- uppervp, lowervp);
+ uppervp, lowervp, 1);
if (error) {
- if (uppervp)
+ if (uppervp != NULLVP)
vput(uppervp);
- if (lowervp)
+ if (lowervp != NULLVP)
vrele(lowervp);
} else {
if (*ap->a_vpp != dvp)
if (!lockparent || !(cnp->cn_flags & ISLASTCN))
- VOP_UNLOCK(dvp);
+ VOP_UNLOCK(dvp, 0, p);
}
return (error);
@@ -372,28 +406,26 @@ union_create(ap)
{
struct union_node *un = VTOUNION(ap->a_dvp);
struct vnode *dvp = un->un_uppervp;
+ struct componentname *cnp = ap->a_cnp;
+ struct proc *p = cnp->cn_proc;
- if (dvp) {
+ if (dvp != NULLVP) {
int error;
struct vnode *vp;
+ struct mount *mp;
- FIXUP(un);
+ FIXUP(un, p);
VREF(dvp);
un->un_flags |= UN_KLOCK;
+ mp = ap->a_dvp->v_mount;
vput(ap->a_dvp);
- error = VOP_CREATE(dvp, &vp, ap->a_cnp, ap->a_vap);
+ error = VOP_CREATE(dvp, &vp, cnp, ap->a_vap);
if (error)
return (error);
- error = union_allocvp(
- ap->a_vpp,
- ap->a_dvp->v_mount,
- ap->a_dvp,
- NULLVP,
- ap->a_cnp,
- vp,
- NULLVP);
+ error = union_allocvp(ap->a_vpp, mp, NULLVP, NULLVP, cnp, vp,
+ NULLVP, 1);
if (error)
vput(vp);
return (error);
@@ -404,6 +436,25 @@ union_create(ap)
}
int
+union_whiteout(ap)
+ struct vop_whiteout_args /* {
+ struct vnode *a_dvp;
+ struct componentname *a_cnp;
+ int a_flags;
+ } */ *ap;
+{
+ struct union_node *un = VTOUNION(ap->a_dvp);
+ struct componentname *cnp = ap->a_cnp;
+ struct proc *p = cnp->cn_proc;
+
+ if (un->un_uppervp == NULLVP)
+ return (EOPNOTSUPP);
+
+ FIXUP(un, p);
+ return (VOP_WHITEOUT(un->un_uppervp, cnp, ap->a_flags));
+}
+
+int
union_mknod(ap)
struct vop_mknod_args /* {
struct vnode *a_dvp;
@@ -414,29 +465,27 @@ union_mknod(ap)
{
struct union_node *un = VTOUNION(ap->a_dvp);
struct vnode *dvp = un->un_uppervp;
+ struct componentname *cnp = ap->a_cnp;
+ struct proc *p = cnp->cn_proc;
- if (dvp) {
+ if (dvp != NULLVP) {
int error;
struct vnode *vp;
+ struct mount *mp;
- FIXUP(un);
+ FIXUP(un, p);
VREF(dvp);
un->un_flags |= UN_KLOCK;
+ mp = ap->a_dvp->v_mount;
vput(ap->a_dvp);
- error = VOP_MKNOD(dvp, &vp, ap->a_cnp, ap->a_vap);
+ error = VOP_MKNOD(dvp, &vp, cnp, ap->a_vap);
if (error)
return (error);
- if (vp) {
- error = union_allocvp(
- ap->a_vpp,
- ap->a_dvp->v_mount,
- ap->a_dvp,
- NULLVP,
- ap->a_cnp,
- vp,
- NULLVP);
+ if (vp != NULLVP) {
+ error = union_allocvp(ap->a_vpp, mp, NULLVP, NULLVP,
+ cnp, vp, NULLVP, 1);
if (error)
vput(vp);
}
@@ -476,77 +525,7 @@ union_open(ap)
*/
tvp = un->un_lowervp;
if ((ap->a_mode & FWRITE) && (tvp->v_type == VREG)) {
- struct vnode *vp;
- int i;
-
- /*
- * Open the named file in the upper layer. Note that
- * the file may have come into existence *since* the
- * lookup was done, since the upper layer may really
- * be a loopback mount of some other filesystem...
- * so open the file with exclusive create and barf if
- * it already exists.
- * XXX - perhaps should re-lookup the node (once more
- * with feeling) and simply open that. Who knows.
- */
- error = union_vn_create(&vp, un, p);
- if (error)
- return (error);
-
- /* at this point, uppervp is locked */
- union_newupper(un, vp);
- un->un_flags |= UN_ULOCK;
-
- /*
- * Now, if the file is being opened with truncation,
- * then the (new) upper vnode is ready to fly,
- * otherwise the data from the lower vnode must be
- * copied to the upper layer first. This only works
- * for regular files (check is made above).
- */
- if ((mode & O_TRUNC) == 0) {
- /*
- * XXX - should not ignore errors
- * from VOP_CLOSE
- */
- VOP_LOCK(tvp);
- error = VOP_OPEN(tvp, FREAD, cred, p);
- if (error == 0) {
- error = union_copyfile(p, cred,
- tvp, un->un_uppervp);
- VOP_UNLOCK(tvp);
- (void) VOP_CLOSE(tvp, FREAD, cred, p);
- } else {
- VOP_UNLOCK(tvp);
- }
-
-#ifdef UNION_DIAGNOSTIC
- if (!error)
- uprintf("union: copied up %s\n",
- un->un_path);
-#endif
- }
-
- un->un_flags &= ~UN_ULOCK;
- VOP_UNLOCK(un->un_uppervp);
- union_vn_close(un->un_uppervp, FWRITE, cred, p);
- VOP_LOCK(un->un_uppervp);
- un->un_flags |= UN_ULOCK;
-
- /*
- * Subsequent IOs will go to the top layer, so
- * call close on the lower vnode and open on the
- * upper vnode to ensure that the filesystem keeps
- * its references counts right. This doesn't do
- * the right thing with (cred) and (FREAD) though.
- * Ignoring error returns is not righ, either.
- */
- for (i = 0; i < un->un_openl; i++) {
- (void) VOP_CLOSE(tvp, FREAD, cred, p);
- (void) VOP_OPEN(un->un_uppervp, FREAD, cred, p);
- }
- un->un_openl = 0;
-
+ error = union_copyup(un, (mode&O_TRUNC) == 0, cred, p);
if (error == 0)
error = VOP_OPEN(un->un_uppervp, mode, cred, p);
return (error);
@@ -556,14 +535,14 @@ union_open(ap)
* Just open the lower vnode
*/
un->un_openl++;
- VOP_LOCK(tvp);
+ vn_lock(tvp, LK_EXCLUSIVE | LK_RETRY, p);
error = VOP_OPEN(tvp, mode, cred, p);
- VOP_UNLOCK(tvp);
+ VOP_UNLOCK(tvp, 0, p);
return (error);
}
- FIXUP(un);
+ FIXUP(un, p);
error = VOP_OPEN(tvp, mode, cred, p);
@@ -582,9 +561,7 @@ union_close(ap)
struct union_node *un = VTOUNION(ap->a_vp);
struct vnode *vp;
- if (un->un_uppervp) {
- vp = un->un_uppervp;
- } else {
+ if ((vp = un->un_uppervp) == NULLVP) {
#ifdef UNION_DIAGNOSTIC
if (un->un_openl <= 0)
panic("union: un_openl cnt");
@@ -593,7 +570,8 @@ union_close(ap)
vp = un->un_lowervp;
}
- return (VOP_CLOSE(vp, ap->a_fflag, ap->a_cred, ap->a_p));
+ ap->a_vp = vp;
+ return (VCALL(vp, VOFFSET(vop_close), ap));
}
/*
@@ -615,27 +593,29 @@ union_access(ap)
} */ *ap;
{
struct union_node *un = VTOUNION(ap->a_vp);
+ struct proc *p = ap->a_p;
int error = EACCES;
struct vnode *vp;
- vp = un->un_uppervp;
- if (vp) {
- FIXUP(un);
- return (VOP_ACCESS(vp, ap->a_mode, ap->a_cred, ap->a_p));
+ if ((vp = un->un_uppervp) != NULLVP) {
+ FIXUP(un, p);
+ ap->a_vp = vp;
+ return (VCALL(vp, VOFFSET(vop_access), ap));
}
- vp = un->un_lowervp;
- if (vp) {
- VOP_LOCK(vp);
- error = VOP_ACCESS(vp, ap->a_mode, ap->a_cred, ap->a_p);
+ if ((vp = un->un_lowervp) != NULLVP) {
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
+ ap->a_vp = vp;
+ error = VCALL(vp, VOFFSET(vop_access), ap);
if (error == 0) {
struct union_mount *um = MOUNTTOUNIONMOUNT(vp->v_mount);
- if (um->um_op == UNMNT_BELOW)
- error = VOP_ACCESS(vp, ap->a_mode,
- um->um_cred, ap->a_p);
+ if (um->um_op == UNMNT_BELOW) {
+ ap->a_cred = um->um_cred;
+ error = VCALL(vp, VOFFSET(vop_access), ap);
+ }
}
- VOP_UNLOCK(vp);
+ VOP_UNLOCK(vp, 0, p);
if (error)
return (error);
}
@@ -644,7 +624,8 @@ union_access(ap)
}
/*
- * We handle getattr only to change the fsid.
+ * We handle getattr only to change the fsid and
+ * track object sizes
*/
int
union_getattr(ap)
@@ -658,6 +639,7 @@ union_getattr(ap)
int error;
struct union_node *un = VTOUNION(ap->a_vp);
struct vnode *vp = un->un_uppervp;
+ struct proc *p = ap->a_p;
struct vattr *vap;
struct vattr va;
@@ -675,10 +657,21 @@ union_getattr(ap)
vp = un->un_uppervp;
if (vp != NULLVP) {
- FIXUP(un);
+ /*
+ * It's not clear whether VOP_GETATTR is to be
+ * called with the vnode locked or not. stat() calls
+ * it with (vp) locked, and fstat calls it with
+ * (vp) unlocked.
+ * In the mean time, compensate here by checking
+ * the union_node's lock flag.
+ */
+ if (un->un_flags & UN_LOCKED)
+ FIXUP(un, p);
+
error = VOP_GETATTR(vp, vap, ap->a_cred, ap->a_p);
if (error)
return (error);
+ union_newsize(ap->a_vp, vap->va_size, VNOVAL);
}
if (vp == NULLVP) {
@@ -691,17 +684,16 @@ union_getattr(ap)
}
if (vp != NULLVP) {
- VOP_LOCK(vp);
error = VOP_GETATTR(vp, vap, ap->a_cred, ap->a_p);
- VOP_UNLOCK(vp);
if (error)
return (error);
+ union_newsize(ap->a_vp, VNOVAL, vap->va_size);
}
if ((vap != ap->a_vap) && (vap->va_type == VDIR))
ap->a_vap->va_nlink += vap->va_nlink;
- vap->va_fsid = ap->a_vp->v_mount->mnt_stat.f_fsid.val[0];
+ ap->a_vap->va_fsid = ap->a_vp->v_mount->mnt_stat.f_fsid.val[0];
return (0);
}
@@ -715,6 +707,7 @@ union_setattr(ap)
} */ *ap;
{
struct union_node *un = VTOUNION(ap->a_vp);
+ struct proc *p = ap->a_p;
int error;
/*
@@ -724,21 +717,11 @@ union_setattr(ap)
*/
if ((un->un_uppervp == NULLVP) &&
/* assert(un->un_lowervp != NULLVP) */
- (un->un_lowervp->v_type == VREG) &&
- (ap->a_vap->va_size == 0)) {
- struct vnode *vp;
-
- error = union_vn_create(&vp, un, ap->a_p);
+ (un->un_lowervp->v_type == VREG)) {
+ error = union_copyup(un, (ap->a_vap->va_size != 0),
+ ap->a_cred, ap->a_p);
if (error)
return (error);
-
- /* at this point, uppervp is locked */
- union_newupper(un, vp);
-
- VOP_UNLOCK(vp);
- union_vn_close(un->un_uppervp, FWRITE, ap->a_cred, ap->a_p);
- VOP_LOCK(vp);
- un->un_flags |= UN_ULOCK;
}
/*
@@ -746,9 +729,11 @@ union_setattr(ap)
* otherwise return read-only filesystem error.
*/
if (un->un_uppervp != NULLVP) {
- FIXUP(un);
+ FIXUP(un, p);
error = VOP_SETATTR(un->un_uppervp, ap->a_vap,
ap->a_cred, ap->a_p);
+ if ((error == 0) && (ap->a_vap->va_size != VNOVAL))
+ union_newsize(ap->a_vp, ap->a_vap->va_size, VNOVAL);
} else {
error = EROFS;
}
@@ -766,16 +751,36 @@ union_read(ap)
} */ *ap;
{
int error;
+ struct proc *p = ap->a_uio->uio_procp;
struct vnode *vp = OTHERVP(ap->a_vp);
int dolock = (vp == LOWERVP(ap->a_vp));
if (dolock)
- VOP_LOCK(vp);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
else
- FIXUP(VTOUNION(ap->a_vp));
+ FIXUP(VTOUNION(ap->a_vp), p);
error = VOP_READ(vp, ap->a_uio, ap->a_ioflag, ap->a_cred);
if (dolock)
- VOP_UNLOCK(vp);
+ VOP_UNLOCK(vp, 0, p);
+
+ /*
+ * XXX
+ * perhaps the size of the underlying object has changed under
+ * our feet. take advantage of the offset information present
+ * in the uio structure.
+ */
+ if (error == 0) {
+ struct union_node *un = VTOUNION(ap->a_vp);
+ off_t cur = ap->a_uio->uio_offset;
+
+ if (vp == un->un_uppervp) {
+ if (cur > un->un_uppersz)
+ union_newsize(ap->a_vp, cur, VNOVAL);
+ } else {
+ if (cur > un->un_lowersz)
+ union_newsize(ap->a_vp, VNOVAL, cur);
+ }
+ }
return (error);
}
@@ -790,21 +795,47 @@ union_write(ap)
} */ *ap;
{
int error;
- struct vnode *vp = OTHERVP(ap->a_vp);
- int dolock = (vp == LOWERVP(ap->a_vp));
+ struct vnode *vp;
+ struct union_node *un = VTOUNION(ap->a_vp);
+ struct proc *p = ap->a_uio->uio_procp;
- if (dolock)
- VOP_LOCK(vp);
- else
- FIXUP(VTOUNION(ap->a_vp));
+ vp = UPPERVP(ap->a_vp);
+ if (vp == NULLVP)
+ panic("union: missing upper layer in write");
+
+ FIXUP(un, p);
error = VOP_WRITE(vp, ap->a_uio, ap->a_ioflag, ap->a_cred);
- if (dolock)
- VOP_UNLOCK(vp);
+
+ /*
+ * the size of the underlying object may be changed by the
+ * write.
+ */
+ if (error == 0) {
+ off_t cur = ap->a_uio->uio_offset;
+
+ if (cur > un->un_uppersz)
+ union_newsize(ap->a_vp, cur, VNOVAL);
+ }
return (error);
}
int
+union_lease(ap)
+ struct vop_lease_args /* {
+ struct vnode *a_vp;
+ struct proc *a_p;
+ struct ucred *a_cred;
+ int a_flag;
+ } */ *ap;
+{
+ register struct vnode *ovp = OTHERVP(ap->a_vp);
+
+ ap->a_vp = ovp;
+ return (VCALL(ovp, VOFFSET(vop_lease), ap));
+}
+
+int
union_ioctl(ap)
struct vop_ioctl_args /* {
struct vnode *a_vp;
@@ -815,9 +846,10 @@ union_ioctl(ap)
struct proc *a_p;
} */ *ap;
{
+ register struct vnode *ovp = OTHERVP(ap->a_vp);
- return (VOP_IOCTL(OTHERVP(ap->a_vp), ap->a_command, ap->a_data,
- ap->a_fflag, ap->a_cred, ap->a_p));
+ ap->a_vp = ovp;
+ return (VCALL(ovp, VOFFSET(vop_ioctl), ap));
}
int
@@ -830,9 +862,28 @@ union_select(ap)
struct proc *a_p;
} */ *ap;
{
+ register struct vnode *ovp = OTHERVP(ap->a_vp);
- return (VOP_SELECT(OTHERVP(ap->a_vp), ap->a_which, ap->a_fflags,
- ap->a_cred, ap->a_p));
+ ap->a_vp = ovp;
+ return (VCALL(ovp, VOFFSET(vop_select), ap));
+}
+
+int
+union_revoke(ap)
+ struct vop_revoke_args /* {
+ struct vnode *a_vp;
+ int a_flags;
+ struct proc *a_p;
+ } */ *ap;
+{
+ struct vnode *vp = ap->a_vp;
+
+ if (UPPERVP(vp))
+ VOP_REVOKE(UPPERVP(vp), ap->a_flags);
+ if (LOWERVP(vp))
+ VOP_REVOKE(LOWERVP(vp), ap->a_flags);
+ vgone(vp);
+ return (0);
}
int
@@ -844,9 +895,10 @@ union_mmap(ap)
struct proc *a_p;
} */ *ap;
{
+ register struct vnode *ovp = OTHERVP(ap->a_vp);
- return (VOP_MMAP(OTHERVP(ap->a_vp), ap->a_fflags,
- ap->a_cred, ap->a_p));
+ ap->a_vp = ovp;
+ return (VCALL(ovp, VOFFSET(vop_mmap), ap));
}
int
@@ -859,19 +911,19 @@ union_fsync(ap)
} */ *ap;
{
int error = 0;
+ struct proc *p = ap->a_p;
struct vnode *targetvp = OTHERVP(ap->a_vp);
- if (targetvp) {
+ if (targetvp != NULLVP) {
int dolock = (targetvp == LOWERVP(ap->a_vp));
if (dolock)
- VOP_LOCK(targetvp);
+ vn_lock(targetvp, LK_EXCLUSIVE | LK_RETRY, p);
else
- FIXUP(VTOUNION(ap->a_vp));
- error = VOP_FSYNC(targetvp, ap->a_cred,
- ap->a_waitfor, ap->a_p);
+ FIXUP(VTOUNION(ap->a_vp), p);
+ error = VOP_FSYNC(targetvp, ap->a_cred, ap->a_waitfor, p);
if (dolock)
- VOP_UNLOCK(targetvp);
+ VOP_UNLOCK(targetvp, 0, p);
}
return (error);
@@ -886,8 +938,10 @@ union_seek(ap)
struct ucred *a_cred;
} */ *ap;
{
+ register struct vnode *ovp = OTHERVP(ap->a_vp);
- return (VOP_SEEK(OTHERVP(ap->a_vp), ap->a_oldoff, ap->a_newoff, ap->a_cred));
+ ap->a_vp = ovp;
+ return (VCALL(ovp, VOFFSET(vop_seek), ap));
}
int
@@ -901,34 +955,37 @@ union_remove(ap)
int error;
struct union_node *dun = VTOUNION(ap->a_dvp);
struct union_node *un = VTOUNION(ap->a_vp);
+ struct componentname *cnp = ap->a_cnp;
+ struct proc *p = cnp->cn_proc;
- if (dun->un_uppervp && un->un_uppervp) {
+ if (dun->un_uppervp == NULLVP)
+ panic("union remove: null upper vnode");
+
+ if (un->un_uppervp != NULLVP) {
struct vnode *dvp = dun->un_uppervp;
struct vnode *vp = un->un_uppervp;
- FIXUP(dun);
+ FIXUP(dun, p);
VREF(dvp);
dun->un_flags |= UN_KLOCK;
vput(ap->a_dvp);
- FIXUP(un);
+ FIXUP(un, p);
VREF(vp);
un->un_flags |= UN_KLOCK;
vput(ap->a_vp);
- error = VOP_REMOVE(dvp, vp, ap->a_cnp);
+ if (union_dowhiteout(un, cnp->cn_cred, cnp->cn_proc))
+ cnp->cn_flags |= DOWHITEOUT;
+ error = VOP_REMOVE(dvp, vp, cnp);
if (!error)
union_removed_upper(un);
-
- /*
- * XXX: should create a whiteout here
- */
} else {
- /*
- * XXX: should create a whiteout here
- */
+ FIXUP(dun, p);
+ error = union_mkwhiteout(
+ MOUNTTOUNIONMOUNT(UNIONTOV(dun)->v_mount),
+ dun->un_uppervp, ap->a_cnp, un->un_path);
vput(ap->a_dvp);
vput(ap->a_vp);
- error = EROFS;
}
return (error);
@@ -942,34 +999,51 @@ union_link(ap)
struct componentname *a_cnp;
} */ *ap;
{
- int error;
- struct union_node *dun = VTOUNION(ap->a_vp);
- struct union_node *un = VTOUNION(ap->a_tdvp);
-
- if (dun->un_uppervp && un->un_uppervp) {
- struct vnode *dvp = dun->un_uppervp;
- struct vnode *vp = un->un_uppervp;
+ int error = 0;
+ struct componentname *cnp = ap->a_cnp;
+ struct proc *p = cnp->cn_proc;
+ struct union_node *un;
+ struct vnode *vp;
+ struct vnode *tdvp;
- FIXUP(dun);
- VREF(dvp);
- dun->un_flags |= UN_KLOCK;
- vput(ap->a_vp);
- FIXUP(un);
- VREF(vp);
- vrele(ap->a_tdvp);
+ un = VTOUNION(ap->a_tdvp);
- error = VOP_LINK(dvp, vp, ap->a_cnp);
+ if (ap->a_tdvp->v_op != ap->a_vp->v_op) {
+ vp = ap->a_vp;
} else {
- /*
- * XXX: need to copy to upper layer
- * and do the link there.
- */
- vput(ap->a_vp);
- vrele(ap->a_tdvp);
+ struct union_node *tun = VTOUNION(ap->a_vp);
+ if (tun->un_uppervp == NULLVP) {
+ vn_lock(ap->a_vp, LK_EXCLUSIVE | LK_RETRY, p);
+ if (un->un_uppervp == tun->un_dirvp) {
+ un->un_flags &= ~UN_ULOCK;
+ VOP_UNLOCK(un->un_uppervp, 0, p);
+ }
+ error = union_copyup(tun, 1, cnp->cn_cred, p);
+ if (un->un_uppervp == tun->un_dirvp) {
+ vn_lock(un->un_uppervp,
+ LK_EXCLUSIVE | LK_RETRY, p);
+ un->un_flags |= UN_ULOCK;
+ }
+ VOP_UNLOCK(ap->a_vp, 0, p);
+ }
+ vp = tun->un_uppervp;
+ }
+
+ tdvp = un->un_uppervp;
+ if (tdvp == NULLVP)
error = EROFS;
+
+ if (error) {
+ vput(ap->a_tdvp);
+ return (error);
}
- return (error);
+ FIXUP(un, p);
+ VREF(tdvp);
+ un->un_flags |= UN_KLOCK;
+ vput(ap->a_tdvp);
+
+ return (VOP_LINK(vp, tdvp, cnp));
}
int
@@ -993,11 +1067,16 @@ union_rename(ap)
if (fdvp->v_op == union_vnodeop_p) { /* always true */
struct union_node *un = VTOUNION(fdvp);
if (un->un_uppervp == NULLVP) {
- error = EROFS;
+ /*
+ * this should never happen in normal
+ * operation but might if there was
+ * a problem creating the top-level shadow
+ * directory.
+ */
+ error = EXDEV;
goto bad;
}
- FIXUP(un);
fdvp = un->un_uppervp;
VREF(fdvp);
vrele(ap->a_fdvp);
@@ -1006,11 +1085,14 @@ union_rename(ap)
if (fvp->v_op == union_vnodeop_p) { /* always true */
struct union_node *un = VTOUNION(fvp);
if (un->un_uppervp == NULLVP) {
- error = EROFS;
+ /* XXX: should do a copyup */
+ error = EXDEV;
goto bad;
}
- FIXUP(un);
+ if (un->un_lowervp != NULLVP)
+ ap->a_fcnp->cn_flags |= DOWHITEOUT;
+
fvp = un->un_uppervp;
VREF(fvp);
vrele(ap->a_fvp);
@@ -1019,7 +1101,13 @@ union_rename(ap)
if (tdvp->v_op == union_vnodeop_p) {
struct union_node *un = VTOUNION(tdvp);
if (un->un_uppervp == NULLVP) {
- error = EROFS;
+ /*
+ * this should never happen in normal
+ * operation but might if there was
+ * a problem creating the top-level shadow
+ * directory.
+ */
+ error = EXDEV;
goto bad;
}
@@ -1029,16 +1117,14 @@ union_rename(ap)
vput(ap->a_tdvp);
}
- if (tvp && tvp->v_op == union_vnodeop_p) {
+ if (tvp != NULLVP && tvp->v_op == union_vnodeop_p) {
struct union_node *un = VTOUNION(tvp);
- if (un->un_uppervp == NULLVP) {
- error = EROFS;
- goto bad;
- }
tvp = un->un_uppervp;
- VREF(tvp);
- un->un_flags |= UN_KLOCK;
+ if (tvp != NULLVP) {
+ VREF(tvp);
+ un->un_flags |= UN_KLOCK;
+ }
vput(ap->a_tvp);
}
@@ -1048,7 +1134,7 @@ bad:
vrele(fdvp);
vrele(fvp);
vput(tdvp);
- if (tvp)
+ if (tvp != NULLVP)
vput(tvp);
return (error);
@@ -1065,27 +1151,26 @@ union_mkdir(ap)
{
struct union_node *un = VTOUNION(ap->a_dvp);
struct vnode *dvp = un->un_uppervp;
+ struct componentname *cnp = ap->a_cnp;
+ struct proc *p = cnp->cn_proc;
- if (dvp) {
+ if (dvp != NULLVP) {
int error;
struct vnode *vp;
- FIXUP(un);
+ FIXUP(un, p);
VREF(dvp);
un->un_flags |= UN_KLOCK;
- vput(ap->a_dvp);
- error = VOP_MKDIR(dvp, &vp, ap->a_cnp, ap->a_vap);
- if (error)
+ VOP_UNLOCK(ap->a_dvp, 0, p);
+ error = VOP_MKDIR(dvp, &vp, cnp, ap->a_vap);
+ if (error) {
+ vrele(ap->a_dvp);
return (error);
+ }
- error = union_allocvp(
- ap->a_vpp,
- ap->a_dvp->v_mount,
- ap->a_dvp,
- NULLVP,
- ap->a_cnp,
- vp,
- NULLVP);
+ error = union_allocvp(ap->a_vpp, ap->a_dvp->v_mount, ap->a_dvp,
+ NULLVP, cnp, vp, NULLVP, 1);
+ vrele(ap->a_dvp);
if (error)
vput(vp);
return (error);
@@ -1106,34 +1191,37 @@ union_rmdir(ap)
int error;
struct union_node *dun = VTOUNION(ap->a_dvp);
struct union_node *un = VTOUNION(ap->a_vp);
+ struct componentname *cnp = ap->a_cnp;
+ struct proc *p = cnp->cn_proc;
- if (dun->un_uppervp && un->un_uppervp) {
+ if (dun->un_uppervp == NULLVP)
+ panic("union rmdir: null upper vnode");
+
+ if (un->un_uppervp != NULLVP) {
struct vnode *dvp = dun->un_uppervp;
struct vnode *vp = un->un_uppervp;
- FIXUP(dun);
+ FIXUP(dun, p);
VREF(dvp);
dun->un_flags |= UN_KLOCK;
vput(ap->a_dvp);
- FIXUP(un);
+ FIXUP(un, p);
VREF(vp);
un->un_flags |= UN_KLOCK;
vput(ap->a_vp);
+ if (union_dowhiteout(un, cnp->cn_cred, cnp->cn_proc))
+ cnp->cn_flags |= DOWHITEOUT;
error = VOP_RMDIR(dvp, vp, ap->a_cnp);
if (!error)
union_removed_upper(un);
-
- /*
- * XXX: should create a whiteout here
- */
} else {
- /*
- * XXX: should create a whiteout here
- */
+ FIXUP(dun, p);
+ error = union_mkwhiteout(
+ MOUNTTOUNIONMOUNT(UNIONTOV(dun)->v_mount),
+ dun->un_uppervp, ap->a_cnp, un->un_path);
vput(ap->a_dvp);
vput(ap->a_vp);
- error = EROFS;
}
return (error);
@@ -1151,17 +1239,18 @@ union_symlink(ap)
{
struct union_node *un = VTOUNION(ap->a_dvp);
struct vnode *dvp = un->un_uppervp;
+ struct componentname *cnp = ap->a_cnp;
+ struct proc *p = cnp->cn_proc;
- if (dvp) {
+ if (dvp != NULLVP) {
int error;
struct vnode *vp;
- FIXUP(un);
+ FIXUP(un, p);
VREF(dvp);
un->un_flags |= UN_KLOCK;
vput(ap->a_dvp);
- error = VOP_SYMLINK(dvp, &vp, ap->a_cnp,
- ap->a_vap, ap->a_target);
+ error = VOP_SYMLINK(dvp, &vp, cnp, ap->a_vap, ap->a_target);
*ap->a_vpp = NULLVP;
return (error);
}
@@ -1183,17 +1272,21 @@ union_readdir(ap)
struct vnode *a_vp;
struct uio *a_uio;
struct ucred *a_cred;
+ int *a_eofflag;
+ u_long *a_cookies;
+ int a_ncookies;
} */ *ap;
{
- int error = 0;
struct union_node *un = VTOUNION(ap->a_vp);
+ struct vnode *uvp = un->un_uppervp;
+ struct proc *p = ap->a_uio->uio_procp;
- if (un->un_uppervp) {
- FIXUP(un);
- error = VOP_READDIR(un->un_uppervp, ap->a_uio, ap->a_cred, NULL, NULL, NULL);
- }
+ if (uvp == NULLVP)
+ return (0);
- return (error);
+ FIXUP(un, p);
+ ap->a_vp = uvp;
+ return (VCALL(uvp, VOFFSET(vop_readdir), ap));
}
int
@@ -1205,16 +1298,19 @@ union_readlink(ap)
} */ *ap;
{
int error;
+ struct uio *uio = ap->a_uio;
+ struct proc *p = uio->uio_procp;
struct vnode *vp = OTHERVP(ap->a_vp);
int dolock = (vp == LOWERVP(ap->a_vp));
if (dolock)
- VOP_LOCK(vp);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
else
- FIXUP(VTOUNION(ap->a_vp));
- error = VOP_READLINK(vp, ap->a_uio, ap->a_cred);
+ FIXUP(VTOUNION(ap->a_vp), p);
+ ap->a_vp = vp;
+ error = VCALL(vp, VOFFSET(vop_readlink), ap);
if (dolock)
- VOP_UNLOCK(vp);
+ VOP_UNLOCK(vp, 0, p);
return (error);
}
@@ -1227,6 +1323,8 @@ union_abortop(ap)
} */ *ap;
{
int error;
+ struct componentname *cnp = ap->a_cnp;
+ struct proc *p = cnp->cn_proc;
struct vnode *vp = OTHERVP(ap->a_dvp);
struct union_node *un = VTOUNION(ap->a_dvp);
int islocked = un->un_flags & UN_LOCKED;
@@ -1234,13 +1332,14 @@ union_abortop(ap)
if (islocked) {
if (dolock)
- VOP_LOCK(vp);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
else
- FIXUP(VTOUNION(ap->a_dvp));
+ FIXUP(VTOUNION(ap->a_dvp), p);
}
- error = VOP_ABORTOP(vp, ap->a_cnp);
+ ap->a_dvp = vp;
+ error = VCALL(vp, VOFFSET(vop_abortop), ap);
if (islocked && dolock)
- VOP_UNLOCK(vp);
+ VOP_UNLOCK(vp, 0, p);
return (error);
}
@@ -1249,8 +1348,13 @@ int
union_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;
+ struct union_node *un = VTOUNION(vp);
+ struct vnode **vpp;
/*
* Do nothing (and _don't_ bypass).
@@ -1265,12 +1369,17 @@ union_inactive(ap)
* That's too much work for now.
*/
-#ifdef UNION_DIAGNOSTIC
- struct union_node *un = VTOUNION(ap->a_vp);
+ if (un->un_dircache != 0) {
+ for (vpp = un->un_dircache; *vpp != NULLVP; vpp++)
+ vrele(*vpp);
+ free(un->un_dircache, M_TEMP);
+ un->un_dircache = 0;
+ }
- if (un->un_flags & UN_LOCKED)
- panic("union: inactivating locked node");
-#endif
+ VOP_UNLOCK(vp, 0, p);
+
+ if ((un->un_flags & UN_CACHED) == 0)
+ vgone(vp);
return (0);
}
@@ -1292,24 +1401,39 @@ union_lock(ap)
struct vop_lock_args *ap;
{
struct vnode *vp = ap->a_vp;
+ struct proc *p = ap->a_p;
+ int flags = ap->a_flags;
struct union_node *un;
+ int error;
-start:
- while (vp->v_flag & VXLOCK) {
- vp->v_flag |= VXWANT;
- (void) tsleep((caddr_t)vp, PINOD, "unnlk1", 0);
- }
+ vop_nolock(ap);
+ /*
+ * Need to do real lockmgr-style locking here.
+ * in the mean time, draining won't work quite right,
+ * which could lead to a few race conditions.
+ * the following test was here, but is not quite right, we
+ * still need to take the lock:
+ if ((flags & LK_TYPE_MASK) == LK_DRAIN)
+ return (0);
+ */
+ flags &= ~LK_INTERLOCK;
+start:
un = VTOUNION(vp);
- if (un->un_uppervp) {
- if ((un->un_flags & UN_ULOCK) == 0) {
+ if (un->un_uppervp != NULLVP) {
+ if (((un->un_flags & UN_ULOCK) == 0) &&
+ (vp->v_usecount != 0)) {
+ error = vn_lock(un->un_uppervp, flags, p);
+ if (error)
+ return (error);
un->un_flags |= UN_ULOCK;
- VOP_LOCK(un->un_uppervp);
}
#ifdef DIAGNOSTIC
- if (un->un_flags & UN_KLOCK)
- panic("union: dangling upper lock");
+ if (un->un_flags & UN_KLOCK) {
+ vprint("union: dangling klock", vp);
+ panic("union: dangling upper lock (%lx)", vp);
+ }
#endif
}
@@ -1320,7 +1444,7 @@ start:
panic("union: locking against myself");
#endif
un->un_flags |= UN_WANT;
- (void) tsleep((caddr_t) &un->un_flags, PINOD, "unnlk2", 0);
+ tsleep((caddr_t)&un->un_flags, PINOD, "unionlk2", 0);
goto start;
}
@@ -1335,11 +1459,27 @@ start:
return (0);
}
+/*
+ * When operations want to vput() a union node yet retain a lock on
+ * the upper vnode (say, to do some further operations like link(),
+ * mkdir(), ...), they set UN_KLOCK on the union node, then call
+ * vput() which calls VOP_UNLOCK() and comes here. union_unlock()
+ * unlocks the union node (leaving the upper vnode alone), clears the
+ * KLOCK flag, and then returns to vput(). The caller then does whatever
+ * is left to do with the upper vnode, and ensures that it gets unlocked.
+ *
+ * If UN_KLOCK isn't set, then the upper vnode is unlocked here.
+ */
int
union_unlock(ap)
- struct vop_lock_args *ap;
+ struct vop_unlock_args /* {
+ struct vnode *a_vp;
+ int a_flags;
+ struct proc *a_p;
+ } */ *ap;
{
struct union_node *un = VTOUNION(ap->a_vp);
+ struct proc *p = ap->a_p;
#ifdef DIAGNOSTIC
if ((un->un_flags & UN_LOCKED) == 0)
@@ -1352,7 +1492,7 @@ union_unlock(ap)
un->un_flags &= ~UN_LOCKED;
if ((un->un_flags & (UN_ULOCK|UN_KLOCK)) == UN_ULOCK)
- VOP_UNLOCK(un->un_uppervp);
+ VOP_UNLOCK(un->un_uppervp, 0, p);
un->un_flags &= ~(UN_ULOCK|UN_KLOCK);
@@ -1364,6 +1504,7 @@ union_unlock(ap)
#ifdef DIAGNOSTIC
un->un_pid = 0;
#endif
+ vop_nounlock(ap);
return (0);
}
@@ -1380,16 +1521,18 @@ union_bmap(ap)
} */ *ap;
{
int error;
+ struct proc *p = curproc; /* XXX */
struct vnode *vp = OTHERVP(ap->a_vp);
int dolock = (vp == LOWERVP(ap->a_vp));
if (dolock)
- VOP_LOCK(vp);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
else
- FIXUP(VTOUNION(ap->a_vp));
- error = VOP_BMAP(vp, ap->a_bn, ap->a_vpp, ap->a_bnp, ap->a_runp, ap->a_runb);
+ FIXUP(VTOUNION(ap->a_vp), p);
+ ap->a_vp = vp;
+ error = VCALL(vp, VOFFSET(vop_bmap), ap);
if (dolock)
- VOP_UNLOCK(vp);
+ VOP_UNLOCK(vp, 0, p);
return (error);
}
@@ -1404,6 +1547,11 @@ union_print(ap)
printf("\ttag VT_UNION, vp=%p, uppervp=%p, lowervp=%p\n",
vp, UPPERVP(vp), LOWERVP(vp));
+ if (UPPERVP(vp) != NULLVP)
+ vprint("union: upper", UPPERVP(vp));
+ if (LOWERVP(vp) != NULLVP)
+ vprint("union: lower", LOWERVP(vp));
+
return (0);
}
@@ -1426,16 +1574,18 @@ union_pathconf(ap)
} */ *ap;
{
int error;
+ struct proc *p = curproc; /* XXX */
struct vnode *vp = OTHERVP(ap->a_vp);
int dolock = (vp == LOWERVP(ap->a_vp));
if (dolock)
- VOP_LOCK(vp);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
else
- FIXUP(VTOUNION(ap->a_vp));
- error = VOP_PATHCONF(vp, ap->a_name, ap->a_retval);
+ FIXUP(VTOUNION(ap->a_vp), p);
+ ap->a_vp = vp;
+ error = VCALL(vp, VOFFSET(vop_pathconf), ap);
if (dolock)
- VOP_UNLOCK(vp);
+ VOP_UNLOCK(vp, 0, p);
return (error);
}
@@ -1450,9 +1600,10 @@ union_advlock(ap)
int a_flags;
} */ *ap;
{
+ register struct vnode *ovp = OTHERVP(ap->a_vp);
- return (VOP_ADVLOCK(OTHERVP(ap->a_vp), ap->a_id, ap->a_op,
- ap->a_fl, ap->a_flags));
+ ap->a_vp = ovp;
+ return (VCALL(ovp, VOFFSET(vop_advlock), ap));
}
@@ -1496,6 +1647,7 @@ struct vnodeopv_entry_desc union_vnodeop_entries[] = {
{ &vop_default_desc, (vop_t *)vn_default_error },
{ &vop_lookup_desc, (vop_t *)union_lookup }, /* lookup */
{ &vop_create_desc, (vop_t *)union_create }, /* create */
+ { &vop_whiteout_desc, (vop_t *)union_whiteout }, /* whiteout */
{ &vop_mknod_desc, (vop_t *)union_mknod }, /* mknod */
{ &vop_open_desc, (vop_t *)union_open }, /* open */
{ &vop_close_desc, (vop_t *)union_close }, /* close */
@@ -1504,8 +1656,10 @@ struct vnodeopv_entry_desc union_vnodeop_entries[] = {
{ &vop_setattr_desc, (vop_t *)union_setattr }, /* setattr */
{ &vop_read_desc, (vop_t *)union_read }, /* read */
{ &vop_write_desc, (vop_t *)union_write }, /* write */
+ { &vop_lease_desc, (vop_t *)union_lease }, /* lease */
{ &vop_ioctl_desc, (vop_t *)union_ioctl }, /* ioctl */
{ &vop_select_desc, (vop_t *)union_select }, /* select */
+ { &vop_revoke_desc, (vop_t *)union_revoke }, /* revoke */
{ &vop_mmap_desc, (vop_t *)union_mmap }, /* mmap */
{ &vop_fsync_desc, (vop_t *)union_fsync }, /* fsync */
{ &vop_seek_desc, (vop_t *)union_seek }, /* seek */
OpenPOWER on IntegriCloud