aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/volumes.c
diff options
context:
space:
mode:
authorIlya Dryomov <idryomov@gmail.com>2011-02-15 13:14:25 -0500
committerChris Mason <chris.mason@oracle.com>2011-02-16 15:37:59 -0500
commit9b3517e9136824346227b7b04f8f7ea1f3a726cc (patch)
treeb317f5ed612c5adae478a7acd48f6d8096a1656d /fs/btrfs/volumes.c
parentca9b688c1c9a21635cfc8af8b68565b154185196 (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>
Diffstat (limited to 'fs/btrfs/volumes.c')
-rw-r--r--fs/btrfs/volumes.c11
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;
1418error_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/*