From fe10f991534936fcee413836e88b06d6bf7992b5 Mon Sep 17 00:00:00 2001 From: Lai Siyao Date: Mon, 9 Apr 2012 15:33:29 +0800 Subject: [PATCH] LU-506 statahead: revalidating dentry may be stale The revalidating dentry may be stale (other client recreated this file), so the statahead inode can be different from dentry inode. Return -ESTALE instead of LASSERT here. And for this kind of dentry, it shouldn't be revalidated, but dropped and re-lookup. To achieve this, if ll_statahead_enter() fails to get a valid dentry, and the return value is not 0 or -EAGAIN, ll_revalidate_it() should return 0 directly, and let VFS calls .lookup to get a new dentry. Signed-off-by: Lai Siyao Change-Id: I3eae450069a59d18d138d0cf7538a225e6d6deb8 Reviewed-on: http://review.whamcloud.com/2492 Reviewed-by: Fan Yong Reviewed-by: Peng Tao Tested-by: Hudson Tested-by: Maloo Reviewed-by: Oleg Drokin --- lustre/llite/dcache.c | 2 ++ lustre/llite/llite_internal.h | 2 +- lustre/llite/statahead.c | 19 +++++++++++++++---- 3 files changed, 18 insertions(+), 5 deletions(-) diff --git a/lustre/llite/dcache.c b/lustre/llite/dcache.c index 0c24635..044faf7 100644 --- a/lustre/llite/dcache.c +++ b/lustre/llite/dcache.c @@ -504,6 +504,8 @@ int ll_revalidate_it(struct dentry *de, int lookup_flags, rc = ll_statahead_enter(parent, &de, 0); if (rc == 1) goto mark; + else if (rc != -EAGAIN && rc != 0) + GOTO(out, rc = 0); } do_lock: diff --git a/lustre/llite/llite_internal.h b/lustre/llite/llite_internal.h index ab3cdf1..f5e54f7 100644 --- a/lustre/llite/llite_internal.h +++ b/lustre/llite/llite_internal.h @@ -1267,7 +1267,7 @@ ll_statahead_enter(struct inode *dir, struct dentry **dentryp, int only_unplug) struct ll_dentry_data *ldd; if (ll_i2sbi(dir)->ll_sa_max == 0) - return -ENOTSUPP; + return -EAGAIN; lli = ll_i2info(dir); /* not the same process, don't statahead */ diff --git a/lustre/llite/statahead.c b/lustre/llite/statahead.c index 81d2bd0..0b06d9b 100644 --- a/lustre/llite/statahead.c +++ b/lustre/llite/statahead.c @@ -1660,9 +1660,20 @@ int do_statahead_enter(struct inode *dir, struct dentry **dentryp, lld = ll_d2d(*dentryp); if (unlikely(lld == NULL)) ll_dops_init(*dentryp, 1, 1); + } else if ((*dentryp)->d_inode != inode) { + /* revalidate, but inode is recreated */ + CDEBUG(D_READA, + "stale dentry %.*s inode %lu/%u, " + "statahead inode %lu/%u\n", + (*dentryp)->d_name.len, + (*dentryp)->d_name.name, + (*dentryp)->d_inode->i_ino, + (*dentryp)->d_inode->i_generation, + inode->i_ino, + inode->i_generation); + ll_sai_unplug(sai, entry); + RETURN(-ESTALE); } else { - LASSERT((*dentryp)->d_inode == inode); - ll_dentry_rehash(*dentryp, 0); iput(inode); } @@ -1732,9 +1743,9 @@ int do_statahead_enter(struct inode *dir, struct dentry **dentryp, /* * We don't stat-ahead for the first dirent since we are already in - * lookup, and -EEXIST also indicates that this is the first dirent. + * lookup. */ - RETURN(-EEXIST); + RETURN(-EAGAIN); out: if (sai != NULL) -- 1.8.3.1