btrfs-progs: deal with no extent info
Previously we used to just set FULL_BACKREF if we couldn't lookup an extent info for an extent. Now we just bail out if we can't lookup the extent info, which is less than good since fsck is supposed to fix these very problems. So instead figure out the flag we are supposed to use and pass that along instead. This patch also provides a test image to test this functionality. Thanks, Signed-off-by: Josef Bacik <jbacik@fb.com>
This commit is contained in:
parent
63d66268f4
commit
8ab2d7a9dd
39
cmds-check.c
39
cmds-check.c
|
@ -5686,6 +5686,7 @@ static int run_next_block(struct btrfs_trans_handle *trans,
|
||||||
struct root_item_record *ri)
|
struct root_item_record *ri)
|
||||||
{
|
{
|
||||||
struct extent_buffer *buf;
|
struct extent_buffer *buf;
|
||||||
|
struct extent_record *rec = NULL;
|
||||||
u64 bytenr;
|
u64 bytenr;
|
||||||
u32 size;
|
u32 size;
|
||||||
u64 parent;
|
u64 parent;
|
||||||
|
@ -5738,8 +5739,6 @@ static int run_next_block(struct btrfs_trans_handle *trans,
|
||||||
}
|
}
|
||||||
cache = lookup_cache_extent(extent_cache, bytenr, size);
|
cache = lookup_cache_extent(extent_cache, bytenr, size);
|
||||||
if (cache) {
|
if (cache) {
|
||||||
struct extent_record *rec;
|
|
||||||
|
|
||||||
rec = container_of(cache, struct extent_record, cache);
|
rec = container_of(cache, struct extent_record, cache);
|
||||||
gen = rec->parent_generation;
|
gen = rec->parent_generation;
|
||||||
}
|
}
|
||||||
|
@ -5758,20 +5757,30 @@ static int run_next_block(struct btrfs_trans_handle *trans,
|
||||||
* FIXME, this only works only if we don't have any full
|
* FIXME, this only works only if we don't have any full
|
||||||
* backref mode.
|
* backref mode.
|
||||||
*/
|
*/
|
||||||
|
flags = 0;
|
||||||
if (!init_extent_tree) {
|
if (!init_extent_tree) {
|
||||||
ret = btrfs_lookup_extent_info(NULL, root, bytenr,
|
ret = btrfs_lookup_extent_info(NULL, root, bytenr,
|
||||||
btrfs_header_level(buf), 1, NULL,
|
btrfs_header_level(buf), 1, NULL,
|
||||||
&flags);
|
&flags);
|
||||||
if (ret < 0)
|
if (ret < 0) {
|
||||||
goto out;
|
ret = calc_extent_flag(root, extent_cache, buf, ri, &flags);
|
||||||
|
if (ret < 0) {
|
||||||
|
fprintf(stderr, "Couldn't calc extent flags\n");
|
||||||
|
flags |= BTRFS_BLOCK_FLAG_FULL_BACKREF;
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
flags = 0;
|
flags = 0;
|
||||||
ret = calc_extent_flag(root, extent_cache, buf, ri, &flags);
|
ret = calc_extent_flag(root, extent_cache, buf, ri, &flags);
|
||||||
if (ret < 0)
|
if (ret < 0) {
|
||||||
goto out;
|
fprintf(stderr, "Couldn't calc extent flags\n");
|
||||||
|
flags |= BTRFS_BLOCK_FLAG_FULL_BACKREF;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flags & BTRFS_BLOCK_FLAG_FULL_BACKREF) {
|
if (flags & BTRFS_BLOCK_FLAG_FULL_BACKREF) {
|
||||||
|
if (rec)
|
||||||
|
rec->flag_block_full_backref = 1;
|
||||||
parent = bytenr;
|
parent = bytenr;
|
||||||
owner = 0;
|
owner = 0;
|
||||||
} else {
|
} else {
|
||||||
|
@ -7030,21 +7039,8 @@ static int fixup_extent_refs(struct btrfs_trans_handle *trans,
|
||||||
int allocated = 0;
|
int allocated = 0;
|
||||||
u64 flags = 0;
|
u64 flags = 0;
|
||||||
|
|
||||||
/*
|
|
||||||
* remember our flags for recreating the extent.
|
|
||||||
* FIXME, if we have cleared extent tree, we can not
|
|
||||||
* lookup extent info in extent tree.
|
|
||||||
*/
|
|
||||||
if (!init_extent_tree) {
|
|
||||||
ret = btrfs_lookup_extent_info(NULL, info->extent_root,
|
|
||||||
rec->start, rec->max_size,
|
|
||||||
rec->metadata, NULL, &flags);
|
|
||||||
if (ret < 0)
|
|
||||||
return ret;
|
|
||||||
} else {
|
|
||||||
if (rec->flag_block_full_backref)
|
if (rec->flag_block_full_backref)
|
||||||
flags |= BTRFS_BLOCK_FLAG_FULL_BACKREF;
|
flags |= BTRFS_BLOCK_FLAG_FULL_BACKREF;
|
||||||
}
|
|
||||||
|
|
||||||
path = btrfs_alloc_path();
|
path = btrfs_alloc_path();
|
||||||
if (!path)
|
if (!path)
|
||||||
|
@ -7691,8 +7687,6 @@ static int deal_root_from_list(struct list_head *list,
|
||||||
* one by one, otherwise we deal with node firstly which
|
* one by one, otherwise we deal with node firstly which
|
||||||
* can maximize readahead.
|
* can maximize readahead.
|
||||||
*/
|
*/
|
||||||
if (!init_extent_tree && !rec->drop_level)
|
|
||||||
goto skip;
|
|
||||||
while (1) {
|
while (1) {
|
||||||
ret = run_next_block(trans, root, bits, bits_nr, &last,
|
ret = run_next_block(trans, root, bits, bits_nr, &last,
|
||||||
pending, seen, reada,
|
pending, seen, reada,
|
||||||
|
@ -7703,10 +7697,11 @@ static int deal_root_from_list(struct list_head *list,
|
||||||
if (ret != 0)
|
if (ret != 0)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
skip:
|
|
||||||
free_extent_buffer(buf);
|
free_extent_buffer(buf);
|
||||||
list_del(&rec->list);
|
list_del(&rec->list);
|
||||||
free(rec);
|
free(rec);
|
||||||
|
if (ret < 0)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
while (ret >= 0) {
|
while (ret >= 0) {
|
||||||
ret = run_next_block(trans, root, bits, bits_nr, &last,
|
ret = run_next_block(trans, root, bits, bits_nr, &last,
|
||||||
|
|
Binary file not shown.
Loading…
Reference in New Issue