From 79f80c71c54ed07d136009335bd60424662beefa Mon Sep 17 00:00:00 2001 From: Jan-Simon Pendry Date: Thu, 3 Feb 1994 20:25:30 -0800 Subject: [PATCH] checkpoint SCCS-vsn: sys/miscfs/union/union_vnops.c 1.4 SCCS-vsn: sys/miscfs/union/union_vfsops.c 1.4 SCCS-vsn: sys/miscfs/union/union.h 1.4 SCCS-vsn: sys/miscfs/union/union_subr.c 1.4 --- usr/src/sys/miscfs/union/union.h | 6 +-- usr/src/sys/miscfs/union/union_subr.c | 42 +++++++++------ usr/src/sys/miscfs/union/union_vfsops.c | 6 ++- usr/src/sys/miscfs/union/union_vnops.c | 72 ++++++++++++++++--------- 4 files changed, 81 insertions(+), 45 deletions(-) diff --git a/usr/src/sys/miscfs/union/union.h b/usr/src/sys/miscfs/union/union.h index 74522c1447..5c82d1d511 100644 --- a/usr/src/sys/miscfs/union/union.h +++ b/usr/src/sys/miscfs/union/union.h @@ -8,7 +8,7 @@ * * %sccs.include.redist.c% * - * @(#)union.h 1.3 (Berkeley) %G% + * @(#)union.h 1.4 (Berkeley) %G% */ struct union_args { @@ -41,10 +41,10 @@ struct union_mount { */ struct union_node { struct union_node *un_next; /* Hash chain */ + struct vnode *un_vnode; /* Back pointer */ struct vnode *un_uppervp; /* overlaying object */ struct vnode *un_lowervp; /* underlying object */ struct vnode *un_dirvp; /* Parent dir of uppervp */ - struct vnode *un_vnode; /* Back pointer */ char *un_path; /* saved component name */ int un_flags; pid_t un_pid; @@ -53,7 +53,7 @@ struct union_node { #define UN_WANT 0x01 #define UN_LOCKED 0x02 -extern int union_node_create __P((struct mount *mp, struct vnode *target, struct vnode **vpp)); +extern int union_allocvp __P((struct vnode **, struct mount *, struct vnode *, struct vnode *, struct componentname *, struct vnode *, struct vnode *)); #define MOUNTTOUNIONMOUNT(mp) ((struct union_mount *)((mp)->mnt_data)) #define VTOUNION(vp) ((struct union_node *)(vp)->v_data) diff --git a/usr/src/sys/miscfs/union/union_subr.c b/usr/src/sys/miscfs/union/union_subr.c index 71c7f1344f..a963d7d76b 100644 --- a/usr/src/sys/miscfs/union/union_subr.c +++ b/usr/src/sys/miscfs/union/union_subr.c @@ -8,7 +8,7 @@ * * %sccs.include.redist.c% * - * @(#)union_subr.c 1.3 (Berkeley) %G% + * @(#)union_subr.c 1.4 (Berkeley) %G% */ #include @@ -20,6 +20,10 @@ #include #include "union.h" /**/ +#ifdef DIAGNOSTIC +#include +#endif + static struct union_node *unhead; static int unvplock; @@ -60,9 +64,10 @@ union_init() * the vnode free list. */ int -union_allocvp(vpp, mp, dvp, cnp, uppervp, lowervp) +union_allocvp(vpp, mp, undvp, dvp, cnp, uppervp, lowervp) struct vnode **vpp; struct mount *mp; + struct vnode *undvp; struct vnode *dvp; /* may be null */ struct componentname *cnp; /* may be null */ struct vnode *uppervp; /* may be null */ @@ -88,13 +93,21 @@ loop: (un->un_uppervp == uppervp || un->un_uppervp == 0) && (UNIONTOV(un)->v_mount == mp)) { - if (vget(un->un_vnode, 1)) + if (vget(UNIONTOV(un), 0)) goto loop; - un->un_uppervp = uppervp; - if ((lowervp == 0) && un->un_lowervp) - vrele(un->un_lowervp); - un->un_lowervp = lowervp; - *vpp = un->un_vnode; + if (UNIONTOV(un) != undvp) + VOP_LOCK(UNIONTOV(un)); + if (uppervp != un->un_uppervp) { + if (un->un_uppervp) + vrele(un->un_uppervp); + un->un_uppervp = uppervp; + } + if (lowervp != un->un_lowervp) { + if (un->un_lowervp) + vrele(un->un_lowervp); + un->un_lowervp = lowervp; + } + *vpp = UNIONTOV(un); return (0); } } @@ -122,10 +135,10 @@ loop: else (*vpp)->v_type = lowervp->v_type; un = VTOUNION(*vpp); + un->un_vnode = *vpp; un->un_next = 0; un->un_uppervp = uppervp; un->un_lowervp = lowervp; - un->un_vnode = *vpp; un->un_flags = 0; if (uppervp == 0 && cnp) { un->un_path = malloc(cnp->cn_namelen+1, M_TEMP, M_WAITOK); @@ -138,17 +151,16 @@ loop: un->un_dirvp = 0; } -#ifdef DIAGNOSTIC - un->un_pid = 0; -#endif - /* add to union vnode list */ for (pp = &unhead; *pp; pp = &(*pp)->un_next) continue; *pp = un; - if (un) - un->un_flags |= UN_LOCKED; + un->un_flags |= UN_LOCKED; + +#ifdef DIAGNOSTIC + un->un_pid = curproc->p_pid; +#endif if (xlowervp) vrele(xlowervp); diff --git a/usr/src/sys/miscfs/union/union_vfsops.c b/usr/src/sys/miscfs/union/union_vfsops.c index 2a5d97ebaf..85d1957efe 100644 --- a/usr/src/sys/miscfs/union/union_vfsops.c +++ b/usr/src/sys/miscfs/union/union_vfsops.c @@ -8,7 +8,7 @@ * * %sccs.include.redist.c% * - * @(#)union_vfsops.c 1.3 (Berkeley) %G% + * @(#)union_vfsops.c 1.4 (Berkeley) %G% */ /* @@ -214,7 +214,9 @@ union_root(mp, vpp) */ VREF(um->um_uppervp); VREF(um->um_lowervp); - error = union_allocvp(vpp, mp, (struct vnode *) 0, + error = union_allocvp(vpp, mp, + (struct vnode *) 0, + (struct vnode *) 0, (struct componentname *) 0, um->um_uppervp, um->um_lowervp); diff --git a/usr/src/sys/miscfs/union/union_vnops.c b/usr/src/sys/miscfs/union/union_vnops.c index 413e3be610..1cb2e3d3e0 100644 --- a/usr/src/sys/miscfs/union/union_vnops.c +++ b/usr/src/sys/miscfs/union/union_vnops.c @@ -8,7 +8,7 @@ * * %sccs.include.redist.c% * - * @(#)union_vnops.c 1.3 (Berkeley) %G% + * @(#)union_vnops.c 1.4 (Berkeley) %G% */ #include @@ -62,7 +62,8 @@ union_mkshadow(dvp, cnp, vpp) } static int -union_lookup1(dvp, vpp, cnp) +union_lookup1(udvp, dvp, vpp, cnp) + struct vnode *udvp; struct vnode *dvp; struct vnode **vpp; struct componentname *cnp; @@ -90,7 +91,8 @@ union_lookup1(dvp, vpp, cnp) return (error); dvp = tdvp; - while ((dvp->v_type == VDIR) && (mp = dvp->v_mountedhere) && + while (dvp != udvp && (dvp->v_type == VDIR) && + (mp = dvp->v_mountedhere) && (cnp->cn_flags & NOCROSSMOUNT) == 0) { if (mp->mnt_flag & MNT_MLOCK) { @@ -126,7 +128,7 @@ union_lookup(ap) struct vnode *uppervp, *lowervp; struct vnode *upperdvp, *lowerdvp; struct vnode *dvp = ap->a_dvp; - struct union_node *dun = VTOUNION(ap->a_dvp); + struct union_node *dun = VTOUNION(dvp); struct componentname *cnp = ap->a_cnp; int lockparent = cnp->cn_flags & LOCKPARENT; @@ -143,11 +145,13 @@ union_lookup(ap) * then assume that something special is going * on and just return that vnode. */ - uppervp = 0; if (upperdvp) { VOP_LOCK(upperdvp); - uerror = union_lookup1(upperdvp, &uppervp, cnp); - VOP_UNLOCK(upperdvp); + uerror = union_lookup1( + MOUNTTOUNIONMOUNT(dvp->v_mount)->um_uppervp, + upperdvp, &uppervp, cnp); + if (uppervp != upperdvp) + VOP_UNLOCK(upperdvp); if (cnp->cn_consume != 0) { *ap->a_vpp = uppervp; @@ -166,11 +170,13 @@ union_lookup(ap) * back from the upper layer and return the lower vnode * instead. */ - lowervp = 0; if (lowerdvp) { VOP_LOCK(lowerdvp); - lerror = union_lookup1(lowerdvp, &lowervp, cnp); - VOP_UNLOCK(lowerdvp); + lerror = union_lookup1( + MOUNTTOUNIONMOUNT(dvp->v_mount)->um_lowervp, + lowerdvp, &lowervp, cnp); + if (lowervp != lowerdvp) + VOP_UNLOCK(lowerdvp); if (cnp->cn_consume != 0) { if (uppervp) { @@ -222,9 +228,11 @@ union_lookup(ap) /* case 2. */ if (uerror != 0 /* && (lerror == 0) */ ) { if (lowervp->v_type == VDIR) { /* case 2b. */ - VOP_LOCK(upperdvp); + if (uppervp != upperdvp) + VOP_LOCK(upperdvp); uerror = union_mkshadow(upperdvp, cnp, &uppervp); - VOP_UNLOCK(upperdvp); + if (uppervp != upperdvp) + VOP_UNLOCK(upperdvp); if (uerror) { if (lowervp) { vput(lowervp); @@ -235,7 +243,7 @@ union_lookup(ap) } } - error = union_allocvp(ap->a_vpp, dvp->v_mount, dvp, cnp, + error = union_allocvp(ap->a_vpp, dvp->v_mount, dvp, upperdvp, cnp, uppervp, lowervp); if (uppervp) @@ -249,8 +257,8 @@ union_lookup(ap) if (lowervp) vrele(lowervp); } else { - if (!lockparent) - VOP_UNLOCK(*ap->a_vpp); + if (!lockparent && (*ap->a_vpp != dvp)) + VOP_UNLOCK(dvp); } return (error); @@ -271,7 +279,6 @@ union_create(ap) if (dvp) { int error; struct vnode *vp; - struct mount *mp = ap->a_dvp->v_mount; VREF(dvp); VOP_LOCK(dvp); @@ -282,7 +289,8 @@ union_create(ap) error = union_allocvp( ap->a_vpp, - mp, + ap->a_dvp->v_mount, + ap->a_dvp, NULLVP, ap->a_cnp, vp, @@ -312,7 +320,6 @@ union_mknod(ap) if (dvp) { int error; struct vnode *vp; - struct mount *mp = ap->a_dvp->v_mount; VREF(dvp); VOP_LOCK(dvp); @@ -324,7 +331,8 @@ union_mknod(ap) if (vp) { error = union_allocvp( ap->a_vpp, - mp, + ap->a_dvp->v_mount, + ap->a_dvp, NULLVP, ap->a_cnp, vp, @@ -892,7 +900,6 @@ union_mkdir(ap) if (dvp) { int error; struct vnode *vp; - struct mount *mp = ap->a_dvp->v_mount; VREF(dvp); VOP_LOCK(dvp); @@ -903,7 +910,8 @@ union_mkdir(ap) error = union_allocvp( ap->a_vpp, - mp, + ap->a_dvp->v_mount, + ap->a_dvp, NULLVP, ap->a_cnp, vp, @@ -1073,6 +1081,14 @@ union_inactive(ap) * like they do in the name lookup cache code. * That's too much work for now. */ + +#ifdef DIAGNOSTIC + struct union_node *un = VTOUNION(ap->a_vp); + + if (un->un_flags & UN_LOCKED) + panic("union: inactivating locked node"); +#endif + return (0); } @@ -1118,15 +1134,20 @@ union_lock(ap) while (un->un_flags & UN_LOCKED) { #ifdef DIAGNOSTIC - if (un->un_pid == curproc->p_pid) - panic("union: locking agsinst myself"); + if (curproc && un->un_pid == curproc->p_pid && + un->un_pid > -1 && curproc->p_pid > -1) + panic("union: locking against myself"); #endif un->un_flags |= UN_WANT; sleep((caddr_t) &un->un_flags, PINOD); } un->un_flags |= UN_LOCKED; + #ifdef DIAGNOSTIC - un->un_pid = curproc->p_pid; + if (curproc) + un->un_pid = curproc->p_pid; + else + un->un_pid = -1; #endif } @@ -1139,7 +1160,8 @@ union_unlock(ap) #ifdef DIAGNOSTIC if ((un->un_flags & UN_LOCKED) == 0) panic("union: unlock unlocked node"); - if (un->un_pid != curproc->p_pid) + if (curproc && un->un_pid != curproc->p_pid && + curproc->p_pid > -1 && un->un_pid > -1) panic("union: unlocking other process's union node"); #endif -- 2.20.1