PERFORCE change 181468 for review
Gleb Kurtsou
gk at FreeBSD.org
Wed Jul 28 08:21:39 UTC 2010
http://p4web.freebsd.org/@@181468?ac=10
Change 181468 by gk at gk_h1 on 2010/07/26 16:48:09
Move children list head to dircache_ref to simplify forthcoming weak-only cache. Replace inode numbers with 64 bit ids (until ino_t remains 32 bit)
Affected files ...
.. //depot/projects/soc2010/gk_namecache/sys/fs/tmpfs/tmpfs_subr.c#6 edit
.. //depot/projects/soc2010/gk_namecache/sys/fs/tmpfs/tmpfs_vfsops.c#4 edit
.. //depot/projects/soc2010/gk_namecache/sys/fs/tmpfs/tmpfs_vnops.c#6 edit
.. //depot/projects/soc2010/gk_namecache/sys/kern/vfs_dircache.c#8 edit
.. //depot/projects/soc2010/gk_namecache/sys/modules/tmpfs/Makefile#4 edit
.. //depot/projects/soc2010/gk_namecache/sys/sys/dircache.h#8 edit
Differences ...
==== //depot/projects/soc2010/gk_namecache/sys/fs/tmpfs/tmpfs_subr.c#6 (text+ko) ====
@@ -401,7 +401,7 @@
error = insmntque(vp, mp);
if (error)
vp = NULL;
-#ifndef NO_DIRCACHE
+#if !defined(NO_DIRCACHE) && !defined(DIRCACHE_WEAK)
else
dircache_allocvnode(vp, node->tn_id);
#endif
@@ -524,7 +524,7 @@
* insert the new node into the directory, an operation that
* cannot fail. */
tmpfs_dir_attach(dvp, de);
-#ifndef NO_DIRCACHE
+#if !defined(NO_DIRCACHE) && !defined(DIRCACHE_WEAK)
dircache_add(dvp, *vpp, cnp, DT_STRONG);
#endif
==== //depot/projects/soc2010/gk_namecache/sys/fs/tmpfs/tmpfs_vfsops.c#4 (text+ko) ====
@@ -247,6 +247,9 @@
MNT_ILOCK(mp);
mp->mnt_flag |= MNT_LOCAL;
mp->mnt_kern_flag |= MNTK_MPSAFE;
+#if !defined(NO_DIRCACHE) && !defined(DIRCACHE_WEAK)
+ mp->mnt_kern_flag |= MNTK_DIRCACHE;
+#endif
MNT_IUNLOCK(mp);
mp->mnt_data = tmp;
@@ -254,8 +257,10 @@
vfs_getnewfsid(mp);
vfs_mountedfrom(mp, "tmpfs");
-#ifndef NO_DIRCACHE
+#if !defined(NO_DIRCACHE) && !defined(DIRCACHE_WEAK)
dircache_init(mp, root->tn_id);
+#elif defined(DIRCACHE_WEAK)
+ dircache_init(mp, 0);
#endif
return 0;
@@ -327,7 +332,7 @@
mp->mnt_flag &= ~MNT_LOCAL;
MNT_IUNLOCK(mp);
-#ifndef NO_DIRCACHE
+#if !defined(NO_DIRCACHE)
dircache_uninit(mp);
#endif
==== //depot/projects/soc2010/gk_namecache/sys/fs/tmpfs/tmpfs_vnops.c#6 (text+ko) ====
@@ -185,7 +185,10 @@
* request was for creation, as it does not improve timings on
* emprical tests. */
if ((cnp->cn_flags & MAKEENTRY) && cnp->cn_nameiop != CREATE) {
-#ifndef NO_DIRCACHE
+#if !defined(NO_DIRCACHE) && !defined(DIRCACHE_WEAK)
+ dircache_add(dvp, *vpp, cnp,
+ *vpp == NULL ? DT_NEGATIVE : DT_STRONG);
+#elif defined(DIRCACHE_WEAK)
dircache_enter(dvp, *vpp, cnp);
#else
cache_enter(dvp, *vpp, cnp);
@@ -844,7 +847,7 @@
/* Remove the entry from the directory; as it is a file, we do not
* have to change the number of hard links of the directory. */
tmpfs_dir_detach(dvp, de);
-#ifndef NO_DIRCACHE
+#if !defined(NO_DIRCACHE) && !defined(DIRCACHE_WEAK)
dircache_remove(dvp, vp, v->a_cnp);
#endif
@@ -918,7 +921,7 @@
/* Insert the new directory entry into the appropriate directory. */
tmpfs_dir_attach(dvp, de);
-#ifndef NO_DIRCACHE
+#if !defined(NO_DIRCACHE) && !defined(DIRCACHE_WEAK)
dircache_add(dvp, vp, cnp, DT_STRONG);
#endif
@@ -1145,7 +1148,7 @@
tmpfs_free_dirent(VFS_TO_TMPFS(tvp->v_mount), de, TRUE);
}
-#ifndef NO_DIRCACHE
+#if !defined(NO_DIRCACHE) && !defined(DIRCACHE_WEAK)
dircache_rename(fdvp, fcnp, tdvp, tcnp);
#endif
@@ -1243,7 +1246,7 @@
/* Detach the directory entry from the directory (dnode). */
tmpfs_dir_detach(dvp, de);
-#ifndef NO_DIRCACHE
+#if !defined(NO_DIRCACHE) && !defined(DIRCACHE_WEAK)
dircache_remove(dvp, vp, v->a_cnp);
#endif
@@ -1264,8 +1267,13 @@
TMPFS_NODE_CHANGED | TMPFS_NODE_MODIFIED;
TMPFS_NODE_UNLOCK(dnode);
+#if defined(DIRCACHE_WEAK)
+ dircache_purge(dvp);
+ dircache_purge(vp);
+#elif defined(NO_DIRCACHE)
cache_purge(dvp);
cache_purge(vp);
+#endif
/* Free the directory entry we just deleted. Note that the node
* referred by it will not be removed until the vnode is really
@@ -1449,7 +1457,11 @@
tmp = VFS_TO_TMPFS(vp->v_mount);
vnode_destroy_vobject(vp);
+#if defined(DIRCACHE_WEAK)
+ dircache_purge(vp);
+#elif defined(NO_DIRCACHE)
cache_purge(vp);
+#endif
TMPFS_NODE_LOCK(node);
TMPFS_ASSERT_ELOCKED(node);
@@ -1468,7 +1480,7 @@
MPASS(vp->v_data == NULL);
-#ifndef NO_DIRCACHE
+#if !defined(NO_DIRCACHE)
dircache_reclaimvnode(vp);
#endif
@@ -1576,7 +1588,7 @@
*/
struct vop_vector tmpfs_vnodeop_entries = {
.vop_default = &default_vnodeops,
-#ifndef NO_DIRCACHE
+#if !defined(NO_DIRCACHE)
.vop_lookup = vfs_dircache_lookup,
#else
.vop_lookup = vfs_cache_lookup,
==== //depot/projects/soc2010/gk_namecache/sys/kern/vfs_dircache.c#8 (text+ko) ====
@@ -53,7 +53,7 @@
#define DC_NAMEROUND 32 /* power of 2 */
-#define DC_OP_VLOCK 0x00000001
+#define DC_OP_LOCKPREF 0x00000001
#define DP_UNUSED_MIN 512
#define DP_THRESHOLD_DFLT 256
@@ -64,6 +64,11 @@
printf(format ,## args); \
} while (0)
+#define DC_ISTRONG(v) \
+ ((v)->v_mount->mnt_kern_flag & MNTK_DIRCACHE)
+#define DC_ASSERT_STRONG(v) MPASS(DC_ISTRONG(v) != 0)
+#define DC_ASSERT_WEAK(v) MPASS(DC_ISTRONG(v) == 0)
+
struct dircache_pool {
struct mtx dp_mtx;
TAILQ_HEAD(, dircache) dp_unused;
@@ -80,10 +85,10 @@
struct dircache_mount {
struct mtx dm_mtx;
- struct dircache_inotree dm_inohead;
+ struct dircache_idtree dm_idhead;
struct dircache_ref *dm_rootref;
struct dircache_ref *dm_negativeref;
- u_long dm_inocnt;
+ u_long dm_idcnt;
};
static struct dircache * dc_use(struct dircache *dc);
@@ -125,7 +130,7 @@
SYSCTL_PROC(_vfs_dircache_stats, OID_AUTO, inoderefs,
CTLFLAG_RD | CTLTYPE_ULONG | CTLFLAG_MPSAFE, NULL,
- __offsetof(struct dircache_mount, dm_inocnt), ds_mountstats, "LU", "");
+ __offsetof(struct dircache_mount, dm_idcnt), ds_mountstats, "LU", "");
enum {
ds_hit,
@@ -199,6 +204,7 @@
#define dr_assertlock(dr, w) mtx_assert(&(dr)->dr_mtx, (w))
#define dr_lock(dr) mtx_lock(&(dr)->dr_mtx)
+#define dr_trylock(dr) mtx_trylock(&(dr)->dr_mtx)
#define dr_unlock(dr) mtx_unlock(&(dr)->dr_mtx)
#define dc_lock(dc) mtx_lock(&(dc)->dc_mtx)
@@ -280,32 +286,32 @@
static __inline int
dr_cmp(struct dircache_ref *a, struct dircache_ref *b)
{
- if (a->dr_ino > b->dr_ino)
+ if (a->dr_id > b->dr_id)
return (1);
- else if (a->dr_ino < b->dr_ino)
+ else if (a->dr_id < b->dr_id)
return (-1);
return (0);
}
-RB_GENERATE_STATIC(dircache_inotree, dircache_ref, dr_inotree, dr_cmp);
+RB_GENERATE_STATIC(dircache_idtree, dircache_ref, dr_idtree, dr_cmp);
static struct dircache_ref *
-dr_alloc(struct dircache_mount *dm, struct vnode *vp, ino_t ino)
+dr_alloc(struct dircache_mount *dm, struct vnode *vp, uint64_t id)
{
struct dircache_ref *dr, *col;
dr = uma_zalloc(dircache_ref_zone, M_WAITOK | M_ZERO);
- mtx_init(&dr->dr_mtx, "dircache ref", NULL, MTX_DEF);
+ mtx_init(&dr->dr_mtx, "dircache ref", NULL, MTX_DEF | MTX_DUPOK);
LIST_INIT(&dr->dr_entries);
- dr->dr_ino = ino;
+ dr->dr_id = id;
dr->dr_mount = dm;
dr->dr_vnode = vp;
if (vp != NULL)
MPASS(dm_get(vp) == dr->dr_mount);
- if (ino != 0) {
+ if (id != 0) {
dm_lock(dm);
- col = RB_INSERT(dircache_inotree, &dm->dm_inohead, dr);
- dm->dm_inocnt++;
+ col = RB_INSERT(dircache_idtree, &dm->dm_idhead, dr);
+ dm->dm_idcnt++;
MPASS(col == NULL);
dm_unlock(dm);
}
@@ -322,10 +328,11 @@
if (dr->dr_vnode == NULL && LIST_EMPTY(&dr->dr_entries) &&
dr != dm->dm_rootref && dr != dm->dm_negativeref) {
+ MPASS(RB_EMPTY(&dr->dr_children));
dr_unlock(dr);
dm_lock(dm);
- RB_REMOVE(dircache_inotree, &dm->dm_inohead, dr);
- dm->dm_inocnt--;
+ RB_REMOVE(dircache_idtree, &dm->dm_idhead, dr);
+ dm->dm_idcnt--;
dm_unlock(dm);
uma_zfree(dircache_ref_zone, dr);
} else
@@ -338,17 +345,29 @@
{
struct dircache_ref *dr;
-restart:
dr = vp->v_dircache;
- if (dr == NULL)
- return (NULL);
+ MPASS(dr != NULL);
dr_lock(dr);
- if (vp->v_dircache != dr) {
- dr_unlock(dr);
- goto restart;
- }
+ MPASS(vp->v_dircache == dr);
+ return (dr);
+}
+
+static __inline struct dircache *
+dr_singleentry(struct dircache_ref *dr)
+{
+ struct dircache *dc;
+
+ dc = LIST_FIRST(&dr->dr_entries);
+ MPASS(dc != NULL);
+ MPASS(LIST_NEXT(dc, dc_reflist) == NULL);
+
+ return (dc);
+}
- return (dr);
+static __inline struct dircache_ref *
+dr_parentref(struct dircache_ref *dr)
+{
+ return (dr_singleentry(dr)->dc_parentref);
}
static void
@@ -356,8 +375,8 @@
{
dr_assertlock(dr, MA_OWNED);
- MPASS(dc->dc_ref == NULL);
- dc->dc_ref = dr;
+ MPASS(dc->dc_selfref == NULL);
+ dc->dc_selfref = dr;
DCDEBUG("add ref: vp=%p dc=%p dr=%p\n",
dr->dr_vnode, dc, dr);
if (dr->dr_vnode != NULL && dr->dr_vnode->v_type == VDIR)
@@ -372,7 +391,7 @@
static void
dr_remove(struct dircache_ref *dr, struct dircache *dc)
{
- MPASS(dc->dc_ref == NULL);
+ MPASS(dc->dc_selfref == NULL);
LIST_REMOVE(dc, dc_reflist);
if (dr->dr_vnode != NULL) {
@@ -461,14 +480,13 @@
}
static __inline void
-dc_updategen(struct dircache *dc)
+dr_updategen(struct dircache_ref *dr)
{
static u_long gen = 1;
- dc_assertlock(dc, MA_OWNED);
do {
- dc->dc_gen = atomic_fetchadd_long(&gen, 1);
- } while (__predict_false(dc->dc_gen == 0));
+ dr->dr_gen = atomic_fetchadd_long(&gen, 1);
+ } while (__predict_false(dr->dr_gen == 0));
}
static struct dircache *
@@ -493,9 +511,8 @@
static void
dc_free(struct dircache *dc)
{
- MPASS(RB_EMPTY(&dc->dc_children));
- MPASS(dc->dc_parent == NULL);
- MPASS(dc->dc_ref == NULL);
+ MPASS(dc->dc_parentref == NULL);
+ MPASS(dc->dc_selfref == NULL);
DCDEBUG("free: %p %s\n", dc, dc->dc_name);
if (dc->dc_name != NULL)
@@ -527,10 +544,10 @@
} else {
dc_assertlock(dc, MA_NOTOWNED);
}
- dr = dc->dc_ref;
+ dr = dc->dc_selfref;
if (dr != NULL) {
dr_lock(dr);
- dc->dc_ref = NULL;
+ dc->dc_selfref = NULL;
dr_remove(dr, dc);
}
dc_free(dc);
@@ -575,8 +592,20 @@
return (dc);
}
-static __inline int
-dc_rele_int(struct dircache *dc, int unlock)
+static void
+dc_use_byref(struct dircache_ref *dr)
+{
+ struct dircache *dc;
+
+ dr_assertlock(dr, MA_OWNED);
+ dc = dr_singleentry(dr);
+ dc_lock(dc);
+ dc_use(dc);
+ dc_unlock(dc);
+}
+
+static int
+dc_rele(struct dircache *dc)
{
int dropped;
@@ -584,11 +613,11 @@
MPASS(dc->dc_usecnt > 0);
dc->dc_usecnt--;
- DCDEBUG("rele: %p usecnt=%d holdcnt=%d-1 unlock=%d\n",
- dc, dc->dc_usecnt, dc->dc_holdcnt, unlock);
+ DCDEBUG("rele: %p usecnt=%d holdcnt=%d-1\n",
+ dc, dc->dc_usecnt, dc->dc_holdcnt);
if (dc->dc_usecnt > 0) {
- dropped = dc_drop_int(dc, 1, unlock);
+ dropped = dc_droplocked(dc);
MPASS(dropped == 0);
return (dropped);
}
@@ -600,18 +629,14 @@
}
static int
-dc_rele(struct dircache *dc)
+dc_rele_byref(struct dircache_ref *dr)
{
- return (dc_rele_int(dc, 1));
-}
+ struct dircache *dc;
-#if 0
-static int
-dc_relesafe(struct dircache *dc)
-{
- return (dc_rele_int(dc, 0));
+ dc = dr_singleentry(dr);
+ dc_lock(dc);
+ return (dc_rele(dc));
}
-#endif
static __inline void
dc_invalidate(struct dircache *dc)
@@ -635,15 +660,12 @@
}
static struct dircache *
-dc_getentry(struct vnode *vp, struct componentname *cnp, struct vnode *dvp)
+dc_getentry(struct vnode *vp, struct componentname *cnp, struct dircache_ref *parentref)
{
struct dircache_ref *dr;
struct dircache *dc;
dr = dr_get(vp);
- if (dr == NULL)
- panic("dircache: reference to vnode disappeared: %.*s",
- (int)cnp->cn_namelen, cnp->cn_nameptr);
dc = LIST_FIRST(&dr->dr_entries);
if (dc == NULL) {
dr_unlock(dr);
@@ -656,7 +678,7 @@
return (NULL);
} else {
if (LIST_NEXT(dc, dc_reflist) != NULL) {
- MPASS(cnp != NULL && dvp != NULL);
+ MPASS(cnp != NULL && parentref != NULL);
MPASS(vp->v_type != VDIR);
MPASS(!(cnp->cn_nameptr[0] == '.' &&
(cnp->cn_namelen == 1 || (cnp->cn_namelen == 2 &&
@@ -664,21 +686,17 @@
for(; dc != NULL; dc = LIST_NEXT(dc, dc_reflist)) {
dc_lock(dc);
- if (dc->dc_ref == NULL) {
+ if (dc->dc_selfref == NULL) {
dc_unlock(dc);
continue;
}
- dr_unlock(dr);
- dc_lock(dc->dc_parent);
if (dc_cmpname(dc, cnp->cn_nameptr,
cnp->cn_namelen) == 0 &&
- dvp->v_dircache == dc->dc_parent->dc_ref) {
- dc_unlock(dc->dc_parent);
+ parentref == dc->dc_parentref) {
+ dr_unlock(dr);
break;
}
- dc_unlock(dc->dc_parent);
dc_unlock(dc);
- dr_lock(dr);
}
if (dc == NULL) {
dr_unlock(dr);
@@ -696,71 +714,28 @@
}
dc_assertlock(dc, MA_OWNED);
- MPASS(dc->dc_ref->dr_vnode == vp);
+ MPASS(dc->dc_selfref->dr_vnode == vp);
return (dc);
}
-static int
-dc_parentinterlock(struct dircache *pdc, struct dircache *dc, int *pdcholdp)
-{
- dc_assertlock(pdc, MA_OWNED);
-
- if (dc_trylock(dc) != 0)
- return (0);
-
- if (pdcholdp != NULL && *pdcholdp == 0) {
- dc_hold(pdc);
- *pdcholdp += 1;
- }
-
- dc_hold(dc);
- dc_unlock(pdc);
- dc_lock(dc);
- if (dc->dc_parent != pdc) {
- dc_droplocked(dc);
- dc_lock(pdc);
- return (1);
- }
- if (dc_dropsafe(dc) != 0) {
- dc_lock(pdc);
- return (1);
- }
- dc_lock(pdc);
- return (0);
-}
-
static struct dircache *
-dc_find(struct vnode *dvp, struct componentname *cnp)
+dc_find(struct vnode *dvp, struct componentname *cnp, int flags)
{
struct dircache key;
- struct dircache *pdc, *dc;
- int pdchold;
+ struct dircache_ref *parentref;
+ struct dircache *dc;
- pdc = dc_getentry(dvp, NULL, NULL);
- if (pdc == NULL)
- return (NULL);
- dc_assertlock(pdc, MA_OWNED);
-
- pdchold = 0;
+ parentref = dr_get(dvp);
dc_initname(&key, cnp->cn_nameptr, cnp->cn_namelen);
-restart:
- dc = RB_FIND(dircache_tree, &pdc->dc_children, &key);
- if (dc == NULL) {
- dc_unlock(pdc);
- goto out;
- }
-
- if (dc_parentinterlock(pdc, dc, &pdchold) != 0) {
- DC_STAT_INC(ds_lookup_restart);
- goto restart;
- }
- dc_assertlock(dc, MA_OWNED);
- dc_unlock(pdc);
+ dc = RB_FIND(dircache_tree, &parentref->dr_children, &key);
+ if (dc != NULL) {
+ dc_lock(dc);
+ if ((flags & DC_OP_LOCKPREF) == 0)
+ dr_unlock(parentref);
+ } else
+ dr_unlock(parentref);
-out:
- if (pdchold != 0)
- dc_drop(pdc);
return (dc);
}
@@ -769,43 +744,43 @@
{
struct dircache *child;
- RB_FOREACH(child, dircache_tree, &dc->dc_children) {
+ RB_FOREACH(child, dircache_tree, &dc->dc_selfref->dr_children) {
MPASS(child->dc_type == DT_NEGATIVE);
}
}
-static void dc_removechildren(struct dircache *dc);
+static void dr_removechildren(struct dircache_ref *ref);
static void
-dc_removeentry(struct dircache *dc)
+dc_removeentry(struct dircache *dc, int flags)
{
- struct dircache *parent;
- struct dircache_ref *dr;
+ struct dircache_ref *parentref;
+ struct dircache_ref *selfref;
- MPASS(dc->dc_parent != NULL);
+ MPASS(dc->dc_parentref != NULL);
dc_assertlock(dc, MA_OWNED);
- dc_assertlock(dc->dc_parent, MA_OWNED);
+ dr_assertlock(dc->dc_parentref, MA_OWNED);
dc_assertempty(dc);
DCDEBUG("remove entry: %p %s\n", dc, dc->dc_name);
- parent = dc->dc_parent;
- dc->dc_parent = NULL;
- RB_REMOVE(dircache_tree, &parent->dc_children, dc);
+ parentref = dc->dc_parentref;
+ dc->dc_parentref = NULL;
+ RB_REMOVE(dircache_tree, &parentref->dr_children, dc);
if (dc->dc_type != DT_INVALID);
dc_invalidate(dc);
- dr = dc->dc_ref;
- dc->dc_ref = NULL;
+ selfref = dc->dc_selfref;
+ dc->dc_selfref = NULL;
- dc_rele(parent);
+ dc_unlock(dc);
+ dr_lock(selfref);
- if (!RB_EMPTY(&dc->dc_children)) {
- dc_removechildren(dc);
- } else
- dc_unlock(dc);
-
- dr_lock(dr);
- dr_remove(dr, dc);
+ if (!RB_EMPTY(&selfref->dr_children))
+ dr_removechildren(selfref);
+ dr_remove(selfref, dc);
+ dc_rele_byref(parentref);
+ if ((flags & DC_OP_LOCKPREF) == 0)
+ dr_unlock(parentref);
dc_drop(dc);
}
@@ -813,120 +788,104 @@
static void
dc_marknegative(struct dircache *dc)
{
- struct dircache_mount *dm;
- struct dircache_ref *dr;
+ struct dircache_ref *selfref, *negativeref;
- MPASS(dc->dc_parent != NULL);
+ MPASS(dc->dc_parentref != NULL);
dc_assertlock(dc, MA_OWNED);
- dc_assertlock(dc->dc_parent, MA_OWNED);
+ dr_assertlock(dc->dc_parentref, MA_OWNED);
dc_assertempty(dc);
DCDEBUG("mark negative: %p %s; vp=%p\n",
- dc, dc->dc_name, dc->dc_ref->dr_vnode);
- dc_updategen(dc->dc_parent);
+ dc, dc->dc_name, dc->dc_selfref->dr_vnode);
+ dr_updategen(dc->dc_parentref);
dc->dc_type = DT_NEGATIVE;
- dc_unlock(dc->dc_parent);
- dr = dc->dc_ref;
- dm = dr->dr_mount;
- dc->dc_ref = NULL;
+ selfref = dc->dc_selfref;
+ negativeref = selfref->dr_mount->dm_negativeref;
+ dc->dc_selfref = NULL;
dc_hold(dc);
+ dc_unlock(dc);
+ dr_lock(selfref);
- if (!RB_EMPTY(&dc->dc_children))
- dc_removechildren(dc);
- else
- dc_unlock(dc);
+ dr_removechildren(selfref);
+ dr_remove(selfref, dc);
- dr_lock(dr);
- dr_remove(dr, dc);
-
- dr = dm->dm_negativeref;
- dr_lock(dr);
+ dr_lock(negativeref);
+ dr_unlock(dc->dc_parentref);
dc_lock(dc);
- dr_add(dr, dc);
+ dr_add(negativeref, dc);
dc_unlock(dc);
- dr_unlock(dr);
+ dr_unlock(negativeref);
dc_drop(dc);
}
static void
-dc_removechildren(struct dircache *dc)
+dr_removechildren(struct dircache_ref *ref)
{
struct dircache *child;
- dc_assertlock(dc, MA_OWNED);
+ dr_assertlock(ref, MA_OWNED);
- DCDEBUG("remove children: %p %s\n", dc, dc->dc_name);
- while(!RB_EMPTY(&dc->dc_children)) {
- child = RB_MIN(dircache_tree, &dc->dc_children);
- if (dc_parentinterlock(dc, child, NULL) != 0)
- continue;
- MPASS(RB_EMPTY(&child->dc_children));
- dc_removeentry(child);
- dc_lock(dc);
+ DCDEBUG("remove children: ref=%p\n", ref);
+ 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_unlock(dc);
+
+ dr_assertlock(ref, MA_OWNED);
}
static struct dircache *
-dc_insertentry(struct dircache *pdc, struct dircache *dc)
+dc_insertentry(struct dircache_ref *parentref, struct dircache *dc)
{
struct dircache *col;
- DCDEBUG("insert: parent=%p name=%s dc=%p\n",
- pdc, pdc->dc_name, dc);
+ DCDEBUG("insert: parent=%p dc=%p\n",
+ parentref, dc);
restart:
+ dr_assertlock(parentref, MA_OWNED);
dc_assertlock(dc, MA_OWNED);
- dc_assertlock(pdc, MA_OWNED);
- col = RB_INSERT(dircache_tree, &pdc->dc_children, dc);
+ col = RB_INSERT(dircache_tree, &parentref->dr_children, dc);
if (col != NULL) {
if (dc->dc_type == col->dc_type) {
DCDEBUG("insert: warn: same entry added: %s\n",
dc->dc_name);
- /* TODO
- KASSERT(col->dc_ref == dr,
- ("dircache: entry already exists: %s %p %p\n",
- dc->dc_name, col->dc_ref, dc->dc_ref));
- */
- dc_unlock(pdc);
+ dr_unlock(parentref);
dc_unlock(dc);
dc_drop(dc);
- return (NULL);
+ return (col);
} else if (col->dc_type == DT_NEGATIVE) {
DCDEBUG("insert: replace negative entry: %p %s\n",
dc, dc->dc_name);
dc_unlock(dc);
- if (dc_trylock(col) == 0) {
- dc_unlock(pdc);
- dc_lock(col);
- if (col->dc_parent != pdc) {
- dc_unlock(col);
- dc_lock(dc);
- dc_lock(pdc);
- DC_STAT_INC(ds_insert_restart);
- goto restart;
- }
- dc_lock(pdc);
+ dc_lock(col);
+ if (col->dc_parentref != parentref) {
+ dc_unlock(col);
+ dc_lock(dc);
+ dr_assertlock(parentref, MA_OWNED);
+ DC_STAT_INC(ds_insert_restart);
+ goto restart;
}
- dc_removeentry(col);
+ dc_removeentry(col, DC_OP_LOCKPREF);
dc_lock(dc);
- dc_lock(pdc);
+ dr_assertlock(parentref, MA_OWNED);
goto restart;
} else
panic("dircache: insert: ivalid entry: %d %s\n",
dc->dc_type, dc->dc_name);
} else {
- dc->dc_parent = pdc;
+ dc->dc_parentref = parentref;
dp_unused_insert(dc);
- dc_use(pdc);
+ dc_use_byref(parentref);
dc_hold(dc);
- dc_unlock(pdc);
- dc_updategen(dc);
dc_unlock(dc);
+ dr_unlock(parentref);
}
return (dc);
}
@@ -981,8 +940,8 @@
DC_STAT_INC(ds_clearunused_restart);
continue;
}
- if (dc->dc_parent != NULL) {
- if (dc_trylock(dc->dc_parent) == 0) {
+ if (dc->dc_parentref != NULL) {
+ if (dr_trylock(dc->dc_parentref) == 0) {
dc_unlock(dc);
dc = TAILQ_NEXT(dc, dc_list);
shift++;
@@ -993,8 +952,8 @@
}
}
mtx_unlock(&pool.dp_mtx);
- MPASS(RB_EMPTY(&dc->dc_children));
- dc_removeentry(dc);
+ MPASS(RB_EMPTY(&dc->dc_selfref->dr_children));
+ dc_removeentry(dc, 0);
mtx_lock(&pool.dp_mtx);
dc = TAILQ_FIRST(&pool.dp_unused);
shift = 0;
@@ -1015,6 +974,7 @@
dp_invalid_clear(void)
{
struct dircache *dc;
+ struct dircache_ref *parentref;
mtx_assert(&pool.dp_mtx, MA_OWNED);
@@ -1027,15 +987,23 @@
dc_lock(dc);
if (dc_dropsafe(dc) == 0) {
dc_assertlock(dc, MA_OWNED);
- dc_hold(dc);
- MPASS(dc->dc_ref == NULL);
- if (dc->dc_parent != NULL) {
- dc_lock(dc->dc_parent);
- dc_removeentry(dc);
+ MPASS(dc->dc_selfref == NULL);
+ parentref = dc->dc_parentref;
+ if (parentref != NULL) {
+ dc_hold(dc);
+ dc_unlock(dc);
+ dr_lock(parentref);
dc_lock(dc);
+ if (dc->dc_parentref != parentref) {
+ dr_unlock(parentref);
+ dc_unlock(dc);
+ mtx_lock(&pool.dp_mtx);
+ continue;
+ }
+ dc_removeentry(dc, 0);
+ dc_drop(dc);
} else
- dc_removechildren(dc);
- dc_drop(dc);
+ dc_unlock(dc);
}
mtx_lock(&pool.dp_mtx);
}
@@ -1064,7 +1032,7 @@
}
void
-dircache_init(struct mount *mp, ino_t inode)
+dircache_init(struct mount *mp, uint64_t id)
{
struct dircache_mount *dm;
struct dircache *dc;
@@ -1072,34 +1040,40 @@
dm = malloc(sizeof(struct dircache_mount), M_DIRCACHE,
M_WAITOK | M_ZERO);
mtx_init(&dm->dm_mtx, "dircache mount", NULL, MTX_DEF);
- RB_INIT(&dm->dm_inohead);
+ RB_INIT(&dm->dm_idhead);
dm->dm_negativeref = dr_alloc(dm, NULL, 0);
- dm->dm_rootref = dr_alloc(dm, NULL, inode);
+ 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);
+ 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);
+ 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);
+ } else {
+ MPASS((mp->mnt_kern_flag & MNTK_DIRCACHE) == 0);
+ DCDEBUG("init: weak\n");
+ }
MNT_ILOCK(mp);
mp->mnt_dircache = dm;
MNT_IUNLOCK(mp);
-
- DCDEBUG("init: root=%p %d\n", dc, inode);
}
void
dircache_uninit(struct mount *mp)
{
+ struct dircache_ref *dr, *childref;
struct dircache *dc, *child;
struct dircache_mount *dm;
- int dropped, dchold;
+ int dropped;
MPASS(mp->mnt_dircache != NULL);
@@ -1113,54 +1087,49 @@
MNT_IUNLOCK(mp);
restart:
- dc = LIST_FIRST(&dm->dm_rootref->dr_entries);
- MPASS(LIST_NEXT(dc, dc_reflist) == NULL);
- DCDEBUG("uninit: root=%p\n", dc);
- dc_lock(dc);
+ dr = dm->dm_rootref;
+ dr_lock(dr);
+ DCDEBUG("uninit: rootref=%p\n", dr);
- while (dc != NULL && !RB_EMPTY(&dc->dc_children)) {
+ while (dr != NULL && !RB_EMPTY(&dr->dr_children)) {
nested:
- dc_assertlock(dc, MA_OWNED);
- RB_FOREACH(child, dircache_tree, &dc->dc_children) {
- if (!RB_EMPTY(&child->dc_children)) {
- dchold = 0;
- dropped = dc_parentinterlock(dc, child,
- &dchold);
- if (dchold != 0)
- dc_droplocked(dc);
- else
- dc_unlock(dc);
- if (dropped != 0)
- goto restart;
- dc = child;
- DCDEBUG("uninit: go down: %p %s\n",
- dc, dc->dc_name);
+ dr_assertlock(dr, MA_OWNED);
+ RB_FOREACH(child, dircache_tree, &dr->dr_children) {
+ childref = child->dc_selfref;
+ dr_lock(childref);
+ if (!RB_EMPTY(&childref->dr_children)) {
+ dr_unlock(dr);
+ dr = childref;
+ DCDEBUG("uninit: go down: ref=%p %s\n",
+ childref, child->dc_name);
goto nested;
}
+ dr_unlock(childref);
}
- child = dc;
- dc = dc->dc_parent;
- if (dc != NULL)
- dc_hold(dc);
- dc_hold(child);
- dc_removechildren(child);
- dc_drop(child);
- if (dc != NULL) {
- dc_lock(dc);
- if (dc_dropsafe(dc) != 0)
+ childref = dr;
+ dr = dr_parentref(dr);
+ dr_removechildren(childref);
+ if (dr != NULL) {
+ if (dr_trylock(dr) == 0) {
+ dr_unlock(childref);
goto restart;
- DCDEBUG("uninit: go up: %p %s\n", dc, dc->dc_name);
- }
+ }
+ dr_unlock(childref);
+ DCDEBUG("uninit: go up: ref=%p\n", dr);
+ } else
+ dr_unlock(childref);
}
- if (dc == NULL) {
- dc = LIST_FIRST(&dm->dm_rootref->dr_entries);
- MPASS(LIST_NEXT(dc, dc_reflist) == NULL);
- dc_lock(dc);
>>> TRUNCATED FOR MAIL (1000 lines) <<<
More information about the p4-projects
mailing list