]> git.proxmox.com Git - mirror_ubuntu-kernels.git/commitdiff
bcachefs: Check for unlinked inodes not on deleted list
authorKent Overstreet <kent.overstreet@linux.dev>
Thu, 16 Nov 2023 22:24:54 +0000 (17:24 -0500)
committerKent Overstreet <kent.overstreet@linux.dev>
Mon, 1 Jan 2024 16:47:36 +0000 (11:47 -0500)
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
fs/bcachefs/fsck.c
fs/bcachefs/sb-errors_types.h

index f7bcde976f9245fb69f103b210c4fbe2dc3f222f..d959400757573fd9968fcc4ca74dbd8bbe6c13e2 100644 (file)
@@ -826,6 +826,18 @@ fsck_err:
        goto out;
 }
 
+static int check_inode_deleted_list(struct btree_trans *trans, struct bpos p)
+{
+       struct btree_iter iter;
+       struct bkey_s_c k = bch2_bkey_get_iter(trans, &iter, BTREE_ID_deleted_inodes, p, 0);
+       int ret = bkey_err(k);
+       if (ret)
+               return ret;
+
+       bch2_trans_iter_exit(trans, &iter);
+       return k.k->type == KEY_TYPE_set;
+}
+
 static int check_inode(struct btree_trans *trans,
                       struct btree_iter *iter,
                       struct bkey_s_c k,
@@ -867,7 +879,7 @@ static int check_inode(struct btree_trans *trans,
                        c, inode_snapshot_mismatch,
                        "inodes in different snapshots don't match")) {
                bch_err(c, "repair not implemented yet");
-               return -EINVAL;
+               return -BCH_ERR_fsck_repair_unimplemented;
        }
 
        if ((u.bi_flags & (BCH_INODE_i_size_dirty|BCH_INODE_unlinked)) &&
@@ -890,6 +902,18 @@ static int check_inode(struct btree_trans *trans,
                return 0;
        }
 
+       if (u.bi_flags & BCH_INODE_unlinked &&
+           c->sb.version >= bcachefs_metadata_version_deleted_inodes) {
+               ret = check_inode_deleted_list(trans, k.k->p);
+               if (ret < 0)
+                       return ret;
+
+               fsck_err_on(ret, c, unlinked_inode_not_on_deleted_list,
+                           "inode %llu:%u unlinked, but not on deleted list",
+                           u.bi_inum, k.k->p.snapshot);
+               ret = 0;
+       }
+
        if (u.bi_flags & BCH_INODE_unlinked &&
            (!c->sb.clean ||
             fsck_err(c, inode_unlinked_but_clean,
@@ -976,7 +1000,6 @@ fsck_err:
        return ret;
 }
 
-noinline_for_stack
 int bch2_check_inodes(struct bch_fs *c)
 {
        bool full = c->opts.fsck;
index 3504c2d09c291ce2010dc14020933ccede3b7060..e7be1f9bdaabb39190e9d598683ae5fc171a14b6 100644 (file)
        x(root_inode_not_dir,                                   240)    \
        x(dir_loop,                                             241)    \
        x(hash_table_key_duplicate,                             242)    \
-       x(hash_table_key_wrong_offset,                          243)
+       x(hash_table_key_wrong_offset,                          243)    \
+       x(unlinked_inode_not_on_deleted_list,                   244)
 
 enum bch_sb_error_id {
 #define x(t, n) BCH_FSCK_ERR_##t = n,