Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 12 Aug 2010 12:51:27 GMT
From:      Gleb Kurtsou <gk@FreeBSD.org>
To:        Perforce Change Reviews <perforce@FreeBSD.org>
Subject:   PERFORCE change 182315 for review
Message-ID:  <201008121251.o7CCpRtv024076@skunkworks.freebsd.org>

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

Change 182315 by gk@gk_h1 on 2010/08/12 12:50:31

	Fix weak-only cache and bug in tmpfs. Remove root node type

Affected files ...

.. //depot/projects/soc2010/gk_namecache/sys/fs/tmpfs/tmpfs_vnops.c#7 edit
.. //depot/projects/soc2010/gk_namecache/sys/kern/vfs_dircache.c#10 edit
.. //depot/projects/soc2010/gk_namecache/sys/modules/tmpfs/Makefile#6 edit
.. //depot/projects/soc2010/gk_namecache/sys/sys/dircache.h#10 edit

Differences ...

==== //depot/projects/soc2010/gk_namecache/sys/fs/tmpfs/tmpfs_vnops.c#7 (text+ko) ====

@@ -991,10 +991,14 @@
 	fnode = VP_TO_TMPFS_NODE(fvp);
 	de = tmpfs_dir_lookup(fdnode, fnode, fcnp);
 
-	/* Avoid manipulating '.' and '..' entries. */
+	/* Entry can disappear before we lock fdvp,
+	 * also avoid manipulating '.' and '..' entries. */
 	if (de == NULL) {
-		MPASS(fvp->v_type == VDIR);
-		error = EINVAL;
+		if ((fcnp->cn_flags & ISDOTDOT) != 0 ||
+		    (fcnp->cn_namelen == 1 && fcnp->cn_nameptr[0] == '.'))
+			error = EINVAL;
+		else
+			error = ENOENT;
 		goto out_locked;
 	}
 	MPASS(de->td_node == fnode);

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

@@ -53,8 +53,8 @@
 
 #define	DC_NAMEROUND			32	/* power of 2 */
 
-#define	DC_OP_LOCKPREF			0x00000001
-#define	DC_OP_CREATEREF			0x00000002
+#define	DC_LOCKPREF			0x00000001
+#define	DC_CREATEREF			0x00000002
 
 #define DP_UNUSED_MIN			512
 #define DP_THRESHOLD_DFLT		256
@@ -352,7 +352,7 @@
 	return (dr);
 }
 
-static __inline void
+static __inline int
 dr_drop(struct dircache_ref *dr)
 {
 	struct dircache_mount *dm = dr->dr_mount;
@@ -362,14 +362,17 @@
 	if (dr->dr_vnode == NULL && LIST_EMPTY(&dr->dr_entries) &&
 	    dr != dm->dm_rootref && dr != dm->dm_negativeref) {
 		MPASS(RB_EMPTY(&dr->dr_children));
+		DCDEBUG("free ref %p\n", dr);
 		dr_unlock(dr);
 		dm_lock(dm);
 		dr_mntq_remove(dr);
 		dm_unlock(dm);
 		mtx_destroy(&dr->dr_mtx);
 		uma_zfree(dircache_ref_zone, dr);
-	} else
-		dr_unlock(dr);
+		return (1);
+	}
+	dr_unlock(dr);
+	return (0);
 
 }
 
@@ -379,15 +382,17 @@
 	struct dircache_ref *dr;
 
 	dr = vp->v_dircache;
-	if (dr == NULL && (flags & DC_OP_CREATEREF) != 0 &&
+	if (dr == NULL && (flags & DC_CREATEREF) != 0 &&
 	    (vp->v_mount->mnt_kern_flag & MNTK_DIRCACHE) == 0) {
+		DCDEBUG("dr_get: allocate weak ref: vp=%p\n", vp);
 		dircache_allocvnode(vp, 0);
 		dr = vp->v_dircache;
 	}
 	if (dr != NULL) {
 		dr_lock(dr);
 		MPASS(vp->v_dircache == dr);
-	}
+	} else
+		DCDEBUG("dr_get: NULL result\n");
 	return (dr);
 }
 
@@ -713,7 +718,7 @@
 	struct dircache_ref *dr;
 	struct dircache *dc;
 
-	dr = dr_get(vp, DC_OP_CREATEREF);
+	dr = dr_get(vp, DC_CREATEREF);
 	dc = LIST_FIRST(&dr->dr_entries);
 	if (dc == NULL) {
 		dr_unlock(dr);
@@ -773,13 +778,13 @@
 	struct dircache_ref *parentref;
 	struct dircache *dc;
 
-	parentref = dr_get(dvp, DC_OP_CREATEREF);
+	parentref = dr_get(dvp, DC_CREATEREF);
 	dc_initname(&key, cnp->cn_nameptr, cnp->cn_namelen);
 
 	dc = RB_FIND(dircache_tree, &parentref->dr_children, &key);
 	if (dc != NULL) {
 		dc_lock(dc);
-		if ((flags & DC_OP_LOCKPREF) == 0)
+		if ((flags & DC_LOCKPREF) == 0)
 			dr_unlock(parentref);
 	} else
 		dr_unlock(parentref);
@@ -808,9 +813,9 @@
 	MPASS(dc->dc_parentref != NULL);
 	dc_assertlock(dc, MA_OWNED);
 	dr_assertlock(dc->dc_parentref, MA_OWNED);
-	dc_assertempty(dc);
 
-	DCDEBUG("remove entry: %p %s\n", dc, dc->dc_name);
+	DCDEBUG("remove entry: dc=%p ref=%p parentref=%p %s\n",
+	    dc, dc->dc_selfref, dc->dc_parentref, dc->dc_name);
 	parentref = dc->dc_parentref;
 	dc->dc_parentref = NULL;
 	RB_REMOVE(dircache_tree, &parentref->dr_children, dc);
@@ -827,7 +832,7 @@
 		dc_removechildren(selfref);
 	dr_remove(selfref, dc);
 	dc_rele_byref(parentref);
-	if ((flags & DC_OP_LOCKPREF) == 0)
+	if ((flags & DC_LOCKPREF) == 0)
 		dr_unlock(parentref);
 
 	dc_drop(dc);
@@ -843,8 +848,9 @@
 	dr_assertlock(dc->dc_parentref, MA_OWNED);
 	dc_assertempty(dc);
 
-	DCDEBUG("mark negative: %p %s; vp=%p\n",
-	    dc, dc->dc_name, dc->dc_selfref->dr_vnode);
+	DCDEBUG("mark negative: dc=%p vp=%p ref=%p parentref=%p %s\n",
+	    dc, dc->dc_selfref->dr_vnode, dc->dc_selfref,
+	    dc->dc_parentref, dc->dc_name);
 	dr_updategen(dc->dc_parentref);
 	dc->dc_type = DT_NEGATIVE;
 
@@ -870,25 +876,6 @@
 }
 
 static void
-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;
@@ -899,8 +886,7 @@
 	while(!RB_EMPTY(&ref->dr_children)) {
 		child = RB_MIN(dircache_tree, &ref->dr_children);
 		dc_lock(child);
-		MPASS(RB_EMPTY(&child->dc_selfref->dr_children));
-		dc_removeentry(child, DC_OP_LOCKPREF);
+		dc_removeentry(child, DC_LOCKPREF);
 	}
 
 	dr_assertlock(ref, MA_OWNED);
@@ -939,7 +925,7 @@
 				DC_STAT_INC(ds_insert_restart);
 				goto restart;
 			}
-			dc_removeentry(col, DC_OP_LOCKPREF);
+			dc_removeentry(col, DC_LOCKPREF);
 			dc_lock(dc);
 			dr_assertlock(parentref, MA_OWNED);
 			goto restart;
