]> git.michaelhowe.org Git - packages/o/openafs.git/commitdiff
LINUX: Do not lookup immediately recursive mtpts
authorAndrew Deason <adeason@sinenomine.net>
Fri, 6 Apr 2012 19:56:07 +0000 (14:56 -0500)
committerDerrick Brashear <shadow@dementix.org>
Tue, 14 Aug 2012 13:19:55 +0000 (06:19 -0700)
On Linux, having a mountpoint in a volume root that points to the same
volume can cause serious problems. By 'immediately recursive', I mean
a situation like the following:

fs mkm mtpt vol
fs mkm mtpt/mtpt vol

If there are multiple dentry aliases for the directory (which is
possible if the directory is a mountpoint), an 'rmdir' on the
recursive mountpoint can cause the client to deadlock. Since the
'rmdir' code path in Linux locks the parent directory inode to perform
the rmdir, and locks the child directory inode after performing a
couple of sanity checks. For an immediately recursive mountpoint,
these two inodes are the same, and so we will deadlock.

Reviewed-on: http://gerrit.openafs.org/7742
Tested-by: BuildBot <buildbot@rampaginggeek.com>
Reviewed-by: Derrick Brashear <shadow@dementix.org>
(cherry picked from commit d785abd5ec9302bdc1b3c33368246e573e0cd65d)

Change-Id: I531adbf66cf6714e04811356b072b17335980aa3
Reviewed-on: http://gerrit.openafs.org/7952
Tested-by: BuildBot <buildbot@rampaginggeek.com>
Reviewed-by: Derrick Brashear <shadow@dementix.org>
src/afs/LINUX/osi_vnodeops.c
src/afs/LINUX24/osi_vnodeops.c

index 1934114b71436d7b8594131a0c8542cc9588be94..2390678fac3e61fd771fdc3e0a315ac35ad16114 100644 (file)
@@ -1245,6 +1245,18 @@ afs_linux_lookup(struct inode *dip, struct dentry *dp)
     
     if (vcp) {
        struct vattr vattr;
+       struct vcache *parent_vc = VTOAFS(dip);
+
+       if (parent_vc == vcp) {
+           /* This is possible if the parent dir is a mountpoint to a volume,
+            * and the dir entry we looked up is a mountpoint to the same
+            * volume. Linux cannot cope with this, so return an error instead
+            * of risking a deadlock or panic. */
+           afs_PutVCache(vcp);
+           code = EDEADLK;
+           AFS_GUNLOCK();
+           goto done;
+       }
 
        ip = AFSTOV(vcp);
        afs_getattr(vcp, &vattr, credp);
@@ -1284,6 +1296,7 @@ afs_linux_lookup(struct inode *dip, struct dentry *dp)
     }
     newdp = d_splice_alias(ip, dp);
 
+ done:
     crfree(credp);
 
     /* It's ok for the file to not be found. That's noted by the caller by
index c3a4687b6e9344d02c27bb88cee1cdce2f121706..2fd1a226dc041297b3367af322f45eb9e41fc87a 100644 (file)
@@ -1271,6 +1271,18 @@ afs_linux_lookup(struct inode *dip, struct dentry *dp)
     
     if (vcp) {
        struct vattr vattr;
+       struct vcache *parent_vc = VTOAFS(dip);
+
+       if (parent_vc == vcp) {
+           /* This is possible if the parent dir is a mountpoint to a volume,
+            * and the dir entry we looked up is a mountpoint to the same
+            * volume. Linux cannot cope with this, so return an error instead
+            * of risking a deadlock or panic. */
+           afs_PutVCache(vcp);
+           code = EDEADLK;
+           AFS_GUNLOCK();
+           goto done;
+       }
 
        ip = AFSTOV(vcp);
        afs_getattr(vcp, &vattr, credp);
@@ -1312,6 +1324,7 @@ afs_linux_lookup(struct inode *dip, struct dentry *dp)
 #endif
     d_add(dp, ip);
 
+ done:
     crfree(credp);
 
     /* It's ok for the file to not be found. That's noted by the caller by