This patch series fixes a few existing problems and then addresses the need for better error handling and propagation in btrfs. The handling and propagation patch set first finds all locations of a particular condition not being checked and annotates them with BTRFS_UERROR to designate that there is an error condition that is currently unhandled but should be. Then, another patch traverses the call path to ensure that errors are properly propogated. When the fix for recovering or passing the error is obvious, we do that too. This set is not complete and I expect there to be more fixes coming. In particular, it currently only annotates btrfs_alloc_path failures as the call graph for it is quite large. This is in response to Chris asking for what I already have instead of waiting for it to be complete. -Jeff -- Jeff Mahoney SUSE Labs -- To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Jeff Mahoney
2009-Nov-04 19:03 UTC
[patch 01/10] btrfs: fix btrfs_read_block_groups return value
btrfs_read_block_groups returns an ambiguous value. Whether it finds a block group or not, it will return -ENOENT. find_first_block_group will eventually return -ENOENT when it reaches past the last block group, and that is what is returned to the caller. Also, if the kzalloc fails, it will return 0. None of this matters right now because open_ctree isn''t checking the return value, but I have a patch to handle that as well. This patch returns 0 if find_first_block_group after it has already found at least one block group, and -ENOENT if it has found none. It also returns -ENOMEM if the kzalloc fails. Signed-off-by: Jeff Mahoney <jeffm@suse.com> --- fs/btrfs/extent-tree.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c @@ -7339,7 +7339,7 @@ int btrfs_free_block_groups(struct btrfs int btrfs_read_block_groups(struct btrfs_root *root) { struct btrfs_path *path; - int ret; + int ret, found = 0; struct btrfs_block_group_cache *cache; struct btrfs_fs_info *info = root->fs_info; struct btrfs_space_info *space_info; @@ -7357,12 +7357,13 @@ int btrfs_read_block_groups(struct btrfs while (1) { ret = find_first_block_group(root, path, &key); - if (ret > 0) { + if (ret > 0 || (found && ret == -ENOENT)) { ret = 0; - goto error; + break; } + if (ret != 0) - goto error; + break; leaf = path->nodes[0]; btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]); @@ -7439,9 +7440,8 @@ int btrfs_read_block_groups(struct btrfs set_avail_alloc_bits(root->fs_info, cache->flags); if (btrfs_chunk_readonly(root, cache->key.objectid)) set_block_group_readonly(cache); + found = 1; } - ret = 0; -error: btrfs_free_path(path); return ret; } -- To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Jeff Mahoney
2009-Nov-04 19:03 UTC
[patch 02/10] btrfs: fix memleak in btrfs_init_new_device
If find_next_devid fails, btrfs_init_new_device frees device but not device->name. This patch fixes it. Signed-off-by: Jeff Mahoney <jeffm@suse.com> --- fs/btrfs/volumes.c | 1 + 1 file changed, 1 insertion(+) --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c @@ -1474,6 +1474,7 @@ int btrfs_init_new_device(struct btrfs_r ret = find_next_devid(root, &device->devid); if (ret) { + kfree(device->name); kfree(device); goto error; } -- To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Jeff Mahoney
2009-Nov-04 19:03 UTC
[patch 03/10] btrfs: fix btrfs_read_fs_root* return values
The btrfs_read_fs_root* functions return ERR_PTR values but the return is being checked for NULL instead. This patch fixes up the checks to use IS_ERR. Signed-off-by: Jeff Mahoney <jeffm@suse.com> --- fs/btrfs/disk-io.c | 4 +++- fs/btrfs/extent-tree.c | 6 +++--- fs/btrfs/tree-log.c | 4 ++-- 3 files changed, 8 insertions(+), 6 deletions(-) --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -1987,8 +1987,10 @@ struct btrfs_root *open_ctree(struct sup location.offset = (u64)-1; fs_info->fs_root = btrfs_read_fs_root_no_name(fs_info, &location); - if (!fs_info->fs_root) + if (IS_ERR(fs_info->fs_root)) { + err = PTR_ERR(fs_info->fs_root); goto fail_trans_kthread; + } return tree_root; --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c @@ -6712,7 +6712,7 @@ int btrfs_cleanup_reloc_trees(struct btr location.type = BTRFS_ROOT_ITEM_KEY; reloc_root = btrfs_read_fs_root_no_name(root->fs_info, &location); - BUG_ON(!reloc_root); + BUG_ON(IS_ERR(reloc_root)); btrfs_orphan_cleanup(reloc_root); return 0; } @@ -6757,7 +6757,7 @@ static noinline int init_reloc_tree(stru reloc_root = btrfs_read_fs_root_no_radix(root->fs_info->tree_root, &root_key); - BUG_ON(!reloc_root); + BUG_ON(IS_ERR(reloc_root)); reloc_root->last_trans = trans->transid; reloc_root->commit_root = NULL; reloc_root->ref_tree = &root->fs_info->reloc_ref_tree; @@ -6976,7 +6976,7 @@ static noinline int relocate_one_extent( continue; found_root = read_ref_root(extent_root->fs_info, ref_path); - BUG_ON(!found_root); + BUG_ON(IS_ERR(found_root)); /* * for reference counted tree, only process reference paths * rooted at the latest committed root. --- a/fs/btrfs/tree-log.c +++ b/fs/btrfs/tree-log.c @@ -3042,7 +3042,7 @@ again: log = btrfs_read_fs_root_no_radix(log_root_tree, &found_key); - BUG_ON(!log); + BUG_ON(IS_ERR(log)); tmp_key.objectid = found_key.offset; @@ -3050,7 +3050,7 @@ again: tmp_key.offset = (u64)-1; wc.replay_dest = btrfs_read_fs_root_no_name(fs_info, &tmp_key); - BUG_ON(!wc.replay_dest); + BUG_ON(IS_ERR(wc.replay_dest)); wc.replay_dest->log_root = log; btrfs_record_root_in_trans(trans, wc.replay_dest); -- To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Jeff Mahoney
2009-Nov-04 19:03 UTC
[patch 04/10] btrfs: btrfs_sync_file should return -EIO not EIO
This patch fixes a typo in the return path of btrfs_sync_file, which currently returns EIO instead of -EIO. Signed-off-by: Jeff Mahoney <jeffm@suse.com> --- fs/btrfs/file.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c @@ -1223,7 +1223,7 @@ int btrfs_sync_file(struct file *file, s } mutex_lock(&dentry->d_inode->i_mutex); out: - return ret > 0 ? EIO : ret; + return ret > 0 ? -EIO : ret; } static struct vm_operations_struct btrfs_file_vm_ops = { -- To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Jeff Mahoney
2009-Nov-04 19:03 UTC
[patch 05/10] btrfs: Add BTRFS_UERROR for unhandled errors
This patch adds a BTRFS_UERROR macro to indicate than an error is unhandled but should be. This is to differentiate between internal logic errors and runtime errors so that we can go through later more easily to locate and fix them. It currently BUGs after printing a message indicating where the failure occured and what the failure condition was. Signed-off-by: Jeff Mahoney <jeffm@suse.com> --- fs/btrfs/ctree.h | 8 ++++++++ fs/btrfs/super.c | 8 ++++++++ 2 files changed, 16 insertions(+) --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h @@ -1951,6 +1951,13 @@ static inline struct dentry *fdentry(str return file->f_path.dentry; } +#define BTRFS_UERROR(condition) \ + do { \ + if (condition) \ + btrfs_unhandled_error(__FILE__, __LINE__, \ + #condition); \ + } while(0); + /* extent-tree.c */ void btrfs_put_block_group(struct btrfs_block_group_cache *cache); int btrfs_run_delayed_refs(struct btrfs_trans_handle *trans, @@ -2373,6 +2380,7 @@ ssize_t btrfs_listxattr(struct dentry *d u64 btrfs_parse_size(char *str); int btrfs_parse_options(struct btrfs_root *root, char *options); int btrfs_sync_fs(struct super_block *sb, int wait); +void btrfs_unhandled_error(const char *file, int line, const char *condition); /* acl.c */ #ifdef CONFIG_BTRFS_FS_POSIX_ACL --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c @@ -51,6 +51,14 @@ #include "export.h" #include "compression.h" +void btrfs_unhandled_error(const char *file, int line, const char *msg) +{ + printk(KERN_CRIT "btrfs: Unhandled error at %s:%d: %s\n", + file, line, msg); + + BUG(); +} + static struct super_operations btrfs_super_ops; static void btrfs_put_super(struct super_block *sb) -- To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
This patch adds checks to ensure that kmalloc or kmem_cache_alloc has succeeded before using the memory. Signed-off-by: Jeff Mahoney <jeffm@suse.com> --- fs/btrfs/compression.c | 2 ++ fs/btrfs/ctree.c | 1 + fs/btrfs/disk-io.c | 1 + fs/btrfs/extent-tree.c | 12 +++++++----- fs/btrfs/file-item.c | 4 ++-- fs/btrfs/file.c | 1 + fs/btrfs/inode.c | 4 ++++ fs/btrfs/relocation.c | 8 ++++---- fs/btrfs/transaction.c | 4 +++- fs/btrfs/tree-log.c | 9 +++++++-- fs/btrfs/volumes.c | 2 +- 11 files changed, 33 insertions(+), 15 deletions(-) --- a/fs/btrfs/compression.c +++ b/fs/btrfs/compression.c @@ -351,6 +351,7 @@ int btrfs_submit_compressed_write(struct WARN_ON(start & ((u64)PAGE_CACHE_SIZE - 1)); cb = kmalloc(compressed_bio_size(root, compressed_len), GFP_NOFS); + BTRFS_UERROR(!cb); atomic_set(&cb->pending_bios, 0); cb->errors = 0; cb->inode = inode; @@ -622,6 +623,7 @@ int btrfs_submit_compressed_read(struct PAGE_CACHE_SIZE; cb->compressed_pages = kmalloc(sizeof(struct page *) * nr_pages, GFP_NOFS); + BTRFS_UERROR(!cb->compressed_pages); bdev = BTRFS_I(inode)->root->fs_info->fs_devices->latest_bdev; for (page_index = 0; page_index < nr_pages; page_index++) { --- a/fs/btrfs/ctree.c +++ b/fs/btrfs/ctree.c @@ -3073,6 +3073,7 @@ split: item_size = btrfs_item_size(leaf, item); buf = kmalloc(item_size, GFP_NOFS); + BTRFS_UERROR(!buf); read_extent_buffer(leaf, buf, btrfs_item_ptr_offset(leaf, path->slots[0]), item_size); slot = path->slots[0] + 1; --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -1958,6 +1958,7 @@ struct btrfs_root *open_ctree(struct sup log_tree_root = kzalloc(sizeof(struct btrfs_root), GFP_NOFS); + BTRFS_UERROR(!log_tree_root); __setup_root(nodesize, leafsize, sectorsize, stripesize, log_tree_root, fs_info, BTRFS_TREE_LOG_OBJECTID); --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c @@ -414,7 +414,7 @@ static int cache_block_group(struct btrf return 0; caching_ctl = kzalloc(sizeof(*caching_ctl), GFP_KERNEL); - BUG_ON(!caching_ctl); + BTRFS_UERROR(!caching_ctl); INIT_LIST_HEAD(&caching_ctl->list); mutex_init(&caching_ctl->mutex); @@ -5388,7 +5388,7 @@ int btrfs_drop_snapshot(struct btrfs_roo BUG_ON(!path); wc = kzalloc(sizeof(*wc), GFP_NOFS); - BUG_ON(!wc); + BTRFS_UERROR(!wc); trans = btrfs_start_transaction(tree_root, 1); @@ -5550,7 +5550,7 @@ int btrfs_drop_subtree(struct btrfs_tran BUG_ON(!path); wc = kzalloc(sizeof(*wc), GFP_NOFS); - BUG_ON(!wc); + BTRFS_UERROR(!wc); btrfs_assert_tree_locked(parent); parent_level = btrfs_header_level(parent); @@ -6048,6 +6048,7 @@ static noinline int get_new_locations(st struct disk_extent *old = exts; max *= 2; exts = kzalloc(sizeof(*exts) * max, GFP_NOFS); + BTRFS_UERROR(!exts); memcpy(exts, old, sizeof(*exts) * nr); if (old != *extents) kfree(old); @@ -6527,7 +6528,7 @@ static noinline int replace_extents_in_l int ret; new_extent = kmalloc(sizeof(*new_extent), GFP_NOFS); - BUG_ON(!new_extent); + BTRFS_UERROR(!new_extent) ref = btrfs_lookup_leaf_ref(root, leaf->start); BUG_ON(!ref); @@ -6731,7 +6732,7 @@ static noinline int init_reloc_tree(stru return 0; root_item = kmalloc(sizeof(*root_item), GFP_NOFS); - BUG_ON(!root_item); + BTRFS_UERROR(!root_item); ret = btrfs_copy_root(trans, root, root->commit_root, &eb, BTRFS_TREE_RELOC_OBJECTID); @@ -7047,6 +7048,7 @@ static noinline int relocate_one_extent( u64 group_start = group->key.objectid; new_extents = kmalloc(sizeof(*new_extents), GFP_NOFS); + BTRFS_UERROR(!new_extents); nr_extents = 1; ret = get_new_locations(reloc_inode, extent_key, --- a/fs/btrfs/file-item.c +++ b/fs/btrfs/file-item.c @@ -320,7 +320,7 @@ int btrfs_lookup_csums_range(struct btrf MAX_ORDERED_SUM_BYTES(root)); sums = kzalloc(btrfs_ordered_sum_size(root, size), GFP_NOFS); - BUG_ON(!sums); + BTRFS_UERROR(!sums); sector_sum = sums->sums; sums->bytenr = start; @@ -401,7 +401,7 @@ int btrfs_csum_one_bio(struct btrfs_root sums = kzalloc(btrfs_ordered_sum_size(root, bytes_left), GFP_NOFS); - BUG_ON(!sums); + BTRFS_UERROR(!sums); sector_sum = sums->sums; sums->len = bytes_left; ordered = btrfs_lookup_ordered_extent(inode, offset); --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c @@ -946,6 +946,7 @@ static ssize_t btrfs_file_write(struct f file_update_time(file); pages = kmalloc(nrptrs * sizeof(struct page *), GFP_KERNEL); + BTRFS_UERROR(!pages); /* generic_write_checks can change our pos */ start_pos = pos; --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -273,6 +273,7 @@ static noinline int add_async_extent(str struct async_extent *async_extent; async_extent = kmalloc(sizeof(*async_extent), GFP_NOFS); + BTRFS_UERROR(!async_extent); async_extent->start = start; async_extent->ram_size = ram_size; async_extent->compressed_size = compressed_size; @@ -372,6 +373,7 @@ again: btrfs_test_opt(root, COMPRESS)) { WARN_ON(pages); pages = kzalloc(sizeof(struct page *) * nr_pages, GFP_NOFS); + BTRFS_UERROR(!pages); ret = btrfs_zlib_compress_pages(inode->i_mapping, start, total_compressed, pages, @@ -885,6 +887,7 @@ static int cow_file_range_async(struct i 1, 0, NULL, GFP_NOFS); while (start < end) { async_cow = kmalloc(sizeof(*async_cow), GFP_NOFS); + BTRFS_UERROR(!async_cow); async_cow->inode = inode; async_cow->root = root; async_cow->locked_page = locked_page; @@ -4447,6 +4450,7 @@ static noinline int uncompress_inline(st inline_size = btrfs_file_extent_inline_item_len(leaf, btrfs_item_nr(leaf, path->slots[0])); tmp = kmalloc(inline_size, GFP_NOFS); + BTRFS_UERROR(!tmp); ptr = btrfs_file_extent_inline_start(item); read_extent_buffer(leaf, tmp, ptr, inline_size); --- a/fs/btrfs/relocation.c +++ b/fs/btrfs/relocation.c @@ -850,7 +850,7 @@ static int __add_reloc_root(struct btrfs struct reloc_control *rc = root->fs_info->reloc_ctl; node = kmalloc(sizeof(*node), GFP_NOFS); - BUG_ON(!node); + BTRFS_UERROR(!node); node->bytenr = root->node->start; node->data = root; @@ -925,7 +925,7 @@ int btrfs_init_reloc_root(struct btrfs_t return 0; root_item = kmalloc(sizeof(*root_item), GFP_NOFS); - BUG_ON(!root_item); + BTRFS_UERROR(!root_item); root_key.objectid = BTRFS_TREE_RELOC_OBJECTID; root_key.type = BTRFS_ROOT_ITEM_KEY; @@ -1167,7 +1167,7 @@ static int replace_file_extents(struct b if (root->root_key.objectid != BTRFS_TREE_RELOC_OBJECTID) { if (!ivec || ivec->nr == INODEVEC_SIZE) { ivec = kmalloc(sizeof(*ivec), GFP_NOFS); - BUG_ON(!ivec); + BTRFS_UERROR(!ivec); ivec->nr = 0; list_add_tail(&ivec->list, inode_list); } @@ -1824,7 +1824,7 @@ static int merge_reloc_roots(struct relo list_del_init(&root->root_list); async = kmalloc(sizeof(*async), GFP_NOFS); - BUG_ON(!async); + BTRFS_UERROR(!async); async->work.func = merge_func; async->work.flags = 0; async->rc = rc; --- a/fs/btrfs/transaction.c +++ b/fs/btrfs/transaction.c @@ -56,7 +56,7 @@ static noinline int join_transaction(str if (!cur_trans) { cur_trans = kmem_cache_alloc(btrfs_transaction_cachep, GFP_NOFS); - BUG_ON(!cur_trans); + BTRFS_UERROR(!cur_trans); root->fs_info->generation++; cur_trans->num_writers = 1; cur_trans->num_joined = 0; @@ -170,6 +170,8 @@ static struct btrfs_trans_handle *start_ kmem_cache_alloc(btrfs_trans_handle_cachep, GFP_NOFS); int ret; + BTRFS_UERROR(!h); + mutex_lock(&root->fs_info->trans_mutex); if (!root->fs_info->log_root_recovering && ((wait == 1 && !root->fs_info->open_ioctl_trans) || wait == 2)) --- a/fs/btrfs/tree-log.c +++ b/fs/btrfs/tree-log.c @@ -333,7 +333,9 @@ static noinline int overwrite_item(struc return 0; } dst_copy = kmalloc(item_size, GFP_NOFS); + BTRFS_UERROR(!dst_copy); src_copy = kmalloc(item_size, GFP_NOFS); + BTRFS_UERROR(!src_copy); read_extent_buffer(eb, src_copy, src_ptr, item_size); @@ -661,6 +663,7 @@ static noinline int drop_one_dir_item(st btrfs_dir_item_key_to_cpu(leaf, di, &location); name_len = btrfs_dir_name_len(leaf, di); name = kmalloc(name_len, GFP_NOFS); + BTRFS_UERROR(!name); read_extent_buffer(leaf, name, (unsigned long)(di + 1), name_len); btrfs_release_path(root, path); @@ -816,7 +819,7 @@ again: namelen = btrfs_inode_ref_name_len(eb, ref); name = kmalloc(namelen, GFP_NOFS); - BUG_ON(!name); + BTRFS_UERROR(!name); read_extent_buffer(eb, name, (unsigned long)(ref + 1), namelen); @@ -861,7 +864,7 @@ conflict_again: victim_name_len = btrfs_inode_ref_name_len(leaf, victim_ref); victim_name = kmalloc(victim_name_len, GFP_NOFS); - BUG_ON(!victim_name); + BTRFS_UERROR(!victim_name); read_extent_buffer(leaf, victim_name, (unsigned long)(victim_ref + 1), @@ -1164,6 +1167,7 @@ static noinline int replay_one_name(stru name_len = btrfs_dir_name_len(eb, di); name = kmalloc(name_len, GFP_NOFS); + BTRFS_UERROR(!name); log_type = btrfs_dir_type(eb, di); read_extent_buffer(eb, name, (unsigned long)(di + 1), name_len); @@ -2571,6 +2575,7 @@ static noinline int copy_items(struct bt ins_data = kmalloc(nr * sizeof(struct btrfs_key) + nr * sizeof(u32), GFP_NOFS); + BTRFS_UERROR(!ins_data); ins_sizes = (u32 *)ins_data; ins_keys = (struct btrfs_key *)(ins_data + nr * sizeof(u32)); --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c @@ -2819,7 +2819,7 @@ int btrfs_rmap_block(struct btrfs_mappin do_div(length, map->num_stripes); buf = kzalloc(sizeof(u64) * map->num_stripes, GFP_NOFS); - BUG_ON(!buf); + BTRFS_UERROR(!buf); for (i = 0; i < map->num_stripes; i++) { if (devid && map->stripes[i].dev->devid != devid) -- To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
This patch adds checks to ensure that kmalloc or kmem_cache_alloc has succeeded before using the memory. Signed-off-by: Jeff Mahoney <jeffm@suse.com> --- fs/btrfs/compression.c | 3 ++- fs/btrfs/disk-io.c | 5 ++++- fs/btrfs/extent-tree.c | 28 +++++++++++++++++++--------- fs/btrfs/file.c | 5 ++++- fs/btrfs/inode.c | 17 +++++++++++------ fs/btrfs/relocation.c | 12 ++++++++---- fs/btrfs/transaction.c | 10 +++++++--- fs/btrfs/tree-log.c | 25 +++++++++++++++---------- fs/btrfs/volumes.c | 5 ++++- 9 files changed, 74 insertions(+), 36 deletions(-) --- a/fs/btrfs/compression.c +++ b/fs/btrfs/compression.c @@ -351,7 +351,8 @@ int btrfs_submit_compressed_write(struct WARN_ON(start & ((u64)PAGE_CACHE_SIZE - 1)); cb = kmalloc(compressed_bio_size(root, compressed_len), GFP_NOFS); - BTRFS_UERROR(!cb); + if (!cb) + return -ENOMEM; atomic_set(&cb->pending_bios, 0); cb->errors = 0; cb->inode = inode; --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -1958,7 +1958,10 @@ struct btrfs_root *open_ctree(struct sup log_tree_root = kzalloc(sizeof(struct btrfs_root), GFP_NOFS); - BTRFS_UERROR(!log_tree_root); + if (!log_tree_root) { + err = -EIO; + goto fail_trans_kthread; + } __setup_root(nodesize, leafsize, sectorsize, stripesize, log_tree_root, fs_info, BTRFS_TREE_LOG_OBJECTID); --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c @@ -414,7 +414,8 @@ static int cache_block_group(struct btrf return 0; caching_ctl = kzalloc(sizeof(*caching_ctl), GFP_KERNEL); - BTRFS_UERROR(!caching_ctl); + if (!caching_ctl) + return -ENOMEM; INIT_LIST_HEAD(&caching_ctl->list); mutex_init(&caching_ctl->mutex); @@ -4217,7 +4218,7 @@ have_block_group: if (loop > LOOP_CACHING_NOWAIT || atomic_read(&space_info->caching_threads) < 2) { ret = cache_block_group(block_group); - BUG_ON(ret); + BTRFS_UERROR(ret); } } @@ -4743,7 +4744,8 @@ int btrfs_alloc_logged_file_extent(struc u64 num_bytes = ins->offset; block_group = btrfs_lookup_block_group(root->fs_info, ins->objectid); - cache_block_group(block_group); + ret = cache_block_group(block_group); + BTRFS_UERROR(ret); caching_ctl = get_caching_control(block_group); if (!caching_ctl) { @@ -5388,7 +5390,10 @@ int btrfs_drop_snapshot(struct btrfs_roo BUG_ON(!path); wc = kzalloc(sizeof(*wc), GFP_NOFS); - BTRFS_UERROR(!wc); + if (!wc) { + btrfs_free_path(path); + return -ENOMEM; + } trans = btrfs_start_transaction(tree_root, 1); @@ -5550,7 +5555,10 @@ int btrfs_drop_subtree(struct btrfs_tran BUG_ON(!path); wc = kzalloc(sizeof(*wc), GFP_NOFS); - BTRFS_UERROR(!wc); + if (!wc) { + btrfs_free_path(path); + return -ENOMEM; + } btrfs_assert_tree_locked(parent); parent_level = btrfs_header_level(parent); @@ -6528,7 +6536,8 @@ static noinline int replace_extents_in_l int ret; new_extent = kmalloc(sizeof(*new_extent), GFP_NOFS); - BTRFS_UERROR(!new_extent) + if (!new_extent) + return -ENOMEM; ref = btrfs_lookup_leaf_ref(root, leaf->start); BUG_ON(!ref); @@ -6732,7 +6741,8 @@ static noinline int init_reloc_tree(stru return 0; root_item = kmalloc(sizeof(*root_item), GFP_NOFS); - BTRFS_UERROR(!root_item); + if (!root_item) + return -ENOMEM; ret = btrfs_copy_root(trans, root, root->commit_root, &eb, BTRFS_TREE_RELOC_OBJECTID); @@ -6816,7 +6826,7 @@ static noinline int relocate_one_path(st mutex_lock(&root->fs_info->tree_reloc_mutex); ret = init_reloc_tree(trans, root); - BUG_ON(ret); + BTRFS_UERROR(ret); reloc_root = root->reloc_root; shared_level = ref_path->shared_level; @@ -6849,7 +6859,7 @@ static noinline int relocate_one_path(st eb = path->nodes[0]; ret = replace_extents_in_leaf(trans, reloc_root, eb, group, reloc_inode); - BUG_ON(ret); + BTRFS_UERROR(ret); } btrfs_release_path(reloc_root, path); } else { --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c @@ -946,7 +946,10 @@ static ssize_t btrfs_file_write(struct f file_update_time(file); pages = kmalloc(nrptrs * sizeof(struct page *), GFP_KERNEL); - BTRFS_UERROR(!pages); + if (!pages) { + err = -ENOMEM; + goto out; + } /* generic_write_checks can change our pos */ start_pos = pos; --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -273,7 +273,8 @@ static noinline int add_async_extent(str struct async_extent *async_extent; async_extent = kmalloc(sizeof(*async_extent), GFP_NOFS); - BTRFS_UERROR(!async_extent); + if (!async_extent) + return -ENOMEM; async_extent->start = start; async_extent->ram_size = ram_size; async_extent->compressed_size = compressed_size; @@ -483,8 +484,9 @@ again: * allocation on disk for these compressed pages, * and will submit them to the elevator. */ - add_async_extent(async_cow, start, num_bytes, - total_compressed, pages, nr_pages_ret); + ret = add_async_extent(async_cow, start, num_bytes, + total_compressed, pages, nr_pages_ret); + BTRFS_UERROR(ret); if (start + num_bytes < end && start + num_bytes < actual_end) { start += num_bytes; @@ -506,7 +508,9 @@ cleanup_and_bail_uncompressed: __set_page_dirty_nobuffers(locked_page); /* unlocked later on in the async handlers */ } - add_async_extent(async_cow, start, end - start + 1, 0, NULL, 0); + ret = add_async_extent(async_cow, start, + end - start + 1, 0, NULL, 0); + BTRFS_UERROR(ret); *num_added += 1; } @@ -4450,7 +4454,8 @@ static noinline int uncompress_inline(st inline_size = btrfs_file_extent_inline_item_len(leaf, btrfs_item_nr(leaf, path->slots[0])); tmp = kmalloc(inline_size, GFP_NOFS); - BTRFS_UERROR(!tmp); + if (!tmp) + return -ENOMEM; ptr = btrfs_file_extent_inline_start(item); read_extent_buffer(leaf, tmp, ptr, inline_size); @@ -4648,7 +4653,7 @@ again: ret = uncompress_inline(path, inode, page, pg_offset, extent_offset, item); - BUG_ON(ret); + BTRFS_UERROR(ret); } else { map = kmap(page); read_extent_buffer(leaf, map + pg_offset, ptr, --- a/fs/btrfs/relocation.c +++ b/fs/btrfs/relocation.c @@ -850,7 +850,8 @@ static int __add_reloc_root(struct btrfs struct reloc_control *rc = root->fs_info->reloc_ctl; node = kmalloc(sizeof(*node), GFP_NOFS); - BTRFS_UERROR(!node); + if (!node) + return -ENOMEM; node->bytenr = root->node->start; node->data = root; @@ -925,7 +926,8 @@ int btrfs_init_reloc_root(struct btrfs_t return 0; root_item = kmalloc(sizeof(*root_item), GFP_NOFS); - BTRFS_UERROR(!root_item); + if (!root_item) + return -ENOMEM; root_key.objectid = BTRFS_TREE_RELOC_OBJECTID; root_key.type = BTRFS_ROOT_ITEM_KEY; @@ -957,7 +959,8 @@ int btrfs_init_reloc_root(struct btrfs_t BUG_ON(IS_ERR(reloc_root)); reloc_root->last_trans = trans->transid; - __add_reloc_root(reloc_root); + ret = __add_reloc_root(reloc_root); + BTRFS_UERROR(ret); root->reloc_root = reloc_root; return 0; } @@ -3721,7 +3724,8 @@ int btrfs_recover_relocation(struct btrf reloc_root->root_key.offset); BUG_ON(IS_ERR(fs_root)); - __add_reloc_root(reloc_root); + err = __add_reloc_root(reloc_root); + BTRFS_UERROR(err); fs_root->reloc_root = reloc_root; } --- a/fs/btrfs/transaction.c +++ b/fs/btrfs/transaction.c @@ -56,7 +56,8 @@ static noinline int join_transaction(str if (!cur_trans) { cur_trans = kmem_cache_alloc(btrfs_transaction_cachep, GFP_NOFS); - BTRFS_UERROR(!cur_trans); + if (!cur_trans) + return -ENOMEM; root->fs_info->generation++; cur_trans->num_writers = 1; cur_trans->num_joined = 0; @@ -102,6 +103,7 @@ static noinline int join_transaction(str static noinline int record_root_in_trans(struct btrfs_trans_handle *trans, struct btrfs_root *root) { + int ret; if (root->ref_cows && root->last_trans < trans->transid) { WARN_ON(root == root->fs_info->extent_root); WARN_ON(root->commit_root != root->node); @@ -110,7 +112,8 @@ static noinline int record_root_in_trans (unsigned long)root->root_key.objectid, BTRFS_ROOT_TRANS_TAG); root->last_trans = trans->transid; - btrfs_init_reloc_root(trans, root); + ret = btrfs_init_reloc_root(trans, root); + BTRFS_UERROR(ret); } return 0; } @@ -170,7 +173,8 @@ static struct btrfs_trans_handle *start_ kmem_cache_alloc(btrfs_trans_handle_cachep, GFP_NOFS); int ret; - BTRFS_UERROR(!h); + if (!h) + return ERR_PTR(-ENOMEM); mutex_lock(&root->fs_info->trans_mutex); if (!root->fs_info->log_root_recovering && --- a/fs/btrfs/tree-log.c +++ b/fs/btrfs/tree-log.c @@ -663,7 +663,8 @@ static noinline int drop_one_dir_item(st btrfs_dir_item_key_to_cpu(leaf, di, &location); name_len = btrfs_dir_name_len(leaf, di); name = kmalloc(name_len, GFP_NOFS); - BTRFS_UERROR(!name); + if (!name) + return -ENOMEM; read_extent_buffer(leaf, name, (unsigned long)(di + 1), name_len); btrfs_release_path(root, path); @@ -895,7 +896,7 @@ conflict_again: name, namelen, 0); if (di && !IS_ERR(di)) { ret = drop_one_dir_item(trans, root, path, dir, di); - BUG_ON(ret); + BTRFS_UERROR(ret); } btrfs_release_path(root, path); @@ -905,7 +906,7 @@ conflict_again: name, namelen, 0); if (di && !IS_ERR(di)) { ret = drop_one_dir_item(trans, root, path, dir, di); - BUG_ON(ret); + BTRFS_UERROR(ret); } btrfs_release_path(root, path); @@ -1167,7 +1168,10 @@ static noinline int replay_one_name(stru name_len = btrfs_dir_name_len(eb, di); name = kmalloc(name_len, GFP_NOFS); - BTRFS_UERROR(!name); + if (!name) { + iput(dir); + return -ENOMEM; + } log_type = btrfs_dir_type(eb, di); read_extent_buffer(eb, name, (unsigned long)(di + 1), name_len); @@ -1217,7 +1221,7 @@ static noinline int replay_one_name(stru goto out; ret = drop_one_dir_item(trans, root, path, dir, dst_di); - BUG_ON(ret); + BTRFS_UERROR(ret); if (key->type == BTRFS_DIR_INDEX_KEY) goto insert; @@ -1261,7 +1265,7 @@ static noinline int replay_one_dir_item( di = (struct btrfs_dir_item *)ptr; name_len = btrfs_dir_name_len(eb, di); ret = replay_one_name(trans, root, path, eb, di, key); - BUG_ON(ret); + BTRFS_UERROR(ret); ptr = (unsigned long)(di + 1); ptr += name_len; } @@ -2575,7 +2579,8 @@ static noinline int copy_items(struct bt ins_data = kmalloc(nr * sizeof(struct btrfs_key) + nr * sizeof(u32), GFP_NOFS); - BTRFS_UERROR(!ins_data); + if (!ins_data) + return -ENOMEM; ins_sizes = (u32 *)ins_data; ins_keys = (struct btrfs_key *)(ins_data + nr * sizeof(u32)); @@ -2766,7 +2771,7 @@ again: ret = copy_items(trans, log, dst_path, src, ins_start_slot, ins_nr, inode_only); - BUG_ON(ret); + BTRFS_UERROR(ret); ins_nr = 1; ins_start_slot = path->slots[0]; next_slot: @@ -2782,7 +2787,7 @@ next_slot: ret = copy_items(trans, log, dst_path, src, ins_start_slot, ins_nr, inode_only); - BUG_ON(ret); + BTRFS_UERROR(ret); ins_nr = 0; } btrfs_release_path(root, path); @@ -2800,7 +2805,7 @@ next_slot: ret = copy_items(trans, log, dst_path, src, ins_start_slot, ins_nr, inode_only); - BUG_ON(ret); + BTRFS_UERROR(ret); ins_nr = 0; } WARN_ON(ins_nr); --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c @@ -2819,7 +2819,10 @@ int btrfs_rmap_block(struct btrfs_mappin do_div(length, map->num_stripes); buf = kzalloc(sizeof(u64) * map->num_stripes, GFP_NOFS); - BTRFS_UERROR(!buf); + if (!buf) { + free_extent_map(em); + return -ENOMEM; + } for (i = 0; i < map->num_stripes; i++) { if (devid && map->stripes[i].dev->devid != devid) -- To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Jeff Mahoney
2009-Nov-04 19:03 UTC
[patch 08/10] btrfs: annotate btrfs_{start,join}_transaction failures
This patch locates and adds checks for failed transaction joins and starts. It doesn''t do anything other than use BTRFS_UERROR to annotate them to keep the patch simple and obvious. The next patch will add handling up the call chain where it''s obvious. Signed-off-by: Jeff Mahoney <jeffm@suse.com> --- fs/btrfs/disk-io.c | 3 +++ fs/btrfs/extent-tree.c | 11 +++++++---- fs/btrfs/file.c | 1 + fs/btrfs/inode.c | 23 ++++++++++++++++++++--- fs/btrfs/ioctl.c | 10 ++++++---- fs/btrfs/relocation.c | 12 +++++++++++- fs/btrfs/super.c | 1 + fs/btrfs/transaction.c | 3 +++ fs/btrfs/tree-log.c | 1 + fs/btrfs/volumes.c | 6 ++++-- fs/btrfs/xattr.c | 1 + 11 files changed, 58 insertions(+), 14 deletions(-) --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -1529,6 +1529,7 @@ static int transaction_kthread(void *arg } mutex_unlock(&root->fs_info->trans_mutex); trans = btrfs_start_transaction(root, 1); + BTRFS_UERROR(!trans); ret = btrfs_commit_transaction(trans, root); sleep: @@ -2395,10 +2396,12 @@ int btrfs_commit_super(struct btrfs_root btrfs_clean_old_snapshots(root); mutex_unlock(&root->fs_info->cleaner_mutex); trans = btrfs_start_transaction(root, 1); + BTRFS_UERROR(!trans); ret = btrfs_commit_transaction(trans, root); BUG_ON(ret); /* run commit again to drop the original snapshot */ trans = btrfs_start_transaction(root, 1); + BTRFS_UERROR(!trans); btrfs_commit_transaction(trans, root); ret = btrfs_write_and_wait_transaction(NULL, root); BUG_ON(ret); --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c @@ -3272,7 +3272,7 @@ alloc: committed = 1; trans = btrfs_join_transaction(root, 1); if (!trans) - return -ENOMEM; + return PTR_ERR(trans); ret = btrfs_commit_transaction(trans, root); if (ret) return ret; @@ -5396,6 +5396,7 @@ int btrfs_drop_snapshot(struct btrfs_roo } trans = btrfs_start_transaction(tree_root, 1); + BTRFS_UERROR(!trans); if (btrfs_disk_key_objectid(&root_item->drop_progress) == 0) { level = btrfs_header_level(root->node); @@ -5492,6 +5493,7 @@ int btrfs_drop_snapshot(struct btrfs_roo btrfs_end_transaction(trans, tree_root); trans = btrfs_start_transaction(tree_root, 1); + BTRFS_UERROR(!trans); } else { unsigned long update; update = trans->delayed_ref_updates; @@ -6654,7 +6656,7 @@ int btrfs_drop_dead_reloc_roots(struct b BUG_ON(reloc_root->commit_root != NULL); while (1) { trans = btrfs_join_transaction(root, 1); - BUG_ON(!trans); + BTRFS_UERROR(!trans); mutex_lock(&root->fs_info->drop_mutex); ret = btrfs_drop_snapshot(trans, reloc_root); @@ -6712,7 +6714,7 @@ int btrfs_cleanup_reloc_trees(struct btr if (found) { trans = btrfs_start_transaction(root, 1); - BUG_ON(!trans); + BTRFS_UERROR(!trans); ret = btrfs_commit_transaction(trans, root); BUG_ON(ret); } @@ -6957,7 +6959,7 @@ static noinline int relocate_one_extent( trans = btrfs_start_transaction(extent_root, 1); - BUG_ON(!trans); + BTRFS_UERROR(!trans); if (extent_key->objectid == 0) { ret = del_extent_zero(trans, extent_root, path, extent_key); @@ -7140,6 +7142,7 @@ static int __alloc_chunk_for_shrink(stru spin_unlock(&shrink_block_group->lock); trans = btrfs_start_transaction(root, 1); + BTRFS_UERROR(!trans); spin_lock(&shrink_block_group->lock); new_alloc_flags = update_block_group_flags(root, --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c @@ -1083,6 +1083,7 @@ out_nolock: if ((file->f_flags & O_SYNC) || IS_SYNC(inode)) { trans = btrfs_start_transaction(root, 1); + BTRFS_UERROR(!trans); ret = btrfs_log_dentry_safe(trans, root, file->f_dentry); if (ret == 0) { --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -403,7 +403,7 @@ again: } if (start == 0) { trans = btrfs_join_transaction(root, 1); - BUG_ON(!trans); + BTRFS_UERROR(!trans); btrfs_set_trans_block_group(trans, inode); /* lets try to make an inline extent */ @@ -550,6 +550,7 @@ static noinline int submit_compressed_ex return 0; trans = btrfs_join_transaction(root, 1); + BTRFS_UERROR(!trans); while (!list_empty(&async_cow->extents)) { async_extent = list_entry(async_cow->extents.next, @@ -664,6 +665,7 @@ static noinline int submit_compressed_ex BUG_ON(ret); trans = btrfs_join_transaction(root, 1); + BTRFS_UERROR(!trans); alloc_hint = ins.objectid + ins.offset; kfree(async_extent); cond_resched(); @@ -708,7 +710,7 @@ static noinline int cow_file_range(struc int ret = 0; trans = btrfs_join_transaction(root, 1); - BUG_ON(!trans); + BTRFS_UERROR(!trans); btrfs_set_trans_block_group(trans, inode); actual_end = min_t(u64, isize, end + 1); @@ -990,7 +992,7 @@ static noinline int run_delalloc_nocow(s path = btrfs_alloc_path(); BUG_ON(!path); trans = btrfs_join_transaction(root, 1); - BUG_ON(!trans); + BTRFS_UERROR(!trans); cow_start = (u64)-1; cur_offset = start; @@ -1709,6 +1711,7 @@ static int btrfs_finish_ordered_io(struc } trans = btrfs_join_transaction(root, 1); + BTRFS_UERROR(!trans); if (!ordered_extent) ordered_extent = btrfs_lookup_ordered_extent(inode, start); @@ -2129,6 +2132,7 @@ void btrfs_orphan_cleanup(struct btrfs_r */ if (is_bad_inode(inode)) { trans = btrfs_start_transaction(root, 1); + BTRFS_UERROR(!trans); btrfs_orphan_del(trans, inode); btrfs_end_transaction(trans, root); iput(inode); @@ -2482,6 +2486,7 @@ static int btrfs_unlink(struct inode *di root = BTRFS_I(dir)->root; trans = btrfs_start_transaction(root, 1); + BTRFS_UERROR(!trans); btrfs_set_trans_block_group(trans, dir); @@ -2577,6 +2582,7 @@ static int btrfs_rmdir(struct inode *dir return -ENOTEMPTY; trans = btrfs_start_transaction(root, 1); + BTRFS_UERROR(!trans); btrfs_set_trans_block_group(trans, dir); if (unlikely(inode->i_ino == BTRFS_EMPTY_SUBVOL_DIR_OBJECTID)) { @@ -3152,6 +3158,7 @@ int btrfs_cont_expand(struct inode *inod } trans = btrfs_start_transaction(root, 1); + BTRFS_UERROR(!trans); btrfs_set_trans_block_group(trans, inode); cur_offset = hole_start; @@ -3249,6 +3256,7 @@ void btrfs_delete_inode(struct inode *in btrfs_i_size_write(inode, 0); trans = btrfs_join_transaction(root, 1); + BTRFS_UERROR(!trans); btrfs_set_trans_block_group(trans, inode); ret = btrfs_truncate_inode_items(trans, root, inode, inode->i_size, 0); @@ -3845,6 +3853,7 @@ int btrfs_write_inode(struct inode *inod if (wait) { trans = btrfs_join_transaction(root, 1); + BTRFS_UERROR(!trans); btrfs_set_trans_block_group(trans, inode); ret = btrfs_commit_transaction(trans, root); } @@ -3863,6 +3872,7 @@ void btrfs_dirty_inode(struct inode *ino struct btrfs_trans_handle *trans; trans = btrfs_join_transaction(root, 1); + BTRFS_UERROR(!trans); btrfs_set_trans_block_group(trans, inode); btrfs_update_inode(trans, root, inode); btrfs_end_transaction(trans, root); @@ -4156,6 +4166,7 @@ static int btrfs_mknod(struct inode *dir return err; trans = btrfs_start_transaction(root, 1); + err = -ENOMEM; if (!trans) goto fail; btrfs_set_trans_block_group(trans, dir); @@ -4226,6 +4237,7 @@ static int btrfs_create(struct inode *di return err; trans = btrfs_start_transaction(root, 1); + err = -ENOMEM; if (!trans) goto fail; btrfs_set_trans_block_group(trans, dir); @@ -4306,6 +4318,7 @@ static int btrfs_link(struct dentry *old goto fail; trans = btrfs_start_transaction(root, 1); + BTRFS_UERROR(!trans); btrfs_set_trans_block_group(trans, dir); atomic_inc(&inode->i_count); @@ -4673,6 +4686,7 @@ again: em = NULL; btrfs_release_path(root, path); trans = btrfs_join_transaction(root, 1); + BTRFS_UERROR(!trans); goto again; } map = kmap(page); @@ -5042,6 +5056,7 @@ static void btrfs_truncate(struct inode btrfs_wait_ordered_range(inode, inode->i_size & (~mask), (u64)-1); trans = btrfs_start_transaction(root, 1); + BTRFS_UERROR(!trans); /* * setattr is responsible for setting the ordered_data_close flag, @@ -5314,6 +5329,7 @@ static int btrfs_rename(struct inode *ol down_read(&root->fs_info->subvol_sem); trans = btrfs_start_transaction(root, 1); + BTRFS_UERROR(!trans); btrfs_set_trans_block_group(trans, new_dir); if (dest != root) @@ -5494,6 +5510,7 @@ static int btrfs_symlink(struct inode *d return err; trans = btrfs_start_transaction(root, 1); + err = -ENOMEM; if (!trans) goto out_fail; btrfs_set_trans_block_group(trans, dir); --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c @@ -199,7 +199,7 @@ static int btrfs_ioctl_setflags(struct f trans = btrfs_join_transaction(root, 1); - BUG_ON(!trans); + BTRFS_UERROR(!trans); ret = btrfs_update_inode(trans, root, inode); BUG_ON(ret); @@ -250,7 +250,7 @@ static noinline int create_subvol(struct return ret; trans = btrfs_start_transaction(root, 1); - BUG_ON(!trans); + BTRFS_UERROR(!trans); ret = btrfs_find_free_objectid(trans, root->fs_info->tree_root, 0, &objectid); @@ -391,7 +391,7 @@ static int create_snapshot(struct btrfs_ pending_snapshot->name[namelen] = ''\0''; pending_snapshot->dentry = dentry; trans = btrfs_start_transaction(root, 1); - BUG_ON(!trans); + BTRFS_UERROR(!trans); pending_snapshot->root = root; list_add(&pending_snapshot->list, &trans->transaction->pending_snapshots); @@ -639,6 +639,7 @@ static noinline int btrfs_ioctl_resize(s if (new_size > old_size) { trans = btrfs_start_transaction(root, 1); + BTRFS_UERROR(!trans); ret = btrfs_grow_device(trans, device, new_size); btrfs_commit_transaction(trans, root); } else { @@ -804,6 +805,7 @@ static noinline int btrfs_ioctl_snap_des goto out_up_write; trans = btrfs_start_transaction(root, 1); + BTRFS_UERROR(!trans); ret = btrfs_unlink_subvol(trans, root, dir, dest->root_key.objectid, dentry->d_name.name, @@ -1024,7 +1026,7 @@ static noinline long btrfs_ioctl_clone(s } trans = btrfs_start_transaction(root, 1); - BUG_ON(!trans); + BTRFS_UERROR(!trans); /* punch hole in destination first */ btrfs_drop_extents(trans, root, inode, off, off + len, --- a/fs/btrfs/relocation.c +++ b/fs/btrfs/relocation.c @@ -1638,6 +1638,7 @@ static noinline_for_stack int merge_relo if (level == 0 && rc->stage == UPDATE_DATA_PTRS) { trans = btrfs_start_transaction(root, 1); + BTRFS_UERROR(!trans); leaf = path->nodes[0]; btrfs_item_key_to_cpu(leaf, &key, 0); @@ -1664,6 +1665,7 @@ static noinline_for_stack int merge_relo leaf = NULL; replaced = 0; trans = btrfs_start_transaction(root, 1); + BTRFS_UERROR(!trans); max_level = level; ret = walk_down_reloc_tree(reloc_root, path, &level); @@ -1799,6 +1801,7 @@ static void merge_func(struct btrfs_work merge_reloc_root(async->rc, root); trans = btrfs_start_transaction(root, 1); + BTRFS_UERROR(!trans); btrfs_update_reloc_root(trans, root); btrfs_end_transaction(trans, root); } @@ -3291,10 +3294,12 @@ static noinline_for_stack int relocate_b set_reloc_control(rc); trans = btrfs_start_transaction(rc->extent_root, 1); + BTRFS_UERROR(!trans); btrfs_commit_transaction(trans, rc->extent_root); while (1) { trans = btrfs_start_transaction(rc->extent_root, 1); + BTRFS_UERROR(!trans); ret = find_next_extent(trans, rc, path); if (ret < 0) @@ -3405,6 +3410,7 @@ static noinline_for_stack int relocate_b if (rc->extents_found > 0) { trans = btrfs_start_transaction(rc->extent_root, 1); + BTRFS_UERROR(!trans); btrfs_commit_transaction(trans, rc->extent_root); } @@ -3414,6 +3420,7 @@ static noinline_for_stack int relocate_b /* get rid of pinned extents */ trans = btrfs_start_transaction(rc->extent_root, 1); + BTRFS_UERROR(!trans); btrfs_commit_transaction(trans, rc->extent_root); return err; @@ -3469,7 +3476,7 @@ static struct inode *create_reloc_inode( return ERR_CAST(root); trans = btrfs_start_transaction(root, 1); - BUG_ON(!trans); + BTRFS_UERROR(!trans); err = btrfs_find_free_objectid(trans, root, objectid, &objectid); if (err) @@ -3603,6 +3610,7 @@ static noinline_for_stack int mark_garba int ret; trans = btrfs_start_transaction(root->fs_info->tree_root, 1); + BTRFS_UERROR(!trans); memset(&root->root_item.drop_progress, 0, sizeof(root->root_item.drop_progress)); @@ -3730,6 +3738,7 @@ int btrfs_recover_relocation(struct btrf } trans = btrfs_start_transaction(rc->extent_root, 1); + BTRFS_UERROR(!trans); btrfs_commit_transaction(trans, rc->extent_root); merge_reloc_roots(rc); @@ -3737,6 +3746,7 @@ int btrfs_recover_relocation(struct btrf unset_reloc_control(rc); trans = btrfs_start_transaction(rc->extent_root, 1); + BTRFS_UERROR(!trans); btrfs_commit_transaction(trans, rc->extent_root); out: if (rc) { --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c @@ -417,6 +417,7 @@ int btrfs_sync_fs(struct super_block *sb btrfs_wait_ordered_extents(root, 0); trans = btrfs_start_transaction(root, 1); + BTRFS_UERROR(!trans); ret = btrfs_commit_transaction(trans, root); return ret; } --- a/fs/btrfs/transaction.c +++ b/fs/btrfs/transaction.c @@ -630,6 +630,7 @@ int btrfs_defrag_root(struct btrfs_root if (root->defrag_running) return 0; trans = btrfs_start_transaction(root, 1); + BTRFS_UERROR(!trans); while (1) { root->defrag_running = 1; ret = btrfs_defrag_leaves(trans, root, cacheonly); @@ -639,6 +640,7 @@ int btrfs_defrag_root(struct btrfs_root cond_resched(); trans = btrfs_start_transaction(root, 1); + BTRFS_UERROR(!trans); if (root->fs_info->closing || ret != -EAGAIN) break; } @@ -812,6 +814,7 @@ static noinline int finish_pending_snaps parent_inode = pending->dentry->d_parent->d_inode; parent_root = BTRFS_I(parent_inode)->root; trans = btrfs_join_transaction(parent_root, 1); + BTRFS_UERROR(!trans); /* * insert the directory item --- a/fs/btrfs/tree-log.c +++ b/fs/btrfs/tree-log.c @@ -3024,6 +3024,7 @@ int btrfs_recover_log_trees(struct btrfs BUG_ON(!path); trans = btrfs_start_transaction(fs_info->tree_root, 1); + BTRFS_UERROR(!trans); wc.trans = trans; wc.pin = 1; --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c @@ -1090,6 +1090,7 @@ static int btrfs_rm_dev_item(struct btrf return -ENOMEM; trans = btrfs_start_transaction(root, 1); + BTRFS_UERROR(!trans); key.objectid = BTRFS_DEV_ITEMS_OBJECTID; key.type = BTRFS_DEV_ITEM_KEY; key.offset = device->devid; @@ -1480,6 +1481,7 @@ int btrfs_init_new_device(struct btrfs_r } trans = btrfs_start_transaction(root, 1); + BTRFS_UERROR(!trans); lock_chunks(root); device->barriers = 1; @@ -1747,7 +1749,7 @@ static int btrfs_relocate_chunk(struct b BUG_ON(ret); trans = btrfs_start_transaction(root, 1); - BUG_ON(!trans); + BTRFS_UERROR(!trans); lock_chunks(root); @@ -1919,7 +1921,7 @@ int btrfs_balance(struct btrfs_root *dev BUG_ON(ret); trans = btrfs_start_transaction(dev_root, 1); - BUG_ON(!trans); + BTRFS_UERROR(!trans); ret = btrfs_grow_device(trans, device, old_size); BUG_ON(ret); --- a/fs/btrfs/xattr.c +++ b/fs/btrfs/xattr.c @@ -99,6 +99,7 @@ int __btrfs_setxattr(struct inode *inode return -ENOMEM; trans = btrfs_join_transaction(root, 1); + BTRFS_UERROR(!trans); btrfs_set_trans_block_group(trans, inode); /* first lets see if we already have this xattr */ -- To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Jeff Mahoney
2009-Nov-04 19:03 UTC
[patch 09/10] btrfs: handle btrfs_{start,join}_transaction call path failures
This patch changes start_transaction() to return an ERR_PTR instead of NULL. Things like I/O errors and allocation failures can be handled differently. Many calls that were previously handled by BTRFS_UERROR are changed to actually pass the error up the tree where appropriate. In cases where the handling isn''t small or obvious, the BTRFS_UERROR call is kept for handling in small patches specific to that site. Eventually it may be preferable to allow passing of gfp_t to btrfs_start_transaction (or a one-off) so that handling can be done at allocation time instead of failing all the way up the call path. Signed-off-by: Jeff Mahoney <jeffm@suse.com> --- fs/btrfs/compression.c | 10 ++- fs/btrfs/disk-io.c | 37 +++++++++----- fs/btrfs/extent-tree.c | 43 ++++++++++------ fs/btrfs/extent_io.c | 60 ++++++++++++++-------- fs/btrfs/file.c | 16 ++++-- fs/btrfs/inode.c | 128 ++++++++++++++++++++++++++++++------------------- fs/btrfs/ioctl.c | 73 +++++++++++++++++++-------- fs/btrfs/relocation.c | 96 ++++++++++++++++++++++++++++-------- fs/btrfs/super.c | 12 +++- fs/btrfs/transaction.c | 34 +++++++++---- fs/btrfs/tree-log.c | 14 +++-- fs/btrfs/volumes.c | 44 ++++++++++------ fs/btrfs/xattr.c | 3 - 13 files changed, 382 insertions(+), 188 deletions(-) --- a/fs/btrfs/compression.c +++ b/fs/btrfs/compression.c @@ -280,6 +280,7 @@ static void end_compressed_bio_write(str struct inode *inode; struct page *page; unsigned long index; + int ret; if (err) cb->errors = 1; @@ -296,10 +297,11 @@ static void end_compressed_bio_write(str inode = cb->inode; tree = &BTRFS_I(inode)->io_tree; cb->compressed_pages[0]->mapping = cb->inode->i_mapping; - tree->ops->writepage_end_io_hook(cb->compressed_pages[0], - cb->start, - cb->start + cb->len - 1, - NULL, 1); + ret = tree->ops->writepage_end_io_hook(cb->compressed_pages[0], + cb->start, + cb->start + cb->len - 1, + NULL, 1); + BTRFS_UERROR(ret); cb->compressed_pages[0]->mapping = NULL; end_compressed_writeback(inode, cb->start, cb->len); --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -1468,6 +1468,7 @@ static void end_workqueue_fn(struct btrf static int cleaner_kthread(void *arg) { struct btrfs_root *root = arg; + int ret; do { smp_mb(); @@ -1478,7 +1479,8 @@ static int cleaner_kthread(void *arg) if (!(root->fs_info->sb->s_flags & MS_RDONLY) && mutex_trylock(&root->fs_info->cleaner_mutex)) { - btrfs_clean_old_snapshots(root); + ret = btrfs_clean_old_snapshots(root); + BTRFS_UERROR(ret); mutex_unlock(&root->fs_info->cleaner_mutex); } @@ -1529,9 +1531,11 @@ static int transaction_kthread(void *arg } mutex_unlock(&root->fs_info->trans_mutex); trans = btrfs_start_transaction(root, 1); - BTRFS_UERROR(!trans); - ret = btrfs_commit_transaction(trans, root); + if (!IS_ERR(trans)) + ret = btrfs_commit_transaction(trans, root); + if (IS_ERR(trans) || ret) + delay = HZ * 5; sleep: wake_up_process(root->fs_info->cleaner_kthread); mutex_unlock(&root->fs_info->transaction_kthread_mutex); @@ -1971,11 +1975,15 @@ struct btrfs_root *open_ctree(struct sup blocksize, generation + 1); ret = btrfs_recover_log_trees(log_tree_root); - BUG_ON(ret); + if (ret) { + /* log_tree_root is cleaned up by + * btrfs_recover_log_trees */ + goto fail_trans_thread; + } if (sb->s_flags & MS_RDONLY) { ret = btrfs_commit_super(tree_root); - BUG_ON(ret); + BTRFS_UERROR(ret); } } @@ -1984,7 +1992,7 @@ struct btrfs_root *open_ctree(struct sup if (!(sb->s_flags & MS_RDONLY)) { ret = btrfs_recover_relocation(tree_root); - BUG_ON(ret); + BTRFS_UERROR(ret); } location.objectid = BTRFS_FS_TREE_OBJECTID; @@ -2393,16 +2401,23 @@ int btrfs_commit_super(struct btrfs_root int ret; mutex_lock(&root->fs_info->cleaner_mutex); - btrfs_clean_old_snapshots(root); + ret = btrfs_clean_old_snapshots(root); mutex_unlock(&root->fs_info->cleaner_mutex); + if (ret) + return ret; trans = btrfs_start_transaction(root, 1); - BTRFS_UERROR(!trans); + if (IS_ERR(trans)) + return PTR_ERR(trans); ret = btrfs_commit_transaction(trans, root); - BUG_ON(ret); + if (ret) + return ret; /* run commit again to drop the original snapshot */ trans = btrfs_start_transaction(root, 1); - BTRFS_UERROR(!trans); - btrfs_commit_transaction(trans, root); + if (IS_ERR(trans)) + return PTR_ERR(trans); + ret = btrfs_commit_transaction(trans, root); + if (ret) + return ret; ret = btrfs_write_and_wait_transaction(NULL, root); BUG_ON(ret); --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c @@ -3009,8 +3009,8 @@ static int maybe_allocate_chunk(struct b } trans = btrfs_start_transaction(root, 1); - if (!trans) { - ret = -ENOMEM; + if (IS_ERR(trans)) { + ret = PTR_ERR(trans); goto out; } @@ -3044,6 +3044,7 @@ int btrfs_reserve_metadata_for_delalloc( u64 alloc_target; int flushed = 0; int force_delalloc; + int ret = 0; /* get the space info for where the metadata will live */ alloc_target = btrfs_get_alloc_profile(root, 0); @@ -3249,8 +3250,8 @@ again: alloc: alloc_target = btrfs_get_alloc_profile(root, 1); trans = btrfs_start_transaction(root, 1); - if (!trans) - return -ENOMEM; + if (IS_ERR(trans)) + return PTR_ERR(trans); ret = do_chunk_alloc(trans, root->fs_info->extent_root, bytes + 2 * 1024 * 1024, @@ -3271,7 +3272,7 @@ alloc: if (!committed && !root->fs_info->open_ioctl_trans) { committed = 1; trans = btrfs_join_transaction(root, 1); - if (!trans) + if (IS_ERR(trans)) return PTR_ERR(trans); ret = btrfs_commit_transaction(trans, root); if (ret) @@ -5396,7 +5397,10 @@ int btrfs_drop_snapshot(struct btrfs_roo } trans = btrfs_start_transaction(tree_root, 1); - BTRFS_UERROR(!trans); + if (IS_ERR(trans)) { + err = PTR_ERR(trans); + goto out_err; + } if (btrfs_disk_key_objectid(&root_item->drop_progress) == 0) { level = btrfs_header_level(root->node); @@ -5493,7 +5497,7 @@ int btrfs_drop_snapshot(struct btrfs_roo btrfs_end_transaction(trans, tree_root); trans = btrfs_start_transaction(tree_root, 1); - BTRFS_UERROR(!trans); + BTRFS_UERROR(IS_ERR(trans)); } else { unsigned long update; update = trans->delayed_ref_updates; @@ -5529,6 +5533,7 @@ int btrfs_drop_snapshot(struct btrfs_roo } out: btrfs_end_transaction(trans, tree_root); +out_err: kfree(wc); btrfs_free_path(path); return err; @@ -6656,7 +6661,7 @@ int btrfs_drop_dead_reloc_roots(struct b BUG_ON(reloc_root->commit_root != NULL); while (1) { trans = btrfs_join_transaction(root, 1); - BTRFS_UERROR(!trans); + BTRFS_UERROR(IS_ERR(trans)); mutex_lock(&root->fs_info->drop_mutex); ret = btrfs_drop_snapshot(trans, reloc_root); @@ -6669,6 +6674,7 @@ int btrfs_drop_dead_reloc_roots(struct b BUG_ON(ret); btrfs_btree_balance_dirty(root, nr); } + BTRFS_UERROR(ret); free_extent_buffer(reloc_root->node); @@ -6714,9 +6720,11 @@ int btrfs_cleanup_reloc_trees(struct btr if (found) { trans = btrfs_start_transaction(root, 1); - BTRFS_UERROR(!trans); + if (IS_ERR(trans)) + return PTR_ERR(trans); ret = btrfs_commit_transaction(trans, root); - BUG_ON(ret); + if (ret) + return ret; } location.objectid = BTRFS_DATA_RELOC_TREE_OBJECTID; @@ -6959,7 +6967,8 @@ static noinline int relocate_one_extent( trans = btrfs_start_transaction(extent_root, 1); - BTRFS_UERROR(!trans); + if (IS_ERR(trans)) + return PTR_ERR(trans); if (extent_key->objectid == 0) { ret = del_extent_zero(trans, extent_root, path, extent_key); @@ -6989,7 +6998,7 @@ static noinline int relocate_one_extent( continue; found_root = read_ref_root(extent_root->fs_info, ref_path); - BUG_ON(IS_ERR(found_root)); + BTRFS_UERROR(IS_ERR(found_root)); /* * for reference counted tree, only process reference paths * rooted at the latest committed root. @@ -7142,7 +7151,8 @@ static int __alloc_chunk_for_shrink(stru spin_unlock(&shrink_block_group->lock); trans = btrfs_start_transaction(root, 1); - BTRFS_UERROR(!trans); + if (IS_ERR(trans)) + return PTR_ERR(trans); spin_lock(&shrink_block_group->lock); new_alloc_flags = update_block_group_flags(root, @@ -7169,9 +7179,10 @@ int btrfs_prepare_block_group_relocation struct btrfs_block_group_cache *group) { - __alloc_chunk_for_shrink(root, group, 1); - set_block_group_readonly(group); - return 0; + int ret = __alloc_chunk_for_shrink(root, group, 1); + if (!ret) + set_block_group_readonly(group); + return ret; } /* --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c @@ -1899,10 +1899,11 @@ static int submit_one_bio(int rw, struct bio_get(bio); - if (tree->ops && tree->ops->submit_bio_hook) - tree->ops->submit_bio_hook(page->mapping->host, rw, bio, - mirror_num, bio_flags); - else + if (tree->ops && tree->ops->submit_bio_hook) { + ret = tree->ops->submit_bio_hook(page->mapping->host, rw, bio, + mirror_num, bio_flags); + BTRFS_UERROR(ret); + } else submit_bio(rw, bio); if (bio_flagged(bio, BIO_EOPNOTSUPP)) ret = -EOPNOTSUPP; @@ -2189,7 +2190,7 @@ static int __extent_writepage(struct pag struct extent_state *cached_state = NULL; struct extent_map *em; struct block_device *bdev; - int ret; + int ret = 0; int nr = 0; size_t pg_offset = 0; size_t blocksize; @@ -2250,9 +2251,12 @@ static int __extent_writepage(struct pag delalloc_start = delalloc_end + 1; continue; } - tree->ops->fill_delalloc(inode, page, delalloc_start, - delalloc_end, &page_started, - &nr_written); + ret = tree->ops->fill_delalloc(inode, page, + delalloc_start, + delalloc_end, + &page_started, + &nr_written); + BTRFS_UERROR(ret); /* * delalloc_end is already one less than the total * length, so we don''t subtract one from @@ -2306,9 +2310,11 @@ static int __extent_writepage(struct pag end = page_end; if (last_byte <= start) { - if (tree->ops && tree->ops->writepage_end_io_hook) - tree->ops->writepage_end_io_hook(page, start, - page_end, NULL, 1); + if (tree->ops && tree->ops->writepage_end_io_hook) { + ret = tree->ops->writepage_end_io_hook(page, start, + page_end, NULL, 1); + BTRFS_UERROR(ret); + } unlock_start = page_end + 1; goto done; } @@ -2317,9 +2323,12 @@ static int __extent_writepage(struct pag while (cur <= end) { if (cur >= last_byte) { - if (tree->ops && tree->ops->writepage_end_io_hook) - tree->ops->writepage_end_io_hook(page, cur, - page_end, NULL, 1); + if (tree->ops && tree->ops->writepage_end_io_hook) { + ret = tree->ops->writepage_end_io_hook(page, + cur, page_end, + NULL, 1); + BTRFS_UERROR(ret); + } unlock_start = page_end + 1; break; } @@ -2353,10 +2362,12 @@ static int __extent_writepage(struct pag * compressed extents */ if (!compressed && tree->ops && - tree->ops->writepage_end_io_hook) - tree->ops->writepage_end_io_hook(page, cur, - cur + iosize - 1, - NULL, 1); + tree->ops->writepage_end_io_hook) { + ret = tree->ops->writepage_end_io_hook(page, + cur, cur + iosize - 1, + NULL, 1); + BTRFS_UERROR(ret); + } else if (compressed) { /* we don''t want to end_page_writeback on * a compressed extent. this happens @@ -2421,7 +2432,7 @@ done_unlocked: /* drop our reference on any cached states */ free_extent_state(cached_state); - return 0; + return ret; } /** @@ -2621,10 +2632,13 @@ int extent_write_locked_range(struct ext if (clear_page_dirty_for_io(page)) ret = __extent_writepage(page, &wbc_writepages, &epd); else { - if (tree->ops && tree->ops->writepage_end_io_hook) - tree->ops->writepage_end_io_hook(page, start, - start + PAGE_CACHE_SIZE - 1, - NULL, 1); + if (tree->ops && tree->ops->writepage_end_io_hook) { + ret = tree->ops->writepage_end_io_hook(page, + start, + start + PAGE_CACHE_SIZE - 1, + NULL, 1); + BTRFS_UERROR(ret); + } unlock_page(page); } page_cache_release(page); --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c @@ -1083,7 +1083,10 @@ out_nolock: if ((file->f_flags & O_SYNC) || IS_SYNC(inode)) { trans = btrfs_start_transaction(root, 1); - BTRFS_UERROR(!trans); + if (IS_ERR(trans)) { + err = PTR_ERR(trans); + goto out; + } ret = btrfs_log_dentry_safe(trans, root, file->f_dentry); if (ret == 0) { @@ -1091,9 +1094,11 @@ out_nolock: if (ret == 0) btrfs_end_transaction(trans, root); else - btrfs_commit_transaction(trans, root); + err = btrfs_commit_transaction(trans, + root); + } else if (ret != BTRFS_NO_LOG_SYNC) { - btrfs_commit_transaction(trans, root); + err = btrfs_commit_transaction(trans, root); } else { btrfs_end_transaction(trans, root); } @@ -1104,6 +1109,7 @@ out_nolock: (start_pos + num_written - 1) >> PAGE_CACHE_SHIFT); } } +out: current->backing_dev_info = NULL; return num_written ? num_written : err; } @@ -1180,8 +1186,8 @@ int btrfs_sync_file(struct file *file, s btrfs_ioctl_trans_end(file); trans = btrfs_start_transaction(root, 1); - if (!trans) { - ret = -ENOMEM; + if (IS_ERR(trans)) { + ret = PTR_ERR(trans); goto out; } --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -403,7 +403,7 @@ again: } if (start == 0) { trans = btrfs_join_transaction(root, 1); - BTRFS_UERROR(!trans); + BTRFS_UERROR(IS_ERR(trans)); btrfs_set_trans_block_group(trans, inode); /* lets try to make an inline extent */ @@ -550,7 +550,8 @@ static noinline int submit_compressed_ex return 0; trans = btrfs_join_transaction(root, 1); - BTRFS_UERROR(!trans); + if (IS_ERR(trans)) + return PTR_ERR(trans); while (!list_empty(&async_cow->extents)) { async_extent = list_entry(async_cow->extents.next, @@ -569,11 +570,12 @@ static noinline int submit_compressed_ex async_extent->ram_size - 1, GFP_NOFS); /* allocate blocks */ - cow_file_range(inode, async_cow->locked_page, - async_extent->start, - async_extent->start + - async_extent->ram_size - 1, - &page_started, &nr_written, 0); + ret = cow_file_range(inode, async_cow->locked_page, + async_extent->start, + async_extent->start + + async_extent->ram_size - 1, + &page_started, &nr_written, 0); + BTRFS_UERROR(ret); /* * if page_started, cow_file_range inserted an @@ -581,13 +583,15 @@ static noinline int submit_compressed_ex * and IO for us. Otherwise, we need to submit * all those pages down to the drive. */ - if (!page_started) - extent_write_locked_range(io_tree, + if (!page_started) { + ret = extent_write_locked_range(io_tree, inode, async_extent->start, async_extent->start + async_extent->ram_size - 1, btrfs_get_extent, WB_SYNC_ALL); + BTRFS_UERROR(ret); + } kfree(async_extent); cond_resched(); continue; @@ -665,7 +669,7 @@ static noinline int submit_compressed_ex BUG_ON(ret); trans = btrfs_join_transaction(root, 1); - BTRFS_UERROR(!trans); + BTRFS_UERROR(IS_ERR(trans)); alloc_hint = ins.objectid + ins.offset; kfree(async_extent); cond_resched(); @@ -710,7 +714,8 @@ static noinline int cow_file_range(struc int ret = 0; trans = btrfs_join_transaction(root, 1); - BTRFS_UERROR(!trans); + if (IS_ERR(trans)) + return PTR_ERR(trans); btrfs_set_trans_block_group(trans, inode); actual_end = min_t(u64, isize, end + 1); @@ -838,10 +843,12 @@ static noinline void async_cow_start(str struct async_cow *async_cow; int num_added = 0; async_cow = container_of(work, struct async_cow, work); + int ret; - compress_file_range(async_cow->inode, async_cow->locked_page, - async_cow->start, async_cow->end, async_cow, - &num_added); + ret = compress_file_range(async_cow->inode, async_cow->locked_page, + async_cow->start, async_cow->end, async_cow, + &num_added); + BTRFS_UERROR(ret); if (num_added == 0) async_cow->inode = NULL; } @@ -992,7 +999,8 @@ static noinline int run_delalloc_nocow(s path = btrfs_alloc_path(); BUG_ON(!path); trans = btrfs_join_transaction(root, 1); - BTRFS_UERROR(!trans); + if (IS_ERR(trans)) + return PTR_ERR(trans); cow_start = (u64)-1; cur_offset = start; @@ -1102,7 +1110,7 @@ out_check: ret = cow_file_range(inode, locked_page, cow_start, found_key.offset - 1, page_started, nr_written, 1); - BUG_ON(ret); + BTRFS_UERROR(ret); cow_start = (u64)-1; } @@ -1154,7 +1162,7 @@ out_check: if (cow_start != (u64)-1) { ret = cow_file_range(inode, locked_page, cow_start, end, page_started, nr_written, 1); - BUG_ON(ret); + BTRFS_UERROR(ret); } ret = btrfs_end_transaction(trans, root); @@ -1711,7 +1719,8 @@ static int btrfs_finish_ordered_io(struc } trans = btrfs_join_transaction(root, 1); - BTRFS_UERROR(!trans); + if (IS_ERR(trans)) + return PTR_ERR(trans); if (!ordered_extent) ordered_extent = btrfs_lookup_ordered_extent(inode, start); @@ -2132,7 +2141,7 @@ void btrfs_orphan_cleanup(struct btrfs_r */ if (is_bad_inode(inode)) { trans = btrfs_start_transaction(root, 1); - BTRFS_UERROR(!trans); + BTRFS_UERROR(IS_ERR(trans)); btrfs_orphan_del(trans, inode); btrfs_end_transaction(trans, root); iput(inode); @@ -2486,7 +2495,8 @@ static int btrfs_unlink(struct inode *di root = BTRFS_I(dir)->root; trans = btrfs_start_transaction(root, 1); - BTRFS_UERROR(!trans); + if (IS_ERR(trans)) + return PTR_ERR(trans); btrfs_set_trans_block_group(trans, dir); @@ -2582,7 +2592,9 @@ static int btrfs_rmdir(struct inode *dir return -ENOTEMPTY; trans = btrfs_start_transaction(root, 1); - BTRFS_UERROR(!trans); + if (IS_ERR(trans)) + return PTR_ERR(trans); + btrfs_set_trans_block_group(trans, dir); if (unlikely(inode->i_ino == BTRFS_EMPTY_SUBVOL_DIR_OBJECTID)) { @@ -3158,14 +3170,17 @@ int btrfs_cont_expand(struct inode *inod } trans = btrfs_start_transaction(root, 1); - BTRFS_UERROR(!trans); + if (IS_ERR(trans)) { + err = PTR_ERR(trans); + goto out; + } btrfs_set_trans_block_group(trans, inode); cur_offset = hole_start; while (1) { em = btrfs_get_extent(inode, NULL, 0, cur_offset, block_end - cur_offset, 0); - BUG_ON(IS_ERR(em) || !em); + BTRFS_UERROR(IS_ERR(em) || !em); last_byte = min(extent_map_end(em), block_end); last_byte = (last_byte + mask) & ~mask; if (test_bit(EXTENT_FLAG_VACANCY, &em->flags)) { @@ -3198,6 +3213,7 @@ int btrfs_cont_expand(struct inode *inod } btrfs_end_transaction(trans, root); +out: unlock_extent(io_tree, hole_start, block_end - 1, GFP_NOFS); return err; } @@ -3256,7 +3272,7 @@ void btrfs_delete_inode(struct inode *in btrfs_i_size_write(inode, 0); trans = btrfs_join_transaction(root, 1); - BTRFS_UERROR(!trans); + BTRFS_UERROR(IS_ERR(trans)); btrfs_set_trans_block_group(trans, inode); ret = btrfs_truncate_inode_items(trans, root, inode, inode->i_size, 0); @@ -3853,7 +3869,8 @@ int btrfs_write_inode(struct inode *inod if (wait) { trans = btrfs_join_transaction(root, 1); - BTRFS_UERROR(!trans); + if (IS_ERR(trans)) + return PTR_ERR(trans); btrfs_set_trans_block_group(trans, inode); ret = btrfs_commit_transaction(trans, root); } @@ -3872,7 +3889,8 @@ void btrfs_dirty_inode(struct inode *ino struct btrfs_trans_handle *trans; trans = btrfs_join_transaction(root, 1); - BTRFS_UERROR(!trans); + if (IS_ERR(trans)) + return; btrfs_set_trans_block_group(trans, inode); btrfs_update_inode(trans, root, inode); btrfs_end_transaction(trans, root); @@ -4166,9 +4184,10 @@ static int btrfs_mknod(struct inode *dir return err; trans = btrfs_start_transaction(root, 1); - err = -ENOMEM; - if (!trans) - goto fail; + if (IS_ERR(trans)) { + btrfs_unreserve_metadata_space(root, 5); + return PTR_ERR(trans); + } btrfs_set_trans_block_group(trans, dir); err = btrfs_find_free_objectid(trans, root, dir->i_ino, &objectid); @@ -4237,9 +4256,10 @@ static int btrfs_create(struct inode *di return err; trans = btrfs_start_transaction(root, 1); - err = -ENOMEM; - if (!trans) - goto fail; + if (IS_ERR(trans)) { + btrfs_unreserve_metadata_space(root, 5); + return PTR_ERR(trans); + } btrfs_set_trans_block_group(trans, dir); err = btrfs_find_free_objectid(trans, root, dir->i_ino, &objectid); @@ -4318,7 +4338,12 @@ static int btrfs_link(struct dentry *old goto fail; trans = btrfs_start_transaction(root, 1); - BTRFS_UERROR(!trans); + if (IS_ERR(trans)) { + btrfs_dec_nlink(inode); + BTRFS_I(dir)->index_cnt = index; + err = PTR_ERR(trans); + goto fail; + } btrfs_set_trans_block_group(trans, dir); atomic_inc(&inode->i_count); @@ -4367,8 +4392,8 @@ static int btrfs_mkdir(struct inode *dir return err; trans = btrfs_start_transaction(root, 1); - if (!trans) { - err = -ENOMEM; + if (IS_ERR(trans)) { + err = PTR_ERR(trans); goto out_unlock; } btrfs_set_trans_block_group(trans, dir); @@ -4686,7 +4711,7 @@ again: em = NULL; btrfs_release_path(root, path); trans = btrfs_join_transaction(root, 1); - BTRFS_UERROR(!trans); + BTRFS_UERROR(IS_ERR(trans)); goto again; } map = kmap(page); @@ -4892,8 +4917,10 @@ static void btrfs_invalidatepage(struct * for the finish_ordered_io */ if (TestClearPagePrivate2(page)) { - btrfs_finish_ordered_io(page->mapping->host, - page_start, page_end); + int ret; + ret = btrfs_finish_ordered_io(page->mapping->host, + page_start, page_end); + BTRFS_UERROR(ret); } btrfs_put_ordered_extent(ordered); lock_extent(tree, page_start, page_end, GFP_NOFS); @@ -5042,7 +5069,7 @@ static void btrfs_truncate(struct inode struct btrfs_root *root = BTRFS_I(inode)->root; int ret; struct btrfs_trans_handle *trans; - unsigned long nr; + unsigned long nr = 0; u64 mask = root->sectorsize - 1; if (!S_ISREG(inode->i_mode)) @@ -5056,7 +5083,7 @@ static void btrfs_truncate(struct inode btrfs_wait_ordered_range(inode, inode->i_size & (~mask), (u64)-1); trans = btrfs_start_transaction(root, 1); - BTRFS_UERROR(!trans); + BTRFS_UERROR(IS_ERR(trans)); /* * setattr is responsible for setting the ordered_data_close flag, @@ -5329,7 +5356,10 @@ static int btrfs_rename(struct inode *ol down_read(&root->fs_info->subvol_sem); trans = btrfs_start_transaction(root, 1); - BTRFS_UERROR(!trans); + if (IS_ERR(trans)) { + ret = PTR_ERR(trans); + goto out_fail_notrans; + } btrfs_set_trans_block_group(trans, new_dir); if (dest != root) @@ -5425,6 +5455,8 @@ static int btrfs_rename(struct inode *ol out_fail: btrfs_end_transaction_throttle(trans, root); +out_fail_notrans: + if (old_inode->i_ino == BTRFS_FIRST_FREE_OBJECTID) up_read(&root->fs_info->subvol_sem); @@ -5510,9 +5542,10 @@ static int btrfs_symlink(struct inode *d return err; trans = btrfs_start_transaction(root, 1); - err = -ENOMEM; - if (!trans) - goto out_fail; + if (IS_ERR(trans)) { + btrfs_unreserve_metadata_space(root, 5); + return PTR_ERR(trans); + } btrfs_set_trans_block_group(trans, dir); err = btrfs_find_free_objectid(trans, root, dir->i_ino, &objectid); @@ -5592,7 +5625,6 @@ static int btrfs_symlink(struct inode *d out_unlock: nr = trans->blocks_used; btrfs_end_transaction_throttle(trans, root); -out_fail: btrfs_unreserve_metadata_space(root, 5); if (drop_inode) { inode_dec_link_count(inode); @@ -5698,8 +5730,8 @@ static long btrfs_fallocate(struct inode struct btrfs_ordered_extent *ordered; trans = btrfs_start_transaction(BTRFS_I(inode)->root, 1); - if (!trans) { - ret = -EIO; + if (IS_ERR(trans)) { + ret = PTR_ERR(trans); goto out_free; } @@ -5735,7 +5767,7 @@ static long btrfs_fallocate(struct inode while (1) { em = btrfs_get_extent(inode, NULL, 0, cur_offset, alloc_end - cur_offset, 0); - BUG_ON(IS_ERR(em) || !em); + BTRFS_UERROR(IS_ERR(em) || !em); last_byte = min(extent_map_end(em), alloc_end); last_byte = (last_byte + mask) & ~mask; if (em->block_start == EXTENT_MAP_HOLE) { --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c @@ -172,6 +172,12 @@ static int btrfs_ioctl_setflags(struct f if (ret) goto out_unlock; + trans = btrfs_join_transaction(root, 1); + if (IS_ERR(trans)) { + ret = PTR_ERR(trans); + goto out_drop_write; + } + if (flags & FS_SYNC_FL) ip->flags |= BTRFS_INODE_SYNC; else @@ -197,10 +203,6 @@ static int btrfs_ioctl_setflags(struct f else ip->flags &= ~BTRFS_INODE_DIRSYNC; - - trans = btrfs_join_transaction(root, 1); - BTRFS_UERROR(!trans); - ret = btrfs_update_inode(trans, root, inode); BUG_ON(ret); @@ -208,10 +210,11 @@ static int btrfs_ioctl_setflags(struct f inode->i_ctime = CURRENT_TIME; btrfs_end_transaction(trans, root); +out_drop_write: mnt_drop_write(file->f_path.mnt); - out_unlock: +out_unlock: mutex_unlock(&inode->i_mutex); - return 0; + return ret; } static int btrfs_ioctl_getversion(struct file *file, int __user *arg) @@ -232,6 +235,7 @@ static noinline int create_subvol(struct struct extent_buffer *leaf; struct btrfs_root *new_root; struct inode *dir = dentry->d_parent->d_inode; + struct inode *inode; int ret; int err; u64 objectid; @@ -250,7 +254,10 @@ static noinline int create_subvol(struct return ret; trans = btrfs_start_transaction(root, 1); - BTRFS_UERROR(!trans); + if (IS_ERR(trans)) { + btrfs_unreserve_metadata_space(root, 6); + return PTR_ERR(trans); + } ret = btrfs_find_free_objectid(trans, root->fs_info->tree_root, 0, &objectid); @@ -312,7 +319,7 @@ static noinline int create_subvol(struct key.offset = (u64)-1; new_root = btrfs_read_fs_root_no_name(root->fs_info, &key); - BUG_ON(IS_ERR(new_root)); + BTRFS_UERROR(IS_ERR(new_root)); btrfs_record_root_in_trans(trans, new_root); @@ -340,13 +347,14 @@ static noinline int create_subvol(struct BUG_ON(ret); - d_instantiate(dentry, btrfs_lookup_dentry(dir, dentry)); + inode = btrfs_lookup_dentry(dir, dentry); + BTRFS_UERROR(IS_ERR(inode)); + d_instantiate(dentry, inode); fail: nr = trans->blocks_used; err = btrfs_commit_transaction(trans, root); if (err && !ret) ret = err; - btrfs_unreserve_metadata_space(root, 6); btrfs_btree_balance_dirty(root, nr); return ret; @@ -358,7 +366,6 @@ static int create_snapshot(struct btrfs_ struct btrfs_pending_snapshot *pending_snapshot; struct btrfs_trans_handle *trans; int ret = 0; - int err; unsigned long nr = 0; if (!root->ref_cows) @@ -391,11 +398,16 @@ static int create_snapshot(struct btrfs_ pending_snapshot->name[namelen] = ''\0''; pending_snapshot->dentry = dentry; trans = btrfs_start_transaction(root, 1); - BTRFS_UERROR(!trans); + if (IS_ERR(trans)) { + kfree(pending_snapshot->name); + kfree(pending_snapshot); + ret = PTR_ERR(trans); + goto fail_unlock; + } pending_snapshot->root = root; list_add(&pending_snapshot->list, &trans->transaction->pending_snapshots); - err = btrfs_commit_transaction(trans, root); + ret = btrfs_commit_transaction(trans, root); fail_unlock: btrfs_btree_balance_dirty(root, nr); @@ -638,10 +650,15 @@ static noinline int btrfs_ioctl_resize(s device->name, (unsigned long long)new_size); if (new_size > old_size) { + int err; trans = btrfs_start_transaction(root, 1); - BTRFS_UERROR(!trans); + if (IS_ERR(trans)) { + ret = PTR_ERR(trans); + goto out_unlock; + } ret = btrfs_grow_device(trans, device, new_size); - btrfs_commit_transaction(trans, root); + err = btrfs_commit_transaction(trans, root); + ret = ret ?: err; } else { ret = btrfs_shrink_device(device, new_size); } @@ -805,7 +822,10 @@ static noinline int btrfs_ioctl_snap_des goto out_up_write; trans = btrfs_start_transaction(root, 1); - BTRFS_UERROR(!trans); + if (IS_ERR(trans)) { + err = PTR_ERR(trans); + goto out_up_write; + } ret = btrfs_unlink_subvol(trans, root, dir, dest->root_key.objectid, dentry->d_name.name, @@ -825,7 +845,7 @@ static noinline int btrfs_ioctl_snap_des BUG_ON(ret); ret = btrfs_commit_transaction(trans, root); - BUG_ON(ret); + BTRFS_UERROR(ret); inode->i_flags |= S_DEAD; out_up_write: up_write(&root->fs_info->subvol_sem); @@ -862,15 +882,16 @@ static int btrfs_ioctl_defrag(struct fil ret = -EPERM; goto out; } - btrfs_defrag_root(root, 0); - btrfs_defrag_root(root->fs_info->extent_root, 0); + ret = btrfs_defrag_root(root, 0); + if (!ret) + ret = btrfs_defrag_root(root->fs_info->extent_root, 0); break; case S_IFREG: if (!(file->f_mode & FMODE_WRITE)) { ret = -EINVAL; goto out; } - btrfs_defrag_file(file); + ret = btrfs_defrag_file(file); break; } out: @@ -1026,7 +1047,12 @@ static noinline long btrfs_ioctl_clone(s } trans = btrfs_start_transaction(root, 1); - BTRFS_UERROR(!trans); + if (IS_ERR(trans)) { + ret = PTR_ERR(trans); + btrfs_release_path(root, path); + unlock_extent(&BTRFS_I(src)->io_tree, off, off+len, GFP_NOFS); + goto out_unlock; + } /* punch hole in destination first */ btrfs_drop_extents(trans, root, inode, off, off + len, @@ -1255,10 +1281,11 @@ static long btrfs_ioctl_trans_start(stru root->fs_info->open_ioctl_trans++; mutex_unlock(&root->fs_info->trans_mutex); - ret = -ENOMEM; trans = btrfs_start_ioctl_transaction(root, 0); - if (!trans) + if (IS_ERR(trans)) { + ret = PTR_ERR(trans); goto out_drop; + } file->private_data = trans; return 0; --- a/fs/btrfs/relocation.c +++ b/fs/btrfs/relocation.c @@ -398,7 +398,8 @@ struct btrfs_root *find_tree_root(struct BUG_ON(root_objectid == BTRFS_TREE_RELOC_OBJECTID); root = read_fs_root(rc->extent_root->fs_info, root_objectid); - BUG_ON(IS_ERR(root)); + if (IS_ERR(root)) + return ERR_CAST(root); if (root->ref_cows && generation != btrfs_root_generation(&root->root_item)) @@ -592,6 +593,7 @@ again: ref0 = btrfs_item_ptr(eb, path1->slots[0], struct btrfs_extent_ref_v0); root = find_tree_root(rc, eb, ref0); + BTRFS_UERROR(IS_ERR(root)); if (root) cur->root = root; else @@ -1638,12 +1640,20 @@ static noinline_for_stack int merge_relo if (level == 0 && rc->stage == UPDATE_DATA_PTRS) { trans = btrfs_start_transaction(root, 1); - BTRFS_UERROR(!trans); + if (IS_ERR(trans)) { + extent_buffer_put(reloc_root->node); + } + BTRFS_UERROR(IS_ERR(trans)); leaf = path->nodes[0]; btrfs_item_key_to_cpu(leaf, &key, 0); btrfs_release_path(reloc_root, path); + if (IS_ERR(trans)) { + err = PTR_ERR(trans); + goto out; + } + ret = btrfs_search_slot(trans, root, &key, path, 0, 1); if (ret < 0) { err = ret; @@ -1665,7 +1675,7 @@ static noinline_for_stack int merge_relo leaf = NULL; replaced = 0; trans = btrfs_start_transaction(root, 1); - BTRFS_UERROR(!trans); + BTRFS_UERROR(IS_ERR(trans)); max_level = level; ret = walk_down_reloc_tree(reloc_root, path, &level); @@ -1788,6 +1798,7 @@ static void merge_func(struct btrfs_work struct btrfs_root *root; struct btrfs_root *reloc_root; struct async_merge *async; + int ret = 0; async = container_of(work, struct async_merge, work); reloc_root = async->root; @@ -1795,18 +1806,20 @@ static void merge_func(struct btrfs_work if (btrfs_root_refs(&reloc_root->root_item) > 0) { root = read_fs_root(reloc_root->fs_info, reloc_root->root_key.offset); - BUG_ON(IS_ERR(root)); + BTRFS_UERROR(IS_ERR(root)); BUG_ON(root->reloc_root != reloc_root); - merge_reloc_root(async->rc, root); + ret = merge_reloc_root(async->rc, root); + BTRFS_UERROR(ret); trans = btrfs_start_transaction(root, 1); - BTRFS_UERROR(!trans); + BTRFS_UERROR(IS_ERR(trans)); btrfs_update_reloc_root(trans, root); btrfs_end_transaction(trans, root); } - btrfs_drop_snapshot(reloc_root, 0); + ret = btrfs_drop_snapshot(reloc_root, 0); + BTRFS_UERROR(ret); if (atomic_dec_and_test(async->num_pending)) complete(async->done); @@ -1868,7 +1881,8 @@ static int record_reloc_root_in_trans(st return 0; root = read_fs_root(reloc_root->fs_info, reloc_root->root_key.offset); - BUG_ON(IS_ERR(root)); + if (IS_ERR(root)) + return PTR_ERR(root); BUG_ON(root->reloc_root != reloc_root); return btrfs_record_root_in_trans(trans, root); @@ -1888,6 +1902,7 @@ static struct btrfs_root *__select_one_r struct btrfs_root *root; int index; int loop = 0; + int ret; again: index = 0; next = node; @@ -1907,7 +1922,11 @@ again: } if (root->root_key.objectid == BTRFS_TREE_RELOC_OBJECTID) { - record_reloc_root_in_trans(trans, root); + ret = record_reloc_root_in_trans(trans, root); + if (ret) { + root = ERR_PTR(ret); + goto out; + } break; } @@ -1946,6 +1965,7 @@ skip: else *nr = 0; +out: return root; } @@ -2026,6 +2046,7 @@ static int do_relocation(struct btrfs_tr root = select_reloc_root(trans, upper, edges, &nr); if (!root) continue; + BTRFS_UERROR(IS_ERR(root)); if (upper->eb && !upper->locked) drop_node_buffer(upper); @@ -2372,6 +2393,11 @@ static int relocate_tree_block(struct bt int ret; root = select_one_root(trans, node); + if (unlikely(IS_ERR(root))) { + ret = PTR_ERR(root); + goto out; + } + if (unlikely(!root)) { rc->found_old_snapshot = 1; update_processed_blocks(rc, node); @@ -3109,6 +3135,7 @@ int add_data_references(struct reloc_con dref = (struct btrfs_extent_data_ref *)(&iref->offset); ret = find_data_references(rc, extent_key, eb, dref, blocks); + BTRFS_UERROR(ret); } else { BUG(); } @@ -3294,12 +3321,18 @@ static noinline_for_stack int relocate_b set_reloc_control(rc); trans = btrfs_start_transaction(rc->extent_root, 1); - BTRFS_UERROR(!trans); + BTRFS_UERROR(IS_ERR(trans)); + if (IS_ERR(trans)) { + rc->create_reloc_root = 0; + smp_mb(); + unset_reloc_control(rc); + return PTR_ERR(trans); + } btrfs_commit_transaction(trans, rc->extent_root); while (1) { trans = btrfs_start_transaction(rc->extent_root, 1); - BTRFS_UERROR(!trans); + BTRFS_UERROR(IS_ERR(trans)); ret = find_next_extent(trans, rc, path); if (ret < 0) @@ -3356,6 +3389,7 @@ static noinline_for_stack int relocate_b } else if (rc->stage == UPDATE_DATA_PTRS && (flags & BTRFS_EXTENT_FLAG_DATA)) { ret = add_data_references(rc, &key, path, &blocks); + BTRFS_UERROR(ret); } else { btrfs_release_path(rc->extent_root, path); ret = 0; @@ -3410,7 +3444,7 @@ static noinline_for_stack int relocate_b if (rc->extents_found > 0) { trans = btrfs_start_transaction(rc->extent_root, 1); - BTRFS_UERROR(!trans); + BTRFS_UERROR(IS_ERR(trans)); btrfs_commit_transaction(trans, rc->extent_root); } @@ -3420,7 +3454,7 @@ static noinline_for_stack int relocate_b /* get rid of pinned extents */ trans = btrfs_start_transaction(rc->extent_root, 1); - BTRFS_UERROR(!trans); + BTRFS_UERROR(IS_ERR(trans)); btrfs_commit_transaction(trans, rc->extent_root); return err; @@ -3476,7 +3510,8 @@ static struct inode *create_reloc_inode( return ERR_CAST(root); trans = btrfs_start_transaction(root, 1); - BTRFS_UERROR(!trans); + if (IS_ERR(trans)) + return ERR_CAST(trans); err = btrfs_find_free_objectid(trans, root, objectid, &objectid); if (err) @@ -3531,9 +3566,14 @@ int btrfs_relocate_block_group(struct bt fs_info->thread_pool_size, NULL); rc->extent_root = extent_root; - btrfs_prepare_block_group_relocation(extent_root, rc->block_group); + ret = btrfs_prepare_block_group_relocation(extent_root, + rc->block_group); + if (ret) + goto out; rc->data_inode = create_reloc_inode(fs_info, rc->block_group); + /* We can''t clean up from btrfs_prepare_block_group_relocation */ + BTRFS_UERROR(IS_ERR(rc->data_inode)); if (IS_ERR(rc->data_inode)) { err = PTR_ERR(rc->data_inode); rc->data_inode = NULL; @@ -3553,7 +3593,8 @@ int btrfs_relocate_block_group(struct bt mutex_lock(&fs_info->cleaner_mutex); - btrfs_clean_old_snapshots(fs_info->tree_root); + ret = btrfs_clean_old_snapshots(fs_info->tree_root); + BTRFS_UERROR(ret); ret = relocate_block_group(rc); mutex_unlock(&fs_info->cleaner_mutex); @@ -3610,7 +3651,8 @@ static noinline_for_stack int mark_garba int ret; trans = btrfs_start_transaction(root->fs_info->tree_root, 1); - BTRFS_UERROR(!trans); + if (IS_ERR(trans)) + return PTR_ERR(trans); memset(&root->root_item.drop_progress, 0, sizeof(root->root_item.drop_progress)); @@ -3689,7 +3731,11 @@ int btrfs_recover_relocation(struct btrf err = ret; goto out; } - mark_garbage_root(reloc_root); + ret = mark_garbage_root(reloc_root); + if (ret) { + err = ret; + goto out; + } } } @@ -3738,16 +3784,22 @@ int btrfs_recover_relocation(struct btrf } trans = btrfs_start_transaction(rc->extent_root, 1); - BTRFS_UERROR(!trans); - btrfs_commit_transaction(trans, rc->extent_root); + if (IS_ERR(trans)) { + err = PTR_ERR(trans); + unset_reloc_control(rc); + goto out; + } + err = btrfs_commit_transaction(trans, rc->extent_root); merge_reloc_roots(rc); unset_reloc_control(rc); trans = btrfs_start_transaction(rc->extent_root, 1); - BTRFS_UERROR(!trans); - btrfs_commit_transaction(trans, rc->extent_root); + if (IS_ERR(trans)) { + err = PTR_ERR(trans); + goto out; + err = btrfs_commit_transaction(trans, rc->extent_root); out: if (rc) { btrfs_stop_workers(&rc->workers); --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c @@ -417,8 +417,11 @@ int btrfs_sync_fs(struct super_block *sb btrfs_wait_ordered_extents(root, 0); trans = btrfs_start_transaction(root, 1); - BTRFS_UERROR(!trans); - ret = btrfs_commit_transaction(trans, root); + if (!IS_ERR(trans)) + ret = btrfs_commit_transaction(trans, root); + else + ret = PTR_ERR(trans); + return ret; } @@ -601,7 +604,8 @@ static int btrfs_remount(struct super_bl /* recover relocation */ ret = btrfs_recover_relocation(root); - WARN_ON(ret); + if (ret) + return ret; ret = btrfs_cleanup_fs_roots(root->fs_info); WARN_ON(ret); @@ -609,7 +613,7 @@ static int btrfs_remount(struct super_bl sb->s_flags &= ~MS_RDONLY; } - return 0; + return ret; } static int btrfs_statfs(struct dentry *dentry, struct kstatfs *buf) --- a/fs/btrfs/transaction.c +++ b/fs/btrfs/transaction.c @@ -181,7 +181,10 @@ static struct btrfs_trans_handle *start_ ((wait == 1 && !root->fs_info->open_ioctl_trans) || wait == 2)) wait_current_trans(root); ret = join_transaction(root); - BUG_ON(ret); + if (ret) { + h = ERR_PTR(ret); + goto out; + } h->transid = root->fs_info->running_transaction->transid; h->transaction = root->fs_info->running_transaction; @@ -197,6 +200,7 @@ static struct btrfs_trans_handle *start_ root->fs_info->running_transaction->use_count++; record_root_in_trans(h, root); +out: mutex_unlock(&root->fs_info->trans_mutex); return h; } @@ -629,8 +633,11 @@ int btrfs_defrag_root(struct btrfs_root smp_mb(); if (root->defrag_running) return 0; + trans = btrfs_start_transaction(root, 1); - BTRFS_UERROR(!trans); + if (IS_ERR(trans)) + return PTR_ERR(trans); + while (1) { root->defrag_running = 1; ret = btrfs_defrag_leaves(trans, root, cacheonly); @@ -640,14 +647,16 @@ int btrfs_defrag_root(struct btrfs_root cond_resched(); trans = btrfs_start_transaction(root, 1); - BTRFS_UERROR(!trans); + if (IS_ERR(trans)) + ret = PTR_ERR(trans); if (root->fs_info->closing || ret != -EAGAIN) break; } root->defrag_running = 0; smp_mb(); - btrfs_end_transaction(trans, root); - return 0; + if (!IS_ERR(trans)) + btrfs_end_transaction(trans, root); + return ret; } #if 0 @@ -814,7 +823,8 @@ static noinline int finish_pending_snaps parent_inode = pending->dentry->d_parent->d_inode; parent_root = BTRFS_I(parent_inode)->root; trans = btrfs_join_transaction(parent_root, 1); - BTRFS_UERROR(!trans); + if (IS_ERR(trans)) + return PTR_ERR(trans); /* * insert the directory item @@ -842,6 +852,7 @@ static noinline int finish_pending_snaps BUG_ON(ret); inode = btrfs_lookup_dentry(parent_inode, pending->dentry); + BTRFS_UERROR(IS_ERR(inode)); d_instantiate(pending->dentry, inode); fail: btrfs_end_transaction(trans, fs_info->fs_root); @@ -876,7 +887,7 @@ static noinline int finish_pending_snaps pending = list_entry(head->next, struct btrfs_pending_snapshot, list); ret = finish_pending_snapshot(fs_info, pending); - BUG_ON(ret); + BTRFS_UERROR(ret); list_del(&pending->list); kfree(pending->name); kfree(pending); @@ -1099,7 +1110,8 @@ int btrfs_commit_transaction(struct btrf btrfs_finish_extent_commit(trans, root); /* do the directory inserts of any pending snapshot creations */ - finish_pending_snapshots(trans, root->fs_info); + ret = finish_pending_snapshots(trans, root->fs_info); + BTRFS_UERROR(ret); mutex_lock(&root->fs_info->trans_mutex); @@ -1128,6 +1140,7 @@ int btrfs_clean_old_snapshots(struct btr { LIST_HEAD(list); struct btrfs_fs_info *fs_info = root->fs_info; + int ret = 0; mutex_lock(&fs_info->trans_mutex); list_splice_init(&fs_info->dead_roots, &list); @@ -1139,9 +1152,10 @@ int btrfs_clean_old_snapshots(struct btr if (btrfs_header_backref_rev(root->node) < BTRFS_MIXED_BACKREF_REV) - btrfs_drop_snapshot(root, 0); + ret = btrfs_drop_snapshot(root, 0); else - btrfs_drop_snapshot(root, 1); + ret = btrfs_drop_snapshot(root, 1); + BTRFS_UERROR(ret); } return 0; } --- a/fs/btrfs/tree-log.c +++ b/fs/btrfs/tree-log.c @@ -3024,7 +3024,10 @@ int btrfs_recover_log_trees(struct btrfs BUG_ON(!path); trans = btrfs_start_transaction(fs_info->tree_root, 1); - BTRFS_UERROR(!trans); + if (IS_ERR(trans)) { + ret = PTR_ERR(trans); + goto fail; + } wc.trans = trans; wc.pin = 1; @@ -3053,8 +3056,7 @@ again: log = btrfs_read_fs_root_no_radix(log_root_tree, &found_key); - BUG_ON(IS_ERR(log)); - + BTRFS_UERROR(IS_ERR(log)); tmp_key.objectid = found_key.offset; tmp_key.type = BTRFS_ROOT_ITEM_KEY; @@ -3098,6 +3100,7 @@ again: goto again; } +fail: btrfs_free_path(path); free_extent_buffer(log_root_tree->node); @@ -3105,10 +3108,11 @@ again: fs_info->log_root_recovering = 0; /* step 4: commit the transaction, which also unpins the blocks */ - btrfs_commit_transaction(trans, fs_info->tree_root); + if (!ret) + ret = btrfs_commit_transaction(trans, fs_info->tree_root); kfree(log_root_tree); - return 0; + return ret; } /* --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c @@ -1078,7 +1078,7 @@ out: static int btrfs_rm_dev_item(struct btrfs_root *root, struct btrfs_device *device) { - int ret; + int ret, err; struct btrfs_path *path; struct btrfs_key key; struct btrfs_trans_handle *trans; @@ -1090,7 +1090,10 @@ static int btrfs_rm_dev_item(struct btrf return -ENOMEM; trans = btrfs_start_transaction(root, 1); - BTRFS_UERROR(!trans); + if (IS_ERR(trans)) { + btrfs_free_path(path); + return PTR_ERR(trans); + } key.objectid = BTRFS_DEV_ITEMS_OBJECTID; key.type = BTRFS_DEV_ITEM_KEY; key.offset = device->devid; @@ -1111,7 +1114,8 @@ static int btrfs_rm_dev_item(struct btrf out: btrfs_free_path(path); unlock_chunks(root); - btrfs_commit_transaction(trans, root); + err = btrfs_commit_transaction(trans, root); + ret = ret ?: err; return ret; } @@ -1429,7 +1433,7 @@ int btrfs_init_new_device(struct btrfs_r struct super_block *sb = root->fs_info->sb; u64 total_bytes; int seeding_dev = 0; - int ret = 0; + int err, ret = 0; if ((sb->s_flags & MS_RDONLY) && !root->fs_info->fs_devices->seeding) return -EINVAL; @@ -1481,7 +1485,12 @@ int btrfs_init_new_device(struct btrfs_r } trans = btrfs_start_transaction(root, 1); - BTRFS_UERROR(!trans); + if (IS_ERR(trans)) { + kfree(device->name); + kfree(device); + ret = PTR_ERR(trans); + goto error; + } lock_chunks(root); device->barriers = 1; @@ -1550,14 +1559,15 @@ int btrfs_init_new_device(struct btrfs_r btrfs_clear_space_info_full(root->fs_info); unlock_chunks(root); - btrfs_commit_transaction(trans, root); + err = btrfs_commit_transaction(trans, root); + ret = ret ?: err; if (seeding_dev) { mutex_unlock(&uuid_mutex); up_write(&sb->s_umount); ret = btrfs_relocate_sys_chunks(root); - BUG_ON(ret); + BTRFS_UERROR(ret); } out: mutex_unlock(&root->fs_info->volume_mutex); @@ -1746,10 +1756,11 @@ static int btrfs_relocate_chunk(struct b /* step one, relocate all the extents inside this chunk */ ret = btrfs_relocate_block_group(extent_root, chunk_offset); - BUG_ON(ret); + if (ret) + return ret; trans = btrfs_start_transaction(root, 1); - BTRFS_UERROR(!trans); + BTRFS_UERROR(IS_ERR(trans)); lock_chunks(root); @@ -1855,8 +1866,8 @@ again: found_key.offset); if (ret == -ENOSPC) failed++; - else if (ret) - BUG(); + else + BTRFS_UERROR(ret); } if (found_key.offset == 0) @@ -1918,10 +1929,11 @@ int btrfs_balance(struct btrfs_root *dev ret = btrfs_shrink_device(device, old_size - size_to_free); if (ret == -ENOSPC) break; - BUG_ON(ret); + else if (ret) + return ret; trans = btrfs_start_transaction(dev_root, 1); - BTRFS_UERROR(!trans); + BTRFS_UERROR(IS_ERR(trans)); ret = btrfs_grow_device(trans, device, old_size); BUG_ON(ret); @@ -1971,7 +1983,7 @@ int btrfs_balance(struct btrfs_root *dev chunk_root->root_key.objectid, found_key.objectid, found_key.offset); - BUG_ON(ret && ret != -ENOSPC); + BTRFS_UERROR(ret && ret != -ENOSPC); key.offset = found_key.offset - 1; } ret = 0; @@ -2090,8 +2102,8 @@ again: /* Shrinking succeeded, else we would be at "done". */ trans = btrfs_start_transaction(root, 1); - if (!trans) { - ret = -ENOMEM; + if (IS_ERR(trans)) { + ret = PTR_ERR(trans); goto done; } lock_chunks(root); --- a/fs/btrfs/xattr.c +++ b/fs/btrfs/xattr.c @@ -99,7 +99,8 @@ int __btrfs_setxattr(struct inode *inode return -ENOMEM; trans = btrfs_join_transaction(root, 1); - BTRFS_UERROR(!trans); + if (IS_ERR(trans)) + return PTR_ERR(trans); btrfs_set_trans_block_group(trans, inode); /* first lets see if we already have this xattr */ -- To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Jeff Mahoney
2009-Nov-04 19:03 UTC
[patch 10/10] btrfs: annotate btrfs_alloc_path failures
This patch adds checks for btrfs_alloc_path failures and annotates them with BTRFS_UERROR. Signed-off-by: Jeff Mahoney <jeffm@suse.com> --- fs/btrfs/ctree.c | 2 +- fs/btrfs/dir-item.c | 1 + fs/btrfs/disk-io.c | 2 +- fs/btrfs/export.c | 1 + fs/btrfs/extent-tree.c | 14 +++++++------- fs/btrfs/file-item.c | 8 +++++--- fs/btrfs/file.c | 2 +- fs/btrfs/inode-map.c | 2 +- fs/btrfs/inode.c | 19 ++++++++++--------- fs/btrfs/root-tree.c | 8 ++++---- fs/btrfs/tree-log.c | 11 ++++++++--- fs/btrfs/volumes.c | 4 ++-- 12 files changed, 42 insertions(+), 32 deletions(-) --- a/fs/btrfs/ctree.c +++ b/fs/btrfs/ctree.c @@ -3635,7 +3635,7 @@ int btrfs_insert_item(struct btrfs_trans unsigned long ptr; path = btrfs_alloc_path(); - BUG_ON(!path); + BTRFS_UERROR(!path); ret = btrfs_insert_empty_item(trans, root, path, cpu_key, data_size); if (!ret) { leaf = path->nodes[0]; --- a/fs/btrfs/dir-item.c +++ b/fs/btrfs/dir-item.c @@ -147,6 +147,7 @@ int btrfs_insert_dir_item(struct btrfs_t key.offset = btrfs_name_hash(name, name_len); path = btrfs_alloc_path(); + BTRFS_UERROR(!path); path->leave_spinning = 1; data_size = sizeof(*dir_item) + name_len; --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -1123,7 +1123,7 @@ struct btrfs_root *btrfs_read_fs_root_no root, fs_info, location->objectid); path = btrfs_alloc_path(); - BUG_ON(!path); + BTRFS_UERROR(!path); ret = btrfs_search_slot(NULL, tree_root, location, path, 0, 0); if (ret == 0) { l = path->nodes[0]; --- a/fs/btrfs/export.c +++ b/fs/btrfs/export.c @@ -176,6 +176,7 @@ static struct dentry *btrfs_get_parent(s int ret; path = btrfs_alloc_path(); + BTRFS_UERROR(!path); if (dir->i_ino == BTRFS_FIRST_FREE_OBJECTID) { key.objectid = root->root_key.objectid; --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c @@ -583,7 +583,7 @@ int btrfs_lookup_extent(struct btrfs_roo struct btrfs_path *path; path = btrfs_alloc_path(); - BUG_ON(!path); + BTRFS_UERROR(!path); key.objectid = start; key.offset = len; btrfs_set_key_type(&key, BTRFS_EXTENT_ITEM_KEY); @@ -4607,7 +4607,7 @@ static int alloc_reserved_file_extent(st size = sizeof(*extent_item) + btrfs_extent_inline_ref_size(type); path = btrfs_alloc_path(); - BUG_ON(!path); + BTRFS_UERROR(!path); path->leave_spinning = 1; ret = btrfs_insert_empty_item(trans, fs_info->extent_root, path, @@ -4668,7 +4668,7 @@ static int alloc_reserved_tree_block(str u32 size = sizeof(*extent_item) + sizeof(*block_info) + sizeof(*iref); path = btrfs_alloc_path(); - BUG_ON(!path); + BTRFS_UERROR(!path); path->leave_spinning = 1; ret = btrfs_insert_empty_item(trans, fs_info->extent_root, path, @@ -5388,7 +5388,7 @@ int btrfs_drop_snapshot(struct btrfs_roo int level; path = btrfs_alloc_path(); - BUG_ON(!path); + BTRFS_UERROR(!path); wc = kzalloc(sizeof(*wc), GFP_NOFS); if (!wc) { @@ -5559,7 +5559,7 @@ int btrfs_drop_subtree(struct btrfs_tran BUG_ON(root->root_key.objectid != BTRFS_TREE_RELOC_OBJECTID); path = btrfs_alloc_path(); - BUG_ON(!path); + BTRFS_UERROR(!path); wc = kzalloc(sizeof(*wc), GFP_NOFS); if (!wc) { @@ -6021,7 +6021,7 @@ static noinline int get_new_locations(st } path = btrfs_alloc_path(); - BUG_ON(!path); + BTRFS_UERROR(!path); cur_pos = extent_key->objectid - offset; last_byte = extent_key->objectid + extent_key->offset; @@ -7578,7 +7578,7 @@ int btrfs_remove_block_group(struct btrf spin_unlock(&cluster->refill_lock); path = btrfs_alloc_path(); - BUG_ON(!path); + BTRFS_UERROR(!path); spin_lock(&root->fs_info->block_group_cache_lock); rb_erase(&block_group->cache_node, --- a/fs/btrfs/file-item.c +++ b/fs/btrfs/file-item.c @@ -47,7 +47,7 @@ int btrfs_insert_file_extent(struct btrf struct extent_buffer *leaf; path = btrfs_alloc_path(); - BUG_ON(!path); + BTRFS_UERROR(!path); file_key.objectid = objectid; file_key.offset = pos; btrfs_set_key_type(&file_key, BTRFS_EXTENT_DATA_KEY); @@ -167,6 +167,7 @@ int btrfs_lookup_bio_sums(struct btrfs_r struct extent_io_tree *io_tree = &BTRFS_I(inode)->io_tree; path = btrfs_alloc_path(); + BTRFS_UERROR(!path); if (bio->bi_size > PAGE_CACHE_SIZE * 8) path->reada = 2; @@ -260,7 +261,7 @@ int btrfs_lookup_csums_range(struct btrf u16 csum_size = btrfs_super_csum_size(&root->fs_info->super_copy); path = btrfs_alloc_path(); - BUG_ON(!path); + BTRFS_UERROR(!path); key.objectid = BTRFS_EXTENT_CSUM_OBJECTID; key.offset = start; @@ -518,6 +519,7 @@ int btrfs_del_csums(struct btrfs_trans_h root = root->fs_info->csum_root; path = btrfs_alloc_path(); + BTRFS_UERROR(!path); while (1) { key.objectid = BTRFS_EXTENT_CSUM_OBJECTID; @@ -639,7 +641,7 @@ int btrfs_csum_file_blocks(struct btrfs_ btrfs_super_csum_size(&root->fs_info->super_copy); path = btrfs_alloc_path(); - BUG_ON(!path); + BTRFS_UERROR(!path); sector_sum = sums->sums; again: next_offset = (u64)-1; --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c @@ -642,7 +642,7 @@ int btrfs_mark_extent_written(struct btr btrfs_drop_extent_cache(inode, start, end - 1, 0); path = btrfs_alloc_path(); - BUG_ON(!path); + BTRFS_UERROR(!path); again: key.objectid = inode->i_ino; key.type = BTRFS_EXTENT_DATA_KEY; --- a/fs/btrfs/inode-map.c +++ b/fs/btrfs/inode-map.c @@ -30,7 +30,7 @@ int btrfs_find_highest_inode(struct btrf int slot; path = btrfs_alloc_path(); - BUG_ON(!path); + BTRFS_UERROR(!path); search_key.objectid = BTRFS_LAST_FREE_OBJECTID; search_key.type = -1; --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -997,7 +997,7 @@ static noinline int run_delalloc_nocow(s int check_prev = 1; path = btrfs_alloc_path(); - BUG_ON(!path); + BTRFS_UERROR(!path); trans = btrfs_join_transaction(root, 1); if (IS_ERR(trans)) return PTR_ERR(trans); @@ -1597,7 +1597,7 @@ static int insert_reserved_file_extent(s int ret; path = btrfs_alloc_path(); - BUG_ON(!path); + BTRFS_UERROR(!path); path->leave_spinning = 1; @@ -2236,7 +2236,7 @@ static void btrfs_read_locked_inode(stru int ret; path = btrfs_alloc_path(); - BUG_ON(!path); + BTRFS_UERROR(!path); memcpy(&location, &BTRFS_I(inode)->location, sizeof(location)); ret = btrfs_lookup_inode(NULL, root, path, &location, 0); @@ -2374,7 +2374,7 @@ noinline int btrfs_update_inode(struct b int ret; path = btrfs_alloc_path(); - BUG_ON(!path); + BTRFS_UERROR(!path); path->leave_spinning = 1; ret = btrfs_lookup_inode(trans, root, path, &BTRFS_I(inode)->location, 1); @@ -2834,7 +2834,7 @@ noinline int btrfs_truncate_inode_items( if (root->ref_cows) btrfs_drop_extent_cache(inode, new_size & (~mask), (u64)-1, 0); path = btrfs_alloc_path(); - BUG_ON(!path); + BTRFS_UERROR(!path); path->reada = -1; /* FIXME, add redo link to tree so we don''t leak on crash */ @@ -3313,7 +3313,7 @@ static int btrfs_inode_by_name(struct in int ret = 0; path = btrfs_alloc_path(); - BUG_ON(!path); + BTRFS_UERROR(!path); di = btrfs_lookup_dir_item(NULL, root, path, dir->i_ino, name, namelen, 0); @@ -3756,6 +3756,7 @@ static int btrfs_real_readdir(struct fil filp->f_pos = 2; } path = btrfs_alloc_path(); + BTRFS_UERROR(!path); path->reada = 2; btrfs_set_key_type(&key, key_type); @@ -3992,7 +3993,7 @@ static struct inode *btrfs_new_inode(str int owner; path = btrfs_alloc_path(); - BUG_ON(!path); + BTRFS_UERROR(!path); inode = new_inode(root->fs_info->sb); if (!inode) @@ -4572,7 +4573,7 @@ again: if (!path) { path = btrfs_alloc_path(); - BUG_ON(!path); + BTRFS_UERROR(!path); } ret = btrfs_lookup_file_extent(trans, root, path, @@ -5586,7 +5587,7 @@ static int btrfs_symlink(struct inode *d goto out_unlock; path = btrfs_alloc_path(); - BUG_ON(!path); + BTRFS_UERROR(!path); key.objectid = inode->i_ino; key.offset = 0; btrfs_set_key_type(&key, BTRFS_EXTENT_DATA_KEY); --- a/fs/btrfs/root-tree.c +++ b/fs/btrfs/root-tree.c @@ -40,7 +40,7 @@ int btrfs_search_root(struct btrfs_root search_key.offset = (u64)-1; path = btrfs_alloc_path(); - BUG_ON(!path); + BTRFS_UERROR(!path); again: ret = btrfs_search_slot(NULL, root, &search_key, path, 0, 0); if (ret < 0) @@ -88,7 +88,7 @@ int btrfs_find_last_root(struct btrfs_ro search_key.offset = (u64)-1; path = btrfs_alloc_path(); - BUG_ON(!path); + BTRFS_UERROR(!path); ret = btrfs_search_slot(NULL, root, &search_key, path, 0, 0); if (ret < 0) goto out; @@ -140,7 +140,7 @@ int btrfs_update_root(struct btrfs_trans unsigned long ptr; path = btrfs_alloc_path(); - BUG_ON(!path); + BTRFS_UERROR(!path); ret = btrfs_search_slot(trans, root, key, path, 0, 1); if (ret < 0) goto out; @@ -319,7 +319,7 @@ int btrfs_del_root(struct btrfs_trans_ha struct extent_buffer *leaf; path = btrfs_alloc_path(); - BUG_ON(!path); + BTRFS_UERROR(!path); ret = btrfs_search_slot(trans, root, key, path, -1, 1); if (ret < 0) goto out; --- a/fs/btrfs/tree-log.c +++ b/fs/btrfs/tree-log.c @@ -744,6 +744,7 @@ static noinline int backref_in_log(struc int match = 0; path = btrfs_alloc_path(); + BTRFS_UERROR(!path); ret = btrfs_search_slot(NULL, log, key, path, 0, 0); if (ret != 0) goto out; @@ -961,6 +962,7 @@ static noinline int fixup_inode_link_cou key.offset = (u64)-1; path = btrfs_alloc_path(); + BTRFS_UERROR(!path); while (1) { ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); @@ -1585,7 +1587,7 @@ static int replay_one_buffer(struct btrf return 0; path = btrfs_alloc_path(); - BUG_ON(!path); + BTRFS_UERROR(!path); nritems = btrfs_header_nritems(eb); for (i = 0; i < nritems; i++) { @@ -1848,7 +1850,7 @@ static int walk_log_tree(struct btrfs_tr int orig_level; path = btrfs_alloc_path(); - BUG_ON(!path); + BTRFS_UERROR(!path); level = btrfs_header_level(log->node); orig_level = level; @@ -2217,6 +2219,7 @@ int btrfs_del_dir_entries_in_log(struct log = root->log_root; path = btrfs_alloc_path(); + BTRFS_UERROR(!path); di = btrfs_lookup_dir_item(trans, log, path, dir->i_ino, name, name_len, -1); if (di && !IS_ERR(di)) { @@ -2708,7 +2711,9 @@ static int btrfs_log_inode(struct btrfs_ log = root->log_root; path = btrfs_alloc_path(); + BTRFS_UERROR(!path); dst_path = btrfs_alloc_path(); + BTRFS_UERROR(!dst_path); min_key.objectid = inode->i_ino; min_key.type = BTRFS_INODE_ITEM_KEY; @@ -3021,7 +3026,7 @@ int btrfs_recover_log_trees(struct btrfs fs_info->log_root_recovering = 1; path = btrfs_alloc_path(); - BUG_ON(!path); + BTRFS_UERROR(!path); trans = btrfs_start_transaction(fs_info->tree_root, 1); if (IS_ERR(trans)) { --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c @@ -946,7 +946,7 @@ static noinline int find_next_chunk(stru struct btrfs_key found_key; path = btrfs_alloc_path(); - BUG_ON(!path); + BTRFS_UERROR(!path); key.objectid = objectid; key.offset = (u64)-1; @@ -1943,7 +1943,7 @@ int btrfs_balance(struct btrfs_root *dev /* step two, relocate all the chunks */ path = btrfs_alloc_path(); - BUG_ON(!path); + BTRFS_UERROR(!path); key.objectid = BTRFS_FIRST_CHUNK_TREE_OBJECTID; key.offset = (u64)-1; -- To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Jeff Mahoney
2009-Nov-04 19:43 UTC
Re: [patch 00/10] btrfs: Error handling/propagation queue
On 11/04/2009 02:03 PM, Jeff Mahoney wrote:> This patch series fixes a few existing problems and then addresses > the need for better error handling and propagation in btrfs. > > The handling and propagation patch set first finds all locations of > a particular condition not being checked and annotates them with > BTRFS_UERROR to designate that there is an error condition that > is currently unhandled but should be. Then, another patch traverses > the call path to ensure that errors are properly propogated. When the > fix for recovering or passing the error is obvious, we do that too. > > This set is not complete and I expect there to be more fixes coming. In > particular, it currently only annotates btrfs_alloc_path failures as > the call graph for it is quite large. This is in response to Chris asking > for what I already have instead of waiting for it to be complete.I should be clear that this is just what I''ve been working on so far and hasn''t received any testing yet. It was a quick quilt mail in the middle of working on it. (As you might notice by the fact that it doesn''t build.) -Jeff -- Jeff Mahoney SUSE Labs -- To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html