@@ -961,44 +947,54 @@
 dc_purge(struct vnode *vp, dc_filter_t *filter)
 {
 	struct dircache_ref *parentref, *dr;
-	struct dircache *dc;
+	struct dircache *dc, *dctmp;
 
 	DC_ASSERT_WEAK(vp);
 
 restart:
 	dr = dr_get(vp, 0);
+	DCDEBUG("purge: ref=%p vp=%p filter=%p\n", dr, vp, filter);
 	if (dr == NULL)
 		return;
-	RB_FOREACH(dc, dircache_tree, &dr->dr_children) {
+	RB_FOREACH_SAFE(dc, dircache_tree, &dr->dr_children, dctmp) {
 		dr_assertlock(dr, MA_OWNED);
 		dc_lock(dc);
 		if (filter == NULL || filter(dc) != 0)
-			dc_detachentry(dc);
+			dc_removeentry(dc, DC_LOCKPREF);
 		else
 			dc_unlock(dc);
 	}
 	while (!LIST_EMPTY(&dr->dr_entries)) {
+		dr_assertlock(dr, MA_OWNED);
 		dc = LIST_FIRST(&dr->dr_entries);
-		if (filter != NULL && filter(dc) == 0)
-			continue;
+		if (filter != NULL) {
+			while (dc != NULL && filter(dc) == 0)
+				dc = LIST_NEXT(dc, dc_reflist);
+			DCDEBUG("purge: skip by filter: dc=%p\n", dc);
+			if (dc == NULL)
+				break;
+		}
+		dc_lock(dc);
 		parentref = dc->dc_parentref;
 		if (parentref != NULL) {
 			dc_hold(dc);
 			if (dr_trylock(parentref) == 0) {
+				dc_unlock(dc);
 				dr_unlock(dr);
 				dr_lock(parentref);
+				dc_lock(dc);
+				if (dc->dc_parentref != parentref) {
+					dr_unlock(parentref);
+					dc_droplocked(dc);
+					goto restart;
+				}
 			} 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);
-		}
+		} else
+			dc_unlock(dc);
 	}
 	dr_unlock(dr);
 }
@@ -1154,7 +1150,6 @@
 dircache_init(struct mount *mp, uint64_t id)
 {
 	struct dircache_mount *dm;
-	struct dircache *dc;
 
 	dm = malloc(sizeof(struct dircache_mount), M_DIRCACHE,
 	    M_WAITOK | M_ZERO);
@@ -1165,52 +1160,25 @@
 	if (id != 0) {
 		MPASS((mp->mnt_kern_flag & MNTK_DIRCACHE) != 0);
 		dm->dm_rootref = dr_alloc(dm, NULL, id);
-
-		MPASS(mp->mnt_dircache == NULL);
-		dc = dc_alloc(DT_ROOT, NULL, 0);
-
-		dr_lock(dm->dm_rootref);
-		dc_lock(dc);
-		dp_unused_insert(dc);
-		dr_add(dm->dm_rootref, dc);
-		dc_use(dc);
-		dc_unlock(dc);
-		dr_unlock(dm->dm_rootref);
-		DCDEBUG("init: root=%p %jd\n", dc, (intmax_t)id);
+		DCDEBUG("init: rootref=%p %jd\n",
+		    dm->dm_rootref,(intmax_t)id);
 	} else {
 		MPASS((mp->mnt_kern_flag & MNTK_DIRCACHE) == 0);
 		DCDEBUG("init: weak\n");
 	}
 
 	MNT_ILOCK(mp);
+	MPASS(mp->mnt_dircache == NULL);
 	mp->mnt_dircache = dm;
 	MNT_IUNLOCK(mp);
 }
 
