Subject: Re: tmpfs memory leak?
To: None <tech-kern@NetBSD.org>
From: Bill Stouder-Studenmund <wrstuden@netbsd.org>
List: tech-kern
Date: 10/29/2007 12:58:19
--sXc4Kmr5FA7axrvy
Content-Type: multipart/mixed; boundary="t0UkRYy7tHLRMCai"
Content-Disposition: inline
--t0UkRYy7tHLRMCai
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
Content-Transfer-Encoding: quoted-printable
On Sat, Oct 27, 2007 at 05:20:04PM -0700, Bill Stouder-Studenmund wrote:
> On Fri, Oct 26, 2007 at 07:15:04PM -0500, David Young wrote:
> > On Tue, Oct 23, 2007 at 08:47:43PM -0700, Bill Stouder-Studenmund wrote:
>=20
> > > You have no quantification of the performance hit. Also, you are in a=
=20
> > > situation where memory issues are more important for you. We have no=
=20
> > > indication that all layer users are in this situation, and I believe =
a=20
> > > number aren't.
> >=20
> > You're right, I don't care too much about it in my app. I am not
> > especially interested in measuring filesystem performance at this time.
> > I don't know what benchmarks the user community likes to see.
> >=20
> > > Ok, I have half-done a patch to do this. I'll post what I come up w/=
=20
> > > tomorrow. I see how to fix this and get most of the way done. What I =
don't=20
> > > see is how to handle locking.
> >=20
> > Tomorrow? :-)
>=20
> Yeah, sorry. Real life and the WoW Haloween events got in the way.
>=20
> Also, I was about half-way through the patch and then realized what I had=
=20
> needed some work. The problem is getting a consistent snapshot of all of=
=20
> the vnodes above a node. My first take was to walk the list of vnodes in =
a=20
> "safe" manner (it's a TAILQ, so take TAILQ_NEXT() before fussing with a=
=20
> given node). The problem is that something else could happen and whatever=
=20
> "next" vnode we look at might not be valid by the time we get around to=
=20
> looking at it. Ick!
>=20
> So what I have to do is go back and vget() all of the vnodes into an arra=
y=20
> (either on-stack or malloc'd). Then start walking them for=20
> VOP_UPCALL()ing.
Ok, so it is taking me longer than I wanted.
Since I've been working on fixsa, I haven't followed current much of late.=
=20
So I started coding this for 4.0. I have an untested first cut at it. It=20
compiles on i386.
This diff should show everything I have in mind except for using the count=
=20
upcall in vcount().
Pieces missing are: unionfs (linking into both underlying vnodes) and=20
non-ufs writable file systems (I know of nfs).
Things I disklike: only one, and that's how I lock the vnode uplink list.=
=20
Right now it's locked with the vnode stack's lock. I think the right thing=
=20
to do is just use the lower vnode's interlock.
The problem is what happens if a vop_reclaim happens on an upper vnode at=
=20
the same time an upcall is coming up. Specifically what happens with the=20
vget() and reclaim. The "advantage" of using the vnode stack lock is that=
=20
the vget() and upcall will happen before the reclaim happens. So we never=
=20
upcall the wrong vnode. The disadvantage is that it means we have to lock=
=20
the vnode stack lock in vop_reclaim(), if only for a little bit.
Thoughts?
Take care,
Bill
--t0UkRYy7tHLRMCai
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="vop_upcall-1.diff"
Content-Transfer-Encoding: quoted-printable
? arch/i386/compile/PARALLELS
Index: kern/vfs_subr.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /cvsroot/src/sys/kern/vfs_subr.c,v
retrieving revision 1.276.2.1.2.1
diff -u -p -r1.276.2.1.2.1 vfs_subr.c
--- kern/vfs_subr.c 3 Sep 2007 07:05:04 -0000 1.276.2.1.2.1
+++ kern/vfs_subr.c 29 Oct 2007 17:45:22 -0000
@@ -2613,6 +2613,109 @@ vfs_timestamp(struct timespec *ts)
}
=20
/*
+ * VOP_UPCALL() helpers
+ */
+
+/* Called w/ the vnode stack locked */
+void
+vn_up_link(struct vnuplink *vu, struct vnode *vp)
+{
+ TAILQ_INSERT_TAIL(&vp->v_uplinks, vu, vup_next);
+ vp->v_upcount++;
+ vu->vup_lower =3D vp;
+}
+
+/* Called w/ the vnode stack locked */
+void
+vn_up_unlink(struct vnuplink *vu, struct vnode *vp)
+{
+ TAILQ_REMOVE(&vp->v_uplinks, vu, vup_next);
+ vp->v_upcount--;
+}
+
+/*
+ * vn_up_doupcall - actually do an upcall to all nodes above vp. Should be
+ * called with the vnode stack locked. Will unlock the stack then re-lock
+ * it.
+ *
+ * This is somewhat complicated as the lock we have is v_interlock, which
+ * is a spin lock. So we have to do a lot of work so that we do only
+ * what we have to do while holding it. We really need a=20
+ */
+#define VN_UP_ONSTACK 8
+int
+vn_up_doupcall(struct vnode *vp, int op, void *cookie)
+{
+ struct vnuplink *vu, *vu_next;
+ struct vnode *v;
+ int rv =3D 0;
+ int i, j;
+ struct vnode **vnodes;
+ struct vnode *v_stack[VN_UP_ONSTACK];
+
+ i =3D vp->v_upcount;
+ j =3D 0;
+
+ if (i <=3D VN_UP_ONSTACK) {
+ /* Use stack storage */
+ vnodes =3D v_stack;
+ } else {
+ vnodes =3D malloc(i * sizeof(struct vnode), M_TEMP, M_WAITOK);
+ if (vnodes =3D=3D NULL) {
+ return ENOMEM;
+ }
+ }
+
+ /* Now make a list of the vnodes we want and vget() them */
+ j =3D 0;
+ for(vu =3D TAILQ_FIRST(&vp->v_uplinks); vu; vu =3D vu_next) {
+ vu_next =3D TAILQ_NEXT(vu, vup_next);
+ v =3D vu->vup_upper;
+ vget(v, 0);
+ vnodes[j++] =3D v;
+ }
+
+ /*
+ * Now do the calls, which may trigger calls into this routine if
+ * there are vnodes above these layered vnodes
+ */
+ for(i =3D 0; (i < j) && (rv =3D=3D 0); i++)
+ rv =3D VOP_UPCALL(v, vp, op, cookie, curlwp);
+
+ VOP_UNLOCK(vp, 0);
+
+ /*
+ * If we are the last reference to the upper vnodes, we will
+ * inactivate them. If they were "removed", we could well be
+ * vgone()ing them now.
+ */
+ for(i =3D 0; i < j; i++)
+ vrele(vnodes[i]);
+
+ vn_lock(vp, LK_EXCLUSIVE);
+
+ if (vnodes !=3D v_stack)
+ free(vnodes, M_TEMP);
+
+ return rv;
+}
+
+void
+vn_up_remove(struct vnode *vp)
+{
+ vn_up_doupcall(vp, VUPCALL_REMOVE, NULL);
+}
+
+int
+vn_up_count(struct vnode *vp, int *counter)
+{
+ simple_lock(&vp->v_interlock);
+ *counter +=3D vp->v_usecount - vp->v_upcount;
+ simple_unlock(&vp->v_interlock);
+ return vn_up_doupcall(vp, VUPCALL_COUNT, (void *)counter);
+}
+
+/*
* mount_specific_key_create --
* Create a key for subsystem mount-specific data.
*/
Index: kern/vnode_if.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /cvsroot/src/sys/kern/vnode_if.c,v
retrieving revision 1.67
diff -u -p -r1.67 vnode_if.c
--- kern/vnode_if.c 30 Nov 2006 21:07:36 -0000 1.67
+++ kern/vnode_if.c 29 Oct 2007 17:45:23 -0000
@@ -1,11 +1,11 @@
-/* $NetBSD: vnode_if.c,v 1.67 2006/11/30 21:07:36 pooka Exp $ */
+/* $NetBSD$ */
=20
/*
* Warning: DO NOT EDIT! This file is automatically generated!
* (Modifications made here may easily be lost!)
*
* Created from the file:
- * NetBSD: vnode_if.src,v 1.50 2006/05/14 21:15:12 elad Exp
+ * NetBSD: vnode_if.src,v 1.50.12.1 2007/02/17 23:27:48 tron Exp
* by the script:
* NetBSD: vnode_if.sh,v 1.43 2006/11/30 21:06:29 pooka Exp
*/
@@ -40,7 +40,7 @@
*/
=20
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: vnode_if.c,v 1.67 2006/11/30 21:07:36 pooka Ex=
p $");
+__KERNEL_RCSID(0, "$NetBSD$");
=20
=20
/*
@@ -1834,6 +1834,53 @@ VOP_SETEXTATTR(struct vnode *vp,
return (VCALL(vp, VOFFSET(vop_setextattr), &a));
}
=20
+const int vop_upcall_vp_offsets[] =3D {
+ VOPARG_OFFSETOF(struct vop_upcall_args,a_uvp),
+ VOPARG_OFFSETOF(struct vop_upcall_args,a_lvp),
+ VDESC_NO_OFFSET
+};
+const struct vnodeop_desc vop_upcall_desc =3D {
+ VOP_UPCALL_DESCOFFSET,
+ "vop_upcall",
+ 0,
+ vop_upcall_vp_offsets,
+ VDESC_NO_OFFSET,
+ VDESC_NO_OFFSET,
+ VOPARG_OFFSETOF(struct vop_upcall_args, a_l),
+ VDESC_NO_OFFSET,
+ NULL,
+};
+int
+VOP_UPCALL(struct vnode *uvp,
+ struct vnode *lvp,
+ int op,
+ void *cookie,
+ struct lwp *l)
+{
+ struct vop_upcall_args a;
+#ifdef VNODE_LOCKDEBUG
+ int islocked_uvp;
+ int islocked_lvp;
+#endif
+ a.a_desc =3D VDESC(vop_upcall);
+ a.a_uvp =3D uvp;
+#ifdef VNODE_LOCKDEBUG
+ islocked_uvp =3D (uvp->v_flag & VLOCKSWORK) ? (VOP_ISLOCKED(uvp) =3D=3D L=
K_EXCLUSIVE) : 1;
+ if (islocked_uvp !=3D 1)
+ panic("vop_upcall: uvp: locked %d, expected %d", islocked_uvp, 1);
+#endif
+ a.a_lvp =3D lvp;
+#ifdef VNODE_LOCKDEBUG
+ islocked_lvp =3D (lvp->v_flag & VLOCKSWORK) ? (VOP_ISLOCKED(lvp) =3D=3D L=
K_EXCLUSIVE) : 1;
+ if (islocked_lvp !=3D 1)
+ panic("vop_upcall: lvp: locked %d, expected %d", islocked_lvp, 1);
+#endif
+ a.a_op =3D op;
+ a.a_cookie =3D cookie;
+ a.a_l =3D l;
+ return (VCALL(uvp, VOFFSET(vop_upcall), &a));
+}
+
/* End of special cases. */
=20
const struct vnodeop_desc * const vfs_op_descs[] =3D {
@@ -1887,6 +1934,7 @@ const struct vnodeop_desc * const vfs_op
&vop_openextattr_desc,
&vop_deleteextattr_desc,
&vop_setextattr_desc,
+ &vop_upcall_desc,
NULL
};
=20
Index: kern/vnode_if.src
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /cvsroot/src/sys/kern/vnode_if.src,v
retrieving revision 1.50.12.1
diff -u -p -r1.50.12.1 vnode_if.src
--- kern/vnode_if.src 17 Feb 2007 23:27:48 -0000 1.50.12.1
+++ kern/vnode_if.src 29 Oct 2007 17:45:23 -0000
@@ -584,3 +584,15 @@ vop_setextattr {
IN kauth_cred_t cred;
IN struct lwp *l;
};
+
+#
+#% upcall uvp L L L
+#% upcall lvp L L L
+#
+vop_upcall {
+ IN LOCKED=3DYES struct vnode *uvp;
+ IN LOCKED=3DYES struct vnode *lvp;
+ IN int op;
+ INOUT void *cookie;
+ IN struct lwp *l;
+};
Index: miscfs/genfs/layer.h
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /cvsroot/src/sys/miscfs/genfs/layer.h,v
retrieving revision 1.11
diff -u -p -r1.11 layer.h
--- miscfs/genfs/layer.h 11 Dec 2005 12:24:50 -0000 1.11
+++ miscfs/genfs/layer.h 29 Oct 2007 17:45:34 -0000
@@ -112,6 +112,7 @@ struct layer_node {
struct vnode *layer_lowervp; /* VREFed once */
struct vnode *layer_vnode; /* Back pointer */
unsigned int layer_flags; /* locking, etc. */
+ struct vnuplink layer_uplink; /* uplink from lower vnode */
};
=20
#define LAYERFS_RESFLAGS 0x00000fff /* flags reserved for layerfs */
Index: miscfs/genfs/layer_extern.h
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /cvsroot/src/sys/miscfs/genfs/layer_extern.h,v
retrieving revision 1.22
diff -u -p -r1.22 layer_extern.h
--- miscfs/genfs/layer_extern.h 13 Jul 2006 12:00:25 -0000 1.22
+++ miscfs/genfs/layer_extern.h 29 Oct 2007 17:45:34 -0000
@@ -115,3 +115,4 @@ int layer_rename(void *);
int layer_rmdir(void *);
int layer_getpages(void *);
int layer_putpages(void *);
+int layer_upcall(void *);
Index: miscfs/genfs/layer_subr.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /cvsroot/src/sys/miscfs/genfs/layer_subr.c,v
retrieving revision 1.20.2.1
diff -u -p -r1.20.2.1 layer_subr.c
--- miscfs/genfs/layer_subr.c 17 Feb 2007 23:27:49 -0000 1.20.2.1
+++ miscfs/genfs/layer_subr.c 29 Oct 2007 17:45:34 -0000
@@ -254,6 +254,8 @@ layer_node_alloc(mp, lowervp, vpp)
LIST_INSERT_HEAD(hd, xp, layer_hash);
uvm_vnp_setsize(vp, 0);
simple_unlock(&lmp->layerm_hashlock);
+ xp->layer_uplink.vup_upper =3D vp;
+ vn_up_link(&xp->layer_uplink, lowervp);
return (0);
}
=20
Index: miscfs/genfs/layer_vnops.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /cvsroot/src/sys/miscfs/genfs/layer_vnops.c,v
retrieving revision 1.28.2.2
diff -u -p -r1.28.2.2 layer_vnops.c
--- miscfs/genfs/layer_vnops.c 16 Apr 2007 20:01:13 -0000 1.28.2.2
+++ miscfs/genfs/layer_vnops.c 29 Oct 2007 17:45:34 -0000
@@ -780,11 +780,7 @@ layer_remove(v)
int error;
struct vnode *vp =3D ap->a_vp;
=20
- vref(vp);
- if ((error =3D LAYERFS_DO_BYPASS(vp, ap)) =3D=3D 0)
- VTOLAYER(vp)->layer_flags |=3D LAYERFS_REMOVED;
-
- vrele(vp);
+ error =3D LAYERFS_DO_BYPASS(vp, ap);
=20
return (error);
}
@@ -874,6 +870,9 @@ layer_reclaim(v)
*/
lmp->layerm_rootvp =3D NULL;
}
+ VOP_LOCK(lowervp, LK_EXCLUSIVE);
+ vn_up_unlink(&xp->layer_uplink, lowervp);
+ VOP_UNLOCK(lowervp, LK_EXCLUSIVE);
xp->layer_lowervp =3D NULL;
simple_lock(&lmp->layerm_hashlock);
LIST_REMOVE(xp, layer_hash);
@@ -1002,3 +1001,30 @@ layer_putpages(v)
error =3D VCALL(ap->a_vp, VOFFSET(vop_putpages), ap);
return error;
}
+
+int
+layer_upcall(v)
+ void *v;
+{
+ struct vop_upcall_args /* {
+ struct vnode *a_uvp;=20
+ struct vnode *a_lvp;
+ int a_op;
+ void *a_cookie;
+ struct lwp *a_l;
+ } */ *ap =3D v;
+ struct vnode *uvp =3D ap->a_uvp;
+
+ switch (ap->a_op) {
+ case VUPCALL_REMOVE:
+ VTOLAYER(uvp)->layer_flags |=3D LAYERFS_REMOVED;
+ vn_up_remove(uvp);
+ return 0;
+
+ case VUPCALL_COUNT:
+ return vn_up_count(uvp, ap->a_cookie);
+
+ default:
+ return EINVAL;
+ }
+}
Index: miscfs/nullfs/null_vnops.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /cvsroot/src/sys/miscfs/nullfs/null_vnops.c,v
retrieving revision 1.34
diff -u -p -r1.34 null_vnops.c
--- miscfs/nullfs/null_vnops.c 11 Dec 2005 12:24:51 -0000 1.34
+++ miscfs/nullfs/null_vnops.c 29 Oct 2007 17:45:35 -0000
@@ -247,6 +247,8 @@ const struct vnodeopv_entry_desc null_vn
{ &vop_getpages_desc, layer_getpages },
{ &vop_putpages_desc, layer_putpages },
=20
+ { &vop_upcall_desc, layer_upcall },
+
{ NULL, NULL }
};
const struct vnodeopv_desc null_vnodeop_opv_desc =3D
Index: miscfs/overlay/overlay_vnops.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /cvsroot/src/sys/miscfs/overlay/overlay_vnops.c,v
retrieving revision 1.16
diff -u -p -r1.16 overlay_vnops.c
--- miscfs/overlay/overlay_vnops.c 11 Dec 2005 12:24:51 -0000 1.16
+++ miscfs/overlay/overlay_vnops.c 29 Oct 2007 17:45:35 -0000
@@ -170,6 +170,8 @@ const struct vnodeopv_entry_desc overlay
{ &vop_getpages_desc, layer_getpages },
{ &vop_putpages_desc, layer_putpages },
=20
+ { &vop_upcall_desc, layer_upcall },
+
{ NULL, NULL }
};
const struct vnodeopv_desc overlay_vnodeop_opv_desc =3D
Index: miscfs/umapfs/umap_vnops.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /cvsroot/src/sys/miscfs/umapfs/umap_vnops.c,v
retrieving revision 1.42.2.1
diff -u -p -r1.42.2.1 umap_vnops.c
--- miscfs/umapfs/umap_vnops.c 17 Feb 2007 23:27:50 -0000 1.42.2.1
+++ miscfs/umapfs/umap_vnops.c 29 Oct 2007 17:45:37 -0000
@@ -94,6 +94,8 @@ const struct vnodeopv_entry_desc umap_vn
{ &vop_getpages_desc, layer_getpages },
{ &vop_putpages_desc, layer_putpages },
=20
+ { &vop_upcall_desc, layer_upcall },
+
{ NULL, NULL }
};
const struct vnodeopv_desc umapfs_vnodeop_opv_desc =3D
Index: sys/vnode.h
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /cvsroot/src/sys/sys/vnode.h,v
retrieving revision 1.162
diff -u -p -r1.162 vnode.h
--- sys/vnode.h 21 Nov 2006 02:37:20 -0000 1.162
+++ sys/vnode.h 29 Oct 2007 17:46:52 -0000
@@ -83,6 +83,9 @@ enum vtagtype {
=20
LIST_HEAD(buflists, buf);
=20
+struct vnuplink;
+TAILQ_HEAD(vnuplink_head, vnuplink);
+
/*
* Reading or writing any of these items requires holding the appropriate =
lock.
* v_freelist is locked by the global vnode_free_list simple lock.
@@ -126,6 +129,8 @@ struct vnode {
struct lock *v_vnlock; /* pointer to lock */
void *v_data; /* private data for fs */
struct klist v_klist; /* knotes attached to vnode */
+ struct vnuplink_head v_uplinks; /* vnodes above us */
+ int v_upcount; /* # vnodes on ^^ */
};
#define v_mountedhere v_un.vu_mountedhere
#define v_socket v_un.vu_socket
@@ -209,6 +214,18 @@ struct vattr {
#define VA_UTIMES_NULL 0x01 /* utimes argument was NULL */
#define VA_EXCLUSIVE 0x02 /* exclusive create request */
=20
+/*
+ * supoprt VOP_UPCALL()
+ * Each vnode has a list (TAILQ) of vnuplinks. Each vnuplink points
+ * to the next one above the lower node, and also points to the upper
+ * and lower nodes.
+ */
+struct vnuplink {
+ TAILQ_ENTRY(vnuplink) vup_next;
+ struct vnode *vup_upper;
+ struct vnode *vup_lower;
+};
+
#ifdef _KERNEL
=20
/*
@@ -255,6 +272,12 @@ extern struct simplelock global_v_numout
#define VNOVAL (-1)
=20
/*
+ * Defines for VOP_UPCALL
+ */
+#define VUPCALL_REMOVE 1 /* lower vnode has been removed */
+#define VUPCALL_COUNT 2 /* Itteratively count # external refs */
+
+/*
* Convert between vnode types and inode formats (since POSIX.1
* defines mode word of stat structure in terms of inode formats).
*/
@@ -579,6 +602,15 @@ void vn_ra_allocctx(struct vnode *);
/* initialise global vnode management */
void vntblinit(void);
=20
+/* tell vnode stack we removed the vnode */
+void vn_up_remove(struct vnode *);
+int vn_up_count(struct vnode *, int *);
+
+/* Helpers for layer file systems */
+int vn_up_doupcall(struct vnode *, int, void *);
+void vn_up_link(struct vnuplink *, struct vnode *);
+void vn_up_unlink(struct vnuplink *, struct vnode *);
+
/* misc stuff */
void vn_syncer_add_to_worklist(struct vnode *, int);
void vn_syncer_remove_from_worklist(struct vnode *);
Index: sys/vnode_if.h
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /cvsroot/src/sys/sys/vnode_if.h,v
retrieving revision 1.63
diff -u -p -r1.63 vnode_if.h
--- sys/vnode_if.h 30 Nov 2006 21:07:36 -0000 1.63
+++ sys/vnode_if.h 29 Oct 2007 17:46:52 -0000
@@ -1,11 +1,11 @@
-/* $NetBSD: vnode_if.h,v 1.63 2006/11/30 21:07:36 pooka Exp $ */
+/* $NetBSD$ */
=20
/*
* Warning: DO NOT EDIT! This file is automatically generated!
* (Modifications made here may easily be lost!)
*
* Created from the file:
- * NetBSD: vnode_if.src,v 1.50 2006/05/14 21:15:12 elad Exp
+ * NetBSD: vnode_if.src,v 1.50.12.1 2007/02/17 23:27:48 tron Exp
* by the script:
* NetBSD: vnode_if.sh,v 1.43 2006/11/30 21:06:29 pooka Exp
*/
@@ -583,7 +583,19 @@ extern const struct vnodeop_desc vop_set
int VOP_SETEXTATTR(struct vnode *, int, const char *, struct uio *,=20
kauth_cred_t, struct lwp *);
=20
-#define VNODE_OPS_COUNT 49
+#define VOP_UPCALL_DESCOFFSET 49
+struct vop_upcall_args {
+ const struct vnodeop_desc *a_desc;
+ struct vnode *a_uvp;
+ struct vnode *a_lvp;
+ int a_op;
+ void *a_cookie;
+ struct lwp *a_l;
+};
+extern const struct vnodeop_desc vop_upcall_desc;
+int VOP_UPCALL(struct vnode *, struct vnode *, int, void *, struct lwp *);
+
+#define VNODE_OPS_COUNT 50
=20
/* End of special cases. */
=20
Index: ufs/ufs/ufs_vnops.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /cvsroot/src/sys/ufs/ufs/ufs_vnops.c,v
retrieving revision 1.143.2.3
diff -u -p -r1.143.2.3 ufs_vnops.c
--- ufs/ufs/ufs_vnops.c 10 Mar 2007 18:40:49 -0000 1.143.2.3
+++ ufs/ufs/ufs_vnops.c 29 Oct 2007 17:47:04 -0000
@@ -656,6 +656,7 @@ ufs_remove(void *v)
error =3D ufs_dirremove(dvp, ip, ap->a_cnp->cn_flags, 0);
VN_KNOTE(vp, NOTE_DELETE);
VN_KNOTE(dvp, NOTE_WRITE);
+ vn_up_remove(vp);
if (dvp =3D=3D vp)
vrele(vp);
else
@@ -1150,6 +1151,7 @@ ufs_rename(void *v)
VN_KNOTE(tdvp, NOTE_WRITE);
vput(tdvp);
VN_KNOTE(tvp, NOTE_DELETE);
+ vn_up_remove(tvp);
vput(tvp);
xp =3D NULL;
}
--t0UkRYy7tHLRMCai--
--sXc4Kmr5FA7axrvy
Content-Type: application/pgp-signature
Content-Disposition: inline
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.7 (NetBSD)
iD8DBQFHJjtbWz+3JHUci9cRAixaAJ0fOGr81LZu/jrHUDNW8B4WCld23gCdHDGu
WKbwkE4hhaP3Fmsu+pLl5qA=
=HXLB
-----END PGP SIGNATURE-----
--sXc4Kmr5FA7axrvy--