Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 4 Aug 2010 19:35:26 GMT
From:      Gleb Kurtsou <gk@FreeBSD.org>
To:        Perforce Change Reviews <perforce@FreeBSD.org>
Subject:   PERFORCE change 181847 for review
Message-ID:  <201008041935.o74JZQLZ039780@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://p4web.freebsd.org/@@181847?ac=10

Change 181847 by gk@gk_h1 on 2010/08/04 19:35:09

	Weak only cache support 

Affected files ...

.. //depot/projects/soc2010/gk_namecache/sys/kern/vfs_dircache.c#9 edit
.. //depot/projects/soc2010/gk_namecache/sys/modules/tmpfs/Makefile#5 edit
.. //depot/projects/soc2010/gk_namecache/sys/sys/dircache.h#9 edit

Differences ...

==== //depot/projects/soc2010/gk_namecache/sys/kern/vfs_dircache.c#9 (text+ko) ====

@@ -54,6 +54,7 @@
 #define	DC_NAMEROUND			32	/* power of 2 */
 
 #define	DC_OP_LOCKPREF			0x00000001
+#define	DC_OP_CREATEREF			0x00000002
 
 #define DP_UNUSED_MIN			512
 #define DP_THRESHOLD_DFLT		256
@@ -86,11 +87,14 @@
 struct dircache_mount {
 	struct mtx dm_mtx;
 	struct dircache_idtree dm_idhead;
+	TAILQ_HEAD(, dircache_ref) dm_weakhead;
 	struct dircache_ref *dm_rootref;
 	struct dircache_ref *dm_negativeref;
 	u_long dm_idcnt;
 };
 
+typedef int dc_filter_t(struct dircache *dc);
+
 static struct dircache * dc_use(struct dircache *dc);
 static int dc_rele(struct dircache *dc);
 
@@ -199,6 +203,7 @@
 DC_STAT_DEFINE(clearunused_restart, "");
 DC_STAT_DEFINE(clearinvalid, "");
 
+#define dm_assertlock(dm, w)	mtx_assert(&(dm)->dm_mtx, (w))
 #define dm_lock(dm)		mtx_lock(&(dm)->dm_mtx)
 #define dm_unlock(dm)		mtx_unlock(&(dm)->dm_mtx)
 
@@ -295,10 +300,42 @@
 
 RB_GENERATE_STATIC(dircache_idtree, dircache_ref, dr_idtree, dr_cmp);
 
+static __inline void
+dr_mntq_insert(struct dircache_ref *dr)
+{
+	struct dircache_mount *dm;
+	struct dircache_ref *col;
+
+	dm = dr->dr_mount;
+	dm_assertlock(dm, MA_OWNED);
+
+	if (dr->dr_id != 0) {
+		col = RB_INSERT(dircache_idtree, &dm->dm_idhead, dr);
+		MPASS(col == NULL);
+	} else
+		TAILQ_INSERT_HEAD(&dm->dm_weakhead, dr, dr_weaklist);
+	dm->dm_idcnt++;
+}
+
+static __inline void
+dr_mntq_remove(struct dircache_ref *dr)
+{
+	struct dircache_mount *dm;
+
+	dm = dr->dr_mount;
+	dm_assertlock(dm, MA_OWNED);
+
+	if (dr->dr_id != 0)
+		RB_REMOVE(dircache_idtree, &dm->dm_idhead, dr);
+	else
+		TAILQ_REMOVE(&dm->dm_weakhead, dr, dr_weaklist);
+	dm->dm_idcnt--;
+}
+
 static struct dircache_ref *
 dr_alloc(struct dircache_mount *dm, struct vnode *vp, uint64_t id)
 {
-	struct dircache_ref *dr, *col;
+	struct dircache_ref *dr;
 
 	dr = uma_zalloc(dircache_ref_zone, M_WAITOK | M_ZERO);
 	mtx_init(&dr->dr_mtx, "dircache ref", NULL, MTX_DEF | MTX_DUPOK);
@@ -308,13 +345,9 @@
 	dr->dr_vnode = vp;
 	if (vp != NULL)
 		MPASS(dm_get(vp) == dr->dr_mount);
-	if (id != 0) {
-		dm_lock(dm);
-		col = RB_INSERT(dircache_idtree, &dm->dm_idhead, dr);
-		dm->dm_idcnt++;
-		MPASS(col == NULL);
-		dm_unlock(dm);
-	}
+	dm_lock(dm);
+	dr_mntq_insert(dr);
+	dm_unlock(dm);
 
 	return (dr);
 }