-void
-dircache_uninit(struct mount *mp)
+static int
+dc_destroyref(struct dircache_ref *dr)
 {
-	struct dircache_ref *dr, *childref;
-	struct dircache *dc, *child;
-	struct dircache_mount *dm;
-	int dropped;
-
-	MPASS(mp->mnt_dircache != NULL);
-
-	mtx_lock(&pool.dp_mtx);
-	dp_invalid_clear();
-	mtx_unlock(&pool.dp_mtx);
+	struct dircache_ref *childref;
+	struct dircache *child;
 
-	MNT_ILOCK(mp);
-	dm = mp->mnt_dircache;
-	mp->mnt_dircache = NULL;
-	MNT_IUNLOCK(mp);
-
-restart:
-	dr = dm->dm_rootref;
-	dr_lock(dr);
-	DCDEBUG("uninit: rootref=%p\n", dr);
-
 	while (dr != NULL && !RB_EMPTY(&dr->dr_children)) {
 nested:
 		dr_assertlock(dr, MA_OWNED);
@@ -1220,7 +1188,7 @@
 			if (!RB_EMPTY(&childref->dr_children)) {
 				dr_unlock(dr);
 				dr = childref;
-				DCDEBUG("uninit: go down: ref=%p %s\n",
+				DCDEBUG("dc_destroyref: go down: ref=%p %s\n",
 				    childref, child->dc_name);
 				goto nested;
 			}
@@ -1232,37 +1200,76 @@
 		if (dr != NULL) {
 			if (dr_trylock(dr) == 0)  {
 				dr_unlock(childref);
-				goto restart;
+				return (-1);
 			}
 			dr_unlock(childref);
-			DCDEBUG("uninit: go up: ref=%p\n", dr);
+			DCDEBUG("dc_destroyref: go up: ref=%p\n", dr);
 		} else
 			dr_unlock(childref);
 	}
+	if (dr != NULL)
+		dr_unlock(dr);
+	return (0);
+}
+
+void
+dircache_uninit(struct mount *mp)
+{
+	struct dircache_ref *dr;
+	struct dircache_mount *dm;
+
+	MPASS(mp->mnt_dircache != NULL);
+
+	mtx_lock(&pool.dp_mtx);
+	dp_invalid_clear();
+	mtx_unlock(&pool.dp_mtx);
+
+	MNT_ILOCK(mp);
+	dm = mp->mnt_dircache;
+	mp->mnt_dircache = NULL;
+	MNT_IUNLOCK(mp);
+
+	dm_lock(dm);
+	while (!TAILQ_EMPTY(&dm->dm_weakhead)) {
+		dr = TAILQ_FIRST(&dm->dm_weakhead);
+		if (dr == dm->dm_negativeref) {
+			MPASS(TAILQ_NEXT(dr, dr_weaklist) == NULL);
+			break;
+		}
+		dm_unlock(dm);
+		dr_lock(dr);
+		dc_destroyref(dr);
+		dm_lock(dm);
+	}
+	dm_unlock(dm);
 
-	if (dr == NULL) {
+	while (1) {
 		dr = dm->dm_rootref;
+		if (dr == NULL)
+			break;
 		dr_lock(dr);
+		DCDEBUG("uninit: rootref=%p\n", dr);
+		if (dc_destroyref(dr) == 0)
+			break;
 	}
-	MPASS(dr == dm->dm_rootref);
-	MPASS(RB_EMPTY(&dr->dr_children));
-	dc = dr_singleentry(dr);
-	dc_lock(dc);
-	dr_unlock(dr);
 
-	dc_invalidate(dc);
-	dropped = dc_rele(dc);
-	MPASS(dropped != 0);
+	dr = dm->dm_rootref;
+	if (dr != NULL) {
+		MPASS(RB_EMPTY(&dr->dr_children));
+		MPASS(LIST_EMPTY(&dr->dr_entries));
+	}
 
 	mtx_lock(&pool.dp_mtx);
 	dp_invalid_clear();
 	mtx_unlock(&pool.dp_mtx);
 
 	dm_lock(dm);
-	dr_mntq_remove(dm->dm_rootref);
+	if (dm->dm_rootref != NULL)
+		dr_mntq_remove(dm->dm_rootref);
 	dr_mntq_remove(dm->dm_negativeref);
 	dm_unlock(dm);
-	uma_zfree(dircache_ref_zone, dm->dm_rootref);
+	if (dm->dm_rootref != NULL)
+		uma_zfree(dircache_ref_zone, dm->dm_rootref);
 	uma_zfree(dircache_ref_zone, dm->dm_negativeref);
 
 	MPASS(RB_EMPTY(&dm->dm_idhead));
@@ -1312,18 +1319,23 @@
 	struct dircache *dc;
 	int error, ltype;
 
+	/* FIXME:
+	 * Remove entries for DOT and DOTDOT if (cn_flags & MAKEENTRY) == 0
+	 */
 	error = 0;
 	selfref = NULL;
-	if (cnp->cn_nameptr[0] == '.' && cnp->cn_namelen == 1)
+	if (cnp->cn_nameptr[0] == '.' && cnp->cn_namelen == 1) {
+		MPASS((cnp->cn_flags & MAKEENTRY) != 0);
 		return (dircache_lookupdot(dvp, vpp, cnp));
-	else if (cnp->cn_nameptr[0] == '.' && cnp->cn_nameptr[1] == '.' &&
+	} else if (cnp->cn_nameptr[0] == '.' && cnp->cn_nameptr[1] == '.' &&
 	    cnp->cn_namelen == 2) {
 		MPASS((cnp->cn_flags & ISDOTDOT) != 0);
-		parentref = dr_get(dvp, DC_OP_CREATEREF);
+		parentref = dr_get(dvp, DC_CREATEREF);
 		if (parentref != NULL) {
 			DCDEBUG("lookup dotdot: dvp=%p\n", dvp);
 			selfref = dr_parentref(parentref);
 			if (selfref != NULL) {
+				MPASS((cnp->cn_flags & MAKEENTRY) != 0);
 				*vpp = selfref->dr_vnode;
 				if (*vpp != NULL)
 					error = -1;
@@ -1332,7 +1344,7 @@
 			dr_unlock(parentref);
 		}
 	} else {
-		dc = dc_find(dvp, cnp, DC_OP_LOCKPREF);
+		dc = dc_find(dvp, cnp, DC_LOCKPREF);
 		if (dc == NULL) {
 			DCDEBUG("lookup: not found: %s; dvp=%p; op=%ld\n",
 			    cnp->cn_nameptr, dvp, cnp->cn_nameiop);
@@ -1361,8 +1373,13 @@
 		    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 (dc->dc_type == DT_WEAK &&
+			    (cnp->cn_flags & MAKEENTRY) == 0) {
+				dc_removeentry(dc, 0);
+			} else {
+				dr_unlock(dc->dc_parentref);
+				dc_unlock(dc);
+			}
 		}
 	}
 
@@ -1403,17 +1420,17 @@
 	ndc = dc_alloc(type, cnp->cn_nameptr, cnp->cn_namelen);
 
 	DCDEBUG("add: %s; vp=%p\n", cnp->cn_nameptr, vp);
-	parentref = dr_get(dvp, DC_OP_CREATEREF);
+	parentref = dr_get(dvp, DC_CREATEREF);
 	dc_lock(ndc);
 	rdc = dc_insertentry(parentref, ndc);
-	dr_assertlock(parentref, MA_NOTOWNED); // XXX
+	dr_assertlock(parentref, MA_NOTOWNED);
 	if (rdc == ndc) {
 		if (type == DT_NEGATIVE) {
 			MPASS(vp == NULL);
 			selfref = dm_get(dvp)->dm_negativeref;
 			dr_lock(selfref);
 		} else {
-			selfref = dr_get(vp, DC_OP_CREATEREF);
+			selfref = dr_get(vp, DC_CREATEREF);
 			dr_updategen(selfref);
 		}
 		MPASS(selfref != NULL);
@@ -1461,113 +1478,85 @@
     struct vnode *tdvp, struct componentname *tcnp)
 {
 	struct dircache *dc, *col;
-	struct dircache_ref *parentref, *fromref;
+	struct dircache_ref *toref, *fromref;
 	char *namebuf;
-	int error;
 
 	DC_ASSERT_STRONG(tdvp);
 
-	error = 0; /* FIXME */
 	namebuf = NULL;
 	if (dc_namebuffits(fcnp->cn_namelen, tcnp->cn_namelen) == 0) {
 		namebuf = dc_allocnamebuf(tcnp->cn_namelen);
 		DC_STAT_INC(ds_rename_realloc);
 	}
 
-	dc = dc_find(tdvp, tcnp, DC_OP_LOCKPREF);
+	dc = dc_find(tdvp, tcnp, DC_LOCKPREF);
 	if (dc != NULL) {
-		parentref = dc->dc_parentref;
-		dr_assertlock(parentref, MA_OWNED);
-		dr_updategen(parentref);
-		dc_use_byref(parentref);
+		toref = dc->dc_parentref;
+		MPASS(toref != NULL); /* FIXME */
+		dr_assertlock(toref, MA_OWNED);
+		dr_updategen(toref);
+		dc_use_byref(toref);
 		DCDEBUG("rename: remove target: %p %s; parent=%p\n",
 		    dc, dc->dc_name, dc->dc_parentref);
 		dc_removeentry(dc, 0);
 	} else {
-		parentref = dr_get(tdvp, 0);
-		dc_use_byref(parentref);
-		dr_unlock(parentref);
+		toref = dr_get(tdvp, 0);
+		MPASS(toref != NULL); /* FIXME */
+		dr_updategen(toref);
+		dc_use_byref(toref);
+		dr_unlock(toref);
 	}
 
 	if (fdvp == tdvp) {
-		if (parentref == NULL) {
+		/* FIXME */
+		if (toref == NULL) {
 			if (namebuf != NULL)
 				free(namebuf, M_DIRCACHE);
 			return (ENOENT);
 		}
-	} else {
-#if 0
-		if (tcr.dcr_parent == NULL && fcr.dcr_parent == NULL) {
-			MPASS(dc_getentry(fvp, fcnp) == NULL);
-			MPASS(tvp == NULL ||
-			    dc_getentry(tvp, NULL) == NULL);
-			return (ENOENT);
-		} else if (tcr.dcr_parent == NULL) {
-			fdc = dc_getentry(fvp, fcnp);
-			if (fdc != NULL) {
-				dc_marknegative(fdc, fvp);
-			} else {
-				MPASS(dc_find(fdvp, fcnp) == 0);
-				error = ENOENT;
-			}
-			dircache_endupdate(&fcr, 0);
-			return (error);
-		} else if (fcr.dcr_parent == NULL) {
-			dircache_partialupdate(&tcr);
-			return (0);
-		}
-#else
-		MPASS(parentref != NULL);
-#endif
 	}
+	MPASS(toref != NULL);
 
-	dc = dc_find(fdvp, fcnp, DC_OP_LOCKPREF);
-	MPASS(dc != NULL);
-	MPASS(dc->dc_parentref != NULL);
+	dc = dc_find(fdvp, fcnp, DC_LOCKPREF);
+	KASSERT(dc != NULL,
+	    ("dircache_rename: fvp referenece disappeared: %.*s -> %.*s",
+	    (int)fcnp->cn_namelen, fcnp->cn_nameptr,
+	    (int)tcnp->cn_namelen, tcnp->cn_nameptr));
+	fromref = dc->dc_parentref;
+	MPASS(fromref != NULL);
 
 	DCDEBUG("rename: rename: %p %s\n", dc, dc->dc_name);
-	RB_REMOVE(dircache_tree, &dc->dc_parentref->dr_children, dc);
+	RB_REMOVE(dircache_tree, &fromref->dr_children, dc);
+	dc->dc_parentref = NULL;
 	dc_setname(dc, tcnp->cn_nameptr, tcnp->cn_namelen, namebuf);
 	dr_updategen(dc->dc_selfref);
-	dr_updategen(dc->dc_parentref);
+	dr_updategen(fromref);
+	dc_rele_byref(fromref);
+	dr_unlock(fromref);
 
-	if (dr_trylock(parentref) == 0) {
-		fromref = dc->dc_parentref;
-		dc->dc_parentref = NULL;
+	if (dr_trylock(toref) == 0) {
+		DCDEBUG("rename: trylock(toref) failed: dc=%p %s\n",
+		    dc, dc->dc_name);
 		dc_unlock(dc);
-		dr_unlock(fromref);
-		dr_lock(parentref);
+		dr_lock(toref);
 		dc_lock(dc);
-		// FIXME restart
-	} else
-		dr_unlock(dc->dc_parentref);
+		MPASS(dc->dc_parentref == NULL);
+	}
 
-	dc->dc_parentref = parentref;
-	dr_updategen(parentref);
+	dc_assertlock(dc, MA_OWNED);
 	DCDEBUG("rename: insert to tree: %p %s; parent=%p\n",
-	    dc, dc->dc_name, parentref);
-	col = RB_INSERT(dircache_tree, &parentref->dr_children, dc);
+	    dc, dc->dc_name, toref);
+	col = RB_INSERT(dircache_tree, &toref->dr_children, dc);
+	KASSERT(col == NULL,
+	    ("dircache_rename: destination already exists: %.*s -> %.*s",
+	    (int)fcnp->cn_namelen, fcnp->cn_nameptr,
+	    (int)tcnp->cn_namelen, tcnp->cn_nameptr));
 	MPASS(col == NULL);
+	dc->dc_parentref = toref;
 	dc_unlock(dc);
-
-	dc_rele_byref(parentref);
-	dr_unlock(parentref);
+	dr_unlock(toref);
 	DC_STAT_INC(ds_rename);
 
-#if 0
-	if (col != NULL) {
-		DCDEBUG("rename: insert collision: %p %s; type=%d\n", col,
-		    col->dc_name, col->dc_type);
-		if (col->dc_type != DT_NEGATIVE)
-			panic("dircache: rename: invalid entry: %d %s\n",
-			    col->dc_type, col->dc_name);
-		dc_interlock(fdc, col);
-		dc_removeentry(col);
-		dc_lock(fdc);
-		goto reinsert;
-	}
-#endif
-
 	return (0);
 }
 
@@ -1579,6 +1568,7 @@
 	struct dircache_ref *dr, key;
 
 	MPASS(vp->v_type != VNON && vp->v_type != VBAD);
+	MPASS((vp->v_iflag & VI_DOOMED) == 0);
 
 	dm = dm_get(vp);
 	dr = NULL;
@@ -1637,10 +1627,12 @@
 {
 	struct dircache *dc;
 	struct dircache_ref *dr;
+	int weak, dropped;
 
 	dr = dr_get(vp, 0);
 	if (dr == NULL)
 		return;
+	DCDEBUG("reclaimvnode: dr=%p vp=%p\n", dr, vp);
 
 	VI_LOCK(vp);
 	dr->dr_vnode = NULL;
@@ -1654,7 +1646,10 @@
 		}
 		dc_rele(dc);
 	}
-	dr_drop(dr);
+	weak = (dr->dr_id == 0);
+	dropped = dr_drop(dr);
+	if (weak != 0)
+		MPASS(dropped != 0);
 
 	DC_STAT_INC(ds_reclaimvnode);
 }
@@ -1713,6 +1708,11 @@
 
 	DC_ASSERT_WEAK(dvp);
 
+	if ((cnp->cn_flags & ISDOTDOT) != 0) {
+		DCDEBUG("enter: skip dotdot: dvp=%p vp=%p\n", dvp, vp);
+		return (ENOENT);
+	}
+
 	dircache_allocvnode(dvp, 0);
 
 	if (vp != NULL) {
@@ -1737,7 +1737,7 @@
 }
 
 
-/* FIXME: Remove it. Make cache lookup vfs op. */
+/* FIXME: Should be in vfs_cache.c */
 int
 vfs_dircache_lookup(struct vop_lookup_args *ap)
 {

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


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

@@ -34,7 +34,7 @@
 #include <sys/queue.h>
 #include <sys/tree.h>
 
-enum dircache_type { DT_INVALID, DT_NEGATIVE, DT_WEAK, DT_STRONG, DT_ROOT };
+enum dircache_type { DT_INVALID, DT_NEGATIVE, DT_WEAK, DT_STRONG };
 
 struct componentname;
 struct mount;



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