Index: linux-2.6.17-rc6-mm2/fs/dcache.c =================================================================== --- linux-2.6.17-rc6-mm2.orig/fs/dcache.c 2006-06-10 11:11:52.568029305 -0700 +++ linux-2.6.17-rc6-mm2/fs/dcache.c 2006-06-14 19:12:10.808183118 -0700 @@ -68,15 +68,6 @@ struct dentry_stat_t dentry_stat = { .age_limit = 45, }; -static void d_callback(struct rcu_head *head) -{ - struct dentry * dentry = container_of(head, struct dentry, d_u.d_rcu); - - if (dname_external(dentry)) - kfree(dentry->d_name.name); - kmem_cache_free(dentry_cache, dentry); -} - /* * no dcache_lock, please. The caller must decrement dentry_stat.nr_dentry * inside dcache_lock. @@ -85,7 +76,9 @@ static void d_free(struct dentry *dentry { if (dentry->d_op && dentry->d_op->d_release) dentry->d_op->d_release(dentry); - call_rcu(&dentry->d_u.d_rcu, d_callback); + if (dname_external(dentry)) + kfree(dentry->d_name.name); + kmem_cache_free(dentry_cache, dentry); } /* @@ -1112,7 +1105,7 @@ struct dentry * __d_lookup(struct dentry struct dentry *dentry; rcu_read_lock(); - + hlist_for_each_entry_rcu(dentry, node, head, d_hash) { struct qstr *qstr; @@ -1148,8 +1141,13 @@ struct dentry * __d_lookup(struct dentry if (!d_unhashed(dentry)) { atomic_inc(&dentry->d_count); + /* + * Now we have a stable reference. + * Check that the object was not switched by RCU + */ found = dentry; } + spin_unlock(&dentry->d_lock); break; next: @@ -1759,8 +1757,8 @@ static void __init dcache_init(unsigned sizeof(struct dentry), 0, (SLAB_RECLAIM_ACCOUNT|SLAB_PANIC| - SLAB_MEM_SPREAD), - NULL, NULL); + SLAB_MEM_SPREAD|SLAB_DESTROY_BY_RCU), + dentry_ctor, NULL); shrinker = set_shrinker(DEFAULT_SEEKS, shrink_dcache_memory); kmem_set_shrinker(dentry_cache, shrinker); Index: linux-2.6.17-rc6-mm2/include/linux/dcache.h =================================================================== --- linux-2.6.17-rc6-mm2.orig/include/linux/dcache.h 2006-06-10 11:11:56.696679941 -0700 +++ linux-2.6.17-rc6-mm2/include/linux/dcache.h 2006-06-14 18:11:22.399108536 -0700 @@ -94,13 +94,7 @@ struct dentry { struct qstr d_name; struct list_head d_lru; /* LRU list */ - /* - * d_child and d_rcu can share memory - */ - union { - struct list_head d_child; /* child of parent list */ - struct rcu_head d_rcu; - } d_u; + struct list_head d_child; /* child of parent list */ struct list_head d_subdirs; /* our children */ struct list_head d_alias; /* inode alias list */ unsigned long d_time; /* used by d_revalidate */