diff options
Diffstat (limited to 'fs/btrfs/volumes.c')
-rw-r--r-- | fs/btrfs/volumes.c | 33 |
1 files changed, 30 insertions, 3 deletions
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index 35bb2d4ed29f..2854c824ab64 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c | |||
@@ -684,6 +684,12 @@ int btrfs_close_devices(struct btrfs_fs_devices *fs_devices) | |||
684 | __btrfs_close_devices(fs_devices); | 684 | __btrfs_close_devices(fs_devices); |
685 | free_fs_devices(fs_devices); | 685 | free_fs_devices(fs_devices); |
686 | } | 686 | } |
687 | /* | ||
688 | * Wait for rcu kworkers under __btrfs_close_devices | ||
689 | * to finish all blkdev_puts so device is really | ||
690 | * free when umount is done. | ||
691 | */ | ||
692 | rcu_barrier(); | ||
687 | return ret; | 693 | return ret; |
688 | } | 694 | } |
689 | 695 | ||
@@ -2379,7 +2385,11 @@ static int btrfs_relocate_chunk(struct btrfs_root *root, | |||
2379 | return ret; | 2385 | return ret; |
2380 | 2386 | ||
2381 | trans = btrfs_start_transaction(root, 0); | 2387 | trans = btrfs_start_transaction(root, 0); |
2382 | BUG_ON(IS_ERR(trans)); | 2388 | if (IS_ERR(trans)) { |
2389 | ret = PTR_ERR(trans); | ||
2390 | btrfs_std_error(root->fs_info, ret); | ||
2391 | return ret; | ||
2392 | } | ||
2383 | 2393 | ||
2384 | lock_chunks(root); | 2394 | lock_chunks(root); |
2385 | 2395 | ||
@@ -3050,7 +3060,8 @@ static void __cancel_balance(struct btrfs_fs_info *fs_info) | |||
3050 | 3060 | ||
3051 | unset_balance_control(fs_info); | 3061 | unset_balance_control(fs_info); |
3052 | ret = del_balance_item(fs_info->tree_root); | 3062 | ret = del_balance_item(fs_info->tree_root); |
3053 | BUG_ON(ret); | 3063 | if (ret) |
3064 | btrfs_std_error(fs_info, ret); | ||
3054 | 3065 | ||
3055 | atomic_set(&fs_info->mutually_exclusive_operation_running, 0); | 3066 | atomic_set(&fs_info->mutually_exclusive_operation_running, 0); |
3056 | } | 3067 | } |
@@ -3230,6 +3241,11 @@ int btrfs_balance(struct btrfs_balance_control *bctl, | |||
3230 | update_ioctl_balance_args(fs_info, 0, bargs); | 3241 | update_ioctl_balance_args(fs_info, 0, bargs); |
3231 | } | 3242 | } |
3232 | 3243 | ||
3244 | if ((ret && ret != -ECANCELED && ret != -ENOSPC) || | ||
3245 | balance_need_close(fs_info)) { | ||
3246 | __cancel_balance(fs_info); | ||
3247 | } | ||
3248 | |||
3233 | wake_up(&fs_info->balance_wait_q); | 3249 | wake_up(&fs_info->balance_wait_q); |
3234 | 3250 | ||
3235 | return ret; | 3251 | return ret; |
@@ -4919,7 +4935,18 @@ int btrfs_rmap_block(struct btrfs_mapping_tree *map_tree, | |||
4919 | em = lookup_extent_mapping(em_tree, chunk_start, 1); | 4935 | em = lookup_extent_mapping(em_tree, chunk_start, 1); |
4920 | read_unlock(&em_tree->lock); | 4936 | read_unlock(&em_tree->lock); |
4921 | 4937 | ||
4922 | BUG_ON(!em || em->start != chunk_start); | 4938 | if (!em) { |
4939 | printk(KERN_ERR "btrfs: couldn't find em for chunk %Lu\n", | ||
4940 | chunk_start); | ||
4941 | return -EIO; | ||
4942 | } | ||
4943 | |||
4944 | if (em->start != chunk_start) { | ||
4945 | printk(KERN_ERR "btrfs: bad chunk start, em=%Lu, wanted=%Lu\n", | ||
4946 | em->start, chunk_start); | ||
4947 | free_extent_map(em); | ||
4948 | return -EIO; | ||
4949 | } | ||
4923 | map = (struct map_lookup *)em->bdev; | 4950 | map = (struct map_lookup *)em->bdev; |
4924 | 4951 | ||
4925 | length = em->len; | 4952 | length = em->len; |