Whamcloud - gitweb
add workaround for race in dcache with patchless client.
authorshadow <shadow>
Mon, 8 Sep 2008 08:57:42 +0000 (08:57 +0000)
committershadow <shadow>
Mon, 8 Sep 2008 08:57:42 +0000 (08:57 +0000)
Branch b1_6
b=15975
i=johann
i=adilger

lustre/ChangeLog
lustre/llite/dcache.c
lustre/llite/file.c
lustre/llite/llite_internal.h
lustre/llite/namei.c

index 8a05fe9..9ea69c8 100644 (file)
@@ -38,6 +38,7 @@ tbd Sun Microsystems, Inc.
        * Output of lfs quota has been made less detailed by default,
          old (verbose) output can be obtained by using -v option.
 
+
 Severity   : normal
 Bugzilla   : 16907
 Description: Prevent import from entering FULL state when server in recovery
@@ -153,6 +154,11 @@ Details    : Apply the MGS_CONNECT_SUPPORTED mask at reconnect time so
          old (verbose) output can be obtained by using -v option.
 
 Severity   : normal
+Bugzilla   : 15975
+Frequency  : only patchless client
+Description: add workaround for race between add/remove dentry from hash
+
+Severity   : normal
 Bugzilla   : 15139
 Frequency  : rare
 Description: avoid ASSERTION(client_stat->nid_exp_ref_count == 0) failed
index 1730caf..0d9510a 100644 (file)
@@ -49,6 +49,8 @@
 
 #include "llite_internal.h"
 
+spinlock_t ll_lookup_lock = SPIN_LOCK_UNLOCKED;
+
 /* should NOT be called with the dcache lock, see fs/dcache.c */
 void ll_release(struct dentry *de)
 {
@@ -206,7 +208,9 @@ int ll_drop_dentry(struct dentry *dentry)
                 __d_drop(dentry);
                 unlock_dentry(dentry);
                 spin_unlock(&dcache_lock);
+                spin_unlock(&ll_lookup_lock);
                 dput(dentry);
+                spin_lock(&ll_lookup_lock);
                 spin_lock(&dcache_lock);
                 return 1;
         }
@@ -263,6 +267,7 @@ void ll_unhash_aliases(struct inode *inode)
                inode->i_ino, inode->i_generation, inode);
 
         head = &inode->i_dentry;
+        spin_lock(&ll_lookup_lock);
         spin_lock(&dcache_lock);
 restart:
         tmp = head;
@@ -291,6 +296,8 @@ restart:
                           goto restart;
         }
         spin_unlock(&dcache_lock);
+        spin_unlock(&ll_lookup_lock);
+
         EXIT;
 }
 
@@ -491,12 +498,14 @@ revalidate_finish:
 
         /* unfortunately ll_intent_lock may cause a callback and revoke our
          * dentry */
+        spin_lock(&ll_lookup_lock);
         spin_lock(&dcache_lock);
         lock_dentry(de);
         __d_drop(de);
         unlock_dentry(de);
         d_rehash_cond(de, 0);
         spin_unlock(&dcache_lock);
+        spin_unlock(&ll_lookup_lock);
 
  out:
         /* We do not free request as it may be reused during following lookup
index 86d836c..d31f23d 100644 (file)
@@ -2979,9 +2979,11 @@ int ll_inode_revalidate_it(struct dentry *dentry, struct lookup_intent *it)
                    here to preserve get_cwd functionality on 2.6.
                    Bug 10503 */
                 if (!dentry->d_inode->i_nlink) {
+                        spin_lock(&ll_lookup_lock);
                         spin_lock(&dcache_lock);
                         ll_drop_dentry(dentry);
                         spin_unlock(&dcache_lock);
+                        spin_unlock(&ll_lookup_lock);
                 }
 
                 ll_lookup_finish_locks(&oit, dentry);
index 1a38d4a..d004c38 100644 (file)
@@ -590,7 +590,6 @@ static inline unsigned long dir_pages(struct inode *inode)
         return (inode->i_size + CFS_PAGE_SIZE - 1) >> CFS_PAGE_SHIFT;
 }
 
-/* llite/namei.c */
 int ll_objects_destroy(struct ptlrpc_request *request, struct inode *dir);
 struct inode *ll_iget(struct super_block *sb, ino_t hash,
                       struct lustre_md *lic);
@@ -687,6 +686,11 @@ int ll_fiemap(struct inode *inode, struct ll_user_fiemap *fiemap,
               int num_bytes);
 
 /* llite/dcache.c */
+/* llite/namei.c */
+/**
+ * protect race ll_find_aliases vs ll_revalidate_it vs ll_unhash_aliases
+ */
+extern spinlock_t ll_lookup_lock;
 extern struct dentry_operations ll_init_d_ops;
 extern struct dentry_operations ll_d_ops;
 extern struct dentry_operations ll_fini_d_ops;
index 860ece9..435f9ec 100644 (file)
@@ -167,6 +167,7 @@ static void ll_drop_negative_dentry(struct inode *dir)
 { 
         struct dentry *dentry, *tmp_alias, *tmp_subdir;
 
+        spin_lock(&ll_lookup_lock);
         spin_lock(&dcache_lock);
 restart:
         list_for_each_entry_safe(dentry, tmp_alias,
@@ -187,6 +188,7 @@ restart:
                 }
         }
         spin_unlock(&dcache_lock);
+        spin_unlock(&ll_lookup_lock);
 }
 
 int ll_mdc_blocking_ast(struct ldlm_lock *lock, struct ldlm_lock_desc *desc,
@@ -393,6 +395,7 @@ static struct dentry *ll_find_alias(struct inode *inode, struct dentry *de)
         struct dentry *dentry;
         struct dentry *last_discon = NULL;
 
+        spin_lock(&ll_lookup_lock);
         spin_lock(&dcache_lock);
         list_for_each(tmp, &inode->i_dentry) {
                 dentry = list_entry(tmp, struct dentry, d_alias);
@@ -431,6 +434,7 @@ static struct dentry *ll_find_alias(struct inode *inode, struct dentry *de)
                 unlock_dentry(dentry);
                 d_rehash_cond(dentry, 0); /* avoid taking dcache_lock inside */
                 spin_unlock(&dcache_lock);
+                spin_unlock(&ll_lookup_lock);
                 iput(inode);
                 CDEBUG(D_DENTRY, "alias dentry %.*s (%p) parent %p inode %p "
                        "refc %d\n", de->d_name.len, de->d_name.name, de,
@@ -445,6 +449,8 @@ static struct dentry *ll_find_alias(struct inode *inode, struct dentry *de)
                  spin_unlock(&dcache_lock);
                  d_rehash(de);
                  d_move(last_discon, de);
+                 spin_unlock(&ll_lookup_lock);
+
                  iput(inode);
                  return last_discon;
         }
@@ -452,6 +458,7 @@ static struct dentry *ll_find_alias(struct inode *inode, struct dentry *de)
         ll_d_add(de, inode);
 
         spin_unlock(&dcache_lock);
+        spin_unlock(&ll_lookup_lock);
 
         return de;
 }