source: trunk/server/common/patches/openafs-d_revalidate-mtpt.patch @ 2658

Last change on this file since 2658 was 2637, checked in by andersk, 9 years ago
Upgrade to OpenAFS 1.6.10; new patch for Scripts #387?
File size: 3.8 KB
[2637]1From c9bbebe869acadd61abfa50656447429cde18aaf Mon Sep 17 00:00:00 2001
2From: Andrew Deason <>
3Date: Tue, 28 Oct 2014 00:10:56 -0500
4Subject: [PATCH] LINUX: Avoid d_revalidate failure on mtpt mismatch
6Currently, if afs_linux_dentry_revalidate is given an inode that
7corresponds to a mtpt vcache ('vcp'), it resolves the mtpt to its root
8dir if it's easy to do so (mvid and CMValid are set). Later on, we run
9afs_lookup to see if looking up our dentry's name returns the same
10vcache that we got; afs_lookup presumably will also resolve the mtpt
11if it's easy to do so.
13However, it is possible that afs_linux_dentry_revalidate and
14afs_lookup will make different decisions as to whether or not they
15resolve a mtpt to a dir. Specifically, if CMValid is cleared after
16afs_linux_dentry_revalidate checks for it, but before afs_lookup does,
17then afs_lookup will return a different vcache than
18afs_linux_dentry_revalidate is expecting, even though the relevant
19directory entry has not changed. That is, tvc is not equal to vcp, but
20tvc could be a mtpt that resolves to vcp, or vice versa. CMValid can
21be cleared by another thread at virtually any time, since this is
22cleared in some situations when we're not sure if the mtpt resolution
23is still valid (callbacks are broken, vldb cache entries expire, etc).
25afs_linux_dentry_revalidate interprets this situation to mean that the
26directory entry has changed, and so it eventually d_drop's the
27associated dentry. The way that this manifests to users is that a
28"fakestatted" mtpt can appear to be deleted effectively randomly, even
29when nothing has changed. This can be a problem because this causes
30the getcwd() syscall to return ENOENT when the working directory
31involves such an affected directory.
33To fix this situation, we just detect if afs_lookup returned either
34'vcp' (our possibly-resolved vcache), or the original inode associated
35with the dentry we are revalidating. If the returned vcache matches
36either of these, then the entry is okay and we don't need to
37invalidate or drop anything.
39FIXES 131780
41Change-Id: Ide1dd224d1ea1e29a82eb7130a010877cf4e9fc7
42(cherry picked from commit 45d9ff86571cbe70fedd524266fac50bd2d4bc2d)
44 src/afs/LINUX/osi_vnodeops.c | 29 ++++++++++++++++++++++++++++-
45 1 file changed, 28 insertions(+), 1 deletion(-)
47diff --git a/src/afs/LINUX/osi_vnodeops.c b/src/afs/LINUX/osi_vnodeops.c
48index 9ed6f01..8c63f96 100644
49--- a/src/afs/LINUX/osi_vnodeops.c
50+++ b/src/afs/LINUX/osi_vnodeops.c
51@@ -1231,10 +1231,37 @@ afs_linux_dentry_revalidate(struct dentry *dp, int flags)
52        if (hgetlo(pvcp->f.m.DataVersion) > dp->d_time || !(vcp->f.states & CStatd)) {
53            struct vattr *vattr = NULL;
54            int code;
55+           int lookup_good;
57            credp = crref();
58            code = afs_lookup(pvcp, (char *)dp->, &tvc, credp);
59-           if (code || tvc != vcp) {
61+           if (code) {
62+               /* We couldn't perform the lookup, so we're not okay. */
63+               lookup_good = 0;
65+           } else if (tvc == vcp) {
66+               /* We got back the same vcache, so we're good. */
67+               lookup_good = 1;
69+           } else if (tvc == VTOAFS(dp->d_inode)) {
70+               /* We got back the same vcache, so we're good. This is
71+                * different from the above case, because sometimes 'vcp' is
72+                * not the same as the vcache for dp->d_inode, if 'vcp' was a
73+                * mtpt and we evaluated it to a root dir. In rare cases,
74+                * afs_lookup might not evalute the mtpt when we do, or vice
75+                * versa, so the previous case will not succeed. But this is
76+                * still 'correct', so make sure not to mark the dentry as
77+                * invalid; it still points to the same thing! */
78+               lookup_good = 1;
80+           } else {
81+               /* We got back a different file, so we're definitely not
82+                * okay. */
83+               lookup_good = 0;
84+           }
86+           if (!lookup_good) {
87                dput(parent);
88                /* Force unhash; the name doesn't point to this file
89                 * anymore. */
Note: See TracBrowser for help on using the repository browser.