summary |
tags |
clone url |
shortlog |
log |
commit | commitdiff |
tree
raw |
patch |
inline | side by side (from parent 1:
84dfe96)
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
*
* %sccs.include.redist.c%
*
*
* %sccs.include.redist.c%
*
- * @(#)union.h 1.3 (Berkeley) %G%
+ * @(#)union.h 1.4 (Berkeley) %G%
*/
struct union_node {
struct union_node *un_next; /* Hash chain */
*/
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_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;
char *un_path; /* saved component name */
int un_flags;
pid_t un_pid;
#define UN_WANT 0x01
#define UN_LOCKED 0x02
#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)
#define MOUNTTOUNIONMOUNT(mp) ((struct union_mount *)((mp)->mnt_data))
#define VTOUNION(vp) ((struct union_node *)(vp)->v_data)
*
* %sccs.include.redist.c%
*
*
* %sccs.include.redist.c%
*
- * @(#)union_subr.c 1.3 (Berkeley) %G%
+ * @(#)union_subr.c 1.4 (Berkeley) %G%
*/
#include <sys/param.h>
*/
#include <sys/param.h>
#include <sys/malloc.h>
#include "union.h" /*<miscfs/union/union.h>*/
#include <sys/malloc.h>
#include "union.h" /*<miscfs/union/union.h>*/
+#ifdef DIAGNOSTIC
+#include <sys/proc.h>
+#endif
+
static struct union_node *unhead;
static int unvplock;
static struct union_node *unhead;
static int unvplock;
* the vnode free list.
*/
int
* 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 **vpp;
struct mount *mp;
struct vnode *dvp; /* may be null */
struct componentname *cnp; /* may be null */
struct vnode *uppervp; /* may be null */
struct vnode *dvp; /* may be null */
struct componentname *cnp; /* may be null */
struct vnode *uppervp; /* may be null */
(un->un_uppervp == uppervp ||
un->un_uppervp == 0) &&
(UNIONTOV(un)->v_mount == mp)) {
(un->un_uppervp == uppervp ||
un->un_uppervp == 0) &&
(UNIONTOV(un)->v_mount == mp)) {
- if (vget(un->un_vnode, 1))
+ if (vget(UNIONTOV(un), 0))
- 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);
else
(*vpp)->v_type = lowervp->v_type;
un = VTOUNION(*vpp);
else
(*vpp)->v_type = lowervp->v_type;
un = VTOUNION(*vpp);
un->un_next = 0;
un->un_uppervp = uppervp;
un->un_lowervp = lowervp;
un->un_next = 0;
un->un_uppervp = uppervp;
un->un_lowervp = lowervp;
un->un_flags = 0;
if (uppervp == 0 && cnp) {
un->un_path = malloc(cnp->cn_namelen+1, M_TEMP, M_WAITOK);
un->un_flags = 0;
if (uppervp == 0 && cnp) {
un->un_path = malloc(cnp->cn_namelen+1, M_TEMP, M_WAITOK);
-#ifdef DIAGNOSTIC
- un->un_pid = 0;
-#endif
-
/* add to union vnode list */
for (pp = &unhead; *pp; pp = &(*pp)->un_next)
continue;
*pp = un;
/* 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);
if (xlowervp)
vrele(xlowervp);
*
* %sccs.include.redist.c%
*
*
* %sccs.include.redist.c%
*
- * @(#)union_vfsops.c 1.3 (Berkeley) %G%
+ * @(#)union_vfsops.c 1.4 (Berkeley) %G%
*/
VREF(um->um_uppervp);
VREF(um->um_lowervp);
*/
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);
(struct componentname *) 0,
um->um_uppervp,
um->um_lowervp);
*
* %sccs.include.redist.c%
*
*
* %sccs.include.redist.c%
*
- * @(#)union_vnops.c 1.3 (Berkeley) %G%
+ * @(#)union_vnops.c 1.4 (Berkeley) %G%
*/
#include <sys/param.h>
*/
#include <sys/param.h>
-union_lookup1(dvp, vpp, cnp)
+union_lookup1(udvp, dvp, vpp, cnp)
+ struct vnode *udvp;
struct vnode *dvp;
struct vnode **vpp;
struct componentname *cnp;
struct vnode *dvp;
struct vnode **vpp;
struct componentname *cnp;
return (error);
dvp = tdvp;
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) {
(cnp->cn_flags & NOCROSSMOUNT) == 0) {
if (mp->mnt_flag & MNT_MLOCK) {
struct vnode *uppervp, *lowervp;
struct vnode *upperdvp, *lowerdvp;
struct vnode *dvp = ap->a_dvp;
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;
struct componentname *cnp = ap->a_cnp;
int lockparent = cnp->cn_flags & LOCKPARENT;
* then assume that something special is going
* on and just return that vnode.
*/
* then assume that something special is going
* on and just return that vnode.
*/
if (upperdvp) {
VOP_LOCK(upperdvp);
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;
if (cnp->cn_consume != 0) {
*ap->a_vpp = uppervp;
* back from the upper layer and return the lower vnode
* instead.
*/
* back from the upper layer and return the lower vnode
* instead.
*/
if (lowerdvp) {
VOP_LOCK(lowerdvp);
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) {
if (cnp->cn_consume != 0) {
if (uppervp) {
/* case 2. */
if (uerror != 0 /* && (lerror == 0) */ ) {
if (lowervp->v_type == VDIR) { /* case 2b. */
/* case 2. */
if (uerror != 0 /* && (lerror == 0) */ ) {
if (lowervp->v_type == VDIR) { /* case 2b. */
+ if (uppervp != upperdvp)
+ VOP_LOCK(upperdvp);
uerror = union_mkshadow(upperdvp, cnp, &uppervp);
uerror = union_mkshadow(upperdvp, cnp, &uppervp);
+ if (uppervp != upperdvp)
+ VOP_UNLOCK(upperdvp);
if (uerror) {
if (lowervp) {
vput(lowervp);
if (uerror) {
if (lowervp) {
vput(lowervp);
- 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)
uppervp, lowervp);
if (uppervp)
if (lowervp)
vrele(lowervp);
} else {
if (lowervp)
vrele(lowervp);
} else {
- if (!lockparent)
- VOP_UNLOCK(*ap->a_vpp);
+ if (!lockparent && (*ap->a_vpp != dvp))
+ VOP_UNLOCK(dvp);
if (dvp) {
int error;
struct vnode *vp;
if (dvp) {
int error;
struct vnode *vp;
- struct mount *mp = ap->a_dvp->v_mount;
VREF(dvp);
VOP_LOCK(dvp);
VREF(dvp);
VOP_LOCK(dvp);
error = union_allocvp(
ap->a_vpp,
error = union_allocvp(
ap->a_vpp,
+ ap->a_dvp->v_mount,
+ ap->a_dvp,
if (dvp) {
int error;
struct vnode *vp;
if (dvp) {
int error;
struct vnode *vp;
- struct mount *mp = ap->a_dvp->v_mount;
VREF(dvp);
VOP_LOCK(dvp);
VREF(dvp);
VOP_LOCK(dvp);
if (vp) {
error = union_allocvp(
ap->a_vpp,
if (vp) {
error = union_allocvp(
ap->a_vpp,
+ ap->a_dvp->v_mount,
+ ap->a_dvp,
if (dvp) {
int error;
struct vnode *vp;
if (dvp) {
int error;
struct vnode *vp;
- struct mount *mp = ap->a_dvp->v_mount;
VREF(dvp);
VOP_LOCK(dvp);
VREF(dvp);
VOP_LOCK(dvp);
error = union_allocvp(
ap->a_vpp,
error = union_allocvp(
ap->a_vpp,
+ ap->a_dvp->v_mount,
+ ap->a_dvp,
* like they do in the name lookup cache code.
* That's too much work for now.
*/
* 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
+
while (un->un_flags & UN_LOCKED) {
#ifdef DIAGNOSTIC
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;
#endif
un->un_flags |= UN_WANT;
sleep((caddr_t) &un->un_flags, PINOD);
}
un->un_flags |= UN_LOCKED;
- un->un_pid = curproc->p_pid;
+ if (curproc)
+ un->un_pid = curproc->p_pid;
+ else
+ un->un_pid = -1;
#ifdef DIAGNOSTIC
if ((un->un_flags & UN_LOCKED) == 0)
panic("union: unlock unlocked node");
#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
panic("union: unlocking other process's union node");
#endif