Whamcloud - gitweb
Branch b1_6
authorfanyong <fanyong>
Sat, 26 Apr 2008 14:30:54 +0000 (14:30 +0000)
committerfanyong <fanyong>
Sat, 26 Apr 2008 14:30:54 +0000 (14:30 +0000)
b=15658
i=huanghua
i=tappro

Support directory read ahead under patchless client mode.
When "ls" a dentry, the system trigger more than once "revalidate" or
"lookup", for "getattr", for "getxattr", and maybe for others.
Under patchless client mode, the operation intent is not accurate,
it maybe misguide the statahead thread. For example:
The "revalidate" call for "getattr" and "getxattr" of a dentry maybe
have the same operation intent -- "IT_GETATTR".
In fact, one dentry should has only one chance to interact with the
statahead thread, otherwise the statahead windows will be confused.

lustre/llite/llite_internal.h
lustre/llite/statahead.c

index 3ae815a..10fed7c 100644 (file)
@@ -56,6 +56,7 @@ struct ll_dentry_data {
 #ifndef HAVE_VFS_INTENT_PATCHES
         struct lookup_intent    *lld_it;
 #endif
+        unsigned int             lld_sa_generation;
         cfs_waitq_t              lld_waitq;
 };
 
@@ -883,6 +884,7 @@ int ll_statahead_enter(struct inode *dir, struct dentry **dentryp, int lookup)
 {
         struct ll_sb_info        *sbi = ll_i2sbi(dir);
         struct ll_inode_info     *lli = ll_i2info(dir);
+        struct ll_dentry_data    *ldd = ll_d2d(*dentryp);
 
         if (sbi->ll_sa_max == 0)
                 return -ENOTSUPP;
@@ -891,6 +893,25 @@ int ll_statahead_enter(struct inode *dir, struct dentry **dentryp, int lookup)
         if (lli->lli_opendir_pid != cfs_curproc_pid())
                 return -EBADF;
 
+        /*
+         * When "ls" a dentry, the system trigger more than once "revalidate" or
+         * "lookup", for "getattr", for "getxattr", and maybe for others.
+         * Under patchless client mode, the operation intent is not accurate,
+         * it maybe misguide the statahead thread. For example:
+         * The "revalidate" call for "getattr" and "getxattr" of a dentry maybe
+         * have the same operation intent -- "IT_GETATTR".
+         * In fact, one dentry should has only one chance to interact with the
+         * statahead thread, otherwise the statahead windows will be confused.
+         * The solution is as following:
+         * Assign "lld_sa_generation" with "sai_generation" when a dentry
+         * "IT_GETATTR" for the first time, and the subsequent "IT_GETATTR"
+         * will bypass interacting with statahead thread for checking:
+         * "lld_sa_generation == lli_sai->sai_generation"
+         */ 
+        if (ldd && lli->lli_sai &&
+            ldd->lld_sa_generation == lli->lli_sai->sai_generation)
+                return -EAGAIN;
+
         return do_statahead_enter(dir, dentryp, lookup);
 }
 
index 24b245d..2692b96 100644 (file)
@@ -58,6 +58,8 @@ static struct ll_statahead_info *ll_sai_alloc(void)
 
         spin_lock(&sai_generation_lock);
         sai->sai_generation = ++sai_generation;
+        if (unlikely(sai_generation == 0))
+                sai->sai_generation = ++sai_generation;
         spin_unlock(&sai_generation_lock);
         atomic_set(&sai->sai_refcount, 1);
         sai->sai_max = LL_SA_RPC_MIN;
@@ -90,8 +92,8 @@ static void ll_sai_put(struct ll_statahead_info *sai)
                 LASSERT(sai->sai_thread.t_flags & SVC_STOPPED);
 
                 if (sai->sai_sent > sai->sai_replied)
-                        CWARN("statahead for dir %lu/%u does not finish: "
-                              "[sent:%u] [replied:%u]\n",
+                        CDEBUG(D_READA,"statahead for dir %lu/%u does not "
+                              "finish: [sent:%u] [replied:%u]\n",
                               inode->i_ino, inode->i_generation,
                               sai->sai_sent, sai->sai_replied);
 
@@ -886,9 +888,10 @@ int do_statahead_enter(struct inode *dir, struct dentry **dentryp, int lookup)
 /* update hit/miss count */
 void ll_statahead_exit(struct dentry *dentry, int result)
 {
-        struct dentry        *parent = dentry->d_parent;
-        struct ll_inode_info *lli = ll_i2info(parent->d_inode);
-        struct ll_sb_info    *sbi = ll_i2sbi(parent->d_inode);
+        struct dentry         *parent = dentry->d_parent;
+        struct ll_inode_info  *lli = ll_i2info(parent->d_inode);
+        struct ll_sb_info     *sbi = ll_i2sbi(parent->d_inode);
+        struct ll_dentry_data *ldd = ll_d2d(dentry);
 
         if (lli->lli_opendir_pid != cfs_curproc_pid())
                 return;
@@ -921,7 +924,11 @@ void ll_statahead_exit(struct dentry *dentry, int result)
                                 spin_unlock(&lli->lli_lock);
                         }
                 }
+
                 cfs_waitq_signal(&sai->sai_thread.t_ctl_waitq);
                 ll_sai_entry_put(sai);
+
+                if (likely(ldd != NULL))
+                        ldd->lld_sa_generation = sai->sai_generation;
         }
 }