diff options
author | Constantine Sapuntzakis <csapuntz@cvs.openbsd.org> | 1997-11-06 05:59:40 +0000 |
---|---|---|
committer | Constantine Sapuntzakis <csapuntz@cvs.openbsd.org> | 1997-11-06 05:59:40 +0000 |
commit | 4e165724f1631d1deee6fd89b941fabdbcc855d4 (patch) | |
tree | 3aca36af68e90377984b00e9f0050674b0763db5 /sys/miscfs/union | |
parent | fec1be888534eb37405f6bf7a195f28670e1392b (diff) |
Updates for VFS Lite 2 + soft update.
Diffstat (limited to 'sys/miscfs/union')
-rw-r--r-- | sys/miscfs/union/union.h | 6 | ||||
-rw-r--r-- | sys/miscfs/union/union_subr.c | 360 | ||||
-rw-r--r-- | sys/miscfs/union/union_vfsops.c | 101 | ||||
-rw-r--r-- | sys/miscfs/union/union_vnops.c | 257 |
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; { |