Commit 0678b618 authored by Mark Fasheh's avatar Mark Fasheh Committed by David Sterba

btrfs: Don't BUG_ON kzalloc error in btrfs_lookup_csums_range()

Unfortunately it isn't enough to just exit here - the kzalloc() happens in a
loop and the allocated items are added to a linked list whose head is passed
in from the caller.

To fix the BUG_ON() and also provide the semantic that the list passed in is
only modified on success, I create function-local temporary list that we add
items too. If no error is met, that list is spliced to the callers at the
end of the function. Otherwise the list will be walked and all items freed
before the error value is returned.

I did a simple test on this patch by forcing an error at the kzalloc() point
and verifying that when this hits (git clone seemed to exercise this), the
function throws the proper error. Unfortunately but predictably, we later
hit a BUG_ON(ret) type line that still hasn't been fixed up ;)
Signed-off-by: default avatarMark Fasheh <mfasheh@suse.com>
parent be1a5564
...@@ -284,6 +284,7 @@ int btrfs_lookup_csums_range(struct btrfs_root *root, u64 start, u64 end, ...@@ -284,6 +284,7 @@ int btrfs_lookup_csums_range(struct btrfs_root *root, u64 start, u64 end,
struct btrfs_ordered_sum *sums; struct btrfs_ordered_sum *sums;
struct btrfs_sector_sum *sector_sum; struct btrfs_sector_sum *sector_sum;
struct btrfs_csum_item *item; struct btrfs_csum_item *item;
LIST_HEAD(tmplist);
unsigned long offset; unsigned long offset;
int ret; int ret;
size_t size; size_t size;
...@@ -358,7 +359,10 @@ int btrfs_lookup_csums_range(struct btrfs_root *root, u64 start, u64 end, ...@@ -358,7 +359,10 @@ int btrfs_lookup_csums_range(struct btrfs_root *root, u64 start, u64 end,
MAX_ORDERED_SUM_BYTES(root)); MAX_ORDERED_SUM_BYTES(root));
sums = kzalloc(btrfs_ordered_sum_size(root, size), sums = kzalloc(btrfs_ordered_sum_size(root, size),
GFP_NOFS); GFP_NOFS);
BUG_ON(!sums); if (!sums) {
ret = -ENOMEM;
goto fail;
}
sector_sum = sums->sums; sector_sum = sums->sums;
sums->bytenr = start; sums->bytenr = start;
...@@ -380,12 +384,19 @@ int btrfs_lookup_csums_range(struct btrfs_root *root, u64 start, u64 end, ...@@ -380,12 +384,19 @@ int btrfs_lookup_csums_range(struct btrfs_root *root, u64 start, u64 end,
offset += csum_size; offset += csum_size;
sector_sum++; sector_sum++;
} }
list_add_tail(&sums->list, list); list_add_tail(&sums->list, &tmplist);
} }
path->slots[0]++; path->slots[0]++;
} }
ret = 0; ret = 0;
fail: fail:
while (ret < 0 && !list_empty(&tmplist)) {
sums = list_entry(&tmplist, struct btrfs_ordered_sum, list);
list_del(&sums->list);
kfree(sums);
}
list_splice_tail(&tmplist, list);
btrfs_free_path(path); btrfs_free_path(path);
return ret; return ret;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment