diff options
author | Ilya Dryomov <idryomov@gmail.com> | 2011-02-15 13:14:25 -0500 |
---|---|---|
committer | Chris Mason <chris.mason@oracle.com> | 2011-02-16 15:37:59 -0500 |
commit | 9b3517e9136824346227b7b04f8f7ea1f3a726cc (patch) | |
tree | b317f5ed612c5adae478a7acd48f6d8096a1656d | |
parent | ca9b688c1c9a21635cfc8af8b68565b154185196 (diff) |
Btrfs: make btrfs_rm_device() fail gracefully
If shrinking done as part of the online device removal fails add that
device back to the allocation list and increment the rw_devices counter.
This fixes two bugs:
1) we could have a perfectly good device out of alloc list for no good
reason;
2) in the btrfs consisting of two devices, failure in btrfs_rm_device()
could lead to a situation where it was impossible to remove any of the
devices because of the "unable to remove the only writeable device"
error.
Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
Signed-off-by: Chris Mason <chris.mason@oracle.com>
-rw-r--r-- | fs/btrfs/volumes.c | 11 |
1 files changed, 9 insertions, 2 deletions
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index dadaaa8005c8..f31c33119bb6 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c | |||
@@ -1337,11 +1337,11 @@ int btrfs_rm_device(struct btrfs_root *root, char *device_path) | |||
1337 | 1337 | ||
1338 | ret = btrfs_shrink_device(device, 0); | 1338 | ret = btrfs_shrink_device(device, 0); |
1339 | if (ret) | 1339 | if (ret) |
1340 | goto error_brelse; | 1340 | goto error_undo; |
1341 | 1341 | ||
1342 | ret = btrfs_rm_dev_item(root->fs_info->chunk_root, device); | 1342 | ret = btrfs_rm_dev_item(root->fs_info->chunk_root, device); |
1343 | if (ret) | 1343 | if (ret) |
1344 | goto error_brelse; | 1344 | goto error_undo; |
1345 | 1345 | ||
1346 | device->in_fs_metadata = 0; | 1346 | device->in_fs_metadata = 0; |
1347 | 1347 | ||
@@ -1415,6 +1415,13 @@ out: | |||
1415 | mutex_unlock(&root->fs_info->volume_mutex); | 1415 | mutex_unlock(&root->fs_info->volume_mutex); |
1416 | mutex_unlock(&uuid_mutex); | 1416 | mutex_unlock(&uuid_mutex); |
1417 | return ret; | 1417 | return ret; |
1418 | error_undo: | ||
1419 | if (device->writeable) { | ||
1420 | list_add(&device->dev_alloc_list, | ||
1421 | &root->fs_info->fs_devices->alloc_list); | ||
1422 | root->fs_info->fs_devices->rw_devices++; | ||
1423 | } | ||
1424 | goto error_brelse; | ||
1418 | } | 1425 | } |
1419 | 1426 | ||
1420 | /* | 1427 | /* |