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

Last change on this file since 2639 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
  • src/afs/LINUX/osi_vnodeops.c

    From c9bbebe869acadd61abfa50656447429cde18aaf Mon Sep 17 00:00:00 2001
    From: Andrew Deason <adeason@sinenomine.net>
    Date: Tue, 28 Oct 2014 00:10:56 -0500
    Subject: [PATCH] LINUX: Avoid d_revalidate failure on mtpt mismatch
    
    Currently, if afs_linux_dentry_revalidate is given an inode that
    corresponds to a mtpt vcache ('vcp'), it resolves the mtpt to its root
    dir if it's easy to do so (mvid and CMValid are set). Later on, we run
    afs_lookup to see if looking up our dentry's name returns the same
    vcache that we got; afs_lookup presumably will also resolve the mtpt
    if it's easy to do so.
    
    However, it is possible that afs_linux_dentry_revalidate and
    afs_lookup will make different decisions as to whether or not they
    resolve a mtpt to a dir. Specifically, if CMValid is cleared after
    afs_linux_dentry_revalidate checks for it, but before afs_lookup does,
    then afs_lookup will return a different vcache than
    afs_linux_dentry_revalidate is expecting, even though the relevant
    directory entry has not changed. That is, tvc is not equal to vcp, but
    tvc could be a mtpt that resolves to vcp, or vice versa. CMValid can
    be cleared by another thread at virtually any time, since this is
    cleared in some situations when we're not sure if the mtpt resolution
    is still valid (callbacks are broken, vldb cache entries expire, etc).
    
    afs_linux_dentry_revalidate interprets this situation to mean that the
    directory entry has changed, and so it eventually d_drop's the
    associated dentry. The way that this manifests to users is that a
    "fakestatted" mtpt can appear to be deleted effectively randomly, even
    when nothing has changed. This can be a problem because this causes
    the getcwd() syscall to return ENOENT when the working directory
    involves such an affected directory.
    
    To fix this situation, we just detect if afs_lookup returned either
    'vcp' (our possibly-resolved vcache), or the original inode associated
    with the dentry we are revalidating. If the returned vcache matches
    either of these, then the entry is okay and we don't need to
    invalidate or drop anything.
    
    FIXES 131780
    
    Change-Id: Ide1dd224d1ea1e29a82eb7130a010877cf4e9fc7
    (cherry picked from commit 45d9ff86571cbe70fedd524266fac50bd2d4bc2d)
    ---
     src/afs/LINUX/osi_vnodeops.c | 29 ++++++++++++++++++++++++++++-
     1 file changed, 28 insertions(+), 1 deletion(-)
    
    diff --git a/src/afs/LINUX/osi_vnodeops.c b/src/afs/LINUX/osi_vnodeops.c
    index 9ed6f01..8c63f96 100644
    a b afs_linux_dentry_revalidate(struct dentry *dp, int flags) 
    12311231        if (hgetlo(pvcp->f.m.DataVersion) > dp->d_time || !(vcp->f.states & CStatd)) {
    12321232            struct vattr *vattr = NULL;
    12331233            int code;
     1234            int lookup_good;
    12341235
    12351236            credp = crref();
    12361237            code = afs_lookup(pvcp, (char *)dp->d_name.name, &tvc, credp);
    1237             if (code || tvc != vcp) {
     1238
     1239            if (code) {
     1240                /* We couldn't perform the lookup, so we're not okay. */
     1241                lookup_good = 0;
     1242
     1243            } else if (tvc == vcp) {
     1244                /* We got back the same vcache, so we're good. */
     1245                lookup_good = 1;
     1246
     1247            } else if (tvc == VTOAFS(dp->d_inode)) {
     1248                /* We got back the same vcache, so we're good. This is
     1249                 * different from the above case, because sometimes 'vcp' is
     1250                 * not the same as the vcache for dp->d_inode, if 'vcp' was a
     1251                 * mtpt and we evaluated it to a root dir. In rare cases,
     1252                 * afs_lookup might not evalute the mtpt when we do, or vice
     1253                 * versa, so the previous case will not succeed. But this is
     1254                 * still 'correct', so make sure not to mark the dentry as
     1255                 * invalid; it still points to the same thing! */
     1256                lookup_good = 1;
     1257
     1258            } else {
     1259                /* We got back a different file, so we're definitely not
     1260                 * okay. */
     1261                lookup_good = 0;
     1262            }
     1263
     1264            if (!lookup_good) {
    12381265                dput(parent);
    12391266                /* Force unhash; the name doesn't point to this file
    12401267                 * anymore. */
Note: See TracBrowser for help on using the repository browser.