Linux Btrfs filesystem development
 help / color / mirror / Atom feed
From: Qu Wenruo <wqu@suse.com>
To: linux-btrfs@vger.kernel.org
Subject: [PATCH 1/2] btrfs-progs: check: add repair ability for missing orphan root item
Date: Sat, 15 Nov 2025 08:15:59 +1030	[thread overview]
Message-ID: <6511d4175e77e7f9cd11e074c4e06bd745ff4568.1763156743.git.wqu@suse.com> (raw)
In-Reply-To: <cover.1763156743.git.wqu@suse.com>

There is a known bug in older kernels that orphan items can be missing
for dropped subvolumes.

This makes those subvolumes unable to be removed on the next mount, and
recent kernel commit 4289b494ac55 ("btrfs: do not allow relocation of
partially dropped subvolumes") introduced one extra safe net to catch
such problem.

But unfortunately there is no way to repair it.

Add the repair ability to both the original and lowmem modes.

Link: https://lore.kernel.org/linux-btrfs/01f8b560-fb57-4861-8382-141c39655478@gmx.com/
Signed-off-by: Qu Wenruo <wqu@suse.com>
---
 check/main.c        |  5 +++++
 check/mode-common.c | 33 +++++++++++++++++++++++++++++++++
 check/mode-common.h |  1 +
 check/mode-lowmem.c | 13 ++++++++++---
 4 files changed, 49 insertions(+), 3 deletions(-)

diff --git a/check/main.c b/check/main.c
index 77458a769028..db055ae194f8 100644
--- a/check/main.c
+++ b/check/main.c
@@ -3550,6 +3550,11 @@ static int check_root_refs(struct btrfs_root *root,
 				 */
 				if (!rec->found_root_item)
 					continue;
+				if (opt_check_repair) {
+					ret = repair_subvol_orphan_item(gfs_info, rec->objectid);
+					if (!ret)
+						continue;
+				}
 				errors++;
 				fprintf(stderr, "fs tree %llu missing orphan item\n", rec->objectid);
 			}
diff --git a/check/mode-common.c b/check/mode-common.c
index 0467ba28395e..2d11a96dfb7e 100644
--- a/check/mode-common.c
+++ b/check/mode-common.c
@@ -1672,3 +1672,36 @@ int check_and_repair_super_num_devs(struct btrfs_fs_info *fs_info)
 	printf("Successfully reset super num devices to %u\n", found_devs);
 	return 0;
 }
+
+int repair_subvol_orphan_item(struct btrfs_fs_info *fs_info, u64 rootid)
+{
+	struct btrfs_root *tree_root = fs_info->tree_root;
+	struct btrfs_trans_handle *trans;
+	struct btrfs_path path = { 0 };
+	int ret;
+
+	trans = btrfs_start_transaction(tree_root, 1);
+	if (IS_ERR(trans)) {
+		ret = PTR_ERR(trans);
+		errno = -ret;
+		error_msg(ERROR_MSG_START_TRANS, "%m");
+		return ret;
+	}
+	ret = btrfs_add_orphan_item(trans, tree_root, &path, rootid);
+	btrfs_release_path(&path);
+	if (ret < 0) {
+		errno = -ret;
+		error("failed to insert orphan item for subvolume %llu: %m", rootid);
+		btrfs_abort_transaction(trans, ret);
+		btrfs_commit_transaction(trans, tree_root);
+		return ret;
+	}
+	ret = btrfs_commit_transaction(trans, tree_root);
+	if (ret < 0) {
+		errno = -ret;
+		error_msg(ERROR_MSG_COMMIT_TRANS, "%m");
+		return ret;
+	}
+	printf("Added back missing orphan item for subvolume %llu\n", rootid);
+	return 0;
+}
diff --git a/check/mode-common.h b/check/mode-common.h
index c37b4dc00e54..e97835a5b6a3 100644
--- a/check/mode-common.h
+++ b/check/mode-common.h
@@ -197,5 +197,6 @@ int repair_dev_item_bytes_used(struct btrfs_fs_info *fs_info,
 int fill_csum_tree(struct btrfs_trans_handle *trans, bool search_fs_tree);
 
 int check_and_repair_super_num_devs(struct btrfs_fs_info *fs_info);
+int repair_subvol_orphan_item(struct btrfs_fs_info *fs_info, u64 rootid);
 
 #endif
diff --git a/check/mode-lowmem.c b/check/mode-lowmem.c
index 363dc4ae1904..ea4d4017827f 100644
--- a/check/mode-lowmem.c
+++ b/check/mode-lowmem.c
@@ -5569,9 +5569,16 @@ static int check_btrfs_root(struct btrfs_root *root, int check_all)
 	 * If this tree is a subvolume (not a reloc tree) and has no refs, there
 	 * should be an orphan item for it, or this subvolume will never be deleted.
 	 */
-	if (btrfs_root_refs(root_item) == 0 && is_fstree(btrfs_root_id(root))) {
-		if (!has_orphan_item(root->fs_info->tree_root,
-				     btrfs_root_id(root))) {
+	if (btrfs_root_refs(root_item) == 0 && is_fstree(btrfs_root_id(root)) &&
+	    !has_orphan_item(root->fs_info->tree_root, btrfs_root_id(root))) {
+		bool repaired = false;
+
+		if (opt_check_repair) {
+			ret = repair_subvol_orphan_item(root->fs_info, btrfs_root_id(root));
+			if (!ret)
+				repaired = true;
+		}
+		if (!repaired) {
 			error("missing orphan item for root %lld", btrfs_root_id(root));
 			err |= REFERENCER_MISSING;
 		}
-- 
2.51.2


  reply	other threads:[~2025-11-14 21:46 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-11-14 21:45 [PATCH 0/2] btrfs-progs: check: add repair ability for missing root orphan item Qu Wenruo
2025-11-14 21:45 ` Qu Wenruo [this message]
2025-11-19 23:02   ` [PATCH 1/2] btrfs-progs: check: add repair ability for missing orphan root item Boris Burkov
2025-11-14 21:46 ` [PATCH 2/2] btrfs-progs: fsck-tests: make test case 066 to be repairable Qu Wenruo
     [not found]   ` <314461b6-9c30-4f19-aed3-486656db661e@libero.it>
2025-11-15 10:45     ` Qu Wenruo
2025-11-19 23:03   ` Boris Burkov

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=6511d4175e77e7f9cd11e074c4e06bd745ff4568.1763156743.git.wqu@suse.com \
    --to=wqu@suse.com \
    --cc=linux-btrfs@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox