]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
6.15-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 7 Jun 2025 08:34:27 +0000 (10:34 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 7 Jun 2025 08:34:27 +0000 (10:34 +0200)
added patches:
bcachefs-delete-dead-code-from-may_delete_deleted_inode.patch
bcachefs-fix-subvol-to-missing-root-repair.patch
bcachefs-kill-un-reverted-directory-i_size-code.patch
bcachefs-repair-code-for-directory-i_size.patch
bcachefs-run-may_delete_deleted_inode-checks-in-bch2_inode_rm.patch

queue-6.15/bcachefs-delete-dead-code-from-may_delete_deleted_inode.patch [new file with mode: 0644]
queue-6.15/bcachefs-fix-subvol-to-missing-root-repair.patch [new file with mode: 0644]
queue-6.15/bcachefs-kill-un-reverted-directory-i_size-code.patch [new file with mode: 0644]
queue-6.15/bcachefs-repair-code-for-directory-i_size.patch [new file with mode: 0644]
queue-6.15/bcachefs-run-may_delete_deleted_inode-checks-in-bch2_inode_rm.patch [new file with mode: 0644]
queue-6.15/series

diff --git a/queue-6.15/bcachefs-delete-dead-code-from-may_delete_deleted_inode.patch b/queue-6.15/bcachefs-delete-dead-code-from-may_delete_deleted_inode.patch
new file mode 100644 (file)
index 0000000..b108ed1
--- /dev/null
@@ -0,0 +1,68 @@
+From ca7e8d8060e62d118a8fea3cc67551c5dfd89f73 Mon Sep 17 00:00:00 2001
+From: Kent Overstreet <kent.overstreet@linux.dev>
+Date: Mon, 2 Jun 2025 18:26:44 -0400
+Subject: bcachefs: delete dead code from may_delete_deleted_inode()
+
+From: Kent Overstreet <kent.overstreet@linux.dev>
+
+commit bb6689bbeebc6fb51f0f120b486bdcc9a38ffcf6 upstream.
+
+Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/bcachefs/inode.c |   15 +++------------
+ 1 file changed, 3 insertions(+), 12 deletions(-)
+
+--- a/fs/bcachefs/inode.c
++++ b/fs/bcachefs/inode.c
+@@ -1342,10 +1342,7 @@ int bch2_inode_rm_snapshot(struct btree_
+               delete_ancestor_snapshot_inodes(trans, SPOS(0, inum, snapshot));
+ }
+-static int may_delete_deleted_inode(struct btree_trans *trans,
+-                                  struct btree_iter *iter,
+-                                  struct bpos pos,
+-                                  bool *need_another_pass)
++static int may_delete_deleted_inode(struct btree_trans *trans, struct bpos pos)
+ {
+       struct bch_fs *c = trans->c;
+       struct btree_iter inode_iter;
+@@ -1434,9 +1431,8 @@ delete:
+ int bch2_delete_dead_inodes(struct bch_fs *c)
+ {
+       struct btree_trans *trans = bch2_trans_get(c);
+-      bool need_another_pass;
+       int ret;
+-again:
++
+       /*
+        * if we ran check_inodes() unlinked inodes will have already been
+        * cleaned up but the write buffer will be out of sync; therefore we
+@@ -1446,8 +1442,6 @@ again:
+       if (ret)
+               goto err;
+-      need_another_pass = false;
+-
+       /*
+        * Weird transaction restart handling here because on successful delete,
+        * bch2_inode_rm_snapshot() will return a nested transaction restart,
+@@ -1457,7 +1451,7 @@ again:
+       ret = for_each_btree_key_commit(trans, iter, BTREE_ID_deleted_inodes, POS_MIN,
+                                       BTREE_ITER_prefetch|BTREE_ITER_all_snapshots, k,
+                                       NULL, NULL, BCH_TRANS_COMMIT_no_enospc, ({
+-              ret = may_delete_deleted_inode(trans, &iter, k.k->p, &need_another_pass);
++              ret = may_delete_deleted_inode(trans, k.k->p);
+               if (ret > 0) {
+                       bch_verbose_ratelimited(c, "deleting unlinked inode %llu:%u",
+                                               k.k->p.offset, k.k->p.snapshot);
+@@ -1478,9 +1472,6 @@ again:
+               ret;
+       }));
+-
+-      if (!ret && need_another_pass)
+-              goto again;
+ err:
+       bch2_trans_put(trans);
+       return ret;
diff --git a/queue-6.15/bcachefs-fix-subvol-to-missing-root-repair.patch b/queue-6.15/bcachefs-fix-subvol-to-missing-root-repair.patch
new file mode 100644 (file)
index 0000000..8babee3
--- /dev/null
@@ -0,0 +1,72 @@
+From fc9459c9a888766c4c4adff59b072aad1bfbf6ad Mon Sep 17 00:00:00 2001
+From: Kent Overstreet <kent.overstreet@linux.dev>
+Date: Mon, 2 Jun 2025 19:48:27 -0400
+Subject: bcachefs: Fix subvol to missing root repair
+
+From: Kent Overstreet <kent.overstreet@linux.dev>
+
+commit 29cc6fb7c068c773049d3bde14b939033893eff4 upstream.
+
+We had a bug where the root inode of a subvolume was erronously deleted:
+bch2_evict_inode() called bch2_inode_rm(), meaning the VFS inode's
+i_nlink was somehow set to 0 when it shouldn't have - the inode in the
+btree indicated it clearly was not unlinked.
+
+This has been addressed with additional safety checks in
+bch2_inode_rm() - pulling in the safety checks we already were doing
+when deleting unlinked inodes in recovery - but the really disastrous
+bug was in check_subvols(), which on finding a dangling subvol (subvol
+with a missing root inode) would delete the subvolume.
+
+I assume this bug dates from early check_directory_structure() code,
+which originally handled subvolumes and normal paths - the idea being
+that still live contents of the subvolume would get reattached
+somewhere.
+
+But that's incorrect, and disastrously so; deleting a subvolume triggers
+deleting the snapshot ID it points to, deleting the entire contents.
+
+The correct way to repair is to recreate the root inode if it's missing;
+then any contents will get reattached under that subvolume's lost+found.
+
+Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/bcachefs/subvolume.c |   19 +++++++++++++++----
+ 1 file changed, 15 insertions(+), 4 deletions(-)
+
+--- a/fs/bcachefs/subvolume.c
++++ b/fs/bcachefs/subvolume.c
+@@ -6,6 +6,7 @@
+ #include "errcode.h"
+ #include "error.h"
+ #include "fs.h"
++#include "inode.h"
+ #include "recovery_passes.h"
+ #include "snapshot.h"
+ #include "subvolume.h"
+@@ -113,10 +114,20 @@ static int check_subvol(struct btree_tra
+                            "subvolume %llu points to missing subvolume root %llu:%u",
+                            k.k->p.offset, le64_to_cpu(subvol.v->inode),
+                            le32_to_cpu(subvol.v->snapshot))) {
+-                      ret = bch2_subvolume_delete(trans, iter->pos.offset);
+-                      bch_err_msg(c, ret, "deleting subvolume %llu", iter->pos.offset);
+-                      ret = ret ?: -BCH_ERR_transaction_restart_nested;
+-                      goto err;
++                      /*
++                       * Recreate - any contents that are still disconnected
++                       * will then get reattached under lost+found
++                       */
++                      bch2_inode_init_early(c, &inode);
++                      bch2_inode_init_late(&inode, bch2_current_time(c),
++                                           0, 0, S_IFDIR|0700, 0, NULL);
++                      inode.bi_inum                   = le64_to_cpu(subvol.v->inode);
++                      inode.bi_snapshot               = le32_to_cpu(subvol.v->snapshot);
++                      inode.bi_subvol                 = k.k->p.offset;
++                      inode.bi_parent_subvol          = le32_to_cpu(subvol.v->fs_path_parent);
++                      ret = __bch2_fsck_write_inode(trans, &inode);
++                      if (ret)
++                              goto err;
+               }
+       } else {
+               goto err;
diff --git a/queue-6.15/bcachefs-kill-un-reverted-directory-i_size-code.patch b/queue-6.15/bcachefs-kill-un-reverted-directory-i_size-code.patch
new file mode 100644 (file)
index 0000000..386b003
--- /dev/null
@@ -0,0 +1,71 @@
+From 1c2151cdcdbc482ee9c3c3acebdbc6363534405a Mon Sep 17 00:00:00 2001
+From: Kent Overstreet <kent.overstreet@linux.dev>
+Date: Sat, 31 May 2025 18:32:37 -0400
+Subject: bcachefs: Kill un-reverted directory i_size code
+
+From: Kent Overstreet <kent.overstreet@linux.dev>
+
+commit 95fafc0f3407a6446082c11849df585bd3246571 upstream.
+
+Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/bcachefs/dirent.c |   12 ++----------
+ fs/bcachefs/dirent.h |    4 ++--
+ fs/bcachefs/namei.c  |    4 ++--
+ 3 files changed, 6 insertions(+), 14 deletions(-)
+
+--- a/fs/bcachefs/dirent.c
++++ b/fs/bcachefs/dirent.c
+@@ -395,8 +395,8 @@ int bch2_dirent_read_target(struct btree
+ }
+ int bch2_dirent_rename(struct btree_trans *trans,
+-              subvol_inum src_dir, struct bch_hash_info *src_hash, u64 *src_dir_i_size,
+-              subvol_inum dst_dir, struct bch_hash_info *dst_hash, u64 *dst_dir_i_size,
++              subvol_inum src_dir, struct bch_hash_info *src_hash,
++              subvol_inum dst_dir, struct bch_hash_info *dst_hash,
+               const struct qstr *src_name, subvol_inum *src_inum, u64 *src_offset,
+               const struct qstr *dst_name, subvol_inum *dst_inum, u64 *dst_offset,
+               enum bch_rename_mode mode)
+@@ -535,14 +535,6 @@ int bch2_dirent_rename(struct btree_tran
+           new_src->v.d_type == DT_SUBVOL)
+               new_src->v.d_parent_subvol = cpu_to_le32(src_dir.subvol);
+-      if (old_dst.k)
+-              *dst_dir_i_size -= bkey_bytes(old_dst.k);
+-      *src_dir_i_size -= bkey_bytes(old_src.k);
+-
+-      if (mode == BCH_RENAME_EXCHANGE)
+-              *src_dir_i_size += bkey_bytes(&new_src->k);
+-      *dst_dir_i_size += bkey_bytes(&new_dst->k);
+-
+       ret = bch2_trans_update(trans, &dst_iter, &new_dst->k_i, 0);
+       if (ret)
+               goto out;
+--- a/fs/bcachefs/dirent.h
++++ b/fs/bcachefs/dirent.h
+@@ -80,8 +80,8 @@ enum bch_rename_mode {
+ };
+ int bch2_dirent_rename(struct btree_trans *,
+-                     subvol_inum, struct bch_hash_info *, u64 *,
+-                     subvol_inum, struct bch_hash_info *, u64 *,
++                     subvol_inum, struct bch_hash_info *,
++                     subvol_inum, struct bch_hash_info *,
+                      const struct qstr *, subvol_inum *, u64 *,
+                      const struct qstr *, subvol_inum *, u64 *,
+                      enum bch_rename_mode);
+--- a/fs/bcachefs/namei.c
++++ b/fs/bcachefs/namei.c
+@@ -418,8 +418,8 @@ int bch2_rename_trans(struct btree_trans
+       }
+       ret = bch2_dirent_rename(trans,
+-                               src_dir, &src_hash, &src_dir_u->bi_size,
+-                               dst_dir, &dst_hash, &dst_dir_u->bi_size,
++                               src_dir, &src_hash,
++                               dst_dir, &dst_hash,
+                                src_name, &src_inum, &src_offset,
+                                dst_name, &dst_inum, &dst_offset,
+                                mode);
diff --git a/queue-6.15/bcachefs-repair-code-for-directory-i_size.patch b/queue-6.15/bcachefs-repair-code-for-directory-i_size.patch
new file mode 100644 (file)
index 0000000..210932c
--- /dev/null
@@ -0,0 +1,59 @@
+From 91d943790feef381b1d8c4c265e635b659d0b2d9 Mon Sep 17 00:00:00 2001
+From: Kent Overstreet <kent.overstreet@linux.dev>
+Date: Sat, 31 May 2025 11:58:11 -0400
+Subject: bcachefs: Repair code for directory i_size
+
+From: Kent Overstreet <kent.overstreet@linux.dev>
+
+commit 36a2fdf7c5c1ccae6ca16cd14067567096cebe17 upstream.
+
+We had a bug due due to an incomplete revert of the patch implementing
+directory i_size (summing up the size of the dirents), leading to
+completely screwy i_size values that underflow.
+
+Most userspace programs don't seem to care (e.g. du ignores it), but it
+turns out this broke sshfs, so needs to be repaired.
+
+Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/bcachefs/fsck.c             |    8 ++++++++
+ fs/bcachefs/sb-errors_format.h |    3 ++-
+ 2 files changed, 10 insertions(+), 1 deletion(-)
+
+--- a/fs/bcachefs/fsck.c
++++ b/fs/bcachefs/fsck.c
+@@ -1183,6 +1183,14 @@ static int check_inode(struct btree_tran
+               ret = 0;
+       }
++      if (fsck_err_on(S_ISDIR(u.bi_mode) && u.bi_size,
++                      trans, inode_dir_has_nonzero_i_size,
++                      "directory %llu:%u with nonzero i_size %lli",
++                      u.bi_inum, u.bi_snapshot, u.bi_size)) {
++              u.bi_size = 0;
++              do_update = true;
++      }
++
+       ret = bch2_inode_has_child_snapshots(trans, k.k->p);
+       if (ret < 0)
+               goto err;
+--- a/fs/bcachefs/sb-errors_format.h
++++ b/fs/bcachefs/sb-errors_format.h
+@@ -232,6 +232,7 @@ enum bch_fsck_flags {
+       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_dir_has_nonzero_i_size,                         319,    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)   \
+@@ -328,7 +329,7 @@ enum bch_fsck_flags {
+       x(dirent_stray_data_after_cf_name,                      305,    0)              \
+       x(rebalance_work_incorrectly_set,                       309,    FSCK_AUTOFIX)   \
+       x(rebalance_work_incorrectly_unset,                     310,    FSCK_AUTOFIX)   \
+-      x(MAX,                                                  319,    0)
++      x(MAX,                                                  320,    0)
+ enum bch_sb_error_id {
+ #define x(t, n, ...) BCH_FSCK_ERR_##t = n,
diff --git a/queue-6.15/bcachefs-run-may_delete_deleted_inode-checks-in-bch2_inode_rm.patch b/queue-6.15/bcachefs-run-may_delete_deleted_inode-checks-in-bch2_inode_rm.patch
new file mode 100644 (file)
index 0000000..b707c28
--- /dev/null
@@ -0,0 +1,231 @@
+From a458c1d813e74a94def231e6e5f8287d683f83bf Mon Sep 17 00:00:00 2001
+From: Kent Overstreet <kent.overstreet@linux.dev>
+Date: Mon, 2 Jun 2025 17:43:36 -0400
+Subject: bcachefs: Run may_delete_deleted_inode() checks in bch2_inode_rm()
+
+From: Kent Overstreet <kent.overstreet@linux.dev>
+
+commit 09fb85ae565645b982e9030dbb2ff6707f2cdddc upstream.
+
+We had a bug where bch2_evict_inode() incorrectly called bch2_inode_rm()
+- the journal clearly showed the inode was not unlinked.
+
+We've got checks that we use in recovery when cleaning up deleted
+inodes, lift them to bch2_inode_rm() as well.
+
+Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/bcachefs/errcode.h          |    2 +
+ fs/bcachefs/fs.c               |    8 ++++
+ fs/bcachefs/inode.c            |   66 +++++++++++++++++++++++++++++++----------
+ fs/bcachefs/sb-errors_format.h |    3 +
+ 4 files changed, 61 insertions(+), 18 deletions(-)
+
+--- a/fs/bcachefs/errcode.h
++++ b/fs/bcachefs/errcode.h
+@@ -209,6 +209,8 @@
+       x(EINVAL,                       remove_would_lose_data)                 \
+       x(EINVAL,                       no_resize_with_buckets_nouse)           \
+       x(EINVAL,                       inode_unpack_error)                     \
++      x(EINVAL,                       inode_not_unlinked)                     \
++      x(EINVAL,                       inode_has_child_snapshot)               \
+       x(EINVAL,                       varint_decode_error)                    \
+       x(EINVAL,                       erasure_coding_found_btree_node)        \
+       x(EOPNOTSUPP,                   may_not_use_incompat_feature)           \
+--- a/fs/bcachefs/fs.c
++++ b/fs/bcachefs/fs.c
+@@ -2181,7 +2181,13 @@ static void bch2_evict_inode(struct inod
+                               KEY_TYPE_QUOTA_WARN);
+               bch2_quota_acct(c, inode->ei_qid, Q_INO, -1,
+                               KEY_TYPE_QUOTA_WARN);
+-              bch2_inode_rm(c, inode_inum(inode));
++              int ret = bch2_inode_rm(c, inode_inum(inode));
++              if (ret && !bch2_err_matches(ret, EROFS)) {
++                      bch_err_msg(c, ret, "VFS incorrectly tried to delete inode %llu:%llu",
++                                  inode->ei_inum.subvol,
++                                  inode->ei_inum.inum);
++                      bch2_sb_error_count(c, BCH_FSCK_ERR_vfs_bad_inode_rm);
++              }
+               /*
+                * If we are deleting, we need it present in the vfs hash table
+--- a/fs/bcachefs/inode.c
++++ b/fs/bcachefs/inode.c
+@@ -38,6 +38,7 @@ static const char * const bch2_inode_fla
+ #undef  x
+ static int delete_ancestor_snapshot_inodes(struct btree_trans *, struct bpos);
++static int may_delete_deleted_inum(struct btree_trans *, subvol_inum);
+ static const u8 byte_table[8] = { 1, 2, 3, 4, 6, 8, 10, 13 };
+@@ -1048,19 +1049,23 @@ int bch2_inode_rm(struct bch_fs *c, subv
+       u32 snapshot;
+       int ret;
++      ret = lockrestart_do(trans, may_delete_deleted_inum(trans, inum));
++      if (ret)
++              goto err2;
++
+       /*
+        * If this was a directory, there shouldn't be any real dirents left -
+        * but there could be whiteouts (from hash collisions) that we should
+        * delete:
+        *
+-       * XXX: the dirent could ideally would delete whiteouts when they're no
++       * XXX: the dirent code ideally would delete whiteouts when they're no
+        * longer needed
+        */
+       ret   = bch2_inode_delete_keys(trans, inum, BTREE_ID_extents) ?:
+               bch2_inode_delete_keys(trans, inum, BTREE_ID_xattrs) ?:
+               bch2_inode_delete_keys(trans, inum, BTREE_ID_dirents);
+       if (ret)
+-              goto err;
++              goto err2;
+ retry:
+       bch2_trans_begin(trans);
+@@ -1342,7 +1347,8 @@ int bch2_inode_rm_snapshot(struct btree_
+               delete_ancestor_snapshot_inodes(trans, SPOS(0, inum, snapshot));
+ }
+-static int may_delete_deleted_inode(struct btree_trans *trans, struct bpos pos)
++static int may_delete_deleted_inode(struct btree_trans *trans, struct bpos pos,
++                                  bool from_deleted_inodes)
+ {
+       struct bch_fs *c = trans->c;
+       struct btree_iter inode_iter;
+@@ -1357,11 +1363,13 @@ static int may_delete_deleted_inode(stru
+               return ret;
+       ret = bkey_is_inode(k.k) ? 0 : -BCH_ERR_ENOENT_inode;
+-      if (fsck_err_on(!bkey_is_inode(k.k),
++      if (fsck_err_on(from_deleted_inodes && ret,
+                       trans, deleted_inode_missing,
+                       "nonexistent inode %llu:%u in deleted_inodes btree",
+                       pos.offset, pos.snapshot))
+               goto delete;
++      if (ret)
++              goto out;
+       ret = bch2_inode_unpack(k, &inode);
+       if (ret)
+@@ -1369,7 +1377,8 @@ static int may_delete_deleted_inode(stru
+       if (S_ISDIR(inode.bi_mode)) {
+               ret = bch2_empty_dir_snapshot(trans, pos.offset, 0, pos.snapshot);
+-              if (fsck_err_on(bch2_err_matches(ret, ENOTEMPTY),
++              if (fsck_err_on(from_deleted_inodes &&
++                              bch2_err_matches(ret, ENOTEMPTY),
+                               trans, deleted_inode_is_dir,
+                               "non empty directory %llu:%u in deleted_inodes btree",
+                               pos.offset, pos.snapshot))
+@@ -1378,17 +1387,25 @@ static int may_delete_deleted_inode(stru
+                       goto out;
+       }
+-      if (fsck_err_on(!(inode.bi_flags & BCH_INODE_unlinked),
++      ret = inode.bi_flags & BCH_INODE_unlinked ? 0 : -BCH_ERR_inode_not_unlinked;
++      if (fsck_err_on(from_deleted_inodes && ret,
+                       trans, deleted_inode_not_unlinked,
+                       "non-deleted inode %llu:%u in deleted_inodes btree",
+                       pos.offset, pos.snapshot))
+               goto delete;
++      if (ret)
++              goto out;
++
++      ret = !(inode.bi_flags & BCH_INODE_has_child_snapshot)
++              ? 0 : -BCH_ERR_inode_has_child_snapshot;
+-      if (fsck_err_on(inode.bi_flags & BCH_INODE_has_child_snapshot,
++      if (fsck_err_on(from_deleted_inodes && ret,
+                       trans, deleted_inode_has_child_snapshots,
+                       "inode with child snapshots %llu:%u in deleted_inodes btree",
+                       pos.offset, pos.snapshot))
+               goto delete;
++      if (ret)
++              goto out;
+       ret = bch2_inode_has_child_snapshots(trans, k.k->p);
+       if (ret < 0)
+@@ -1405,19 +1422,28 @@ static int may_delete_deleted_inode(stru
+                       if (ret)
+                               goto out;
+               }
++
++              if (!from_deleted_inodes) {
++                      ret =   bch2_trans_commit(trans, NULL, NULL, BCH_TRANS_COMMIT_no_enospc) ?:
++                              -BCH_ERR_inode_has_child_snapshot;
++                      goto out;
++              }
++
+               goto delete;
+       }
+-      if (test_bit(BCH_FS_clean_recovery, &c->flags) &&
+-          !fsck_err(trans, deleted_inode_but_clean,
+-                    "filesystem marked as clean but have deleted inode %llu:%u",
+-                    pos.offset, pos.snapshot)) {
+-              ret = 0;
+-              goto out;
+-      }
++      if (from_deleted_inodes) {
++              if (test_bit(BCH_FS_clean_recovery, &c->flags) &&
++                  !fsck_err(trans, deleted_inode_but_clean,
++                            "filesystem marked as clean but have deleted inode %llu:%u",
++                            pos.offset, pos.snapshot)) {
++                      ret = 0;
++                      goto out;
++              }
+-      ret = 1;
++              ret = 1;
++      }
+ out:
+ fsck_err:
+       bch2_trans_iter_exit(trans, &inode_iter);
+@@ -1428,6 +1454,14 @@ delete:
+       goto out;
+ }
++static int may_delete_deleted_inum(struct btree_trans *trans, subvol_inum inum)
++{
++      u32 snapshot;
++
++      return bch2_subvolume_get_snapshot(trans, inum.subvol, &snapshot) ?:
++              may_delete_deleted_inode(trans, SPOS(0, inum.inum, snapshot), false);
++}
++
+ int bch2_delete_dead_inodes(struct bch_fs *c)
+ {
+       struct btree_trans *trans = bch2_trans_get(c);
+@@ -1451,7 +1485,7 @@ int bch2_delete_dead_inodes(struct bch_f
+       ret = for_each_btree_key_commit(trans, iter, BTREE_ID_deleted_inodes, POS_MIN,
+                                       BTREE_ITER_prefetch|BTREE_ITER_all_snapshots, k,
+                                       NULL, NULL, BCH_TRANS_COMMIT_no_enospc, ({
+-              ret = may_delete_deleted_inode(trans, k.k->p);
++              ret = may_delete_deleted_inode(trans, k.k->p, true);
+               if (ret > 0) {
+                       bch_verbose_ratelimited(c, "deleting unlinked inode %llu:%u",
+                                               k.k->p.offset, k.k->p.snapshot);
+--- a/fs/bcachefs/sb-errors_format.h
++++ b/fs/bcachefs/sb-errors_format.h
+@@ -244,6 +244,7 @@ enum bch_fsck_flags {
+       x(inode_parent_has_case_insensitive_not_set,            317,    FSCK_AUTOFIX)   \
+       x(vfs_inode_i_blocks_underflow,                         311,    FSCK_AUTOFIX)   \
+       x(vfs_inode_i_blocks_not_zero_at_truncate,              313,    FSCK_AUTOFIX)   \
++      x(vfs_bad_inode_rm,                                     320,    0)              \
+       x(deleted_inode_but_clean,                              211,    FSCK_AUTOFIX)   \
+       x(deleted_inode_missing,                                212,    FSCK_AUTOFIX)   \
+       x(deleted_inode_is_dir,                                 213,    FSCK_AUTOFIX)   \
+@@ -329,7 +330,7 @@ enum bch_fsck_flags {
+       x(dirent_stray_data_after_cf_name,                      305,    0)              \
+       x(rebalance_work_incorrectly_set,                       309,    FSCK_AUTOFIX)   \
+       x(rebalance_work_incorrectly_unset,                     310,    FSCK_AUTOFIX)   \
+-      x(MAX,                                                  320,    0)
++      x(MAX,                                                  321,    0)
+ enum bch_sb_error_id {
+ #define x(t, n, ...) BCH_FSCK_ERR_##t = n,
index 4a87bffadbdc90c0fa1c108ce39080e009a4efff..8cb6483948f6641e484f4c28201b34079b2dbdd5 100644 (file)
@@ -11,3 +11,8 @@ documentation-acpi-use-all-string-data-node-references.patch
 pinctrl-mediatek-eint-fix-invalid-pointer-dereference-for-v1-platforms.patch
 rtc-make-rtc_time64_to_tm-support-dates-before-1970.patch
 rtc-fix-offset-calculation-for-.start_secs-0.patch
+bcachefs-kill-un-reverted-directory-i_size-code.patch
+bcachefs-repair-code-for-directory-i_size.patch
+bcachefs-delete-dead-code-from-may_delete_deleted_inode.patch
+bcachefs-run-may_delete_deleted_inode-checks-in-bch2_inode_rm.patch
+bcachefs-fix-subvol-to-missing-root-repair.patch