* [PATCH 0/2] btrfs-progs: check: add repair functionality for
@ 2025-10-06 9:38 Qu Wenruo
2025-10-06 9:38 ` [PATCH 1/2] btrfs-progs: check: add repair functionality for orphan dev extents Qu Wenruo
2025-10-06 9:38 ` [PATCH 2/2] btrfs-progs: fsck-tests: a new test case with orphan dev extent Qu Wenruo
0 siblings, 2 replies; 3+ messages in thread
From: Qu Wenruo @ 2025-10-06 9:38 UTC (permalink / raw)
To: linux-btrfs
Currently any orphan device extents will cause kernels to reject the
mount.
But on the other hand, btrfs check is unable to repair such problem, so
end users may fall into a situation where they are unable to mount the fs.
Add the repair functionality to btrfs check, for both original lowmem
modes, and add a new test case for it.
Qu Wenruo (2):
btrfs-progs: check: add repair functionality for orphan dev extents
btrfs-progs: fsck-tests: a new test case with orphan dev extent
check/main.c | 6 +-
check/mode-lowmem.c | 7 +-
check/repair.c | 78 ++++++++++++++++++
check/repair.h | 1 +
.../068-orphan-dev-extent/.lowmem_repairable | 0
.../068-orphan-dev-extent/default.img.xz | Bin 0 -> 1784 bytes
6 files changed, 90 insertions(+), 2 deletions(-)
create mode 100644 tests/fsck-tests/068-orphan-dev-extent/.lowmem_repairable
create mode 100644 tests/fsck-tests/068-orphan-dev-extent/default.img.xz
--
2.50.1
^ permalink raw reply [flat|nested] 3+ messages in thread
* [PATCH 1/2] btrfs-progs: check: add repair functionality for orphan dev extents
2025-10-06 9:38 [PATCH 0/2] btrfs-progs: check: add repair functionality for Qu Wenruo
@ 2025-10-06 9:38 ` Qu Wenruo
2025-10-06 9:38 ` [PATCH 2/2] btrfs-progs: fsck-tests: a new test case with orphan dev extent Qu Wenruo
1 sibling, 0 replies; 3+ messages in thread
From: Qu Wenruo @ 2025-10-06 9:38 UTC (permalink / raw)
To: linux-btrfs
There is a bug report that btrfs-check --repair didn't repair an orphan
dev extent, which makes kernel to reject the fs due to the overly strict
chunk related checks.
However for btrfs-check, it's pretty easy to remove orphan device
extents (which do not have corresponding chunks), and update the device
item to reflect the used_bytes changes.
Add a repair function, btrfs_remove_dev_extent() which does the repair,
and call that function for both original and lowmem modes.
Signed-off-by: Qu Wenruo <wqu@suse.com>
---
check/main.c | 6 +++-
check/mode-lowmem.c | 7 +++-
check/repair.c | 78 +++++++++++++++++++++++++++++++++++++++++++++
check/repair.h | 1 +
4 files changed, 90 insertions(+), 2 deletions(-)
diff --git a/check/main.c b/check/main.c
index 91ce6d7401a1..e457c9073bfb 100644
--- a/check/main.c
+++ b/check/main.c
@@ -8601,7 +8601,11 @@ int check_chunks(struct cache_tree *chunk_cache,
dext_rec->objectid,
dext_rec->offset,
dext_rec->length);
- if (!ret)
+ err = -ENOENT;
+ if (opt_check_repair)
+ err = btrfs_remove_dev_extent(gfs_info, dext_rec->objectid,
+ dext_rec->offset);
+ if (err && !ret)
ret = 1;
}
return ret;
diff --git a/check/mode-lowmem.c b/check/mode-lowmem.c
index 774a57c861a4..363dc4ae1904 100644
--- a/check/mode-lowmem.c
+++ b/check/mode-lowmem.c
@@ -4749,7 +4749,12 @@ out:
error(
"device extent[%llu, %llu, %llu] did not find the related chunk",
devext_key.objectid, devext_key.offset, length);
- return REFERENCER_MISSING;
+ ret = -ENOENT;
+ if (opt_check_repair)
+ ret = btrfs_remove_dev_extent(gfs_info, devext_key.objectid,
+ devext_key.offset);
+ if (ret < 0)
+ return REFERENCER_MISSING;
}
return 0;
}
diff --git a/check/repair.c b/check/repair.c
index e500c4fa0a3a..729b040ce2fd 100644
--- a/check/repair.c
+++ b/check/repair.c
@@ -31,7 +31,9 @@
#include "kernel-shared/extent_io.h"
#include "kernel-shared/disk-io.h"
#include "kernel-shared/tree-checker.h"
+#include "kernel-shared/volumes.h"
#include "common/extent-cache.h"
+#include "common/messages.h"
#include "check/repair.h"
int opt_check_repair = 0;
@@ -354,6 +356,82 @@ out:
return ret;
}
+int btrfs_remove_dev_extent(struct btrfs_fs_info *fs_info, u64 devid, u64 physical)
+{
+ struct btrfs_trans_handle *trans;
+ struct btrfs_root *dev_root = fs_info->dev_root;
+ struct btrfs_key key = {
+ .objectid = devid,
+ .type = BTRFS_DEV_EXTENT_KEY,
+ .offset = physical,
+ };
+ struct btrfs_path path = { 0 };
+ struct btrfs_dev_extent *dext;
+ struct btrfs_device *dev;
+ u64 length;
+ int ret;
+
+ dev = btrfs_find_device_by_devid(fs_info->fs_devices, devid, 0);
+ if (!dev) {
+ ret = -ENOENT;
+ error("failed to find devid %llu", devid);
+ return ret;
+ }
+ trans = btrfs_start_transaction(dev_root, 1);
+ if (IS_ERR(trans)) {
+ ret = PTR_ERR(trans);
+ errno = -ret;
+ error_msg(ERROR_MSG_START_TRANS, "%m");
+ return ret;
+ }
+ ret = btrfs_search_slot(trans, dev_root, &key, &path, -1, 1);
+ if (ret > 0)
+ ret = -ENOENT;
+ if (ret < 0) {
+ errno = -ret;
+ error("failed to locate dev extent, devid %llu physical %llu: %m",
+ devid, physical);
+ goto abort;
+ }
+ dext = btrfs_item_ptr(path.nodes[0], path.slots[0], struct btrfs_dev_extent);
+ length = btrfs_dev_extent_length(path.nodes[0], dext);
+ ret = btrfs_del_item(trans, dev_root, &path);
+ if (ret < 0) {
+ errno = -ret;
+ error("failed to delete dev extent, devid %llu physical %llu: %m",
+ devid, physical);
+ goto abort;
+ }
+ btrfs_release_path(&path);
+ if (dev->bytes_used < length) {
+ warning("devid %llu has bytes_used %llu, smaller than %llu",
+ devid, dev->bytes_used, length);
+ dev->bytes_used = 0;
+ } else {
+ dev->bytes_used -= length;
+ }
+ ret = btrfs_update_device(trans, dev);
+ if (ret < 0) {
+ errno = -ret;
+ error("failed to update device, devid %llu: %m", devid);
+ goto abort;
+ }
+ ret = btrfs_commit_transaction(trans, dev_root);
+ if (ret < 0) {
+ errno = -ret;
+ error_msg(ERROR_MSG_COMMIT_TRANS, "%m");
+ } else {
+ printf("removed orphan dev extent, devid %llu physical %llu length %llu\n",
+ devid, physical, length);
+ }
+ return ret;
+
+abort:
+ btrfs_release_path(&path);
+ btrfs_abort_transaction(trans, ret);
+ return ret;
+}
+
enum btrfs_tree_block_status btrfs_check_block_for_repair(struct extent_buffer *eb,
struct btrfs_key *first_key)
{
diff --git a/check/repair.h b/check/repair.h
index 4d59ca1dd115..d8a191b89fc8 100644
--- a/check/repair.h
+++ b/check/repair.h
@@ -48,6 +48,7 @@ int btrfs_mark_used_tree_blocks(struct btrfs_fs_info *fs_info,
struct extent_io_tree *tree);
int btrfs_mark_used_blocks(struct btrfs_fs_info *fs_info,
struct extent_io_tree *tree);
+int btrfs_remove_dev_extent(struct btrfs_fs_info *fs_info, u64 devid, u64 physical);
enum btrfs_tree_block_status btrfs_check_block_for_repair(struct extent_buffer *eb,
struct btrfs_key *first_key);
void btrfs_set_item_key_unsafe(struct btrfs_root *root, struct btrfs_path *path,
--
2.50.1
^ permalink raw reply related [flat|nested] 3+ messages in thread
* [PATCH 2/2] btrfs-progs: fsck-tests: a new test case with orphan dev extent
2025-10-06 9:38 [PATCH 0/2] btrfs-progs: check: add repair functionality for Qu Wenruo
2025-10-06 9:38 ` [PATCH 1/2] btrfs-progs: check: add repair functionality for orphan dev extents Qu Wenruo
@ 2025-10-06 9:38 ` Qu Wenruo
1 sibling, 0 replies; 3+ messages in thread
From: Qu Wenruo @ 2025-10-06 9:38 UTC (permalink / raw)
To: linux-btrfs
The fs has the following chunk tree (minor members removed):
item 0 key (DEV_ITEMS DEV_ITEM 1) itemoff 16185 itemsize 98
devid 1 total_bytes 536870912 bytes_used 159383552
io_align 4096 io_width 4096 sector_size 4096 type 0
item 1 key (FIRST_CHUNK_TREE CHUNK_ITEM 13631488) itemoff 16105 itemsize 80
length 8388608 owner 2 stripe_len 65536 type DATA|single
io_align 65536 io_width 65536 sector_size 4096
num_stripes 1 sub_stripes 1
item 2 key (FIRST_CHUNK_TREE CHUNK_ITEM 22020096) itemoff 15993 itemsize 112
length 8388608 owner 2 stripe_len 65536 type SYSTEM|DUP
io_align 65536 io_width 65536 sector_size 4096
item 3 key (FIRST_CHUNK_TREE CHUNK_ITEM 30408704) itemoff 15881 itemsize 112
length 33554432 owner 2 stripe_len 65536 type METADATA|DUP
io_align 65536 io_width 65536 sector_size 4096
And the following dev tree:
item 0 key (DEV_STATS PERSISTENT_ITEM 1) itemoff 16243 itemsize 40
persistent item objectid DEV_STATS offset 1
device stats
write_errs 0 read_errs 0 flush_errs 0 corruption_errs 0 generation 0
item 1 key (1 DEV_EXTENT 13631488) itemoff 16195 itemsize 48
item 2 key (1 DEV_EXTENT 22020096) itemoff 16147 itemsize 48
item 3 key (1 DEV_EXTENT 30408704) itemoff 16099 itemsize 48
item 4 key (1 DEV_EXTENT 38797312) itemoff 16051 itemsize 48
item 5 key (1 DEV_EXTENT 72351744) itemoff 16003 itemsize 48
item 6 key (1 DEV_EXTENT 105906176) itemoff 15955 itemsize 48
dev extent chunk_tree 3
chunk_objectid 256 chunk_offset 63963136 length 67108864
chunk_tree_uuid b2408431-a79a-42b6-aadc-4e853d4caa82
Notice the last dev_extent item, which has no corresponding chunk.
The image is created by calling btrfs_insert_dev_extent(), then
btrfs_update_device() to update dev->bytes_used.
This image can be repaired by both original and lowmem modes.
Signed-off-by: Qu Wenruo <wqu@suse.com>
---
.../068-orphan-dev-extent/.lowmem_repairable | 0
.../068-orphan-dev-extent/default.img.xz | Bin 0 -> 1784 bytes
2 files changed, 0 insertions(+), 0 deletions(-)
create mode 100644 tests/fsck-tests/068-orphan-dev-extent/.lowmem_repairable
create mode 100644 tests/fsck-tests/068-orphan-dev-extent/default.img.xz
diff --git a/tests/fsck-tests/068-orphan-dev-extent/.lowmem_repairable b/tests/fsck-tests/068-orphan-dev-extent/.lowmem_repairable
new file mode 100644
index 000000000000..e69de29bb2d1
diff --git a/tests/fsck-tests/068-orphan-dev-extent/default.img.xz b/tests/fsck-tests/068-orphan-dev-extent/default.img.xz
new file mode 100644
index 0000000000000000000000000000000000000000..6ca960a73a4ded4d7ffe57cb234c9579f8c0f584
GIT binary patch
literal 1784
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
GMgagrz-RdY
literal 0
HcmV?d00001
--
2.50.1
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2025-10-06 9:38 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-10-06 9:38 [PATCH 0/2] btrfs-progs: check: add repair functionality for Qu Wenruo
2025-10-06 9:38 ` [PATCH 1/2] btrfs-progs: check: add repair functionality for orphan dev extents Qu Wenruo
2025-10-06 9:38 ` [PATCH 2/2] btrfs-progs: fsck-tests: a new test case with orphan dev extent Qu Wenruo
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).