diff --git a/tests/btrfs/311 b/tests/btrfs/311
new file mode 100755
index 00000000..b8c9463b
--- /dev/null
+++ b/tests/btrfs/311
@@ -0,0 +1,73 @@
+#! /bin/bash
+# SPDX-License-Identifier: GPL-2.0
+# Copyright (C) 2024 SUSE Linux Products GmbH. All Rights Reserved.
+#
+# FS QA Test 311
+#
+# Make sure subpage btrfs can reflink a compressed inline extent to
+# an non-page aligned but sector aligned file offset
+#
+. ./common/preamble
+_begin_fstest auto quick clone compress
+
+. ./common/filter
+
+_require_command "$XZ_PROG" xz
+_supported_fs btrfs
+_require_scratch
+
+_fixed_by_kernel_commit  2c25716dcc25 \
+	"btrfs: zlib: fix and simplify the inline extent decompression"
+
+# This test requires subpage (sectorsize < PAGE_SIZE) btrfs, and a compressed
+# inline file extent, which is not yet possible to create under subpage btrfs.
+#
+# So here we have to use binary dump of a 4k sector sized btrfs here.
+pagesize=$(_get_page_size)
+if [ "$pagesize" -le "4096" ]; then
+	_notrun "This test case requires page size > 4096, got $pagesize"
+fi
+
+testcase="$0"
+if [ ! -f $testcase.img.xz ]; then
+	_fail "No binary image found"
+fi
+
+# Extra the binary dump to $SCRATCH_DEV
+$XZ_PROG --decompress --stdout $testcase.img.xz > $tmp.img
+dd if=$tmp.img of=$SCRATCH_DEV bs=1M status=none
+rm -f -- $tmp.img
+
+_scratch_mount
+
+# The correct md5 for the 4K file filled with "0xcd"
+md5sum_inline="5fed275e7617a806f94c173746a2a723"
+
+# The correct md5 for the 64K file with 60K hole then a 4K filled with "0xcd".
+md5sum_reflink="2fd82541f4790ea9730cd8b6c0f2fd9a"
+
+# Even subpage can not create compressed inline extents, read should happen without
+# any problem.
+result=$(_md5_checksum "$SCRATCH_MNT/inline")
+echo "initial read, md5sum=${result}" >> $seqres.full
+if [ "$result" != "$md5sum_inline" ]; then
+	_fail "initial read got incorrect content"
+fi
+
+# Now we reflink the compressed inline extent to an non-zero offset,
+# this would require us to decompress the content, and create a regular extent.
+#
+# For unpatched kernel, this would lead to an -EIO error.
+$XFS_IO_PROG -f -c "reflink $SCRATCH_MNT/inline 0 60k 4k" $SCRATCH_MNT/reflink | _filter_xfs_io
+
+# Make sure the reflinked file (which contains the decompressed contents) is correct.
+result=$(_md5_checksum "$SCRATCH_MNT/reflink")
+if [ "$result" != "$md5sum_reflink" ]; then
+	_fail "reflinked file has incorrect content"
+fi
+
+_scratch_unmount
+
+# success, all done
+status=0
+exit
diff --git a/tests/btrfs/311.img.xz b/tests/btrfs/311.img.xz
new file mode 100644
index 0000000000000000000000000000000000000000..ccb8fc1b8da5868f374df1c01ea480715a60b262
GIT binary patch
diff --git a/tests/btrfs/311.out b/tests/btrfs/311.out
new file mode 100644
index 00000000..87a66bc4
--- /dev/null
+++ b/tests/btrfs/311.out
@@ -0,0 +1,3 @@
+QA output created by 311
+linked 4096/4096 bytes at offset 61440
+XXX Bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
