From bd7d02e98c5d210f669641155564040224026cff Mon Sep 17 00:00:00 2001 From: alex Date: Tue, 10 Jan 2006 20:21:52 +0000 Subject: [PATCH] b=9969 - skip invalidated dentries via ll_dcompare() - one more patch to the suse series to embed d_name structure into dentry unconditionally --- .../patches/dcache-qstr-api-fix-2.6-suse.patch | 148 +++++++++++++++++++++ lustre/kernel_patches/series/2.6-suse-newer.series | 1 + lustre/llite/dcache.c | 4 +- lustre/llite/llite_internal.h | 1 + lustre/llite/llite_lib.c | 5 + 5 files changed, 157 insertions(+), 2 deletions(-) create mode 100644 lustre/kernel_patches/patches/dcache-qstr-api-fix-2.6-suse.patch diff --git a/lustre/kernel_patches/patches/dcache-qstr-api-fix-2.6-suse.patch b/lustre/kernel_patches/patches/dcache-qstr-api-fix-2.6-suse.patch new file mode 100644 index 0000000..64b8bd3 --- /dev/null +++ b/lustre/kernel_patches/patches/dcache-qstr-api-fix-2.6-suse.patch @@ -0,0 +1,148 @@ +Index: linux-2.6.5-7.201/include/linux/dcache.h +=================================================================== +--- linux-2.6.5-7.201.orig/include/linux/dcache.h 2005-10-11 00:12:48.000000000 +0400 ++++ linux-2.6.5-7.201/include/linux/dcache.h 2005-12-20 23:16:31.000000000 +0300 +@@ -38,7 +38,6 @@ struct qstr { + const unsigned char * name; + unsigned int len; + unsigned int hash; +- char name_str[0]; + }; + + #include +@@ -104,7 +103,6 @@ struct dentry { + struct rcu_head d_rcu; + struct dcookie_struct * d_cookie; /* cookie, if any */ + unsigned long d_move_count; /* to indicated moved dentry while lockless lookup */ +- struct qstr * d_qstr; /* quick str ptr used in lockless lookup and concurrent d_move */ + struct dentry * d_parent; /* parent directory */ + struct qstr d_name; + struct hlist_node d_hash; /* lookup hash list */ +Index: linux-2.6.5-7.201/fs/dcache.c +=================================================================== +--- linux-2.6.5-7.201.orig/fs/dcache.c 2005-10-11 00:12:45.000000000 +0400 ++++ linux-2.6.5-7.201/fs/dcache.c 2005-12-20 23:16:31.000000000 +0300 +@@ -41,6 +41,8 @@ EXPORT_SYMBOL(dcache_lock); + + static kmem_cache_t *dentry_cache; + ++#define DNAME_INLINE_LEN (sizeof(struct dentry)-offsetof(struct dentry,d_iname)) ++ + /* + * This is the single most critical data structure when it comes + * to the dcache: the hashtable for lookups. Somebody should try +@@ -67,7 +69,7 @@ static void d_callback(void *arg) + struct dentry * dentry = (struct dentry *)arg; + + if (dname_external(dentry)) { +- kfree(dentry->d_qstr); ++ kfree(dentry->d_name.name); + } + kmem_cache_free(dentry_cache, dentry); + } +@@ -678,8 +680,6 @@ static int shrink_dcache_memory(int nr, + return dentry_stat.nr_unused; + } + +-#define NAME_ALLOC_LEN(len) ((len+16) & ~15) +- + /** + * d_alloc - allocate a dcache entry + * @parent: parent of entry to allocate +@@ -694,26 +694,18 @@ struct dentry * d_alloc(struct dentry * + { + char * str; + struct dentry *dentry; +- struct qstr * qstr; + + dentry = kmem_cache_alloc(dentry_cache, GFP_KERNEL); + if (!dentry) + return NULL; + + if (name->len > DNAME_INLINE_LEN-1) { +- qstr = kmalloc(sizeof(*qstr) + NAME_ALLOC_LEN(name->len), +- GFP_KERNEL); +- if (!qstr) { ++ str = kmalloc(name->len + 1, GFP_KERNEL); ++ if (!str) { + kmem_cache_free(dentry_cache, dentry); + return NULL; + } +- qstr->name = qstr->name_str; +- qstr->len = name->len; +- qstr->hash = name->hash; +- dentry->d_qstr = qstr; +- str = qstr->name_str; + } else { +- dentry->d_qstr = &dentry->d_name; + str = dentry->d_iname; + } + +@@ -1010,7 +1002,7 @@ struct dentry * __d_lookup(struct dentry + if (dentry->d_parent != parent) + continue; + +- qstr = dentry->d_qstr; ++ qstr = &dentry->d_name; + smp_read_barrier_depends(); + if (parent->d_op && parent->d_op->d_compare) { + if (parent->d_op->d_compare(parent, qstr, name)) +@@ -1163,26 +1155,38 @@ void d_rehash(struct dentry * entry) + */ + static inline void switch_names(struct dentry * dentry, struct dentry * target) + { +- const unsigned char *old_name, *new_name; +- struct qstr *old_qstr, *new_qstr; +- +- memcpy(dentry->d_iname, target->d_iname, DNAME_INLINE_LEN); +- old_qstr = target->d_qstr; +- old_name = target->d_name.name; +- new_qstr = dentry->d_qstr; +- new_name = dentry->d_name.name; +- if (old_name == target->d_iname) { +- old_name = dentry->d_iname; +- old_qstr = &dentry->d_name; +- } +- if (new_name == dentry->d_iname) { +- new_name = target->d_iname; +- new_qstr = &target->d_name; +- } +- target->d_name.name = new_name; +- dentry->d_name.name = old_name; +- target->d_qstr = new_qstr; +- dentry->d_qstr = old_qstr; ++ if (dname_external(target)) { ++ if (dname_external(dentry)) { ++ /* ++ * Both external: swap the pointers ++ */ ++ do_switch(target->d_name.name, dentry->d_name.name); ++ } else { ++ /* ++ * dentry:internal, target:external. Steal target's ++ * storage and make target internal. ++ */ ++ dentry->d_name.name = target->d_name.name; ++ target->d_name.name = target->d_iname; ++ } ++ } else { ++ if (dname_external(dentry)) { ++ /* ++ * dentry:external, target:internal. Give dentry's ++ * storage to target and make dentry internal ++ */ ++ memcpy(dentry->d_iname, target->d_name.name, ++ target->d_name.len + 1); ++ target->d_name.name = dentry->d_name.name; ++ dentry->d_name.name = dentry->d_iname; ++ } else { ++ /* ++ * Both are internal. Just copy target to dentry ++ */ ++ memcpy(dentry->d_iname, target->d_name.name, ++ target->d_name.len + 1); ++ } ++ } + } + + /* diff --git a/lustre/kernel_patches/series/2.6-suse-newer.series b/lustre/kernel_patches/series/2.6-suse-newer.series index c0de646..1c5d31f 100644 --- a/lustre/kernel_patches/series/2.6-suse-newer.series +++ b/lustre/kernel_patches/series/2.6-suse-newer.series @@ -6,3 +6,4 @@ blkdev_tunables-2.6-suse.patch uml-exprt-clearuser.patch qsnet-suse-2.6.patch fsprivate-2.6.patch +dcache-qstr-api-fix-2.6-suse.patch diff --git a/lustre/llite/dcache.c b/lustre/llite/dcache.c index f61d2eb..b408b42 100644 --- a/lustre/llite/dcache.c +++ b/lustre/llite/dcache.c @@ -59,8 +59,7 @@ static void ll_release(struct dentry *de) * an AST before calling d_revalidate_it(). The dentry still exists (marked * INVALID) so d_lookup() matches it, but we have no lock on it (so * lock_match() fails) and we spin around real_lookup(). */ -static int ll_dcompare(struct dentry *parent, struct qstr *d_name, - struct qstr *name) +int ll_dcompare(struct dentry *parent, struct qstr *d_name, struct qstr *name) { struct dentry *dchild; ENTRY; @@ -71,6 +70,7 @@ static int ll_dcompare(struct dentry *parent, struct qstr *d_name, if (memcmp(d_name->name, name->name, name->len)) RETURN(1); + /* XXX: d_name must be in-dentry structure */ dchild = container_of(d_name, struct dentry, d_name); /* ugh */ if (dchild->d_flags & DCACHE_LUSTRE_INVALID) { CDEBUG(D_DENTRY,"INVALID dentry %p not matched, was bug 3784\n", diff --git a/lustre/llite/llite_internal.h b/lustre/llite/llite_internal.h index 572a5b9..14f9a0c 100644 --- a/lustre/llite/llite_internal.h +++ b/lustre/llite/llite_internal.h @@ -391,6 +391,7 @@ extern void ll_set_dd(struct dentry *de); void ll_unhash_aliases(struct inode *); void ll_frob_intent(struct lookup_intent **itp, struct lookup_intent *deft); void ll_lookup_finish_locks(struct lookup_intent *it, struct dentry *dentry); +int ll_dcompare(struct dentry *parent, struct qstr *d_name, struct qstr *name); /* llite/llite_lib.c */ diff --git a/lustre/llite/llite_lib.c b/lustre/llite/llite_lib.c index c35b8c7..a4d05dd 100644 --- a/lustre/llite/llite_lib.c +++ b/lustre/llite/llite_lib.c @@ -123,6 +123,10 @@ void lustre_free_sbi(struct super_block *sb) EXIT; } +static struct dentry_operations ll_d_root_ops = { + .d_compare = ll_dcompare, +}; + int lustre_common_fill_super(struct super_block *sb, char *mdc, char *osc) { struct inode *root = 0; @@ -330,6 +334,7 @@ int lustre_common_fill_super(struct super_block *sb, char *mdc, char *osc) sb->s_root = d_alloc_root(root); if (data != NULL) OBD_FREE(data, sizeof(*data)); + sb->s_root->d_op = &ll_d_root_ops; RETURN(err); out_root: -- 1.8.3.1