Browse Source

btrfs: fix a deadlock in btrfs_scan_one_device()

pathname resolution under a global mutex, taken on some paths in ->mount()
is a Bad Idea(tm) - think what happens if said pathname resolution triggers
automount of some btrfs instance and walks into attempt to grab the same
mutex.  Deadlock - we are waiting for daemon to finish walking the path,
daemon is waiting for us to release the mutex...

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Al Viro 13 years ago
parent
commit
10f6327b5d
1 changed files with 2 additions and 3 deletions
  1. 2 3
      fs/btrfs/volumes.c

+ 2 - 3
fs/btrfs/volumes.c

@@ -706,8 +706,6 @@ int btrfs_scan_one_device(const char *path, fmode_t flags, void *holder,
 	u64 devid;
 	u64 devid;
 	u64 transid;
 	u64 transid;
 
 
-	mutex_lock(&uuid_mutex);
-
 	flags |= FMODE_EXCL;
 	flags |= FMODE_EXCL;
 	bdev = blkdev_get_by_path(path, flags, holder);
 	bdev = blkdev_get_by_path(path, flags, holder);
 
 
@@ -716,6 +714,7 @@ int btrfs_scan_one_device(const char *path, fmode_t flags, void *holder,
 		goto error;
 		goto error;
 	}
 	}
 
 
+	mutex_lock(&uuid_mutex);
 	ret = set_blocksize(bdev, 4096);
 	ret = set_blocksize(bdev, 4096);
 	if (ret)
 	if (ret)
 		goto error_close;
 		goto error_close;
@@ -737,9 +736,9 @@ int btrfs_scan_one_device(const char *path, fmode_t flags, void *holder,
 
 
 	brelse(bh);
 	brelse(bh);
 error_close:
 error_close:
+	mutex_unlock(&uuid_mutex);
 	blkdev_put(bdev, flags);
 	blkdev_put(bdev, flags);
 error:
 error:
-	mutex_unlock(&uuid_mutex);
 	return ret;
 	return ret;
 }
 }