]> git.dujemihanovic.xyz Git - linux.git/commitdiff
bcachefs: Check for unlinked, non-empty dirs in check_inode()
authorKent Overstreet <kent.overstreet@linux.dev>
Mon, 30 Sep 2024 03:38:37 +0000 (23:38 -0400)
committerKent Overstreet <kent.overstreet@linux.dev>
Sat, 5 Oct 2024 00:25:32 +0000 (20:25 -0400)
We want to check for this early so it can be reattached if necessary in
check_unreachable_inodes(); better than letting it be deleted and having
the children reattached, losing their filenames.

Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
fs/bcachefs/fsck.c
fs/bcachefs/sb-errors_format.h

index 09f890539ded4eb47e99f04c0f961058c2264560..30eca76554f6dcd4fa925c56484454d08aa37703 100644 (file)
@@ -1083,6 +1083,23 @@ static int check_inode(struct btree_trans *trans,
                do_update = true;
        }
 
+       if (S_ISDIR(u.bi_mode) && (u.bi_flags & BCH_INODE_unlinked)) {
+               /* Check for this early so that check_unreachable_inode() will reattach it */
+
+               ret = bch2_empty_dir_snapshot(trans, k.k->p.offset, 0, k.k->p.snapshot);
+               if (ret && ret != -BCH_ERR_ENOTEMPTY_dir_not_empty)
+                       goto err;
+
+               fsck_err_on(ret, trans, inode_dir_unlinked_but_not_empty,
+                           "dir unlinked but not empty\n%s",
+                           (printbuf_reset(&buf),
+                            bch2_inode_unpacked_to_text(&buf, &u),
+                            buf.buf));
+               u.bi_flags &= ~BCH_INODE_unlinked;
+               do_update = true;
+               ret = 0;
+       }
+
        if ((u.bi_flags & (BCH_INODE_i_size_dirty|BCH_INODE_unlinked)) &&
            bch2_key_has_snapshot_overwrites(trans, BTREE_ID_inodes, k.k->p)) {
                struct bpos new_min_pos;
index 4c8ff4cc17c239d726cd9841ff7c563e2d7c9d10..4135b1ea2feccd7763a3f4ab8c29d3698bb8087f 100644 (file)
@@ -221,6 +221,7 @@ enum bch_fsck_flags {
        x(inode_dir_wrong_nlink,                                205,    FSCK_AUTOFIX)   \
        x(inode_dir_multiple_links,                             206,    FSCK_AUTOFIX)   \
        x(inode_dir_missing_backpointer,                        284,    FSCK_AUTOFIX)   \
+       x(inode_dir_unlinked_but_not_empty,                     286,    FSCK_AUTOFIX)   \
        x(inode_multiple_links_but_nlink_0,                     207,    FSCK_AUTOFIX)   \
        x(inode_wrong_backpointer,                              208,    FSCK_AUTOFIX)   \
        x(inode_wrong_nlink,                                    209,    FSCK_AUTOFIX)   \
@@ -297,7 +298,7 @@ enum bch_fsck_flags {
        x(accounting_key_replicas_devs_unsorted,                280,    FSCK_AUTOFIX)   \
        x(accounting_key_version_0,                             282,    FSCK_AUTOFIX)   \
        x(logged_op_but_clean,                                  283,    FSCK_AUTOFIX)   \
-       x(MAX,                                                  286,    0)
+       x(MAX,                                                  287,    0)
 
 enum bch_sb_error_id {
 #define x(t, n, ...) BCH_FSCK_ERR_##t = n,