mirror of
https://github.com/kdave/btrfs-progs
synced 2025-04-11 03:31:17 +00:00
btrfs-progs: check/original: add ability to repair extent item generation
This is pretty much the same as for lowmem mode, it will try to reset the extent item generation using either the tree block generation or current transid. Signed-off-by: Qu Wenruo <wqu@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
This commit is contained in:
parent
b858e3b5c2
commit
05f25a1460
73
check/main.c
73
check/main.c
@ -7915,6 +7915,62 @@ static int record_unaligned_extent_rec(struct extent_record *rec)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int repair_extent_item_generation(struct extent_record *rec)
|
||||
{
|
||||
struct btrfs_trans_handle *trans;
|
||||
struct btrfs_path path;
|
||||
struct btrfs_key key;
|
||||
struct btrfs_extent_item *ei;
|
||||
struct btrfs_root *extent_root = gfs_info->extent_root;
|
||||
u64 new_gen = 0;;
|
||||
int ret;
|
||||
|
||||
key.objectid = rec->start;
|
||||
key.type = BTRFS_METADATA_ITEM_KEY;
|
||||
key.offset = (u64)-1;
|
||||
|
||||
get_extent_item_generation(rec->start, &new_gen);
|
||||
trans = btrfs_start_transaction(extent_root, 1);
|
||||
if (IS_ERR(trans)) {
|
||||
ret = PTR_ERR(trans);
|
||||
errno = -ret;
|
||||
error("failed to start transaction: %m");
|
||||
return ret;
|
||||
}
|
||||
btrfs_init_path(&path);
|
||||
ret = btrfs_search_slot(trans, extent_root, &key, &path, 0, 1);
|
||||
/* Not possible */
|
||||
if (ret == 0)
|
||||
ret = -EUCLEAN;
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
ret = btrfs_previous_extent_item(extent_root, &path, rec->start);
|
||||
if (ret > 0)
|
||||
ret = -ENOENT;
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
if (!new_gen)
|
||||
new_gen = trans->transid;
|
||||
ei = btrfs_item_ptr(path.nodes[0], path.slots[0],
|
||||
struct btrfs_extent_item);
|
||||
btrfs_set_extent_generation(path.nodes[0], ei, new_gen);
|
||||
ret = btrfs_commit_transaction(trans, extent_root);
|
||||
if (ret < 0) {
|
||||
errno = -ret;
|
||||
error("failed to commit transaction: %m");
|
||||
goto out;
|
||||
}
|
||||
printf("Reset extent item (%llu) generation to %llu\n",
|
||||
key.objectid, new_gen);
|
||||
rec->generation = new_gen;
|
||||
out:
|
||||
btrfs_release_path(&path);
|
||||
if (ret < 0)
|
||||
btrfs_abort_transaction(trans, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int check_extent_refs(struct btrfs_root *root,
|
||||
struct cache_tree *extent_cache)
|
||||
{
|
||||
@ -8005,11 +8061,20 @@ static int check_extent_refs(struct btrfs_root *root,
|
||||
}
|
||||
|
||||
if (rec->generation > super_gen + 1) {
|
||||
error(
|
||||
bool repaired = false;
|
||||
|
||||
if (repair) {
|
||||
ret = repair_extent_item_generation(rec);
|
||||
if (ret == 0)
|
||||
repaired = true;
|
||||
}
|
||||
if (!repaired) {
|
||||
error(
|
||||
"invalid generation for extent %llu, have %llu expect (0, %llu]",
|
||||
rec->start, rec->generation,
|
||||
super_gen + 1);
|
||||
cur_err = 1;
|
||||
rec->start, rec->generation,
|
||||
super_gen + 1);
|
||||
cur_err = 1;
|
||||
}
|
||||
}
|
||||
if (rec->refs != rec->extent_item_refs) {
|
||||
fprintf(stderr, "ref mismatch on [%llu %llu] ",
|
||||
|
Loading…
Reference in New Issue
Block a user