@@ -331,9 +364,9 @@
 		MPASS(RB_EMPTY(&dr->dr_children));
 		dr_unlock(dr);
 		dm_lock(dm);
-		RB_REMOVE(dircache_idtree, &dm->dm_idhead, dr);
-		dm->dm_idcnt--;
+		dr_mntq_remove(dr);
 		dm_unlock(dm);
+		mtx_destroy(&dr->dr_mtx);
 		uma_zfree(dircache_ref_zone, dr);
 	} else
 		dr_unlock(dr);
@@ -341,14 +374,20 @@
 }
 
 static struct dircache_ref *
-dr_get(struct vnode *vp)
+dr_get(struct vnode *vp, int flags)
 {
 	struct dircache_ref *dr;
 
 	dr = vp->v_dircache;
-	MPASS(dr != NULL);
-	dr_lock(dr);
-	MPASS(vp->v_dircache == dr);
+	if (dr == NULL && (flags & DC_OP_CREATEREF) != 0 &&
+	    (vp->v_mount->mnt_kern_flag & MNTK_DIRCACHE) == 0) {
+		dircache_allocvnode(vp, 0);
+		dr = vp->v_dircache;
+	}
+	if (dr != NULL) {
+		dr_lock(dr);
+		MPASS(vp->v_dircache == dr);
+	}
 	return (dr);
 }
 
@@ -358,8 +397,7 @@
 	struct dircache *dc;
 
 	dc = LIST_FIRST(&dr->dr_entries);
-	MPASS(dc != NULL);
-	MPASS(LIST_NEXT(dc, dc_reflist) == NULL);
+	MPASS(dc == NULL || LIST_NEXT(dc, dc_reflist) == NULL);
 
 	return (dc);
 }
@@ -367,7 +405,12 @@
 static __inline struct dircache_ref *
 dr_parentref(struct dircache_ref *dr)
 {
-	return (dr_singleentry(dr)->dc_parentref);
+	struct dircache *dc;
+
+	dc = dr_singleentry(dr);
+	if (dc != NULL)
+		return (dc->dc_parentref);
+	return (NULL);
 }
 
 static void
@@ -536,6 +579,7 @@
 
 	DCDEBUG("drop: %p usecnt=%d holdcnt=%d-1\n", dc, dc->dc_usecnt,
 	    dc->dc_holdcnt);
+	dc_assertlock(dc, islocked ? MA_OWNED : MA_NOTOWNED);
 	if (refcount_release(&dc->dc_holdcnt) != 0) {
 		MPASS(dc->dc_usecnt == 0);
 		if (islocked != 0) {
@@ -599,9 +643,11 @@
 
 	dr_assertlock(dr, MA_OWNED);
 	dc = dr_singleentry(dr);
-	dc_lock(dc);
-	dc_use(dc);
-	dc_unlock(dc);
+	if (dc != NULL) {
+		dc_lock(dc);
+		dc_use(dc);
+		dc_unlock(dc);
+	}
 }
 
 static int
@@ -634,6 +680,8 @@
 	struct dircache *dc;
 
 	dc = dr_singleentry(dr);
+	if (dc == NULL)
+		return (0);
 	dc_lock(dc);
 	return (dc_rele(dc));
 }
@@ -665,7 +713,7 @@
 	struct dircache_ref *dr;
 	struct dircache *dc;
 
-	dr = dr_get(vp);
+	dr = dr_get(vp, DC_OP_CREATEREF);
 	dc = LIST_FIRST(&dr->dr_entries);
 	if (dc == NULL) {
 		dr_unlock(dr);
@@ -725,7 +773,7 @@
 	struct dircache_ref *parentref;
 	struct dircache *dc;
 
-	parentref = dr_get(dvp);
+	parentref = dr_get(dvp, DC_OP_CREATEREF);
 	dc_initname(&key, cnp->cn_nameptr, cnp->cn_namelen);
 
 	dc = RB_FIND(dircache_tree, &parentref->dr_children, &key);
@@ -749,7 +797,7 @@
 	}
 }
 
-static void dr_removechildren(struct dircache_ref *ref);
+static void dc_removechildren(struct dircache_ref *ref);
 
 static void
 dc_removeentry(struct dircache *dc, int flags)
