aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/volumes.c
diff options
context:
space:
mode:
authorJeff Mahoney <jeffm@suse.com>2012-03-12 11:03:00 -0400
committerDavid Sterba <dsterba@suse.cz>2012-03-22 06:52:54 -0400
commit79787eaab46121d4713ed03c8fc63b9ec3eaec76 (patch)
treeee6b17d0811ee54ab74a03aa4e0bb92769d2f12a /fs/btrfs/volumes.c
parent49b25e0540904be0bf558b84475c69d72e4de66e (diff)
btrfs: replace many BUG_ONs with proper error handling
btrfs currently handles most errors with BUG_ON. This patch is a work-in- progress but aims to handle most errors other than internal logic errors and ENOMEM more gracefully. This iteration prevents most crashes but can run into lockups with the page lock on occasion when the timing "works out." Signed-off-by: Jeff Mahoney <jeffm@suse.com>
Diffstat (limited to 'fs/btrfs/volumes.c')
-rw-r--r--fs/btrfs/volumes.c103
1 files changed, 76 insertions, 27 deletions
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
index 394bf15ea18c..57305e88ea82 100644
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -549,10 +549,10 @@ static int __btrfs_close_devices(struct btrfs_fs_devices *fs_devices)
549 fs_devices->num_can_discard--; 549 fs_devices->num_can_discard--;
550 550
551 new_device = kmalloc(sizeof(*new_device), GFP_NOFS); 551 new_device = kmalloc(sizeof(*new_device), GFP_NOFS);
552 BUG_ON(!new_device); 552 BUG_ON(!new_device); /* -ENOMEM */
553 memcpy(new_device, device, sizeof(*new_device)); 553 memcpy(new_device, device, sizeof(*new_device));
554 new_device->name = kstrdup(device->name, GFP_NOFS); 554 new_device->name = kstrdup(device->name, GFP_NOFS);
555 BUG_ON(device->name && !new_device->name); 555 BUG_ON(device->name && !new_device->name); /* -ENOMEM */
556 new_device->bdev = NULL; 556 new_device->bdev = NULL;
557 new_device->writeable = 0; 557 new_device->writeable = 0;
558 new_device->in_fs_metadata = 0; 558 new_device->in_fs_metadata = 0;
@@ -1036,8 +1036,10 @@ again:
1036 leaf = path->nodes[0]; 1036 leaf = path->nodes[0];
1037 extent = btrfs_item_ptr(leaf, path->slots[0], 1037 extent = btrfs_item_ptr(leaf, path->slots[0],
1038 struct btrfs_dev_extent); 1038 struct btrfs_dev_extent);
1039 } else {
1040 btrfs_error(root->fs_info, ret, "Slot search failed");
1041 goto out;
1039 } 1042 }
1040 BUG_ON(ret);
1041 1043
1042 if (device->bytes_used > 0) { 1044 if (device->bytes_used > 0) {
1043 u64 len = btrfs_dev_extent_length(leaf, extent); 1045 u64 len = btrfs_dev_extent_length(leaf, extent);
@@ -1047,7 +1049,10 @@ again:
1047 spin_unlock(&root->fs_info->free_chunk_lock); 1049 spin_unlock(&root->fs_info->free_chunk_lock);
1048 } 1050 }
1049 ret = btrfs_del_item(trans, root, path); 1051 ret = btrfs_del_item(trans, root, path);
1050 1052 if (ret) {
1053 btrfs_error(root->fs_info, ret,
1054 "Failed to remove dev extent item");
1055 }
1051out: 1056out:
1052 btrfs_free_path(path); 1057 btrfs_free_path(path);
1053 return ret; 1058 return ret;
@@ -1117,7 +1122,7 @@ static noinline int find_next_chunk(struct btrfs_root *root,
1117 if (ret < 0) 1122 if (ret < 0)
1118 goto error; 1123 goto error;
1119 1124
1120 BUG_ON(ret == 0); 1125 BUG_ON(ret == 0); /* Corruption */
1121 1126
1122 ret = btrfs_previous_item(root, path, 0, BTRFS_CHUNK_ITEM_KEY); 1127 ret = btrfs_previous_item(root, path, 0, BTRFS_CHUNK_ITEM_KEY);
1123 if (ret) { 1128 if (ret) {
@@ -1161,7 +1166,7 @@ static noinline int find_next_devid(struct btrfs_root *root, u64 *objectid)
1161 if (ret < 0) 1166 if (ret < 0)
1162 goto error; 1167 goto error;
1163 1168
1164 BUG_ON(ret == 0); 1169 BUG_ON(ret == 0); /* Corruption */
1165 1170
1166 ret = btrfs_previous_item(root, path, BTRFS_DEV_ITEMS_OBJECTID, 1171 ret = btrfs_previous_item(root, path, BTRFS_DEV_ITEMS_OBJECTID,
1167 BTRFS_DEV_ITEM_KEY); 1172 BTRFS_DEV_ITEM_KEY);
@@ -1595,7 +1600,7 @@ next_slot:
1595 (unsigned long)btrfs_device_fsid(dev_item), 1600 (unsigned long)btrfs_device_fsid(dev_item),
1596 BTRFS_UUID_SIZE); 1601 BTRFS_UUID_SIZE);
1597 device = btrfs_find_device(root, devid, dev_uuid, fs_uuid); 1602 device = btrfs_find_device(root, devid, dev_uuid, fs_uuid);
1598 BUG_ON(!device); 1603 BUG_ON(!device); /* Logic error */
1599 1604
1600 if (device->fs_devices->seeding) { 1605 if (device->fs_devices->seeding) {
1601 btrfs_set_device_generation(leaf, dev_item, 1606 btrfs_set_device_generation(leaf, dev_item,
@@ -1705,7 +1710,7 @@ int btrfs_init_new_device(struct btrfs_root *root, char *device_path)
1705 if (seeding_dev) { 1710 if (seeding_dev) {
1706 sb->s_flags &= ~MS_RDONLY; 1711 sb->s_flags &= ~MS_RDONLY;
1707 ret = btrfs_prepare_sprout(root); 1712 ret = btrfs_prepare_sprout(root);
1708 BUG_ON(ret); 1713 BUG_ON(ret); /* -ENOMEM */
1709 } 1714 }
1710 1715
1711 device->fs_devices = root->fs_info->fs_devices; 1716 device->fs_devices = root->fs_info->fs_devices;
@@ -1743,11 +1748,15 @@ int btrfs_init_new_device(struct btrfs_root *root, char *device_path)
1743 1748
1744 if (seeding_dev) { 1749 if (seeding_dev) {
1745 ret = init_first_rw_device(trans, root, device); 1750 ret = init_first_rw_device(trans, root, device);
1746 BUG_ON(ret); 1751 if (ret)
1752 goto error_trans;
1747 ret = btrfs_finish_sprout(trans, root); 1753 ret = btrfs_finish_sprout(trans, root);
1748 BUG_ON(ret); 1754 if (ret)
1755 goto error_trans;
1749 } else { 1756 } else {
1750 ret = btrfs_add_device(trans, root, device); 1757 ret = btrfs_add_device(trans, root, device);
1758 if (ret)
1759 goto error_trans;
1751 } 1760 }
1752 1761
1753 /* 1762 /*
@@ -1757,17 +1766,31 @@ int btrfs_init_new_device(struct btrfs_root *root, char *device_path)
1757 btrfs_clear_space_info_full(root->fs_info); 1766 btrfs_clear_space_info_full(root->fs_info);
1758 1767
1759 unlock_chunks(root); 1768 unlock_chunks(root);
1760 btrfs_commit_transaction(trans, root); 1769 ret = btrfs_commit_transaction(trans, root);
1761 1770
1762 if (seeding_dev) { 1771 if (seeding_dev) {
1763 mutex_unlock(&uuid_mutex); 1772 mutex_unlock(&uuid_mutex);
1764 up_write(&sb->s_umount); 1773 up_write(&sb->s_umount);
1765 1774
1775 if (ret) /* transaction commit */
1776 return ret;
1777
1766 ret = btrfs_relocate_sys_chunks(root); 1778 ret = btrfs_relocate_sys_chunks(root);
1767 BUG_ON(ret); 1779 if (ret < 0)
1780 btrfs_error(root->fs_info, ret,
1781 "Failed to relocate sys chunks after "
1782 "device initialization. This can be fixed "
1783 "using the \"btrfs balance\" command.");
1768 } 1784 }
1769 1785
1770 return ret; 1786 return ret;
1787
1788error_trans:
1789 unlock_chunks(root);
1790 btrfs_abort_transaction(trans, root, ret);
1791 btrfs_end_transaction(trans, root);
1792 kfree(device->name);
1793 kfree(device);
1771error: 1794error:
1772 blkdev_put(bdev, FMODE_EXCL); 1795 blkdev_put(bdev, FMODE_EXCL);
1773 if (seeding_dev) { 1796 if (seeding_dev) {
@@ -1875,10 +1898,20 @@ static int btrfs_free_chunk(struct btrfs_trans_handle *trans,
1875 key.type = BTRFS_CHUNK_ITEM_KEY; 1898 key.type = BTRFS_CHUNK_ITEM_KEY;
1876 1899
1877 ret = btrfs_search_slot(trans, root, &key, path, -1, 1); 1900 ret = btrfs_search_slot(trans, root, &key, path, -1, 1);
1878 BUG_ON(ret); 1901 if (ret < 0)
1902 goto out;
1903 else if (ret > 0) { /* Logic error or corruption */
1904 btrfs_error(root->fs_info, -ENOENT,
1905 "Failed lookup while freeing chunk.");
1906 ret = -ENOENT;
1907 goto out;
1908 }
1879 1909
1880 ret = btrfs_del_item(trans, root, path); 1910 ret = btrfs_del_item(trans, root, path);
1881 1911 if (ret < 0)
1912 btrfs_error(root->fs_info, ret,
1913 "Failed to delete chunk item.");
1914out:
1882 btrfs_free_path(path); 1915 btrfs_free_path(path);
1883 return ret; 1916 return ret;
1884} 1917}
@@ -2040,7 +2073,7 @@ again:
2040 ret = btrfs_search_slot(NULL, chunk_root, &key, path, 0, 0); 2073 ret = btrfs_search_slot(NULL, chunk_root, &key, path, 0, 0);
2041 if (ret < 0) 2074 if (ret < 0)
2042 goto error; 2075 goto error;
2043 BUG_ON(ret == 0); 2076 BUG_ON(ret == 0); /* Corruption */
2044 2077
2045 ret = btrfs_previous_item(chunk_root, path, key.objectid, 2078 ret = btrfs_previous_item(chunk_root, path, key.objectid,
2046 key.type); 2079 key.type);
@@ -3334,7 +3367,8 @@ static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans,
3334 ret = btrfs_make_block_group(trans, extent_root, 0, type, 3367 ret = btrfs_make_block_group(trans, extent_root, 0, type,
3335 BTRFS_FIRST_CHUNK_TREE_OBJECTID, 3368 BTRFS_FIRST_CHUNK_TREE_OBJECTID,
3336 start, num_bytes); 3369 start, num_bytes);
3337 BUG_ON(ret); 3370 if (ret)
3371 goto error;
3338 3372
3339 for (i = 0; i < map->num_stripes; ++i) { 3373 for (i = 0; i < map->num_stripes; ++i) {
3340 struct btrfs_device *device; 3374 struct btrfs_device *device;
@@ -3347,7 +3381,10 @@ static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans,
3347 info->chunk_root->root_key.objectid, 3381 info->chunk_root->root_key.objectid,
3348 BTRFS_FIRST_CHUNK_TREE_OBJECTID, 3382 BTRFS_FIRST_CHUNK_TREE_OBJECTID,
3349 start, dev_offset, stripe_size); 3383 start, dev_offset, stripe_size);
3350 BUG_ON(ret); 3384 if (ret) {
3385 btrfs_abort_transaction(trans, extent_root, ret);
3386 goto error;
3387 }
3351 } 3388 }
3352 3389
3353 kfree(devices_info); 3390 kfree(devices_info);
@@ -3465,7 +3502,8 @@ int btrfs_alloc_chunk(struct btrfs_trans_handle *trans,
3465 3502
3466 ret = __finish_chunk_alloc(trans, extent_root, map, chunk_offset, 3503 ret = __finish_chunk_alloc(trans, extent_root, map, chunk_offset,
3467 chunk_size, stripe_size); 3504 chunk_size, stripe_size);
3468 BUG_ON(ret); 3505 if (ret)
3506 return ret;
3469 return 0; 3507 return 0;
3470} 3508}
3471 3509
@@ -3497,7 +3535,8 @@ static noinline int init_first_rw_device(struct btrfs_trans_handle *trans,
3497 3535
3498 ret = __btrfs_alloc_chunk(trans, extent_root, &map, &chunk_size, 3536 ret = __btrfs_alloc_chunk(trans, extent_root, &map, &chunk_size,
3499 &stripe_size, chunk_offset, alloc_profile); 3537 &stripe_size, chunk_offset, alloc_profile);
3500 BUG_ON(ret); 3538 if (ret)
3539 return ret;
3501 3540
3502 sys_chunk_offset = chunk_offset + chunk_size; 3541 sys_chunk_offset = chunk_offset + chunk_size;
3503 3542
@@ -3508,10 +3547,12 @@ static noinline int init_first_rw_device(struct btrfs_trans_handle *trans,
3508 ret = __btrfs_alloc_chunk(trans, extent_root, &sys_map, 3547 ret = __btrfs_alloc_chunk(trans, extent_root, &sys_map,
3509 &sys_chunk_size, &sys_stripe_size, 3548 &sys_chunk_size, &sys_stripe_size,
3510 sys_chunk_offset, alloc_profile); 3549 sys_chunk_offset, alloc_profile);
3511 BUG_ON(ret); 3550 if (ret)
3551 goto abort;
3512 3552
3513 ret = btrfs_add_device(trans, fs_info->chunk_root, device); 3553 ret = btrfs_add_device(trans, fs_info->chunk_root, device);
3514 BUG_ON(ret); 3554 if (ret)
3555 goto abort;
3515 3556
3516 /* 3557 /*
3517 * Modifying chunk tree needs allocating new blocks from both 3558 * Modifying chunk tree needs allocating new blocks from both
@@ -3521,13 +3562,20 @@ static noinline int init_first_rw_device(struct btrfs_trans_handle *trans,
3521 */ 3562 */
3522 ret = __finish_chunk_alloc(trans, extent_root, map, chunk_offset, 3563 ret = __finish_chunk_alloc(trans, extent_root, map, chunk_offset,
3523 chunk_size, stripe_size); 3564 chunk_size, stripe_size);
3524 BUG_ON(ret); 3565 if (ret)
3566 goto abort;
3525 3567
3526 ret = __finish_chunk_alloc(trans, extent_root, sys_map, 3568 ret = __finish_chunk_alloc(trans, extent_root, sys_map,
3527 sys_chunk_offset, sys_chunk_size, 3569 sys_chunk_offset, sys_chunk_size,
3528 sys_stripe_size); 3570 sys_stripe_size);
3529 BUG_ON(ret); 3571 if (ret)
3572 goto abort;
3573
3530 return 0; 3574 return 0;
3575
3576abort:
3577 btrfs_abort_transaction(trans, root, ret);
3578 return ret;
3531} 3579}
3532 3580
3533int btrfs_chunk_readonly(struct btrfs_root *root, u64 chunk_offset) 3581int btrfs_chunk_readonly(struct btrfs_root *root, u64 chunk_offset)
@@ -3878,7 +3926,7 @@ int btrfs_rmap_block(struct btrfs_mapping_tree *map_tree,
3878 do_div(length, map->num_stripes); 3926 do_div(length, map->num_stripes);
3879 3927
3880 buf = kzalloc(sizeof(u64) * map->num_stripes, GFP_NOFS); 3928 buf = kzalloc(sizeof(u64) * map->num_stripes, GFP_NOFS);
3881 BUG_ON(!buf); 3929 BUG_ON(!buf); /* -ENOMEM */
3882 3930
3883 for (i = 0; i < map->num_stripes; i++) { 3931 for (i = 0; i < map->num_stripes; i++) {
3884 if (devid && map->stripes[i].dev->devid != devid) 3932 if (devid && map->stripes[i].dev->devid != devid)
@@ -4039,7 +4087,8 @@ int btrfs_map_bio(struct btrfs_root *root, int rw, struct bio *bio,
4039 4087
4040 ret = btrfs_map_block(map_tree, rw, logical, &map_length, &bbio, 4088 ret = btrfs_map_block(map_tree, rw, logical, &map_length, &bbio,
4041 mirror_num); 4089 mirror_num);
4042 BUG_ON(ret); 4090 if (ret) /* -ENOMEM */
4091 return ret;
4043 4092
4044 total_devs = bbio->num_stripes; 4093 total_devs = bbio->num_stripes;
4045 if (map_length < length) { 4094 if (map_length < length) {
@@ -4058,7 +4107,7 @@ int btrfs_map_bio(struct btrfs_root *root, int rw, struct bio *bio,
4058 while (dev_nr < total_devs) { 4107 while (dev_nr < total_devs) {
4059 if (dev_nr < total_devs - 1) { 4108 if (dev_nr < total_devs - 1) {
4060 bio = bio_clone(first_bio, GFP_NOFS); 4109 bio = bio_clone(first_bio, GFP_NOFS);
4061 BUG_ON(!bio); 4110 BUG_ON(!bio); /* -ENOMEM */
4062 } else { 4111 } else {
4063 bio = first_bio; 4112 bio = first_bio;
4064 } 4113 }
@@ -4212,7 +4261,7 @@ static int read_one_chunk(struct btrfs_root *root, struct btrfs_key *key,
4212 write_lock(&map_tree->map_tree.lock); 4261 write_lock(&map_tree->map_tree.lock);
4213 ret = add_extent_mapping(&map_tree->map_tree, em); 4262 ret = add_extent_mapping(&map_tree->map_tree, em);
4214 write_unlock(&map_tree->map_tree.lock); 4263 write_unlock(&map_tree->map_tree.lock);
4215 BUG_ON(ret); 4264 BUG_ON(ret); /* Tree corruption */
4216 free_extent_map(em); 4265 free_extent_map(em);
4217 4266
4218 return 0; 4267 return 0;