Commit 82eca8d
committed
btrfs-progs: check/lowmem: fix INODE_REF repair
[BUG]
Although lowmem has the logical to repair one missing
INODE_REF/DIR_INDEX/DIR_ITEM, there is a catch in missing INODE_REF.
If we're checking an DIR_ITEM (which we normally hits first), and failed
to find the INODE_REF, we are in a situation where there is no @index to
delete the original DIR_INDEX/DIR_ITEM pair.
This can cause further damage to the fs, without really improving
anything.
[CAUSE]
There is a minimal example where there is missing INODE_ITEM:
item 0 key (256 INODE_ITEM 0) itemoff 16123 itemsize 160
generation 3 transid 9 size 12 nbytes 16384
block group 0 mode 40755 links 1 uid 0 gid 0 rdev 0
sequence 1 flags 0x0(none)
item 1 key (256 INODE_REF 256) itemoff 16111 itemsize 12
index 0 namelen 2 name: ..
item 2 key (256 DIR_ITEM 496027801) itemoff 16075 itemsize 36
location key (257 INODE_ITEM 0) type FILE
transid 9 data_len 0 name_len 6
name: foobar
item 3 key (256 DIR_INDEX 2) itemoff 16039 itemsize 36
location key (257 INODE_ITEM 0) type FILE
transid 9 data_len 0 name_len 6
name: foobar
item 4 key (257 INODE_ITEM 0) itemoff 15879 itemsize 160
generation 9 transid 9 size 0 nbytes 0
block group 0 mode 100644 links 1 uid 0 gid 0 rdev 0
sequence 1 flags 0x0(none)
For above case, if we're check the DIR_ITEM, we can find the INODE_ITEM
but not the INODE_REF.
So we need to repair it, but at this stage we haven't checked DIR_INDEX,
this means we have no idea which index we should delete, leaving the
default @index as (-1).
If we call btrfs_unlink() with that (-1) as index, it will not delete
the (256 DIR_INDEX 2) one, then re-add a link using -1 as index, causing
more damage.
[FIX]
Before calling btrfs_unlink(), do an extra check on if we're called from
DIR_ITEM checks (aka, @index is -1) and we only detected a missing
INODE_REF yet.
If so, do find_dir_index() call to determine the DIR_INDEX, if that
failed it means we have missing both DIR_INDEX and INODE_REF, thus
should remove the lone DIR_ITEM instead.
With this enhancement, lowmem mode can properly fix the missing
INODE_REF by adding it back.
Signed-off-by: Qu Wenruo <wqu@suse.com>1 parent b9f35a2 commit 82eca8d
1 file changed
+11
-0
lines changed| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1015 | 1015 | | |
1016 | 1016 | | |
1017 | 1017 | | |
| 1018 | + | |
| 1019 | + | |
| 1020 | + | |
| 1021 | + | |
| 1022 | + | |
| 1023 | + | |
| 1024 | + | |
| 1025 | + | |
| 1026 | + | |
| 1027 | + | |
| 1028 | + | |
1018 | 1029 | | |
1019 | 1030 | | |
1020 | 1031 | | |
| |||
0 commit comments