From 5de3e2dfa39db87241536b43fa754cd1ed121330 Mon Sep 17 00:00:00 2001 From: fanyong <fanyong> Date: Sat, 26 Apr 2008 14:30:54 +0000 Subject: [PATCH] Branch b1_6 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 | 21 +++++++++++++++++++++ lustre/llite/statahead.c | 17 ++++++++++++----- 2 files changed, 33 insertions(+), 5 deletions(-) diff --git a/lustre/llite/llite_internal.h b/lustre/llite/llite_internal.h index 3ae815a1bf..10fed7c7e0 100644 --- a/lustre/llite/llite_internal.h +++ b/lustre/llite/llite_internal.h @@ -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); } diff --git a/lustre/llite/statahead.c b/lustre/llite/statahead.c index 24b245d865..2692b96dd7 100644 --- a/lustre/llite/statahead.c +++ b/lustre/llite/statahead.c @@ -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; } } -- GitLab