Whamcloud - gitweb
b=9969
authoralex <alex>
Tue, 10 Jan 2006 20:21:52 +0000 (20:21 +0000)
committeralex <alex>
Tue, 10 Jan 2006 20:21:52 +0000 (20:21 +0000)
 - skip invalidated dentries via ll_dcompare()
 - one more patch to the suse series to embed d_name structure into dentry unconditionally

lustre/kernel_patches/patches/dcache-qstr-api-fix-2.6-suse.patch [new file with mode: 0644]
lustre/kernel_patches/series/2.6-suse-newer.series
lustre/llite/dcache.c
lustre/llite/llite_internal.h
lustre/llite/llite_lib.c

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 (file)
index 0000000..64b8bd3
--- /dev/null
@@ -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 <linux/namei.h>
+@@ -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);
++              }
++      }
+ }
+ /*
index c0de646..1c5d31f 100644 (file)
@@ -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 
index f61d2eb..b408b42 100644 (file)
@@ -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",
index 572a5b9..14f9a0c 100644 (file)
@@ -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 */
 
index c35b8c7..a4d05dd 100644 (file)
@@ -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: