* [PATCH 0/3] btrfs-progs: restore: handler newer inlined
@ 2026-09-16 6:52 Qu Wenruo
2026-09-16 6:52 ` [PATCH 1/3] btrfs-progs: restore: handle full block compressed inline extent Qu Wenruo
` (2 more replies)
0 siblings, 3 replies; 4+ messages in thread
From: Qu Wenruo @ 2026-09-16 6:52 UTC (permalink / raw)
To: linux-btrfs
The detailed commit message is in the first patch.
And also fix a minor problem related to very rare inlined extent that is
larger than 4K (possible only with page sizes larger than 4K).
Finally a test case for the initial problem.
Qu Wenruo (3):
btrfs-progs: restore: handle full block compressed inline extent
btrfs-progs: restore: handle inlined extent larger than 4K
btrfs-progs: misc-tests: add a test case for btrfs-restore
cmds/restore.c | 23 +++++++++++----
.../073-restore-inline-compressed/test.sh | 28 +++++++++++++++++++
2 files changed, 46 insertions(+), 5 deletions(-)
create mode 100755 tests/misc-tests/073-restore-inline-compressed/test.sh
--
2.55.0
^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH 1/3] btrfs-progs: restore: handle full block compressed inline extent
2026-09-16 6:52 [PATCH 0/3] btrfs-progs: restore: handler newer inlined Qu Wenruo
@ 2026-09-16 6:52 ` Qu Wenruo
2026-09-16 6:52 ` [PATCH 2/3] btrfs-progs: restore: handle inlined extent larger than 4K Qu Wenruo
2026-09-16 6:52 ` [PATCH 3/3] btrfs-progs: misc-tests: add a test case for btrfs-restore Qu Wenruo
2 siblings, 0 replies; 4+ messages in thread
From: Qu Wenruo @ 2026-09-16 6:52 UTC (permalink / raw)
To: linux-btrfs
Since kernel commit 3eaf5f082c4c ("btrfs: extract inlined creation into a
dedicated delalloc helper"), the creation of compressed inlined extent
has changed to compress the whole block, then truncate the ram_bytes to
isize.
This means the compressed data needs to have a full block as the output
buffer.
This is fine for kernel, as the inlined extent is alwasy decompressed to
a folio which is at least one block sized.
But for progs, if the output buffer is smaller than a block, the
decompression will fail early (not enough output buffer), causing
btrfs-restore to completely skip the content of the inlined extent.
Fix it by always allocating a full block for copy_one_inline().
Issue: #1171
Signed-off-by: Qu Wenruo <wqu@suse.com>
---
cmds/restore.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/cmds/restore.c b/cmds/restore.c
index 7d16cc99fa6a..00471b486ac6 100644
--- a/cmds/restore.c
+++ b/cmds/restore.c
@@ -298,6 +298,7 @@ static int copy_one_inline(struct btrfs_root *root, int fd,
char buf[4096];
char *outbuf;
u64 ram_size;
+ u64 out_buf_len;
ssize_t done;
unsigned long ptr;
int ret;
@@ -324,13 +325,14 @@ static int copy_one_inline(struct btrfs_root *root, int fd,
}
ram_size = btrfs_file_extent_ram_bytes(leaf, fi);
- outbuf = calloc(1, ram_size);
+ out_buf_len = root->fs_info->sectorsize;
+ outbuf = malloc(out_buf_len);
if (!outbuf) {
error_mem(NULL);
return -ENOMEM;
}
- ret = decompress(root, buf, outbuf, inline_item_len, &ram_size,
+ ret = decompress(root, buf, outbuf, inline_item_len, &out_buf_len,
compress);
if (ret) {
free(outbuf);
--
2.55.0
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH 2/3] btrfs-progs: restore: handle inlined extent larger than 4K
2026-09-16 6:52 [PATCH 0/3] btrfs-progs: restore: handler newer inlined Qu Wenruo
2026-09-16 6:52 ` [PATCH 1/3] btrfs-progs: restore: handle full block compressed inline extent Qu Wenruo
@ 2026-09-16 6:52 ` Qu Wenruo
2026-09-16 6:52 ` [PATCH 3/3] btrfs-progs: misc-tests: add a test case for btrfs-restore Qu Wenruo
2 siblings, 0 replies; 4+ messages in thread
From: Qu Wenruo @ 2026-09-16 6:52 UTC (permalink / raw)
To: linux-btrfs
Most btrfs are already using 4K sectorsize, but for systems with 64K
page size, it's possible to create large inlined extent that is larger
than 4K:
item 6 key (257 EXTENT_DATA 0) itemoff 56802 itemsize 8213
generation 9 type 0 (inline)
inline extent data size 8192 ram_bytes 8192 compression 0 (none)
In that case, btrfs-restore will crash as its input buffer is only 4K
sized.
Enhance btrfs-restore to handle larger block size correctly, by allocate
a block-sized buffer at input buffer.
Signed-off-by: Qu Wenruo <wqu@suse.com>
---
cmds/restore.c | 19 +++++++++++++++----
1 file changed, 15 insertions(+), 4 deletions(-)
diff --git a/cmds/restore.c b/cmds/restore.c
index 00471b486ac6..b982f2de4699 100644
--- a/cmds/restore.c
+++ b/cmds/restore.c
@@ -295,7 +295,8 @@ static int copy_one_inline(struct btrfs_root *root, int fd,
{
struct extent_buffer *leaf = path->nodes[0];
struct btrfs_file_extent_item *fi;
- char buf[4096];
+ const u32 blocksize = root->fs_info->sectorsize;
+ char *inbuf;
char *outbuf;
u64 ram_size;
u64 out_buf_len;
@@ -306,16 +307,23 @@ static int copy_one_inline(struct btrfs_root *root, int fd,
int inline_item_len;
int compress;
+ inbuf = malloc(blocksize);
+ if (!inbuf) {
+ error_mem(NULL);
+ return -ENOMEM;
+ }
+
fi = btrfs_item_ptr(leaf, path->slots[0],
struct btrfs_file_extent_item);
ptr = btrfs_file_extent_inline_start(fi);
len = btrfs_file_extent_ram_bytes(leaf, fi);
inline_item_len = btrfs_file_extent_inline_item_len(leaf, path->slots[0]);
- read_extent_buffer(leaf, buf, ptr, inline_item_len);
+ read_extent_buffer(leaf, inbuf, ptr, inline_item_len);
compress = btrfs_file_extent_compression(leaf, fi);
if (compress == BTRFS_COMPRESS_NONE) {
- done = pwrite(fd, buf, len, pos);
+ done = pwrite(fd, inbuf, len, pos);
+ free(inbuf);
if (done < len) {
error("short inline write, wanted %d, did %zd: %m",
len, done);
@@ -329,17 +337,20 @@ static int copy_one_inline(struct btrfs_root *root, int fd,
outbuf = malloc(out_buf_len);
if (!outbuf) {
error_mem(NULL);
+ free(inbuf);
return -ENOMEM;
}
- ret = decompress(root, buf, outbuf, inline_item_len, &out_buf_len,
+ ret = decompress(root, inbuf, outbuf, inline_item_len, &out_buf_len,
compress);
if (ret) {
+ free(inbuf);
free(outbuf);
return ret;
}
done = pwrite(fd, outbuf, ram_size, pos);
+ free(inbuf);
free(outbuf);
if (done < ram_size) {
error("short compressed inline write, wanted %llu, did %zd: %m",
--
2.55.0
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH 3/3] btrfs-progs: misc-tests: add a test case for btrfs-restore
2026-09-16 6:52 [PATCH 0/3] btrfs-progs: restore: handler newer inlined Qu Wenruo
2026-09-16 6:52 ` [PATCH 1/3] btrfs-progs: restore: handle full block compressed inline extent Qu Wenruo
2026-09-16 6:52 ` [PATCH 2/3] btrfs-progs: restore: handle inlined extent larger than 4K Qu Wenruo
@ 2026-09-16 6:52 ` Qu Wenruo
2 siblings, 0 replies; 4+ messages in thread
From: Qu Wenruo @ 2026-09-16 6:52 UTC (permalink / raw)
To: linux-btrfs
The new test case will:
- Create an inlined compressed file extent
- Generate checksum for that file
- Use btrfs-restore to extract that file
- Compare the extracted file with the generated checksum
The checksum should match.
This is a regression test for a behavior change in kernel, which results
older btrfs-restore unable to handle newerly created inlined compressed
file extents.
Signed-off-by: Qu Wenruo <wqu@suse.com>
---
.../073-restore-inline-compressed/test.sh | 28 +++++++++++++++++++
1 file changed, 28 insertions(+)
create mode 100755 tests/misc-tests/073-restore-inline-compressed/test.sh
diff --git a/tests/misc-tests/073-restore-inline-compressed/test.sh b/tests/misc-tests/073-restore-inline-compressed/test.sh
new file mode 100755
index 000000000000..e558cd372184
--- /dev/null
+++ b/tests/misc-tests/073-restore-inline-compressed/test.sh
@@ -0,0 +1,28 @@
+#!/bin/bash
+# Test "btrfs restore" on compressed inlined extents.
+
+source "$TEST_TOP/common" || exit
+source "$TEST_TOP/common.convert" || exit
+
+check_prereq mkfs.btrfs
+check_prereq btrfs
+check_global_prereq md5sum
+
+setup_root_helper
+prepare_test_dev
+
+tmp=$(_mktemp_dir "restore-destination")
+run_check_mkfs_test_dev
+run_check_mount_test_dev -o max_inline=4095
+run_check $SUDO_HELPER dd if=/dev/zero of="$TEST_MNT/foobar" bs=2k count=1 status=noxfer
+md5_before=$(run_check_stdout md5sum "$TEST_MNT/foobar" | cut -d ' ' -f 1)
+run_check_umount_test_dev
+
+run_check $SUDO_HELPER "$TOP/btrfs" restore "$TEST_DEV" "$tmp"
+md5_after=$(run_check_stdout md5sum "$tmp/foobar" | cut -d ' ' -f 1)
+
+rm -rf "$tmp"
+
+if [ "$md5_before" != "$md5_after" ]; then
+ _fail "md5 checksum mismatch"
+fi
--
2.55.0
^ permalink raw reply related [flat|nested] 4+ messages in thread
end of thread, other threads:[~2026-09-16 6:52 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-16 6:52 [PATCH 0/3] btrfs-progs: restore: handler newer inlined Qu Wenruo
2026-09-16 6:52 ` [PATCH 1/3] btrfs-progs: restore: handle full block compressed inline extent Qu Wenruo
2026-09-16 6:52 ` [PATCH 2/3] btrfs-progs: restore: handle inlined extent larger than 4K Qu Wenruo
2026-09-16 6:52 ` [PATCH 3/3] btrfs-progs: misc-tests: add a test case for btrfs-restore Qu Wenruo
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.