Skip to content

Commit 9e43e5f

Browse files
committed
btrfs-progs: check: detect deprecated inode cache
[BUG] There are reports about deprecated inode cache causing newer kernels to rejecting them. Such inode cache is rarely utilized and already fully deprecated since v5.11, and newer kernel will reject data extents of inode cache since v6.11. But original mode btrfs check won't detect nor report them as error. Meanwhile lowmem mode can properly detect and report them: ERROR: root 5 INODE[18446744073709551604] nlink(1) not equal to inode_refs(0) ERROR: invalid imode mode bits: 00 ERROR: invalid inode generation 18446744073709551604 or transid 1 for ino 18446744073709551605, expect [0, 72) ERROR: root 5 INODE[18446744073709551605] is orphan item Since those inode cache paid no attention to properly maintain all the numbers, they are easy targets for more recent lowmem mode. [CAUSE] For original mode, it has extra hardcoded hacks to avoid nlink checks for inode cache inode. Furthermore original mode doesn't check the mode bits nor its generation. [FIX] For original mode, remove the hack for inode cache so that the deprecated inode cache can be reported as an error. For both modes, add extra global message to direct the affected users to use 'btrfs rescue clear-ino-cache' to clear the deprecated cache. Signed-off-by: Qu Wenruo <[email protected]>
1 parent e165aa3 commit 9e43e5f

File tree

3 files changed

+21
-3
lines changed

3 files changed

+21
-3
lines changed

check/main.c

+10-3
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ bool no_holes = false;
8686
bool is_free_space_tree = false;
8787
bool init_extent_tree = false;
8888
bool check_data_csum = false;
89+
static bool found_free_ino_cache = false;
8990
struct cache_tree *roots_info_cache = NULL;
9091

9192
enum btrfs_check_mode {
@@ -606,6 +607,8 @@ static void print_inode_error(struct btrfs_root *root, struct inode_record *rec)
606607
fprintf(stderr, "root %llu inode %llu errors %x",
607608
root_objectid, rec->ino, rec->errors);
608609

610+
if (errors & I_ERR_DEPRECATED_FREE_INO)
611+
fprintf(stderr, ", deprecated free inode cache");
609612
if (errors & I_ERR_NO_INODE_ITEM)
610613
fprintf(stderr, ", no inode item");
611614
if (errors & I_ERR_NO_ORPHAN_ITEM)
@@ -773,9 +776,6 @@ static struct inode_record *get_inode_rec(struct cache_tree *inode_cache,
773776
node->cache.size = 1;
774777
node->data = rec;
775778

776-
if (ino == BTRFS_FREE_INO_OBJECTID)
777-
rec->found_link = 1;
778-
779779
ret = insert_cache_extent(inode_cache, &node->cache);
780780
if (ret) {
781781
free(rec);
@@ -3224,6 +3224,10 @@ static int check_inode_recs(struct btrfs_root *root,
32243224
}
32253225
}
32263226

3227+
if (rec->ino == BTRFS_FREE_INO_OBJECTID) {
3228+
rec->errors |= I_ERR_DEPRECATED_FREE_INO;
3229+
found_free_ino_cache = true;
3230+
}
32273231
if (!rec->found_inode_item)
32283232
rec->errors |= I_ERR_NO_INODE_ITEM;
32293233
if (rec->found_link != rec->nlink)
@@ -10834,6 +10838,9 @@ static int cmd_check(const struct cmd_struct *cmd, int argc, char **argv)
1083410838

1083510839
ret = do_check_fs_roots(&root_cache);
1083610840
task_stop(g_task_ctx.info);
10841+
if (found_free_ino_cache)
10842+
pr_verbose(LOG_DEFAULT,
10843+
"deprecated inode cache can be removed by 'btrfs rescue clear-ino-cache'\n");
1083710844
err |= !!ret;
1083810845
if (ret) {
1083910846
error("errors found in fs roots");

check/mode-lowmem.c

+10
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444

4545
static u64 last_allocated_chunk;
4646
static u64 total_used = 0;
47+
static bool found_free_ino_cache = false;
4748

4849
static int calc_extent_flag(struct btrfs_root *root, struct extent_buffer *eb,
4950
u64 *flags_ret)
@@ -2629,6 +2630,12 @@ static int check_inode_item(struct btrfs_root *root, struct btrfs_path *path)
26292630
return err;
26302631
}
26312632

2633+
if (inode_id == BTRFS_FREE_INO_OBJECTID) {
2634+
warning("subvolume %lld has deprecated inode cache",
2635+
root->root_key.objectid);
2636+
found_free_ino_cache = true;
2637+
}
2638+
26322639
is_orphan = has_orphan_item(root, inode_id);
26332640
ii = btrfs_item_ptr(node, slot, struct btrfs_inode_item);
26342641
isize = btrfs_inode_size(node, ii);
@@ -5616,6 +5623,9 @@ int check_fs_roots_lowmem(void)
56165623

56175624
out:
56185625
btrfs_release_path(&path);
5626+
if (found_free_ino_cache)
5627+
pr_verbose(LOG_DEFAULT,
5628+
"deprecated inode cache can be removed by 'btrfs rescue clear-ino-cache'\n");
56195629
return err;
56205630
}
56215631

check/mode-original.h

+1
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,7 @@ struct unaligned_extent_rec_t {
189189
#define I_ERR_INVALID_GEN (1U << 20)
190190
#define I_ERR_INVALID_NLINK (1U << 21)
191191
#define I_ERR_INVALID_XATTR (1U << 22)
192+
#define I_ERR_DEPRECATED_FREE_INO (1U << 23)
192193

193194
struct inode_record {
194195
struct list_head backrefs;

0 commit comments

Comments
 (0)