@@ -776,7 +824,7 @@
 	dr_lock(selfref);
 
 	if (!RB_EMPTY(&selfref->dr_children))
-		dr_removechildren(selfref);
+		dc_removechildren(selfref);
 	dr_remove(selfref, dc);
 	dc_rele_byref(parentref);
 	if ((flags & DC_OP_LOCKPREF) == 0)
@@ -808,7 +856,7 @@
 	dc_unlock(dc);
 	dr_lock(selfref);
 
-	dr_removechildren(selfref);
+	dc_removechildren(selfref);
 	dr_remove(selfref, dc);
 
 	dr_lock(negativeref);
@@ -822,7 +870,26 @@
 }
 
 static void
-dr_removechildren(struct dircache_ref *ref)
+dc_detachentry(struct dircache *dc)
+{
+	struct dircache_ref *parentref;
+
+	MPASS(dc->dc_parentref != NULL);
+	dc_assertlock(dc, MA_OWNED);
+	dr_assertlock(dc->dc_parentref, MA_OWNED);
+
+	DCDEBUG("detach entry: %p %s\n", dc, dc->dc_name);
+	parentref = dc->dc_parentref;
+	dc->dc_parentref = NULL;
+	RB_REMOVE(dircache_tree, &parentref->dr_children, dc);
+	dc_invalidate(dc);
+
+	dc_rele_byref(parentref);
+	dc_droplocked(dc);
+}
+
+static void
+dc_removechildren(struct dircache_ref *ref)
 {
 	struct dircache *child;
 
@@ -891,6 +958,58 @@
 }
 
 static void
+dc_purge(struct vnode *vp, dc_filter_t *filter)
+{
+	struct dircache_ref *parentref, *dr;
+	struct dircache *dc;
+
+	DC_ASSERT_WEAK(vp);
+
+restart:
+	dr = dr_get(vp, 0);
+	if (dr == NULL)
+		return;
+	RB_FOREACH(dc, dircache_tree, &dr->dr_children) {
+		dr_assertlock(dr, MA_OWNED);
+		dc_lock(dc);
+		if (filter == NULL || filter(dc) != 0)
+			dc_detachentry(dc);
+		else
+			dc_unlock(dc);
+	}
+	while (!LIST_EMPTY(&dr->dr_entries)) {
+		dc = LIST_FIRST(&dr->dr_entries);
+		if (filter != NULL && filter(dc) == 0)
+			continue;
+		parentref = dc->dc_parentref;
+		if (parentref != NULL) {
+			dc_hold(dc);
+			if (dr_trylock(parentref) == 0) {
+				dr_unlock(dr);
+				dr_lock(parentref);
+			} else
+				dr_unlock(dr);
+			dc_lock(dc);
+			if (dc->dc_parentref != parentref) {
+				dr_unlock(parentref);
+				dc_droplocked(dc);
+				goto restart;
+			}
+			dc_removeentry(dc, 0);
+			dc_drop(dc);
+			dr_lock(dr);
+		}
+	}
+	dr_unlock(dr);
+}
+
+static int
+dc_filternegative(struct dircache *dc)
+{
+	return (dc->dc_type == DT_NEGATIVE);
+}
+
+static void
 dp_unused_insert(struct dircache *dc)
 {
 	dc_assertlock(dc, MA_OWNED);
@@ -1041,6 +1160,7 @@
 	    M_WAITOK | M_ZERO);
 	mtx_init(&dm->dm_mtx, "dircache mount", NULL, MTX_DEF);
 	RB_INIT(&dm->dm_idhead);
+	TAILQ_INIT(&dm->dm_weakhead);
 	dm->dm_negativeref = dr_alloc(dm, NULL, 0);
 	if (id != 0) {
 		MPASS((mp->mnt_kern_flag & MNTK_DIRCACHE) != 0);
@@ -1108,7 +1228,7 @@
 		}
 		childref = dr;
 		dr = dr_parentref(dr);
