#ifndef HAVE_VFS_INTENT_PATCHES
struct lookup_intent *lld_it;
#endif
+ unsigned int lld_sa_generation;
cfs_waitq_t lld_waitq;
};
{
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;
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);
}
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;
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);
/* 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;
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;
}
}