* [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).