]> git.michaelhowe.org Git - packages/o/openafs.git/commitdiff
LINUX: Fix oops during negative dentry caching
authorMichael Meffie <mmeffie@sinenomine.net>
Tue, 15 Sep 2015 17:33:12 +0000 (13:33 -0400)
committerBenjamin Kaduk <kaduk@mit.edu>
Tue, 15 Sep 2015 18:38:53 +0000 (14:38 -0400)
Commit 2e9dcc069904aaa434787eec53c6f9821911cbab reinstated negative
dentry caching, but introduced an oops when fakestat is in use.  Be sure
the GLOCK is held when looking up the parent vcache dv when the parent
is a mount point and fakestat is in use, since the calls to do the
lookup require the GLOCK to be held.

Change-Id: I6c47fbf53280400bf40271b1ff2837bd7c6dc69e
Reviewed-on: http://gerrit.openafs.org/12019
Tested-by: BuildBot <buildbot@rampaginggeek.com>
Reviewed-by: Benjamin Kaduk <kaduk@mit.edu>
src/afs/LINUX/osi_vnodeops.c

index e0dcca91f846fd2ff102106d7236fe40f1dd2dd9..b2e6dd70747286edb06e1222d9dc49dccb6fad98 100644 (file)
@@ -1089,7 +1089,7 @@ afs_linux_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *sta
 }
 
 static afs_uint32
-parent_vcache_dv(struct inode *inode, cred_t *credp)
+parent_vcache_dv(struct inode *inode, cred_t *credp, int locked)
 {
     int free_cred = 0;
     struct vcache *pvcp;
@@ -1104,6 +1104,9 @@ parent_vcache_dv(struct inode *inode, cred_t *credp)
        struct vrequest treq;
        struct afs_fakestat_state fakestate;
 
+       if (!locked) {
+           AFS_GLOCK();
+       }
        if (!credp) {
            credp = crref();
            free_cred = 1;
@@ -1114,6 +1117,9 @@ parent_vcache_dv(struct inode *inode, cred_t *credp)
        if (free_cred)
            crfree(credp);
        afs_PutFakeStat(&fakestate);
+       if (!locked) {
+           AFS_GUNLOCK();
+       }
     }
     return hgetlo(pvcp->f.m.DataVersion);
 }
@@ -1219,7 +1225,7 @@ afs_linux_dentry_revalidate(struct dentry *dp, int flags)
        }
 #endif
 
-       parent_dv = parent_vcache_dv(parent->d_inode, credp);
+       parent_dv = parent_vcache_dv(parent->d_inode, credp, locked);
 
        /* If the parent's DataVersion has changed or the vnode
         * is longer valid, we need to do a full lookup.  VerifyVCache
@@ -1306,7 +1312,7 @@ afs_linux_dentry_revalidate(struct dentry *dp, int flags)
 
        parent = dget_parent(dp);
        pvcp = VTOAFS(parent->d_inode);
-       parent_dv = parent_vcache_dv(parent->d_inode, credp);
+       parent_dv = parent_vcache_dv(parent->d_inode, credp, locked);
 
        if (parent_dv > dp->d_time || !(pvcp->f.states & CStatd)) {
            dput(parent);
@@ -1483,7 +1489,7 @@ afs_linux_create(struct inode *dip, struct dentry *dp, int mode)
 #if !defined(STRUCT_SUPER_BLOCK_HAS_S_D_OP)
        dp->d_op = &afs_dentry_operations;
 #endif
-       dp->d_time = parent_vcache_dv(dip, credp);
+       dp->d_time = parent_vcache_dv(dip, credp, 1);
        d_instantiate(dp, ip);
     }
 
@@ -1551,7 +1557,7 @@ afs_linux_lookup(struct inode *dip, struct dentry *dp)
 #if !defined(STRUCT_SUPER_BLOCK_HAS_S_D_OP)
     dp->d_op = &afs_dentry_operations;
 #endif
-    dp->d_time = parent_vcache_dv(dip, credp);
+    dp->d_time = parent_vcache_dv(dip, credp, 1);
 
     AFS_GUNLOCK();