-		dr_removechildren(childref);
+		dc_removechildren(childref);
 		if (dr != NULL) {
 			if (dr_trylock(dr) == 0)  {
 				dr_unlock(childref);
@@ -1139,13 +1259,15 @@
 	mtx_unlock(&pool.dp_mtx);
 
 	dm_lock(dm);
-	RB_REMOVE(dircache_idtree, &dm->dm_idhead, dm->dm_rootref);
-	dm->dm_idcnt--;
+	dr_mntq_remove(dm->dm_rootref);
+	dr_mntq_remove(dm->dm_negativeref);
 	dm_unlock(dm);
 	uma_zfree(dircache_ref_zone, dm->dm_rootref);
 	uma_zfree(dircache_ref_zone, dm->dm_negativeref);
 
 	MPASS(RB_EMPTY(&dm->dm_idhead));
+	MPASS(TAILQ_EMPTY(&dm->dm_weakhead));
+	mtx_destroy(&dm->dm_mtx);
 	free(dm, M_DIRCACHE);
 }
 
@@ -1197,17 +1319,20 @@
 	else if (cnp->cn_nameptr[0] == '.' && cnp->cn_nameptr[1] == '.' &&
 	    cnp->cn_namelen == 2) {
 		MPASS((cnp->cn_flags & ISDOTDOT) != 0);
-		parentref = dr_get(dvp);
+		parentref = dr_get(dvp, DC_OP_CREATEREF);
 		if (parentref != NULL) {
 			DCDEBUG("lookup dotdot: dvp=%p\n", dvp);
 			selfref = dr_parentref(parentref);
-			*vpp = selfref->dr_vnode;
-			if (*vpp != NULL)
-				error = -1;
+			if (selfref != NULL) {
+				*vpp = selfref->dr_vnode;
+				if (*vpp != NULL)
+					error = -1;
+			} else
+				*vpp = NULL;
 			dr_unlock(parentref);
 		}
 	} else {
-		dc = dc_find(dvp, cnp, 0);
+		dc = dc_find(dvp, cnp, DC_OP_LOCKPREF);
 		if (dc == NULL) {
 			DCDEBUG("lookup: not found: %s; dvp=%p; op=%ld\n",
 			    cnp->cn_nameptr, dvp, cnp->cn_nameiop);
@@ -1217,6 +1342,8 @@
 			switch (cnp->cn_nameiop) {
 			case CREATE:
 			case RENAME:
+				dc_removeentry(dc, 0);
+				dc = NULL;
 				error = 0;
 				break;
 			default:
@@ -1230,9 +1357,13 @@
 		} else {
 			DC_STAT_INC(ds_miss);
 		}
-		DCDEBUG("lookup: error=%d: %p %s; dvp=%p; op=%ld\n",
-		    error, dc, dc->dc_name, dvp, cnp->cn_nameiop);
-		dc_unlock(dc);
+		DCDEBUG("lookup: error=%d: %p %.*s; dvp=%p; op=%ld\n",
+		    error, dc, (int)cnp->cn_namelen, cnp->cn_nameptr,
+		    dvp, cnp->cn_nameiop);
+		if (dc != NULL) {
+			dr_unlock(dc->dc_parentref);
+			dc_unlock(dc);
+		}
 	}
 
 	if (error == -1) {
@@ -1267,13 +1398,12 @@
 	struct dircache *rdc;
 	struct dircache_ref *selfref;
 
-	DC_ASSERT_STRONG(dvp);
 	MPASS(type == DT_STRONG || type == DT_WEAK || type == DT_NEGATIVE);
 
 	ndc = dc_alloc(type, cnp->cn_nameptr, cnp->cn_namelen);
 
 	DCDEBUG("add: %s; vp=%p\n", cnp->cn_nameptr, vp);
-	parentref = dr_get(dvp);
+	parentref = dr_get(dvp, DC_OP_CREATEREF);
 	dc_lock(ndc);
 	rdc = dc_insertentry(parentref, ndc);
 	dr_assertlock(parentref, MA_NOTOWNED); // XXX
@@ -1283,7 +1413,7 @@
 			selfref = dm_get(dvp)->dm_negativeref;
 			dr_lock(selfref);
 		} else {
-			selfref = dr_get(vp);
+			selfref = dr_get(vp, DC_OP_CREATEREF);
 			dr_updategen(selfref);
 		}
 		MPASS(selfref != NULL);
@@ -1309,7 +1439,7 @@
 	DC_ASSERT_STRONG(dvp);
 	DCDEBUG("remove: %s; vp=%p\n", cnp->cn_nameptr, vp);
 
-	parentref = dr_get(dvp);
+	parentref = dr_get(dvp, 0);
 	dc = dc_getentry(vp, cnp, parentref);
 	if (dc == NULL) {
 		DCDEBUG("remove: vp not found: %s vp=%p\n",
@@ -1354,7 +1484,7 @@
 		    dc, dc->dc_name, dc->dc_parentref);
 		dc_removeentry(dc, 0);
 	} else {
-		parentref = dr_get(tdvp);
+		parentref = dr_get(tdvp, 0);
 		dc_use_byref(parentref);
 		dr_unlock(parentref);
 	}
@@ -1448,21 +1578,26 @@
 	struct dircache_mount *dm;
 	struct dircache_ref *dr, key;
 
-	DC_ASSERT_STRONG(vp);
 	MPASS(vp->v_type != VNON && vp->v_type != VBAD);
-	MPASS(vp->v_dircache == NULL);
-	MPASS(id != 0);
 
 	dm = dm_get(vp);
+	dr = NULL;
 
-	dm_lock(dm);
-	key.dr_id = id;
-	dr = RB_FIND(dircache_idtree, &dm->dm_idhead, &key);
-	dm_unlock(dm);
+	if (id != 0) {
+		MPASS(vp->v_dircache == NULL);
+		MPASS((vp->v_mount->mnt_kern_flag & MNTK_DIRCACHE) != 0);
+		dm_lock(dm);
+		key.dr_id = id;
+		dr = RB_FIND(dircache_idtree, &dm->dm_idhead, &key);
+		dm_unlock(dm);
+	} else if (vp->v_dircache != NULL) {
+		MPASS(vp->v_dircache->dr_id == id);
+		return;
+	}
 
 	if (dr == NULL)
-		dr = dr_alloc(dm_get(vp), vp, id);
-	else
+		dr = dr_alloc(dm, vp, id);
+	else if (id != 0)
 		DC_STAT_INC(ds_allocvnode_inode_hit);
 
 	DCDEBUG("alloc vnode: vp=%p; ino=%jd; dr=%p\n",
@@ -1470,10 +1605,18 @@
 
 	dr_lock(dr);
 	VI_LOCK(vp);
+	if (vp->v_dircache != NULL && vp->v_dircache != dr) {
+		/* Race should be possible only for weak entries. */
+		MPASS(id == 0);
+		dr_unlock(dr);
+		VI_UNLOCK(vp);
+		dr_drop(dr);
+		return;
+	}
 	MPASS(dr->dr_vnode == NULL || dr->dr_vnode == vp);
 	MPASS(vp->v_dircache == NULL || vp->v_dircache == dr);
+	dr->dr_vnode = vp;
 	vp->v_dircache = dr;
-	dr->dr_vnode = vp;
 	VI_UNLOCK(vp);
 	LIST_FOREACH(dc, &dr->dr_entries, dc_reflist) {
 		dc_lock(dc);
@@ -1495,7 +1638,7 @@
 	struct dircache *dc;
 	struct dircache_ref *dr;
 
-	dr = dr_get(vp);
+	dr = dr_get(vp, 0);
 	if (dr == NULL)
 		return;
 
@@ -1523,7 +1666,9 @@
 	struct dircache_ref *dr;
 	int error;
 
-	dr = dr_get(vp);
+	dr = dr_get(vp, 0);
+	if (dr == NULL)
+		return (ENOENT);
 	dc = LIST_FIRST(&dr->dr_entries);
 	if (dc == NULL) {
 		dr_unlock(dr);
@@ -1552,7 +1697,7 @@
 	struct dircache_ref *dr;
 	u_long gen;
 
-	dr = dr_get(vp);
+	dr = dr_get(vp, 0);
 	if (dr == NULL)
 		return (0);
 	gen = dr->dr_gen;
@@ -1568,14 +1713,12 @@
 
 	DC_ASSERT_WEAK(dvp);
 
-#if 0
-	dr_initweak(dvp);
-	dr_initweak(vp);
-#endif
+	dircache_allocvnode(dvp, 0);
 
-	if (vp != NULL)
+	if (vp != NULL) {
+		dircache_allocvnode(vp, 0);
 		error = dircache_add(dvp, vp, cnp, DT_WEAK);
-	else
+	} else
 		error = dircache_add(dvp, NULL, cnp, DT_NEGATIVE);
 
 	return (error);
@@ -1584,90 +1727,13 @@
 void
 dircache_purge(struct vnode *vp)
 {
-#if 0
-	struct dircache_ref *dr;
-	struct dircache *dc;
-
-	DC_ASSERT_WEAK(vp);
-
-	dr = dr_get(vp);
-	if (dr == NULL)
-		return;
-	while (!LIST_EMPTY(&dr->dr_entries)) {
-		dc = LIST_FIRST(&dr->dr_entries);
-		dc_lock(dc);
-		dc_hold(dc);
-		if (!RB_EMPTY(&dc->dc_children))
-			dc_detachchildren(dc);
-		dc_detacheentry(dc);
-		dc_drop(dc);
-	}
-#endif
+	dc_purge(vp, NULL);
 }
 
 void
 dircache_purge_negative(struct vnode *vp)
 {
-#if 0
-	DC_ASSERT_WEAK(vp);
-
-	dr = dr_get(vp);
-	if (dr == NULL)
-		return;
-#endif
-
-#if 0
-	TAILQ_HEAD(, dircache) head = TAILQ_HEAD_INITIALIZER(head);
-	struct dircache *dc, *child, *tmp;
-	int r;
-
-restart:
-	VI_LOCK(vp);
-	dc = TAILQ_FIRST(&vp->v_dircache);
-	if (dc == NULL) {
-		VI_UNLOCK(vp);
-		return;
-	}
-	if (vp->v_type == VDIR) {
-		MPASS(TAILQ_NEXT(dc, dc_list) == NULL);
-		if (dc_refinterlock(vp, dc) != 0)
-			goto restart;
-		dc_use(dc);
-		RB_FOREACH_SAFE(child, dircache_tree, &dc->dc_children, tmp) {
-			if (child->dc_type == DT_NEGATIVE) {
-				RB_REMOVE(dircache_tree, &dc->dc_children,
-				    child);
-				if (dc_trylock(child) != 0) {
-					child->dc_parent = NULL;
-					dc_droplocked(child);
-					r = dc_relesafe(dc);
-					MPASS(r == 0);
-				} else
-					TAILQ_INSERT_HEAD(&head, child,
-					    dc_tmplist);
-			}
-		}
-		dc_unlock(dc);
-		while(!TAILQ_EMPTY(&head)) {
-			child = TAILQ_FIRST(&head);
-			TAILQ_REMOVE(&head, child, dc_tmplist);
-			dc_lock(child);
-			MPASS(child->dc_parent == dc);
-			dc_lock(dc);
-			child->dc_parent = NULL;
-			dc_droplocked(child);
-			dc_rele(dc);
-		}
-		dc_lock(dc);
-		dc_rele(dc);
-	} else {
-		/* Check invariants */
-		TAILQ_FOREACH(dc, &vp->v_dircache, dc_list) {
-			MPASS(dc->dc_type != DT_NEGATIVE);
-		}
-		VI_UNLOCK(vp);
-	}
-#endif
+	dc_purge(vp, dc_filternegative);
 }
 
 

==== //depot/projects/soc2010/gk_namecache/sys/modules/tmpfs/Makefile#5 (text+ko) ====

@@ -10,8 +10,8 @@
 
 .if defined(NO_DIRCACHE)
 DEBUG_FLAGS+= -DNO_DIRCACHE
-#.elif !defined(USE_DIRCACHE)
-#DEBUG_FLAGS+= -DDIRCACHE_WEAK
+.elif !defined(USE_DIRCACHE)
+DEBUG_FLAGS+= -DDIRCACHE_WEAK
 .endif
 
 .include <bsd.kmod.mk>

==== //depot/projects/soc2010/gk_namecache/sys/sys/dircache.h#9 (text+ko) ====

@@ -64,13 +64,19 @@
 	struct mtx dr_mtx;
 	struct dircache_tree dr_children;
 	LIST_HEAD(, dircache) dr_entries;
-	RB_ENTRY(dircache_ref) dr_idtree;
+	union {
+		RB_ENTRY(dircache_ref) drl_idtree;
+		TAILQ_ENTRY(dircache_ref) drl_weaklist;
+	} dr_l;
 	struct vnode *dr_vnode;
 	struct dircache_mount *dr_mount;
 	uint64_t dr_id;
 	u_long dr_gen;
 };
 
+#define	dr_idtree		dr_l.drl_idtree
+#define	dr_weaklist		dr_l.drl_weaklist
+
 RB_HEAD(dircache_idtree, dircache_ref);
 
 void dircache_init(struct mount *mp, uint64_t id);



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201008041935.o74JZQLZ039780>