Whamcloud - gitweb
LU-506 statahead: revalidating dentry may be stale
authorLai Siyao <laisiyao@whamcloud.com>
Mon, 9 Apr 2012 07:33:29 +0000 (15:33 +0800)
committerOleg Drokin <green@whamcloud.com>
Mon, 7 May 2012 19:31:07 +0000 (15:31 -0400)
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 <laisiyao@whamcloud.com>
Change-Id: I3eae450069a59d18d138d0cf7538a225e6d6deb8
Reviewed-on: http://review.whamcloud.com/2492
Reviewed-by: Fan Yong <yong.fan@whamcloud.com>
Reviewed-by: Peng Tao <tao.peng@emc.com>
Tested-by: Hudson
Tested-by: Maloo <whamcloud.maloo@gmail.com>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
lustre/llite/dcache.c
lustre/llite/llite_internal.h
lustre/llite/statahead.c

index 0c24635..044faf7 100644 (file)
@@ -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:
index ab3cdf1..f5e54f7 100644 (file)
@@ -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 */
index 81d2bd0..0b06d9b 100644 (file)
@@ -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)