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>
This commit is contained in:
Ilya Dryomov 2011-02-15 18:14:25 +00:00 коммит произвёл Chris Mason
Родитель ca9b688c1c
Коммит 9b3517e913
1 изменённых файлов: 9 добавлений и 2 удалений

Просмотреть файл

@ -1337,11 +1337,11 @@ int btrfs_rm_device(struct btrfs_root *root, char *device_path)
ret = btrfs_shrink_device(device, 0); ret = btrfs_shrink_device(device, 0);
if (ret) if (ret)
goto error_brelse; goto error_undo;
ret = btrfs_rm_dev_item(root->fs_info->chunk_root, device); ret = btrfs_rm_dev_item(root->fs_info->chunk_root, device);
if (ret) if (ret)
goto error_brelse; goto error_undo;
device->in_fs_metadata = 0; device->in_fs_metadata = 0;
@ -1415,6 +1415,13 @@ out:
mutex_unlock(&root->fs_info->volume_mutex); mutex_unlock(&root->fs_info->volume_mutex);
mutex_unlock(&uuid_mutex); mutex_unlock(&uuid_mutex);
return ret; return ret;
error_undo:
if (device->writeable) {
list_add(&device->dev_alloc_list,
&root->fs_info->fs_devices->alloc_list);
root->fs_info->fs_devices->rw_devices++;
}
goto error_brelse;
} }
/* /*