summaryrefslogtreecommitdiff
path: root/sys/miscfs/union
diff options
context:
space:
mode:
authorConstantine Sapuntzakis <csapuntz@cvs.openbsd.org>1997-11-06 05:59:40 +0000
committerConstantine Sapuntzakis <csapuntz@cvs.openbsd.org>1997-11-06 05:59:40 +0000
commit4e165724f1631d1deee6fd89b941fabdbcc855d4 (patch)
tree3aca36af68e90377984b00e9f0050674b0763db5 /sys/miscfs/union
parentfec1be888534eb37405f6bf7a195f28670e1392b (diff)
Updates for VFS Lite 2 + soft update.
Diffstat (limited to 'sys/miscfs/union')
-rw-r--r--sys/miscfs/union/union.h6
-rw-r--r--sys/miscfs/union/union_subr.c360
-rw-r--r--sys/miscfs/union/union_vfsops.c101
-rw-r--r--sys/miscfs/union/union_vnops.c257
4 files changed, 364 insertions, 360 deletions
diff --git a/sys/miscfs/union/union.h b/sys/miscfs/union/union.h
index 5d71a6ad984..98cebc433c1 100644
--- a/sys/miscfs/union/union.h
+++ b/sys/miscfs/union/union.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: union.h,v 1.5 1997/10/06 21:04:48 deraadt Exp $ */
+/* $OpenBSD: union.h,v 1.6 1997/11/06 05:58:51 csapuntz Exp $ */
/* $NetBSD: union.h,v 1.9 1996/02/09 22:41:08 christos Exp $ */
/*
@@ -40,6 +40,8 @@
* @(#)union.h 8.9 (Berkeley) 12/10/94
*/
+struct vfsconf;
+
struct union_args {
char *target; /* Target of loopback */
int mntflags; /* Options on the mount */
@@ -129,7 +131,7 @@ extern void union_newsize __P((struct vnode *, off_t, off_t));
extern int (**union_vnodeop_p) __P((void *));
extern struct vfsops union_vfsops;
-void union_init __P((void));
+int union_init __P((struct vfsconf *));
int union_freevp __P((struct vnode *));
#endif /* _KERNEL */
diff --git a/sys/miscfs/union/union_subr.c b/sys/miscfs/union/union_subr.c
index 689dd69b114..70dc63b427b 100644
--- a/sys/miscfs/union/union_subr.c
+++ b/sys/miscfs/union/union_subr.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: union_subr.c,v 1.6 1997/10/06 21:04:49 deraadt Exp $ */
+/* $OpenBSD: union_subr.c,v 1.7 1997/11/06 05:58:51 csapuntz Exp $ */
/* $NetBSD: union_subr.c,v 1.18 1996/02/09 22:41:10 christos Exp $ */
/*
@@ -78,7 +78,7 @@ static int union_relookup __P((struct union_mount *, struct vnode *,
struct componentname *, char *, int));
int union_vn_close __P((struct vnode *, int, struct ucred *, struct proc *));
static void union_dircache_r __P((struct vnode *, struct vnode ***, int *));
-struct vnode *union_dircache __P((struct vnode *));
+struct vnode *union_dircache __P((struct vnode *, struct proc *));
/*
* This variable is used to hold a pointer to a function
@@ -105,7 +105,7 @@ int union_check(p, vpp, fp, auio, error)
if ((*vpp)->v_op == union_vnodeop_p) {
struct vnode *lvp;
- lvp = union_dircache(*vpp);
+ lvp = union_dircache(*vpp, p);
if (lvp != NULLVP) {
struct vattr va;
@@ -122,7 +122,7 @@ int union_check(p, vpp, fp, auio, error)
if (lvp != NULLVP) {
*error = VOP_OPEN(lvp, FREAD, fp->f_cred, p);
- VOP_UNLOCK(lvp);
+ VOP_UNLOCK(lvp, 0, p);
if (*error) {
vrele(lvp);
@@ -140,8 +140,9 @@ int union_check(p, vpp, fp, auio, error)
return (0);
};
-void
-union_init()
+int
+union_init(vfsp)
+ struct vfsconf *vfsp;
{
int i;
@@ -149,6 +150,7 @@ union_init()
LIST_INIT(&unhead[i]);
bzero((caddr_t) unvplock, sizeof(unvplock));
union_check_p = union_check;
+ return (0);
}
static int
@@ -408,7 +410,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;
}
@@ -646,12 +649,12 @@ union_copyfile(fvp, tvp, cred, p)
uio.uio_segflg = UIO_SYSSPACE;
uio.uio_offset = 0;
- VOP_UNLOCK(fvp); /* XXX */
+ VOP_UNLOCK(fvp, 0, p); /* XXX */
VOP_LEASE(fvp, p, cred, LEASE_READ);
- VOP_LOCK(fvp); /* XXX */
- VOP_UNLOCK(tvp); /* XXX */
+ vn_lock(fvp, LK_EXCLUSIVE | LK_RETRY, p);
+ VOP_UNLOCK(tvp, 0, p); /* XXX */
VOP_LEASE(tvp, p, cred, LEASE_WRITE);
- VOP_LOCK(tvp); /* XXX */
+ vn_lock(tvp, LK_EXCLUSIVE | LK_RETRY, p);
buf = malloc(MAXBSIZE, M_TEMP, M_WAITOK);
@@ -719,11 +722,11 @@ union_copyup(un, docopy, cred, p)
* XX - should not ignore errors
* from VOP_CLOSE
*/
- VOP_LOCK(lvp);
+ 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);
+ VOP_UNLOCK(lvp, 0, p);
(void) VOP_CLOSE(lvp, FREAD, cred, p);
}
#ifdef UNION_DIAGNOSTIC
@@ -733,166 +736,166 @@ union_copyup(un, docopy, cred, p)
}
un->un_flags &= ~UN_ULOCK;
- VOP_UNLOCK(uvp);
+ VOP_UNLOCK(uvp, 0, p);
union_vn_close(uvp, FWRITE, cred, p);
- VOP_LOCK(uvp);
- 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);
- else {
- free(cn->cn_pnbuf, M_NAMEI);
- cn->cn_pnbuf = 0;
- }
-
- return (error);
-}
-
-/*
- * Create a shadow directory in the upper layer.
- * The new vnode is returned locked.
- *
- * (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 shadow directory.
- * it is unlocked on entry and exit.
- * (cnp) is the componentname to be created.
- * (vpp) is the returned newly created shadow directory, which
- * is returned locked.
- */
-int
-union_mkshadow(um, dvp, cnp, vpp)
- struct union_mount *um;
- struct vnode *dvp;
- struct componentname *cnp;
- struct vnode **vpp;
-{
- int error;
- struct vattr va;
- 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);
- vrele(*vpp);
- *vpp = NULLVP;
- return (EEXIST);
- }
-
- /*
- * policy: when creating the shadow directory in the
- * upper layer, create it owned by the user who did
- * the mount, group from parent directory, and mode
- * 777 modified by umask (ie mostly identical to the
- * mkdir syscall). (jsp, kb)
- */
-
- VATTR_NULL(&va);
- va.va_type = VDIR;
- va.va_mode = um->um_cmode;
-
- /* VOP_LEASE: dvp is locked */
- VOP_LEASE(dvp, p, cn.cn_cred, LEASE_WRITE);
-
- 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 proc *p = cnp->cn_proc;
- struct vnode *wvp;
- struct componentname cn;
-
- VOP_UNLOCK(dvp);
- error = union_relookup(um, dvp, &wvp, cnp, &cn, path, strlen(path));
- if (error) {
- VOP_LOCK(dvp);
- return (error);
+ 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);
+ else {
+ free(cn->cn_pnbuf, M_NAMEI);
+ cn->cn_pnbuf = 0;
+ }
+
+ return (error);
+ }
+
+ /*
+ * Create a shadow directory in the upper layer.
+ * The new vnode is returned locked.
+ *
+ * (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 shadow directory.
+ * it is unlocked on entry and exit.
+ * (cnp) is the componentname to be created.
+ * (vpp) is the returned newly created shadow directory, which
+ * is returned locked.
+ */
+ int
+ union_mkshadow(um, dvp, cnp, vpp)
+ struct union_mount *um;
+ struct vnode *dvp;
+ struct componentname *cnp;
+ struct vnode **vpp;
+ {
+ int error;
+ struct vattr va;
+ 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
+ * the mount, group from parent directory, and mode
+ * 777 modified by umask (ie mostly identical to the
+ * mkdir syscall). (jsp, kb)
+ */
+
+ VATTR_NULL(&va);
+ va.va_type = VDIR;
+ va.va_mode = um->um_cmode;
+
+ /* VOP_LEASE: dvp is locked */
+ VOP_LEASE(dvp, p, cn.cn_cred, LEASE_WRITE);
+
+ 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 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);
}
if (wvp) {
@@ -1018,6 +1021,7 @@ void
union_removed_upper(un)
struct union_node *un;
{
+ struct proc *p = curproc;
/*
* We do not set the uppervp to NULLVP here, because lowervp
@@ -1037,7 +1041,7 @@ union_removed_upper(un)
if (un->un_flags & UN_ULOCK) {
un->un_flags &= ~UN_ULOCK;
- VOP_UNLOCK(un->un_uppervp);
+ VOP_UNLOCK(un->un_uppervp, 0, p);
}
}
@@ -1109,8 +1113,9 @@ union_dircache_r(vp, vppp, cntp)
}
struct vnode *
-union_dircache(vp)
+union_dircache(vp, p)
struct vnode *vp;
+ struct proc *p;
{
int cnt;
struct vnode *nvp = NULLVP;
@@ -1118,8 +1123,7 @@ union_dircache(vp)
struct vnode **dircache;
int error;
- VOP_LOCK(vp);
-
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
dircache = VTOUNION(vp)->un_dircache;
if (dircache == 0) {
cnt = 0;
@@ -1144,7 +1148,7 @@ union_dircache(vp)
if (*vpp == NULLVP)
goto out;
- VOP_LOCK(*vpp);
+ 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) {
@@ -1153,7 +1157,7 @@ union_dircache(vp)
}
out:
- VOP_UNLOCK(vp);
+ VOP_UNLOCK(vp, 0, p);
return (nvp);
}
diff --git a/sys/miscfs/union/union_vfsops.c b/sys/miscfs/union/union_vfsops.c
index 5c2a188ad85..c92d96be7cd 100644
--- a/sys/miscfs/union/union_vfsops.c
+++ b/sys/miscfs/union/union_vfsops.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: union_vfsops.c,v 1.6 1997/10/06 21:04:50 deraadt Exp $ */
+/* $OpenBSD: union_vfsops.c,v 1.7 1997/11/06 05:58:52 csapuntz Exp $ */
/* $NetBSD: union_vfsops.c,v 1.10 1995/06/18 14:47:47 cgd Exp $ */
/*
@@ -64,13 +64,7 @@ int union_mount __P((struct mount *, char *, caddr_t, struct nameidata *,
int union_start __P((struct mount *, int, struct proc *));
int union_unmount __P((struct mount *, int, struct proc *));
int union_root __P((struct mount *, struct vnode **));
-int union_quotactl __P((struct mount *, int, uid_t, caddr_t, struct proc *));
int union_statfs __P((struct mount *, struct statfs *, struct proc *));
-int union_sync __P((struct mount *, int, struct ucred *, struct proc *));
-int union_vget __P((struct mount *, ino_t, struct vnode **));
-int union_fhtovp __P((struct mount *, struct fid *, struct mbuf *,
- struct vnode **, int *, struct ucred **));
-int union_vptofh __P((struct vnode *, struct fid *));
/*
* Mount union filesystem
@@ -214,7 +208,7 @@ union_mount(mp, path, data, ndp, p)
mp->mnt_flag |= (um->um_uppervp->v_mount->mnt_flag & MNT_RDONLY);
mp->mnt_data = (qaddr_t)um;
- getnewfsid(mp, makefstype(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);
@@ -293,16 +287,12 @@ union_unmount(mp, mntflags, p)
int error;
int freeing;
int flags = 0;
- extern int doforce;
#ifdef UNION_DIAGNOSTIC
printf("union_unmount(mp = %p)\n", mp);
#endif
if (mntflags & MNT_FORCE) {
- /* union can never be rootfs so don't check for it */
- if (!doforce)
- return (EINVAL);
flags |= FORCECLOSE;
}
@@ -373,6 +363,7 @@ union_root(mp, vpp)
struct mount *mp;
struct vnode **vpp;
{
+ struct proc *p = curproc;
struct union_mount *um = MOUNTTOUNIONMOUNT(mp);
int error;
int loselock;
@@ -385,7 +376,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)
@@ -399,9 +390,10 @@ union_root(mp, vpp)
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 {
@@ -412,19 +404,6 @@ union_root(mp, vpp)
return (error);
}
-/*ARGSUSED*/
-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;
@@ -491,66 +470,29 @@ union_statfs(mp, sbp, p)
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);
}
- strncpy(sbp->f_fstypename, mp->mnt_op->vfs_name, MFSNAMELEN);
+ strncpy(sbp->f_fstypename, mp->mnt_vfc->vfc_name, MFSNAMELEN);
return (0);
}
-/*ARGSUSED*/
-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);
-}
+#define union_sync ((int (*) __P((struct mount *, int, struct ucred *, \
+ struct proc *)))nullop)
-/*ARGSUSED*/
-int
-union_vget(mp, ino, vpp)
- struct mount *mp;
- ino_t ino;
- struct vnode **vpp;
-{
-
- return (EOPNOTSUPP);
-}
-
-/*ARGSUSED*/
-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);
-}
-
-/*ARGSUSED*/
-int
-union_vptofh(vp, fhp)
- struct vnode *vp;
- struct fid *fhp;
-{
-
- return (EOPNOTSUPP);
-}
+#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 = {
- MOUNT_UNION,
union_mount,
union_start,
union_unmount,
@@ -562,4 +504,5 @@ struct vfsops union_vfsops = {
union_fhtovp,
union_vptofh,
union_init,
+ union_sysctl
};
diff --git a/sys/miscfs/union/union_vnops.c b/sys/miscfs/union/union_vnops.c
index 36da3175e05..835da8d8518 100644
--- a/sys/miscfs/union/union_vnops.c
+++ b/sys/miscfs/union/union_vnops.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: union_vnops.c,v 1.8 1997/10/06 21:04:51 deraadt Exp $ */
+/* $OpenBSD: union_vnops.c,v 1.9 1997/11/06 05:58:54 csapuntz Exp $ */
/* $NetBSD: union_vnops.c,v 1.30.4.1 1996/05/25 22:10:14 jtc Exp $ */
/*
@@ -81,6 +81,7 @@ int union_link __P((void *));
int union_rename __P((void *));
int union_mkdir __P((void *));
int union_rmdir __P((void *));
+int union_revoke __P((void *));
int union_symlink __P((void *));
int union_readdir __P((void *));
int union_readlink __P((void *));
@@ -124,6 +125,7 @@ struct vnodeopv_entry_desc union_vnodeop_entries[] = {
{ &vop_symlink_desc, union_symlink }, /* symlink */
{ &vop_readdir_desc, union_readdir }, /* readdir */
{ &vop_readlink_desc, union_readlink }, /* readlink */
+ { &vop_revoke_desc, union_revoke }, /* revoke */
{ &vop_abortop_desc, union_abortop }, /* abortop */
{ &vop_inactive_desc, union_inactive }, /* inactive */
{ &vop_reclaim_desc, union_reclaim }, /* reclaim */
@@ -148,22 +150,22 @@ struct vnodeopv_entry_desc union_vnodeop_entries[] = {
struct vnodeopv_desc union_vnodeop_opv_desc =
{ &union_vnodeop_p, union_vnodeop_entries };
-#define FIXUP(un) { \
+#define FIXUP(un, p) { \
if (((un)->un_flags & UN_ULOCK) == 0) { \
- union_fixup(un); \
+ union_fixup(un, p); \
} \
}
-static void union_fixup __P((struct union_node *));
+static void union_fixup __P((struct union_node *, struct proc *));
static int union_lookup1 __P((struct vnode *, struct vnode **,
struct vnode **, struct componentname *));
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;
}
@@ -174,6 +176,7 @@ union_lookup1(udvp, dvpp, vpp, cnp)
struct vnode **vpp;
struct componentname *cnp;
{
+ struct proc *p = cnp->cn_proc;
int error;
struct vnode *tdvp;
struct vnode *dvp;
@@ -199,7 +202,7 @@ union_lookup1(udvp, dvpp, vpp, cnp)
*dvpp = dvp = dvp->v_mount->mnt_vnodecovered;
vput(tdvp);
VREF(dvp);
- VOP_LOCK(dvp);
+ vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY, p);
}
}
@@ -213,7 +216,7 @@ union_lookup1(udvp, dvpp, 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;
@@ -225,18 +228,18 @@ union_lookup1(udvp, dvpp, vpp, cnp)
while (dvp != udvp && (dvp->v_type == VDIR) &&
(mp = dvp->v_mountedhere)) {
- if (mp->mnt_flag & MNT_MLOCK) {
- mp->mnt_flag |= MNT_MWAIT;
- sleep((caddr_t) mp, PVFS);
+ if (vfs_busy(mp, 0, 0, p))
continue;
- }
+
+ error = VFS_ROOT(mp, &tdvp);
+ vfs_unbusy(mp, p);
+
+ vput(dvp);
- if ((error = VFS_ROOT(mp, &tdvp)) != 0) {
- vput(dvp);
+ if (error) {
return (error);
}
- vput(dvp);
dvp = tdvp;
}
@@ -260,6 +263,7 @@ union_lookup(v)
struct vnode *upperdvp, *lowerdvp;
struct vnode *dvp = ap->a_dvp;
struct union_node *dun = VTOUNION(dvp);
+ struct proc *p = curproc;
struct componentname *cnp = ap->a_cnp;
int lockparent = cnp->cn_flags & LOCKPARENT;
struct union_mount *um = MOUNTTOUNIONMOUNT(dvp->v_mount);
@@ -276,9 +280,9 @@ union_lookup(v)
if (dvp == NULLVP)
return (ENOENT);
VREF(dvp);
- VOP_LOCK(dvp);
+ vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY, p);
if (!lockparent || !(cnp->cn_flags & ISLASTCN))
- VOP_UNLOCK(ap->a_dvp);
+ VOP_UNLOCK(ap->a_dvp, 0, p, 0, p);
return (0);
}
#endif
@@ -298,7 +302,7 @@ union_lookup(v)
* on and just return that vnode.
*/
if (upperdvp != NULLVP) {
- FIXUP(dun);
+ FIXUP(dun, p);
/*
* If we're doing `..' in the underlying filesystem,
* we must drop our lock on the union node before
@@ -310,7 +314,7 @@ union_lookup(v)
if (cnp->cn_flags & ISDOTDOT) {
/* retain lock on underlying VP: */
dun->un_flags |= UN_KLOCK;
- VOP_UNLOCK(dvp);
+ VOP_UNLOCK(dvp, 0, p);
}
uerror = union_lookup1(um->um_uppervp, &upperdvp,
&uppervp, cnp);
@@ -330,7 +334,7 @@ union_lookup(v)
* dun->un_uppervp locked currently--so we get it
* locked here (don't set the UN_ULOCK flag).
*/
- VOP_LOCK(dvp);
+ vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY, p);
}
/*if (uppervp == upperdvp)
@@ -367,7 +371,7 @@ union_lookup(v)
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
@@ -392,7 +396,7 @@ union_lookup(v)
cnp->cn_nameiop = nameiop;
if (lowervp != lowerdvp)
- VOP_UNLOCK(lowerdvp);
+ VOP_UNLOCK(lowerdvp, 0, p);
if (cnp->cn_consume != 0) {
if (uppervp != NULLVP) {
@@ -413,7 +417,7 @@ union_lookup(v)
lowervp = LOWERVP(dun->un_pvp);
if (lowervp != NULLVP) {
VREF(lowervp);
- VOP_LOCK(lowervp);
+ vn_lock(lowervp, LK_EXCLUSIVE | LK_RETRY, p);
lerror = 0;
}
}
@@ -462,9 +466,9 @@ union_lookup(v)
* locks/etc!
*/
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) {
@@ -478,7 +482,7 @@ union_lookup(v)
}
if (lowervp != NULLVP)
- VOP_UNLOCK(lowervp);
+ VOP_UNLOCK(lowervp, 0, p);
error = union_allocvp(ap->a_vpp, dvp->v_mount, dvp, upperdvp, cnp,
uppervp, lowervp, 1);
@@ -491,7 +495,7 @@ union_lookup(v)
} else {
if (*ap->a_vpp != dvp)
if (!lockparent || !(cnp->cn_flags & ISLASTCN))
- VOP_UNLOCK(dvp);
+ VOP_UNLOCK(dvp, 0, p);
if (cnp->cn_namelen == 1 &&
cnp->cn_nameptr[0] == '.' &&
*ap->a_vpp != dvp) {
@@ -516,19 +520,21 @@ union_create(v)
} */ *ap = v;
struct union_node *un = VTOUNION(ap->a_dvp);
struct vnode *dvp;
+ struct componentname *cnp = ap->a_cnp;
+ struct proc *p = cnp->cn_proc;
if ((dvp = un->un_uppervp) != 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);
@@ -537,7 +543,7 @@ union_create(v)
mp,
NULLVP,
NULLVP,
- ap->a_cnp,
+ cnp,
vp,
NULLVP,
1);
@@ -560,11 +566,12 @@ union_whiteout(v)
int a_flags;
} */ *ap = v;
struct union_node *un = VTOUNION(ap->a_dvp);
+ struct proc *p = curproc;
if (un->un_uppervp == NULLVP)
return (EOPNOTSUPP);
- FIXUP(un);
+ FIXUP(un, p);
return (VOP_WHITEOUT(un->un_uppervp, ap->a_cnp, ap->a_flags));
}
@@ -580,13 +587,14 @@ union_mknod(v)
} */ *ap = v;
struct union_node *un = VTOUNION(ap->a_dvp);
struct vnode *dvp;
+ struct proc *p = ap->a_cnp->cn_proc;
if ((dvp = un->un_uppervp) != NULLVP) {
int error;
struct vnode *vp;
struct mount *mp;
- FIXUP(un);
+ FIXUP(un, p);
VREF(dvp);
un->un_flags |= UN_KLOCK;
@@ -656,14 +664,14 @@ union_open(v)
* 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);
@@ -728,14 +736,15 @@ union_access(v)
struct union_node *un = VTOUNION(ap->a_vp);
int error = EACCES;
struct vnode *vp;
+ struct proc *p = ap->a_p;
if ((vp = un->un_uppervp) != NULLVP) {
- FIXUP(un);
+ FIXUP(un, p);
return (VOP_ACCESS(vp, ap->a_mode, ap->a_cred, ap->a_p));
}
if ((vp = un->un_lowervp) != NULLVP) {
- VOP_LOCK(vp);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
error = VOP_ACCESS(vp, ap->a_mode, ap->a_cred, ap->a_p);
if (error == 0) {
struct union_mount *um = MOUNTTOUNIONMOUNT(ap->a_vp->v_mount);
@@ -744,7 +753,7 @@ union_access(v)
error = VOP_ACCESS(vp, ap->a_mode,
um->um_cred, ap->a_p);
}
- VOP_UNLOCK(vp);
+ VOP_UNLOCK(vp, 0, p);
if (error)
return (error);
}
@@ -771,7 +780,7 @@ union_getattr(v)
struct vnode *vp = un->un_uppervp;
struct vattr *vap;
struct vattr va;
-
+ struct proc *p = ap->a_p;
/*
* Some programs walk the filesystem hierarchy by counting
@@ -794,7 +803,7 @@ union_getattr(v)
* the union_node's lock flag.
*/
if (un->un_flags & UN_LOCKED)
- FIXUP(un);
+ FIXUP(un, p);
error = VOP_GETATTR(vp, vap, ap->a_cred, ap->a_p);
if (error)
@@ -836,6 +845,7 @@ union_setattr(v)
struct proc *a_p;
} */ *ap = v;
struct union_node *un = VTOUNION(ap->a_vp);
+ struct proc *p = ap->a_p;
int error;
/*
@@ -857,7 +867,7 @@ union_setattr(v)
* 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))
@@ -882,14 +892,15 @@ union_read(v)
int error;
struct vnode *vp = OTHERVP(ap->a_vp);
int dolock = (vp == LOWERVP(ap->a_vp));
+ struct proc *p = curproc;
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
@@ -926,12 +937,13 @@ union_write(v)
int error;
struct vnode *vp;
struct union_node *un = VTOUNION(ap->a_vp);
+ struct proc *p = curproc;
vp = UPPERVP(ap->a_vp);
if (vp == NULLVP)
panic("union: missing upper layer in write");
- FIXUP(un);
+ FIXUP(un, p);
error = VOP_WRITE(vp, ap->a_uio, ap->a_ioflag, ap->a_cred);
/*
@@ -1027,18 +1039,19 @@ union_fsync(v)
} */ *ap = v;
int error = 0;
struct vnode *targetvp = OTHERVP(ap->a_vp);
+ struct proc *p = ap->a_p;
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));
+ FIXUP(VTOUNION(ap->a_vp), p);
error = VOP_FSYNC(targetvp, ap->a_cred,
ap->a_waitfor, ap->a_p);
if (dolock)
- VOP_UNLOCK(targetvp);
+ VOP_UNLOCK(targetvp, 0, p);
}
return (error);
@@ -1076,6 +1089,7 @@ union_remove(v)
int error;
struct union_node *dun = VTOUNION(ap->a_dvp);
struct union_node *un = VTOUNION(ap->a_vp);
+ struct proc *p = ap->a_cnp->cn_proc;
if (dun->un_uppervp == NULLVP)
panic("union remove: null upper vnode");
@@ -1085,11 +1099,11 @@ union_remove(v)
struct vnode *vp = un->un_uppervp;
struct componentname *cnp = ap->a_cnp;
- 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);
@@ -1100,7 +1114,7 @@ union_remove(v)
if (!error)
union_removed_upper(un);
} else {
- FIXUP(dun);
+ FIXUP(dun, p);
error = union_mkwhiteout(
MOUNTTOUNIONMOUNT(UNIONTOV(dun)->v_mount),
dun->un_uppervp, ap->a_cnp, un->un_path);
@@ -1128,6 +1142,7 @@ union_link(v)
struct union_node *dun;
struct vnode *dvp;
struct vnode *vp;
+ struct proc *p = ap->a_cnp->cn_proc;
dun = VTOUNION(ap->a_dvp);
@@ -1146,9 +1161,9 @@ union_link(v)
/*
* needs to be copied up before we can link it.
*/
- VOP_LOCK(ap->a_vp);
+ vn_lock(ap->a_vp, LK_EXCLUSIVE | LK_RETRY, p);
if (dun->un_uppervp == un->un_dirvp) {
- VOP_UNLOCK(ap->a_dvp);
+ VOP_UNLOCK(ap->a_dvp, 0, p);
}
error = union_copyup(un, 1, ap->a_cnp->cn_cred,
ap->a_cnp->cn_proc);
@@ -1172,18 +1187,18 @@ union_link(v)
(error = relookup(ap->a_dvp,
&dvp, ap->a_cnp))) {
vrele(ap->a_dvp);
- VOP_UNLOCK(ap->a_vp);
+ VOP_UNLOCK(ap->a_vp, 0, p);
return EROFS;
}
if (dvp != NULLVP) {
/* The name we want to create has
mysteriously appeared (a race?) */
error = EEXIST;
- VOP_UNLOCK(ap->a_vp);
+ VOP_UNLOCK(ap->a_vp, 0, p);
goto croak;
}
}
- VOP_UNLOCK(ap->a_vp);
+ VOP_UNLOCK(ap->a_vp, 0, p);
}
vp = un->un_uppervp;
}
@@ -1198,7 +1213,7 @@ croak:
return (error);
}
- FIXUP(dun);
+ FIXUP(dun, p);
VREF(dvp);
dun->un_flags |= UN_KLOCK;
vput(ap->a_dvp);
@@ -1327,15 +1342,16 @@ union_mkdir(v)
} */ *ap = v;
struct union_node *un = VTOUNION(ap->a_dvp);
struct vnode *dvp = un->un_uppervp;
+ struct proc *p = ap->a_cnp->cn_proc;
if (dvp != NULLVP) {
int error;
struct vnode *vp;
- FIXUP(un);
+ FIXUP(un, p);
VREF(dvp);
un->un_flags |= UN_KLOCK;
- VOP_UNLOCK(ap->a_dvp);
+ VOP_UNLOCK(ap->a_dvp, 0, p);
error = VOP_MKDIR(dvp, &vp, ap->a_cnp, ap->a_vap);
if (error) {
vrele(ap->a_dvp);
@@ -1373,6 +1389,7 @@ union_rmdir(v)
int error;
struct union_node *dun = VTOUNION(ap->a_dvp);
struct union_node *un = VTOUNION(ap->a_vp);
+ struct proc *p = ap->a_cnp->cn_proc;
if (dun->un_uppervp == NULLVP)
panic("union rmdir: null upper vnode");
@@ -1382,11 +1399,11 @@ union_rmdir(v)
struct vnode *vp = un->un_uppervp;
struct componentname *cnp = ap->a_cnp;
- 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);
@@ -1397,7 +1414,7 @@ union_rmdir(v)
if (!error)
union_removed_upper(un);
} else {
- FIXUP(dun);
+ FIXUP(dun, p);
error = union_mkwhiteout(
MOUNTTOUNIONMOUNT(UNIONTOV(dun)->v_mount),
dun->un_uppervp, ap->a_cnp, un->un_path);
@@ -1421,12 +1438,13 @@ union_symlink(v)
} */ *ap = v;
struct union_node *un = VTOUNION(ap->a_dvp);
struct vnode *dvp = un->un_uppervp;
+ struct proc *p = ap->a_cnp->cn_proc;
if (dvp != NULLVP) {
int error;
struct vnode *vp;
- FIXUP(un);
+ FIXUP(un, p);
VREF(dvp);
un->un_flags |= UN_KLOCK;
vput(ap->a_dvp);
@@ -1457,16 +1475,17 @@ union_readdir(v)
struct uio *a_uio;
struct ucred *a_cred;
int *a_eofflag;
- u_long *a_cookies;
- int a_ncookies;
+ int *a_ncookies;
+ u_long **a_cookies;
+
} */ *ap = v;
register struct union_node *un = VTOUNION(ap->a_vp);
register struct vnode *vp;
-
+ struct proc *p = curproc;
if ((vp = un->un_uppervp) == NULLVP)
return (0);
- FIXUP(un);
+ FIXUP(un, p);
ap->a_vp = vp;
return (VCALL(vp, VOFFSET(vop_readdir), ap));
}
@@ -1482,16 +1501,18 @@ union_readlink(v)
} */ *ap = v;
int error;
struct vnode *vp = OTHERVP(ap->a_vp);
+ struct proc *p = curproc;
+
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);
ap->a_vp = vp;
error = VCALL(vp, VOFFSET(vop_readlink), ap);
if (dolock)
- VOP_UNLOCK(vp);
+ VOP_UNLOCK(vp, 0, p);
return (error);
}
@@ -1500,7 +1521,7 @@ union_readlink(v)
* When operations want to vput() a union node yet retain a lock on
* the upper VP (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()
+ * vput() which calls VOP_UNLOCK(, 0, p) and comes here. union_unlock()
* unlocks the union node (leaving the upper VP alone), clears the
* KLOCK flag, and then returns to vput(). The caller then does whatever
* is left to do with the upper VP, and insures that it gets unlocked.
@@ -1519,19 +1540,21 @@ union_abortop(v)
int error;
struct vnode *vp = OTHERVP(ap->a_dvp);
struct union_node *un = VTOUNION(ap->a_dvp);
+ struct proc *p = ap->a_cnp->cn_proc;
+
int islocked = un->un_flags & UN_LOCKED;
int dolock = (vp == LOWERVP(ap->a_dvp));
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);
}
ap->a_dvp = vp;
error = VCALL(vp, VOFFSET(vop_abortop), ap);
if (islocked && dolock)
- VOP_UNLOCK(vp);
+ VOP_UNLOCK(vp, 0, p);
return (error);
}
@@ -1542,6 +1565,7 @@ union_inactive(v)
{
struct vop_inactive_args /* {
struct vnode *a_vp;
+ struct proc *a_p;
} */ *ap = v;
struct union_node *un = VTOUNION(ap->a_vp);
@@ -1593,34 +1617,40 @@ union_lock(v)
struct vop_lock_args *ap = v;
struct vnode *vp = ap->a_vp;
struct union_node *un;
+ struct proc *p = ap->a_p;
+ int flags = ap->a_flags;
+ int error = 0;
-start:
- while (vp->v_flag & VXLOCK) {
- vp->v_flag |= VXWANT;
- sleep((caddr_t)vp, PINOD);
- }
+ 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;
- un = VTOUNION(vp);
+start:
+ un = VTOUNION(vp);
if (un->un_uppervp != NULLVP) {
if (((un->un_flags & UN_ULOCK) == 0) &&
(vp->v_usecount != 0)) {
- /*
- * We MUST always use the order of: take upper
- * vp lock, manipulate union node flags, drop
- * upper vp lock. This code must not be an
- * exception.
- */
- VOP_LOCK(un->un_uppervp);
- un->un_flags |= UN_ULOCK;
+ error = vn_lock(un->un_uppervp, flags, p);
+ if (error)
+ return (error);
+ un->un_flags |= UN_ULOCK;
}
#ifdef DIAGNOSTIC
if (un->un_flags & UN_KLOCK) {
- vprint("dangling upper lock", vp);
- panic("union: dangling upper lock");
+ vprint("union: dangling klock", vp);
+ panic("union: dangling upper lock (%lx)", vp);
}
-#endif
- }
+ #endif
+ }
if (un->un_flags & UN_LOCKED) {
#ifdef DIAGNOSTIC
@@ -1648,7 +1678,7 @@ start:
* When operations want to vput() a union node yet retain a lock on
* the upper VP (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()
+ * vput() which calls VOP_UNLOCK(, 0, p) and comes here. union_unlock()
* unlocks the union node (leaving the upper VP alone), clears the
* KLOCK flag, and then returns to vput(). The caller then does whatever
* is left to do with the upper VP, and insures that it gets unlocked.
@@ -1662,6 +1692,7 @@ union_unlock(v)
{
struct vop_lock_args *ap = v;
struct union_node *un = VTOUNION(ap->a_vp);
+ struct proc *p = ap->a_p;
#ifdef DIAGNOSTIC
if ((un->un_flags & UN_LOCKED) == 0)
@@ -1674,7 +1705,7 @@ union_unlock(v)
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);
@@ -1687,6 +1718,8 @@ union_unlock(v)
un->un_pid = 0;
#endif
+ vop_nounlock(v);
+
return (0);
}
@@ -1702,17 +1735,18 @@ union_bmap(v)
int *a_runp;
} */ *ap = v;
int error;
+ struct proc *p = curproc;
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);
ap->a_vp = vp;
error = VCALL(vp, VOFFSET(vop_bmap), ap);
if (dolock)
- VOP_UNLOCK(vp);
+ VOP_UNLOCK(vp, 0, p);
return (error);
}
@@ -1763,21 +1797,42 @@ union_pathconf(v)
} */ *ap = v;
int error;
struct vnode *vp = OTHERVP(ap->a_vp);
+ struct proc *p = curproc;
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);
ap->a_vp = vp;
error = VCALL(vp, VOFFSET(vop_pathconf), ap);
if (dolock)
- VOP_UNLOCK(vp);
+ VOP_UNLOCK(vp, 0, p);
return (error);
}
int
+union_revoke(v)
+ void *v;
+{
+ struct vop_revoke_args /* {
+ struct vnode *a_vp;
+ int a_flags;
+ struct proc *a_p;
+ } */ *ap = v;
+ 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
union_advlock(v)
void *v;
{