Skip to content

Commit 369aaba

Browse files
author
Josef Bacik
committed
Btrfs-progs: make fsck deal with bogus items
We can deal with corrupt items by deleting them in a few cases. Fsck can easily recover from a missing extent item or a dir index item. So if we notice a item is completely bogus and it is of a key that we know we can repair then just delete it and carry on. Thanks, Signed-off-by: Josef Bacik <jbacik@fb.com>
1 parent 2d3de8a commit 369aaba

File tree

2 files changed

+45
-0
lines changed

2 files changed

+45
-0
lines changed

cmds-check.c

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2621,6 +2621,42 @@ static int fix_key_order(struct btrfs_trans_handle *trans,
26212621
return ret;
26222622
}
26232623

2624+
static int delete_bogus_item(struct btrfs_trans_handle *trans,
2625+
struct btrfs_root *root,
2626+
struct btrfs_path *path,
2627+
struct extent_buffer *buf, int slot)
2628+
{
2629+
struct btrfs_key key;
2630+
int nritems = btrfs_header_nritems(buf);
2631+
2632+
btrfs_item_key_to_cpu(buf, &key, slot);
2633+
2634+
/* These are all the keys we can deal with missing. */
2635+
if (key.type != BTRFS_DIR_INDEX_KEY &&
2636+
key.type != BTRFS_EXTENT_ITEM_KEY &&
2637+
key.type != BTRFS_METADATA_ITEM_KEY &&
2638+
key.type != BTRFS_TREE_BLOCK_REF_KEY &&
2639+
key.type != BTRFS_EXTENT_DATA_REF_KEY)
2640+
return -1;
2641+
2642+
printf("Deleting bogus item [%llu,%u,%llu] at slot %d on block %llu\n",
2643+
(unsigned long long)key.objectid, key.type,
2644+
(unsigned long long)key.offset, slot, buf->start);
2645+
memmove_extent_buffer(buf, btrfs_item_nr_offset(slot),
2646+
btrfs_item_nr_offset(slot + 1),
2647+
sizeof(struct btrfs_item) *
2648+
(nritems - slot - 1));
2649+
btrfs_set_header_nritems(buf, nritems - 1);
2650+
if (slot == 0) {
2651+
struct btrfs_disk_key disk_key;
2652+
2653+
btrfs_item_key(buf, &disk_key, 0);
2654+
btrfs_fixup_low_keys(root, path, &disk_key, 1);
2655+
}
2656+
btrfs_mark_buffer_dirty(buf);
2657+
return 0;
2658+
}
2659+
26242660
static int fix_item_offset(struct btrfs_trans_handle *trans,
26252661
struct btrfs_root *root,
26262662
struct extent_buffer *buf)
@@ -2660,13 +2696,18 @@ static int fix_item_offset(struct btrfs_trans_handle *trans,
26602696
}
26612697

26622698
buf = path->nodes[level];
2699+
again:
26632700
for (i = 0; i < btrfs_header_nritems(buf); i++) {
26642701
unsigned int shift = 0, offset;
26652702

26662703
if (i == 0 && btrfs_item_end_nr(buf, i) !=
26672704
BTRFS_LEAF_DATA_SIZE(root)) {
26682705
if (btrfs_item_end_nr(buf, i) >
26692706
BTRFS_LEAF_DATA_SIZE(root)) {
2707+
ret = delete_bogus_item(trans, root, path,
2708+
buf, i);
2709+
if (!ret)
2710+
goto again;
26702711
fprintf(stderr, "item is off the end of the "
26712712
"leaf, can't fix\n");
26722713
ret = -EIO;
@@ -2678,6 +2719,10 @@ static int fix_item_offset(struct btrfs_trans_handle *trans,
26782719
btrfs_item_offset_nr(buf, i - 1)) {
26792720
if (btrfs_item_end_nr(buf, i) >
26802721
btrfs_item_offset_nr(buf, i - 1)) {
2722+
ret = delete_bogus_item(trans, root, path,
2723+
buf, i);
2724+
if (!ret)
2725+
goto again;
26812726
fprintf(stderr, "items overlap, can't fix\n");
26822727
ret = -EIO;
26832728
break;
389 KB
Binary file not shown.

0 commit comments

Comments
 (0)