Date: Fri, 16 Jul 2010 12:22:27 GMT From: Gleb Kurtsou <gk@FreeBSD.org> To: Perforce Change Reviews <perforce@FreeBSD.org> Subject: PERFORCE change 181047 for review Message-ID: <201007161222.o6GCMREi029515@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://p4web.freebsd.org/@@181047?ac=10 Change 181047 by gk@gk_h1 on 2010/07/16 12:21:43 Refactor to use dircache_ref Affected files ... .. //depot/projects/soc2010/gk_namecache/sys/fs/tmpfs/tmpfs_subr.c#5 edit .. //depot/projects/soc2010/gk_namecache/sys/fs/tmpfs/tmpfs_vnops.c#5 edit .. //depot/projects/soc2010/gk_namecache/sys/kern/vfs_dircache.c#6 edit .. //depot/projects/soc2010/gk_namecache/sys/kern/vfs_subr.c#4 edit .. //depot/projects/soc2010/gk_namecache/sys/sys/dircache.h#6 edit .. //depot/projects/soc2010/gk_namecache/sys/sys/vnode.h#3 edit Differences ... ==== //depot/projects/soc2010/gk_namecache/sys/fs/tmpfs/tmpfs_subr.c#5 (text+ko) ==== @@ -525,7 +525,7 @@ * cannot fail. */ tmpfs_dir_attach(dvp, de); #ifndef NO_DIRCACHE - dircache_add(dvp, *vpp, cnp, DT_STRONG, node->tn_id); + dircache_add(dvp, *vpp, cnp, DT_STRONG); #endif out: ==== //depot/projects/soc2010/gk_namecache/sys/fs/tmpfs/tmpfs_vnops.c#5 (text+ko) ==== @@ -919,7 +919,7 @@ /* Insert the new directory entry into the appropriate directory. */ tmpfs_dir_attach(dvp, de); #ifndef NO_DIRCACHE - dircache_add(dvp, vp, cnp, DT_STRONG, node->tn_id); + dircache_add(dvp, vp, cnp, DT_STRONG); #endif /* vp link count has changed, so update node times. */ ==== //depot/projects/soc2010/gk_namecache/sys/kern/vfs_dircache.c#6 (text+ko) ==== @@ -80,10 +80,14 @@ struct dircache_mount { struct mtx dm_mtx; - LIST_HEAD(, dircache) dm_inodehead; - struct dircache *dm_entry; + LIST_HEAD(, dircache_ref) dm_inohead; + struct dircache_ref *dm_rootref; + struct dircache_ref *dm_negativeref; }; +static struct dircache * dc_use(struct dircache *dc); +static int dc_rele(struct dircache *dc); + static void dp_unused_insert(struct dircache *dc); static void dp_unused_remove(struct dircache *dc); static void dp_unused_lazyclear(void); @@ -96,6 +100,7 @@ static MALLOC_DEFINE(M_DIRCACHE, "dircache buf", "dircache buffers"); static uma_zone_t dircache_zone; +static uma_zone_t dircache_ref_zone; static SYSCTL_NODE(_vfs, OID_AUTO, dircache, CTLFLAG_RW, 0, "Dircache"); static SYSCTL_NODE(_vfs_dircache, OID_AUTO, stats, CTLFLAG_RD, 0, @@ -135,7 +140,6 @@ ds_reclaimvnode, ds_alloc, ds_free, - ds_vinterlock_restart, ds_lookup_restart, ds_insert_restart, ds_clearunused, @@ -183,13 +187,24 @@ DC_STAT_DEFINE(reclaimvnode, ""); DC_STAT_DEFINE(alloc, ""); DC_STAT_DEFINE(free, ""); -DC_STAT_DEFINE(vinterlock_restart, "vnode interlock restarts"); DC_STAT_DEFINE(lookup_restart, "lookup restarts"); DC_STAT_DEFINE(insert_restart, "insert restarts"); DC_STAT_DEFINE(clearunused, ""); DC_STAT_DEFINE(clearunused_restart, ""); DC_STAT_DEFINE(clearinvalid, ""); +#define dm_lock(dm) mtx_lock(&(dm)->dm_mtx) +#define dm_unlock(dm) mtx_unlock(&(dm)->dm_mtx) + +#define dr_assertlock(dr, w) mtx_assert(&(dr)->dr_mtx, (w)) +#define dr_lock(dr) mtx_lock(&(dr)->dr_mtx) +#define dr_unlock(dr) mtx_unlock(&(dr)->dr_mtx) + +#define dc_lock(dc) mtx_lock(&(dc)->dc_mtx) +#define dc_trylock(dc) mtx_trylock(&(dc)->dc_mtx) +#define dc_unlock(dc) mtx_unlock(&(dc)->dc_mtx) +#define dc_assertlock(dc, w) mtx_assert(&(dc)->dc_mtx, (w)) + static void dircache_sysinit(void *arg __unused) { @@ -209,6 +224,10 @@ sizeof(struct dircache), NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, 0); + dircache_ref_zone = uma_zcreate("dircache ref", + sizeof(struct dircache_ref), NULL, NULL, NULL, NULL, + UMA_ALIGN_PTR, 0); + dc_tq = taskqueue_create("dircache tq", M_WAITOK, taskqueue_thread_enqueue, &dc_tq); taskqueue_start_threads(&dc_tq, 1, PWAIT, "dircache taskq"); @@ -223,19 +242,106 @@ MPASS(TAILQ_EMPTY(&pool.dp_invalid)); mtx_destroy(&pool.dp_mtx); uma_zdestroy(dircache_zone); + uma_zdestroy(dircache_ref_zone); } SYSUNINIT(dircache, SI_SUB_VFS, SI_ORDER_SECOND, dircache_sysuninit, NULL); -#define dm_lock(dm) mtx_lock(&(dm)->dm_mtx) - -#define dm_unlock(dm) mtx_unlock(&(dm)->dm_mtx) - static __inline struct dircache_mount * dm_get(struct vnode *vp) { return (vp->v_mount->mnt_dircache); } +static struct dircache_ref * +dr_alloc(struct dircache_mount *dm, struct vnode *vp, ino_t ino) +{ + struct dircache_ref *dr; + + dr = uma_zalloc(dircache_ref_zone, M_WAITOK | M_ZERO); + mtx_init(&dr->dr_mtx, "dircache ref", NULL, MTX_DEF); + LIST_INIT(&dr->dr_entries); + dr->dr_ino = ino; + dr->dr_mount = dm; + dr->dr_vnode = vp; + if (vp != NULL) + MPASS(dm_get(vp) == dr->dr_mount); + if (ino != 0) { + dm_lock(dm); + LIST_INSERT_HEAD(&dm->dm_inohead, dr, dr_inolist); + dm_unlock(dm); + } + + return (dr); +} + +static __inline void +dr_drop(struct dircache_ref *dr) +{ + struct dircache_mount *dm = dr->dr_mount; + + mtx_assert(&dr->dr_mtx, MA_OWNED); + + if (dr->dr_vnode == NULL && LIST_EMPTY(&dr->dr_entries) && + dr != dm->dm_rootref && dr != dm->dm_negativeref) { + dr_unlock(dr); + dm_lock(dm); + LIST_REMOVE(dr, dr_inolist); + dm_unlock(dm); + uma_zfree(dircache_ref_zone, dr); + } else + dr_unlock(dr); + +} + +static struct dircache_ref * +dr_get(struct vnode *vp) +{ + struct dircache_ref *dr; + +restart: + dr = vp->v_dircache; + if (dr == NULL) + return (NULL); + dr_lock(dr); + if (vp->v_dircache != dr) { + dr_unlock(dr); + goto restart; + } + + return (dr); +} + +static void +dr_add(struct dircache_ref *dr, struct dircache *dc) +{ + dr_assertlock(dr, MA_OWNED); + + MPASS(dc->dc_ref == NULL); + dc->dc_ref = 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) + KASSERT(LIST_EMPTY(&dr->dr_entries), + ("dircache: multiple directory vnode references %p", + dr->dr_vnode)); + LIST_INSERT_HEAD(&dr->dr_entries, dc, dc_reflist); + if (dr->dr_vnode != NULL) + dc_use(dc); +} + +static void +dr_remove(struct dircache_ref *dr, struct dircache *dc) +{ + MPASS(dc->dc_ref == NULL); + + LIST_REMOVE(dc, dc_reflist); + if (dr->dr_vnode != NULL) { + dc_lock(dc); + dc_rele(dc); + } + dr_drop(dr); +} + static __inline int dc_cmpname(struct dircache *dc, char *name, u_int namelen) { @@ -265,14 +371,6 @@ RB_GENERATE_STATIC(dircache_tree, dircache, dc_tree, dc_cmp); -#define dc_lock(dc) mtx_lock(&(dc)->dc_mtx) - -#define dc_trylock(dc) mtx_trylock(&(dc)->dc_mtx) - -#define dc_unlock(dc) mtx_unlock(&(dc)->dc_mtx) - -#define dc_assertlock(dc, w) mtx_assert(&(dc)->dc_mtx, (w)) - static __inline void dc_initname(struct dircache *dc, char *name, u_int namelen) { @@ -334,7 +432,7 @@ } static struct dircache * -dc_alloc(struct dircache_mount *dm, enum dircache_type type, +dc_alloc(struct dircache_ref *dr, enum dircache_type type, char *name, u_int namelen) { struct dircache *dc; @@ -342,7 +440,6 @@ dc = uma_zalloc(dircache_zone, M_WAITOK | M_ZERO); DCDEBUG("alloc: %p %s\n", dc, name); - dc->dc_mount = dm; dc->dc_type = type; refcount_init(&dc->dc_holdcnt, 1); mtx_init(&dc->dc_mtx, "dircache entry", NULL, MTX_DEF | MTX_DUPOK); @@ -350,6 +447,13 @@ if (name != NULL && namelen != 0) dc_setname(dc, name, namelen, NULL); + dr_lock(dr); + dc_lock(dc); + dp_unused_insert(dc); + dr_add(dr, dc); + dc_unlock(dc); + dr_unlock(dr); + DC_STAT_INC(ds_alloc); return (dc); } @@ -359,7 +463,7 @@ { MPASS(RB_EMPTY(&dc->dc_children)); MPASS(dc->dc_parent == NULL); - MPASS(dc->dc_vnode == NULL); + MPASS(dc->dc_ref == NULL); DCDEBUG("free: %p %s\n", dc, dc->dc_name); if (dc->dc_name != NULL) @@ -379,6 +483,8 @@ static __inline int dc_drop_int(struct dircache *dc, int islocked, int unlock) { + struct dircache_ref *dr; + DCDEBUG("drop: %p usecnt=%d holdcnt=%d-1\n", dc, dc->dc_usecnt, dc->dc_holdcnt); if (refcount_release(&dc->dc_holdcnt) != 0) { @@ -389,6 +495,12 @@ } else { dc_assertlock(dc, MA_NOTOWNED); } + dr = dc->dc_ref; + if (dr != NULL) { + dr_lock(dr); + dc->dc_ref = NULL; + dr_remove(dr, dc); + } dc_free(dc); return (1); } @@ -416,16 +528,14 @@ } static struct dircache * -dc_ref(struct dircache *dc) +dc_use(struct dircache *dc) { MPASS(dc->dc_type != DT_INVALID); dc_assertlock(dc, MA_OWNED); dc_hold(dc); - if (dc->dc_usecnt == 0) { - MPASS(dc->dc_vnode == NULL); + if (dc->dc_usecnt == 0) dp_unused_remove(dc); - } dc->dc_usecnt++; DCDEBUG("ref: %p usecnt=%d holdcnt=%d\n", dc, dc->dc_usecnt, dc->dc_holdcnt); @@ -451,7 +561,6 @@ return (dropped); } - MPASS(dc->dc_vnode == NULL); dp_unused_insert(dc); dc_droplocked(dc); @@ -464,11 +573,13 @@ return (dc_rele_int(dc, 1)); } +#if 0 static int dc_relesafe(struct dircache *dc) { return (dc_rele_int(dc, 0)); } +#endif static __inline void dc_invalidate(struct dircache *dc) @@ -491,160 +602,53 @@ } } -static void -dc_refvnode(struct dircache *dc, struct vnode *vp) -{ - if (dc->dc_type != DT_ROOT) - dc_assertlock(dc, MA_OWNED); - DCDEBUG("refvnode: %p %s; vp=%p; usecnt=%d\n", dc, dc->dc_name, - vp, dc->dc_usecnt); - - MPASS(vp->v_type != VNON && vp->v_type != VBAD); - MPASS(dc->dc_vnode == NULL); - dc_ref(dc); - dc->dc_vnode = vp; - VI_LOCK(vp); - if (vp->v_type == VDIR && !TAILQ_EMPTY(&vp->v_dircache)) - panic("dircache: multiple directory vnode references %p", vp); - TAILQ_INSERT_HEAD(&vp->v_dircache, dc, dc_list); - VI_UNLOCK(vp); -} - -static void -dc_relevnode(struct dircache *dc, int flags) -{ - MPASS(dc->dc_vnode != NULL); - dc_assertlock(dc, MA_OWNED); - DCDEBUG("relevnode: %p %s; vp=%p; usecnt=%d\n", dc, dc->dc_name, - dc->dc_vnode, dc->dc_usecnt); - - VI_LOCK(dc->dc_vnode); - TAILQ_REMOVE(&dc->dc_vnode->v_dircache, dc, dc_list); - if ((flags & DC_OP_VLOCK) == 0) - VI_UNLOCK(dc->dc_vnode); - dc->dc_vnode = NULL; - dc_rele(dc); -} - -static void -dc_setinode(struct dircache *dc, ino_t inode) -{ - struct dircache_mount *dm = dc->dc_mount; - - dc_assertlock(dc, MA_OWNED); - MPASS(inode != 0); - MPASS(dm != NULL); - MPASS(dc->dc_inode == 0); - - dm_lock(dm); - LIST_INSERT_HEAD(&dm->dm_inodehead, dc, dc_inodelist); - dm_unlock(dm); - dc->dc_inode = inode; -} - -static void -dc_zeroinode(struct dircache *dc) -{ - struct dircache_mount *dm = dc->dc_mount; - - dc_assertlock(dc, MA_OWNED); - MPASS(dm != NULL); - - if (dc->dc_inode == 0) - return; - dm_lock(dm); - LIST_REMOVE(dc, dc_inodelist); - dm_unlock(dm); - dc->dc_inode = 0; -} - -static int -dc_vinterlock(struct vnode *vp, struct dircache *dc) -{ - ASSERT_VI_LOCKED(vp, "dc_vinterlock"); - dc_assertlock(dc, MA_NOTOWNED); - - if (dc_trylock(dc)) { - MPASS(dc->dc_vnode == vp); - VI_UNLOCK(vp); - return (0); - } - - dc_hold(dc); - VI_UNLOCK(vp); - dc_lock(dc); - - if (dc->dc_vnode != vp) { - VI_LOCK(vp); - dc_droplocked(dc); - goto restart; - } - - if (dc_dropsafe(dc) != 0) { - VI_LOCK(vp); - goto restart; - } - - MPASS(dc->dc_vnode == vp); - return (0); - -restart: - DC_STAT_INC(ds_vinterlock_restart); - return (1); -} - static struct dircache * dc_getentry(struct vnode *vp, struct componentname *cnp, struct vnode *dvp) { + struct dircache_ref *dr; struct dircache *dc; -restart: - VI_LOCK(vp); - dc = TAILQ_FIRST(&vp->v_dircache); + 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) { - if ((vp->v_vflag & VV_ROOT) != 0) { - dc = dm_get(vp)->dm_entry; - VI_UNLOCK(vp); - DCDEBUG("getentry: root %p vp=%p\n", dc, vp); - MPASS(dc != NULL); - dc_lock(dc); - dc_refvnode(dc, vp); - } else { - VI_UNLOCK(vp); + dr_unlock(dr); + MPASS((vp->v_vflag & VV_ROOT) == 0); #if 0 - DCDEBUG("getentry: not found vp=%p\n", vp); + DCDEBUG("getentry: not found vp=%p\n", vp); #else - panic("dircache: entry not found for vnode %p\n", vp); + panic("dircache: entry not found for vnode %p\n", vp); #endif - return (NULL); - } + return (NULL); } else { - if (TAILQ_NEXT(dc, dc_list) != NULL) { + if (LIST_NEXT(dc, dc_reflist) != NULL) { MPASS(cnp != NULL && dvp != NULL); MPASS(vp->v_type != VDIR); MPASS(!(cnp->cn_nameptr[0] == '.' && (cnp->cn_namelen == 1 || (cnp->cn_namelen == 2 && cnp->cn_nameptr[1] == '.')))); - for(; dc != NULL; dc = TAILQ_NEXT(dc, dc_list)) { - if (dc_vinterlock(vp, dc) != 0) { - DCDEBUG("getenrty: restart; multiple entries; vp=%p\n", - vp); - goto restart; + for(; dc != NULL; dc = LIST_NEXT(dc, dc_reflist)) { + dc_lock(dc); + if (dc->dc_ref == 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 == dc->dc_parent->dc_vnode) { + dvp->v_dircache == dc->dc_parent->dc_ref) { dc_unlock(dc->dc_parent); break; } dc_unlock(dc->dc_parent); dc_unlock(dc); - VI_LOCK(vp); } if (dc == NULL) { - VI_UNLOCK(vp); + dr_unlock(dr); #if 0 return (NULL); #else @@ -653,16 +657,13 @@ #endif } } else { - if (dc_vinterlock(vp, dc) != 0) { - DCDEBUG("getenrty: restart; node removed; vp=%p\n", - vp); - goto restart; - } + dc_lock(dc); + dr_unlock(dr); } } dc_assertlock(dc, MA_OWNED); - MPASS(dc->dc_vnode == vp); + MPASS(dc->dc_ref->dr_vnode == vp); return (dc); } @@ -730,63 +731,6 @@ return (dc); } -static struct dircache * -dc_insert(struct dircache *pdc, struct dircache *dc, - struct vnode *vp, ino_t inode) -{ - struct dircache *col; - - DCDEBUG("insert: parent=%p name=%s\n", pdc, pdc->dc_name); - -restart: - dc_assertlock(dc, MA_OWNED); - dc_assertlock(pdc, MA_OWNED); - - col = RB_INSERT(dircache_tree, &pdc->dc_children, dc); - if (col != NULL) { - if (dc->dc_type == col->dc_type) { - DCDEBUG("insert: warn: same entry added: %s\n", - dc->dc_name); - MPASS(col->dc_inode == inode); - dc_unlock(pdc); - dc_drop(dc); - return (NULL); - } 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); - } - col->dc_type = dc->dc_type; - dc_setinode(col, inode); - dc_unlock(pdc); - dc_drop(dc); - dc = col; - } else - panic("dircache: insert: ivalid entry: %d %s\n", - dc->dc_type, dc->dc_name); - } else { - dp_unused_insert(dc); - dc->dc_parent = pdc; - dc_ref(pdc); - dc_hold(dc); - dc_unlock(pdc); - } - if (vp != NULL) - dc_refvnode(dc, vp); - return (dc); -} - static __inline void dc_assertempty(struct dircache *dc) { @@ -803,7 +747,7 @@ dc_removeentry(struct dircache *dc) { struct dircache *parent; - int haschildren; + struct dircache_ref *dr; MPASS(dc->dc_parent != NULL); dc_assertlock(dc, MA_OWNED); @@ -816,48 +760,62 @@ RB_REMOVE(dircache_tree, &parent->dc_children, dc); if (dc->dc_type != DT_INVALID); dc_invalidate(dc); - dc_zeroinode(dc); - haschildren = !RB_EMPTY(&dc->dc_children); + + dr = dc->dc_ref; + dc->dc_ref = NULL; + dc_rele(parent); - if (dc->dc_vnode != NULL) { - dc_relevnode(dc, 0); - if (haschildren != 0) - dc_lock(dc); - } else if (haschildren == 0) + + if (!RB_EMPTY(&dc->dc_children)) { + dc_removechildren(dc); + } else dc_unlock(dc); - if (haschildren != 0) - dc_removechildren(dc); + + dr_lock(dr); + dr_remove(dr, dc); + dc_drop(dc); } static void dc_marknegative(struct dircache *dc) { - int haschildren; + struct dircache_mount *dm; + struct dircache_ref *dr; MPASS(dc->dc_parent != NULL); dc_assertlock(dc, MA_OWNED); dc_assertlock(dc->dc_parent, MA_OWNED); dc_assertempty(dc); - DCDEBUG("mark negative: %p %s; vp=%p\n", dc, dc->dc_name, dc->dc_vnode); + DCDEBUG("mark negative: %p %s; vp=%p\n", + dc, dc->dc_name, dc->dc_ref->dr_vnode); dc_updategen(dc->dc_parent); dc->dc_type = DT_NEGATIVE; dc_unlock(dc->dc_parent); - dc_zeroinode(dc); - haschildren = !RB_EMPTY(&dc->dc_children); - if (haschildren != 0) - dc_hold(dc); - if (dc->dc_vnode != NULL) { - dc_relevnode(dc, 0); - if (haschildren != 0) - dc_lock(dc); - } else if (haschildren == 0) + + dr = dc->dc_ref; + dm = dr->dr_mount; + dc->dc_ref = NULL; + + dc_hold(dc); + + if (!RB_EMPTY(&dc->dc_children)) + dc_removechildren(dc); + else dc_unlock(dc); - if (haschildren != 0) { - dc_removechildren(dc); - dc_drop(dc); - } + + dr_lock(dr); + dr_remove(dr, dc); + + dr = dm->dm_negativeref; + dr_lock(dr); + dc_lock(dc); + dr_add(dr, dc); + dc_unlock(dc); + dr_unlock(dr); + + dc_drop(dc); } static void @@ -879,6 +837,58 @@ dc_unlock(dc); } +static struct dircache * +dc_insertentry(struct dircache *pdc, struct dircache *dc) +{ + struct dircache *col; + + DCDEBUG("insert: parent=%p name=%s\n", pdc, pdc->dc_name); + +restart: + dc_assertlock(dc, MA_OWNED); + dc_assertlock(pdc, MA_OWNED); + + col = RB_INSERT(dircache_tree, &pdc->dc_children, dc); + if (col != NULL) { + if (dc->dc_type == col->dc_type) { + DCDEBUG("insert: warn: same entry added: %s\n", + dc->dc_name); + MPASS(col->dc_ref == dc->dc_ref); + dc_unlock(pdc); + dc_drop(dc); + return (NULL); + } 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_removeentry(col); + dc_lock(dc); + dc_lock(pdc); + goto restart; + } else + panic("dircache: insert: ivalid entry: %d %s\n", + dc->dc_type, dc->dc_name); + } else { + dc->dc_parent = pdc; + dc_use(pdc); + dc_hold(dc); + dc_unlock(pdc); + } + return (dc); +} + static void dp_unused_insert(struct dircache *dc) { @@ -976,7 +986,7 @@ if (dc_dropsafe(dc) == 0) { dc_assertlock(dc, MA_OWNED); dc_hold(dc); - MPASS(dc->dc_vnode == NULL); + MPASS(dc->dc_ref->dr_vnode == NULL); if (dc->dc_parent != NULL) { dc_lock(dc->dc_parent); dc_removeentry(dc); @@ -1014,24 +1024,23 @@ void dircache_init(struct mount *mp, ino_t inode) { + struct dircache_mount *dm; struct dircache *dc; - struct dircache_mount *dm; dm = malloc(sizeof(struct dircache_mount), M_DIRCACHE, M_WAITOK | M_ZERO); - mtx_init(&dm->dm_mtx, "dircache root", NULL, MTX_DEF); - LIST_INIT(&dm->dm_inodehead); + mtx_init(&dm->dm_mtx, "dircache mount", NULL, MTX_DEF); + LIST_INIT(&dm->dm_inohead); + dm->dm_negativeref = dr_alloc(dm, NULL, 0); + dm->dm_rootref = dr_alloc(dm, NULL, inode); MPASS(mp->mnt_dircache == NULL); - dc = dc_alloc(dm, DT_ROOT, NULL, 0); - dc_lock(dc); - dp_unused_insert(dc); - dc_setinode(dc, inode); - dm->dm_entry = dc_ref(dc); - dc_unlock(dc); + dc = dc_alloc(dm->dm_rootref, DT_ROOT, NULL, 0); + MNT_ILOCK(mp); mp->mnt_dircache = dm; MNT_IUNLOCK(mp); + DCDEBUG("init: root=%p %d\n", dc, inode); } @@ -1054,8 +1063,9 @@ MNT_IUNLOCK(mp); restart: - DCDEBUG("uninit: root=%p\n", dm->dm_entry); - dc = dm->dm_entry; + dc = LIST_FIRST(&dm->dm_rootref->dr_entries); + MPASS(LIST_NEXT(dc, dc_reflist) == NULL); + DCDEBUG("uninit: root=%p\n", dc); dc_lock(dc); while (dc != NULL && !RB_EMPTY(&dc->dc_children)) { @@ -1094,7 +1104,8 @@ } if (dc == NULL) { - dc = dm->dm_entry; + dc = LIST_FIRST(&dm->dm_rootref->dr_entries); + MPASS(LIST_NEXT(dc, dc_reflist) == NULL); dc_lock(dc); } @@ -1108,13 +1119,14 @@ dp_invalid_clear(); mtx_unlock(&pool.dp_mtx); - MPASS(LIST_EMPTY(&dm->dm_inodehead)); + MPASS(LIST_EMPTY(&dm->dm_inohead)); free(dm, M_DIRCACHE); } void dircache_purge_negative(struct vnode *vp) { +#if 0 TAILQ_HEAD(, dircache) head = TAILQ_HEAD_INITIALIZER(head); struct dircache *dc, *child, *tmp; int r; @@ -1128,9 +1140,9 @@ } if (vp->v_type == VDIR) { MPASS(TAILQ_NEXT(dc, dc_list) == NULL); - if (dc_vinterlock(vp, dc) != 0) + if (dc_refinterlock(vp, dc) != 0) goto restart; - dc_ref(dc); + 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, @@ -1165,6 +1177,7 @@ } VI_UNLOCK(vp); } +#endif } static int @@ -1237,8 +1250,8 @@ error = ENOENT; } DC_STAT_INC(ds_hit_negative); - } else if (dc->dc_vnode != NULL) { - *vpp = dc->dc_vnode; + } else if (dc->dc_ref->dr_vnode != NULL) { + *vpp = dc->dc_ref->dr_vnode; error = -1; DC_STAT_INC(ds_hit); } else { @@ -1272,15 +1285,17 @@ int dircache_add(struct vnode *dvp, struct vnode *vp, struct componentname *cnp, - enum dircache_type type, ino_t inode) + enum dircache_type type) { struct dircache *pdc; struct dircache *ndc; MPASS(type == DT_STRONG || type == DT_WEAK); + MPASS(vp->v_dircache != NULL); - DCDEBUG("add: inode=%d %s; vp=%p\n", inode, cnp->cn_nameptr, vp); - ndc = dc_alloc(dm_get(dvp), type, cnp->cn_nameptr, cnp->cn_namelen); + DCDEBUG("add: %s; vp=%p\n", cnp->cn_nameptr, vp); + ndc = dc_alloc(vp->v_dircache, type, + cnp->cn_nameptr, cnp->cn_namelen); dc_lock(ndc); pdc = dc_getentry(dvp, NULL, NULL); if (pdc == NULL) { @@ -1288,7 +1303,7 @@ DC_STAT_INC(ds_add_error); return (ENOENT); } - ndc = dc_insert(pdc, ndc, vp, inode); + ndc = dc_insertentry(pdc, ndc); if (ndc != NULL) { dc_updategen(ndc); dc_unlock(ndc); @@ -1298,6 +1313,32 @@ } int +dircache_addnegative(struct vnode *dvp, struct componentname *cnp) +{ + struct dircache *pdc; + struct dircache *ndc; + + if (cnp->cn_nameptr[0] == '.' && (cnp->cn_namelen == 1 || + (cnp->cn_namelen == 2 && cnp->cn_nameptr[1] == '.'))) + panic("dircache: set negative for '.' or '..'"); + + ndc = dc_alloc(dm_get(dvp)->dm_negativeref, DT_NEGATIVE, + cnp->cn_nameptr, cnp->cn_namelen); + dc_lock(ndc); + pdc = dc_getentry(dvp, NULL, NULL); + if (pdc == NULL) { + dc_drop(ndc); + DC_STAT_INC(ds_setnegative_error); + return (ENOENT); + } + ndc = dc_insertentry(pdc, ndc); + if (ndc != NULL) + dc_unlock(ndc); + DC_STAT_INC(ds_setnegative); + return (0); +} + +int dircache_remove(struct vnode *dvp, struct vnode *vp, struct componentname *cnp) { struct dircache *dc; @@ -1337,7 +1378,7 @@ if (dc != NULL) { dc_lock(dc->dc_parent); pdc = dc->dc_parent; - dc_ref(pdc); + dc_use(pdc); DCDEBUG("rename: remove target: %p %s; parent=%p\n", dc, dc->dc_name, dc->dc_parent); dc_updategen(dc->dc_parent); @@ -1345,7 +1386,7 @@ } else { pdc = dc_getentry(tdvp, NULL, NULL); MPASS(pdc != NULL); - dc_ref(pdc); + dc_use(pdc); dc_unlock(pdc); } @@ -1421,72 +1462,48 @@ return (0); } -int -dircache_setnegative(struct vnode *dvp, struct componentname *cnp) +void +dircache_allocvnode(struct vnode *vp, ino_t ino) { - struct dircache *pdc; - struct dircache *ndc; + struct dircache *dc; + struct dircache_mount *dm; + struct dircache_ref *dr; + + MPASS(vp->v_type != VNON && vp->v_type != VBAD); + MPASS(vp->v_dircache == NULL); - if (cnp->cn_nameptr[0] == '.' && (cnp->cn_namelen == 1 || - (cnp->cn_namelen == 2 && cnp->cn_nameptr[1] == '.'))) - panic("dircache: set negative for '.' or '..'"); + dm = dm_get(vp); - ndc = dc_alloc(dm_get(dvp), DT_NEGATIVE, cnp->cn_nameptr, - cnp->cn_namelen); - dc_lock(ndc); - pdc = dc_getentry(dvp, NULL, NULL); - if (pdc == NULL) { - dc_drop(ndc); - DC_STAT_INC(ds_setnegative_error); - return (ENOENT); + dm_lock(dm); + LIST_FOREACH(dr, &dm->dm_inohead, dr_inolist) { + if (dr->dr_ino == ino) + break; } - ndc = dc_insert(pdc, ndc, NULL, 0); - if (ndc != NULL) - dc_unlock(ndc); - DC_STAT_INC(ds_setnegative); - return (0); -} + dm_unlock(dm); + + if (dr == NULL) + dr = dr_alloc(dm_get(vp), vp, ino); -int >>> TRUNCATED FOR MAIL (1000 lines) <<<
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201007161222.o6GCMREi029515>