Linux Btrfs filesystem development
 help / color / mirror / Atom feed
From: Qu Wenruo <wqu@suse.com>
To: linux-btrfs@vger.kernel.org, fstests@vger.kernel.org
Cc: ebiggers@kernel.org
Subject: [PATCH v4] fstests: generic: add a test case to check fsverity reads
Date: Sat, 17 Oct 2026 19:33:41 +1030	[thread overview]
Message-ID: <20261017090341.72079-1-wqu@suse.com> (raw)

There is a bug report that with the recently enabled large folios
support, fsverity enabled files on btrfs can trigger reproducible
warnings about file corruption, but in the end no error is returned to
user space.

It turns out to be a bug in the btrfs fsverity integration, where blocks
not included in the read range are passed to be verified.

This is a long-standing bug where btrfs fsverity always assumed that one
folio contains exactly one fs block, ignoring the fact that btrfs had
block size < page size support before fsverity support was added.

Add a new regression test case for it. The workload is pretty simple:

- Create a 32M file

- Punch a 64K hole for every 128K
  This will limit the read bio size to 64K, which is smaller than
  a lot of large folios, and thus can trigger the btrfs bug.

- Enable fsverity digest and drop page cache

- Read that file and verify its content

- Verify there is no "FILE CORRUPTED!" warning

Signed-off-by: Qu Wenruo <wqu@suse.com>
---
Changelog
v4:
- Also output the checksum for the file for content verification

- Update the comment to show the requirement more clearly
  It requires the folio size larger than the fs block size.

  This means either a system with larger page size (e.g. 64K page sized
  arm64 with 4K block size), or large folio support (which requires
  transparent huge page).

- Minor comment updates
  * Concentrate the mention of large folio to the triggering part
  * Explain why fserror is not utilized for error detection

v3:
- Disable signature verification temporarily for the test
  Pointed out by Dhruva, as it's a user configurable behavior that if
  signature is required, reading the file without a signature will lead
  to an EPERM error.

v2:
- Do not use btrfs specific mount options to limit read bio size
  Use holes to limit the size of read bios instead, now the test case
  can be generic other than btrfs specific.

- Add the missing _require_check_dmesg call
---
 tests/generic/807     | 72 +++++++++++++++++++++++++++++++++++++++++++
 tests/generic/807.out |  2 ++
 2 files changed, 74 insertions(+)
 create mode 100755 tests/generic/807
 create mode 100644 tests/generic/807.out

diff --git a/tests/generic/807 b/tests/generic/807
new file mode 100755
index 00000000..db3c6fbb
--- /dev/null
+++ b/tests/generic/807
@@ -0,0 +1,72 @@
+#! /bin/bash
+# SPDX-License-Identifier: GPL-2.0
+# Copyright (c) 2026 SUSE S.A.  All Rights Reserved.
+#
+# FS QA Test 807
+#
+# Verify that reading a large file with holes won't trigger fsverity warnings
+#
+. ./common/preamble
+_begin_fstest auto quick verity
+
+_fixed_by_fs_commit btrfs xxxxxxxxxxxx \
+	"btrfs: fix the fsverity callback where unexpected range is verified"
+
+. ./common/verity
+
+# Override the default cleanup function.
+_cleanup()
+{
+	cd /
+	_restore_fsverity_signatures
+	rm -f $tmp.*
+}
+
+_require_xfs_io_command "fpunch"
+_require_check_dmesg
+_require_scratch_verity
+_disable_fsverity_signatures
+
+filesize=$(( 32 * 1024 * 1024 ))
+interval=$(( 128 * 1024 ))
+holesize=$(( 64 * 1024 ))
+
+_scratch_mkfs_verity >> $seqres.full
+_scratch_mount
+
+# Create a large enough file so that readahead is triggered.
+_pwrite_byte "0xcd" 0 "$filesize" "$SCRATCH_MNT/foobar" > /dev/null
+
+# Create a hole for every $interval bytes. This should limit the read to
+# $(( $interval - $holesize )), which should be much smaller than the maximum
+# folio size (2M for x86_64).
+for (( i = 0; i < $(( $filesize / $interval )); i++ )); do
+	$XFS_IO_PROG -c "fpunch $(( $i * $interval )) $holesize" \
+		"$SCRATCH_MNT/foobar" > /dev/null
+done
+
+_fsv_enable "$SCRATCH_MNT/foobar"
+
+# Cycle mount to drop page cache
+_scratch_cycle_mount
+
+# Read the file, unpatched btrfs will verify blocks outside the read range and
+# trigger fs-verity warnings.
+#
+# This warning is triggered when the folio size is larger than the fs block
+# size, either from block size < page size (e.g. 4K block size on 64K page
+# size systems), or from large folios (requires transparent huge page).
+#
+# But the read itself should still be fine, as the failed part will be retried.
+_md5_checksum "$SCRATCH_MNT/foobar"
+
+# Check for any kernel warnings from fs-verity on file corruption.
+#
+# Using fserror would be more reliable, but unfortunately btrfs doesn't fully
+# support it yet, and the fserror support for fsverity is not available in v7.2,
+# where large folios made this easy to trigger.
+if _check_dmesg_for "FILE CORRUPTED!"; then
+	echo "fs-verity detected corruption"
+fi
+
+_exit 0
diff --git a/tests/generic/807.out b/tests/generic/807.out
new file mode 100644
index 00000000..744d48c9
--- /dev/null
+++ b/tests/generic/807.out
@@ -0,0 +1,2 @@
+QA output created by 807
+9ff4ff01a9e149fcd1c36314ea42102c
-- 
2.56.0


             reply	other threads:[~2026-10-17  9:04 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-17  9:03 Qu Wenruo [this message]
2026-10-17 12:40 ` [PATCH v4] fstests: generic: add a test case to check fsverity reads Eric Biggers

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=20261017090341.72079-1-wqu@suse.com \
    --to=wqu@suse.com \
    --cc=ebiggers@kernel.org \
    --cc=fstests@vger.kernel.org \
    --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