From: Andrey Albershteyn <aalbersh@kernel.org>
To: djwong@kernel.org, ebiggers@kernel.org, hch@lst.de,
Carlos Maiolino <cem@kernel.org>
Cc: Andrey Albershteyn <aalbersh@kernel.org>,
fsverity@lists.linux.dev, linux-fsdevel@vger.kernel.org,
linux-xfs@vger.kernel.org, linux-unionfs@vger.kernel.org,
linux-ext4@vger.kernel.org,
linux-f2fs-devel@lists.sourceforge.net,
linux-btrfs@vger.kernel.org, david@fromorbit.com
Subject: [PATCH v17 00/21] fs-verity support for XFS with post EOF merkle tree
Date: Sat, 3 Oct 2026 00:36:41 +0200 [thread overview]
Message-ID: <20261002223705.2175542-1-aalbersh@kernel.org> (raw)
Hi all,
This is next revision of fsverity for XFS.
Patches without review:
[PATCH v17 12/21] xfs: use read ioend for fsverity data verification
This series based on block/for-next (has lazy-bounce series)
block/for-next:
https://git.kernel.org/pub/scm/linux/kernel/git/axboe/linux.git/log/?h=for-next
kernel:
https://git.kernel.org/pub/scm/linux/kernel/git/aalbersh/xfs-linux.git/log/?h=fsverity
xfsprogs:
https://git.kernel.org/pub/scm/linux/kernel/git/aalbersh/xfsprogs-dev.git/log/?h=fsverity
xfstests:
https://git.kernel.org/pub/scm/linux/kernel/git/aalbersh/xfstests-dev.git/log/?h=fsverity
v16:
https://lore.kernel.org/fsverity/arJC542mXklAeswE@aalbersh-thinkpadx1carbongen13.rmtcz.csb/T/#t
v15:
https://lore.kernel.org/fsverity/20260817070240.GA17371@lst.de/T/#t
v14:
https://lore.kernel.org/fsverity/anmFWhPNOqe4uyht@aalbersh-thinkpadx1carbongen13.rmtcz.csb/T/#t
v13:
https://lore.kernel.org/fsverity/20260721184346.416657-1-aalbersh@kernel.org/T/#t
v12:
https://lore.kernel.org/fsverity/al8xgOwueDOzGakK@aalbersh-thinkpadx1carbongen13.rmtcz.csb/T/#t
v11:
https://lore.kernel.org/all/20260710085256.3464201-1-aalbersh@kernel.org/
v10:
https://lore.kernel.org/fsverity/20260520123722.405752-1-aalbersh@kernel.org/#r
v9:
https://lore.kernel.org/fsverity/20260428083332.768693-1-aalbersh@kernel.org/#r
To: djwong@kernel.org
To: ebiggers@kernel.org
To: hch@lst.de
To: Carlos Maiolino <cem@kernel.org>
Cc: fsverity@lists.linux.dev
Cc: linux-fsdevel@vger.kernel.org
Cc: linux-xfs@vger.kernel.org
Cc: linux-unionfs@vger.kernel.org
Cc: linux-ext4@vger.kernel.org
Cc: linux-f2fs-devel@lists.sourceforge.net
Cc: linux-btrfs@vger.kernel.org
Cc: david@fromorbit.com
---
Changes in v17:
- Add mempool for fsverity ioends cache
- Add xfs_fsverity_reset_inode() as a common clean up function
- Changed ILOCK_SHARED to ILOCK_EXCL for xfs_bmap_last_extent()
- Swap order of truncate_inode_pages() and ilock() due to ABBA
- Add xfs_fsverity_is_hashes_of_zeroed_blocks() helper
- Removed EINVAL and EFBIG from scrub as ambiguous
Changes in v16:
- Rebase to block/for-next
- Removed work_struct from ioend in favor of kmem_cache structs
- Minor adjustments from v15 review
- Skip written extents in lower level of __xfs_bunmapi()
Changes in v15:
- Pull BIO in task context patches
- Drop flag argument in xfs_free_eofblocks()
- Call xfs_free_eofblocks() on fsverity inodes
- Comments and commit messages updates
- Rebased to v7.2-rc7
- Dropped patch for fsverity_fill_zerohash() with highmem optimization
Changes in v14:
- Rebase to lazy-bounce@hch-misc
- Adjust read ioends to BIO in task context flow
- MMAPLOCK/sb_internal deadlock fix reported by sashiko
- Add missing delalloc clean up in verity_end_enable
- Use xfs_free_eofblocks() instead of writing own clean up routine
- Modify xfs_free_eofblocks() to be able to clean unwritten only
- Dropped fix patch for truncate/set_size check
- Various minor code and #include rearrangements for bisecting
Changes in v13:
- Hoisted statx reporting to common code
- Added read ioend sorted for worker self-deadlock fix
- Adjusted fsverity flags in zoned write path
Changes in v12:
- Refactored xfs_fsverity_cancel_unwritten()
- Switched to using inode_set_flags()
- Add a lock for COW fork reading
- Add pagecache truncation in cleanup path
- Added ERANGE and EBADMSG to fsverity scrub handling
- Add missing XFS_FSVERITY_CONSTRUCTION in various xfs_iomap
- Rebase to -rc3
Changes in v11:
- Drop wrong overlayfs patch
- Drop already merged iomap and fsverity patches
- Update to I_INO() use instead of ip->i_ino
- Sashiko.dev fixes. See list of issues below.
Changes in v10:
- Rebase to v7.1-rc3 with relevant adjustments
- Initialize ioend->io_vi to NULL to not get write work onto verity wq
- Range diff below
Changes in v9:
- Fix fsverity_fill_zerohash() parameter names
- A few fixes found by sashiko.dev:
- Replace ip->i_mount->m_attr_geo->blksize with m_sb.sb_blocksize
- Don't call xfs_trans_cancel() after xfs_trans_commit() in
xfs_fsverity_end_enable()
- Call xfs_fsverity_delete_metadata() if verity enable failed
- Change start/end type from xfs_fileoff_t to loff_t
- Return xfs_trans_commit() error from
xfs_fsverity_cancel_unwritten()
Changes in v8:
- Return fsverity_ensure_verity_info() errors from
ovl_ensure_verity_loaded()
Changes in v7:
- Move kerneldoc to fsverity_ensure_verity_info() definition
- Drop patch adding XFS traces
- Fix overly long line in the comment
- Make order of fserror and fsverity_error consistent
- Add overlay patch converting to fsverity_ensure_verity_info()
Changes in v6:
- Removed stub for fsverity_ensure_verity_info() as it's optimized out
- Rename fsverity_folio_zero_hash() to fsverify_fill_zerohash()
- Merge patches 8 to 10 into one
- Merge patch gerating zero_hash and fsverity_fill_zerohash() into one
- Add kerneldoc to fsverity_ensure_verity_info()
- Add comments to iomap_block_needs_zeroing()
Changes in v5:
- Add fserror_report_data_lost() for data blocks in page spanning EOF
- Issue fsverity metadata readahead in data readahead
- iomap_fsverity_write() return type fix
- Use of S_ISREG(mode)
- Make 65536 #define instead of open-coded
- Use transaction per unwritten extent removal
- Fetch fsverity_info for all fsverity metadata
- Revert fsverity_folio_zero_hash() stub as used in iomap
- Extend cancel_unwritten to whole file range to remove cow leftovers
- Drop delayed allocation on the COW fork on fsverity completion
Changes in v4:
- Use fserror interface in fsverity instead of fs callback
- Hoist pagecache_read from f2fs/ext4 to fsverity
- Refactor iomap code
- Fetch fsverity_info only for file data and merkle tree holes
- Do not disable preallocation, remove unwritten extents instead
- Offload fsverity hash I/O to fsverity workqueue in read path
- Store merkle tree at round_up(i_size, 64k)
- Add a spacing between merkle tree and fsverity descriptor as next 64k
aligned block
- Squash helpers into first user commits
- Squash on-disk format changes into single commit
- Drop different offset for pagecache/on-disk
- Don't zero out pages in higher order folios in write path
- Link to v3: https://lore.kernel.org/fsverity/20260217231937.1183679-1-aalbersh@kernel.org/T/#t
Changes in v3:
- Different on-disk and pagecache offset
- Use read path ioends
- Switch to hashtable fsverity info
- Synthesize merkle tree blocks full of zeroes
- Other minor refactors
- Link to v2: https://lore.kernel.org/fsverity/20260114164210.GO15583@frogsfrogsfrogs/T/#t
Changes in v2:
- Move to VFS interface for merkle tree block reading
- Drop patchset for per filesystem workqueues
- Change how offsets of the descriptor and tree metadata is calculated
- Store fs-verity descriptor in data fork side by side with merkle tree
- Simplify iomap changes, remove interface for post eof read/write
- Get rid of extended attribute implementation
- Link to v1: https://lore.kernel.org/r/20250728-fsverity-v1-0-9e5443af0e34@kernel.org
Andrey Albershteyn (19):
fsverity: report validation errors through fserror to fsnotify
fsverity: expose ensure_fsverity_info()
fsverity: pass digest size and hash of the all-zeroes block to ->write
fsverity: hoist pagecache_read from f2fs/ext4 to fsverity
fsverity: don't allow setting DAX file attribute on fsverity files
fsverity: hoist statx reporting of fs-verity flag
xfs: introduce fsverity on-disk changes
xfs: don't allow to enable DAX on fs-verity sealed inode
xfs: disable direct read path for fs-verity files
xfs: don't report dio_mem_align and dio_offset_align for fsverity
files
xfs: handle fsverity I/O in write/read path
xfs: use read ioend for fsverity data verification
xfs: add XFS_BMAPI_UNWRITTEN to unmap unwritten extents in
__xfs_bunmapi()
xfs: don't remove written extents past EOF on fsverity inodes
xfs: add fs-verity support
xfs: initialize fs-verity on file open
xfs: add fs-verity ioctls
xfs: introduce health state for corrupted fsverity metadata
xfs: enable ro-compat fs-verity flag
Darrick J. Wong (2):
xfs: advertise fs-verity being available on filesystem
xfs: check and repair the verity inode flag state
fs/btrfs/inode.c | 3 -
fs/btrfs/verity.c | 6 +-
fs/ext4/inode.c | 5 +-
fs/ext4/verity.c | 36 +--
fs/f2fs/file.c | 5 +-
fs/f2fs/verity.c | 34 +--
fs/file_attr.c | 11 +-
fs/stat.c | 6 +-
fs/verity/enable.c | 4 +-
fs/verity/open.c | 26 +-
fs/verity/pagecache.c | 33 +++
fs/verity/verify.c | 4 +
fs/xfs/Makefile | 1 +
fs/xfs/libxfs/xfs_bmap.c | 15 +-
fs/xfs/libxfs/xfs_bmap.h | 6 +-
fs/xfs/libxfs/xfs_format.h | 35 ++-
fs/xfs/libxfs/xfs_fs.h | 2 +
fs/xfs/libxfs/xfs_health.h | 4 +-
fs/xfs/libxfs/xfs_inode_buf.c | 8 +
fs/xfs/libxfs/xfs_inode_util.c | 5 +-
fs/xfs/libxfs/xfs_sb.c | 4 +
fs/xfs/scrub/common.c | 53 ++++
fs/xfs/scrub/common.h | 2 +
fs/xfs/scrub/inode.c | 7 +
fs/xfs/scrub/inode_repair.c | 36 +++
fs/xfs/xfs_aops.c | 49 +++-
fs/xfs/xfs_bmap_util.c | 31 ++-
fs/xfs/xfs_file.c | 71 +++--
fs/xfs/xfs_fsverity.c | 489 +++++++++++++++++++++++++++++++++
fs/xfs/xfs_fsverity.h | 47 ++++
fs/xfs/xfs_health.c | 1 +
fs/xfs/xfs_inode.h | 6 +
fs/xfs/xfs_ioctl.c | 14 +
fs/xfs/xfs_ioend.c | 53 +++-
fs/xfs/xfs_ioend.h | 4 +-
fs/xfs/xfs_iomap.c | 37 ++-
fs/xfs/xfs_iomap.h | 5 +-
fs/xfs/xfs_iops.c | 12 +-
fs/xfs/xfs_message.c | 4 +
fs/xfs/xfs_message.h | 1 +
fs/xfs/xfs_mount.h | 4 +
fs/xfs/xfs_super.c | 31 ++-
include/linux/fsverity.h | 10 +-
43 files changed, 1079 insertions(+), 141 deletions(-)
create mode 100644 fs/xfs/xfs_fsverity.c
create mode 100644 fs/xfs/xfs_fsverity.h
Range-diff against v16:
-: ------------ > 1: c14aea60fb61 fsverity: report validation errors through fserror to fsnotify
1: d234049f2fc6 ! 2: ba2ec9993a12 fsverity: expose ensure_fsverity_info()
@@ Commit message
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
Acked-by: Eric Biggers <ebiggers@kernel.org>
- Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Andrey Albershteyn <aalbersh@kernel.org>
+ Reviewed-by: Christoph Hellwig <hch@lst.de>
## fs/verity/open.c ##
@@ fs/verity/open.c: int fsverity_get_descriptor(struct inode *inode,
2: ce8681774085 ! 3: 68694ea8ba0d fsverity: pass digest size and hash of the all-zeroes block to ->write
@@ Commit message
hashes of zeroed data blocks. XFS will use this to decide if it want to
store tree block full of these hashes.
+ Signed-off-by: Andrey Albershteyn <aalbersh@kernel.org>
Reviewed-by: "Darrick J. Wong" <djwong@kernel.org>
Acked-by: Eric Biggers <ebiggers@kernel.org>
Acked-by: David Sterba <dsterba@suse.com>
- Signed-off-by: Andrey Albershteyn <aalbersh@kernel.org>
## fs/btrfs/verity.c ##
@@ fs/btrfs/verity.c: static struct page *btrfs_read_merkle_tree_page(struct inode *inode,
3: 363bb4311e70 = 4: 5732f007e676 fsverity: hoist pagecache_read from f2fs/ext4 to fsverity
4: 159c890b697c ! 5: 9928ceefe211 fsverity: don't allow setting DAX file attribute on fsverity files
@@ Commit message
Note, that the only other filesystem supporting DAX and fsverity is
ext4, and ext4 does check for this case.
+ Signed-off-by: Andrey Albershteyn <aalbersh@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: "Darrick J. Wong" <djwong@kernel.org>
Reviewed-by: Eric Biggers <ebiggers@kernel.org>
- Signed-off-by: Andrey Albershteyn <aalbersh@kernel.org>
## fs/file_attr.c ##
@@ fs/file_attr.c: static int fileattr_set_prepare(struct inode *inode,
5: 4989457dc89c ! 6: 8f866da8730c fsverity: hoist statx reporting of fs-verity flag
@@ Commit message
Fixes: 146054090b08 ("btrfs: initial fsverity support")
Cc: stable@vger.kernel.org
+ Signed-off-by: Andrey Albershteyn <aalbersh@kernel.org>
Acked-by: Eric Biggers <ebiggers@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: "Darrick J. Wong" <djwong@kernel.org>
- Signed-off-by: Andrey Albershteyn <aalbersh@kernel.org>
## fs/btrfs/inode.c ##
@@ fs/btrfs/inode.c: static int btrfs_getattr(struct mnt_idmap *idmap,
6: 95e50d365df7 = 7: d93e466c36fd xfs: introduce fsverity on-disk changes
7: bf0fbecea27a = 8: 4bcf1275fa38 xfs: don't allow to enable DAX on fs-verity sealed inode
8: ac7fa296202d ! 9: 082d5f39ae5a xfs: disable direct read path for fs-verity files
@@ Commit message
through the DIO path.
Signed-off-by: Darrick J. Wong <djwong@kernel.org>
- Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Andrey Albershteyn <aalbersh@kernel.org>
+ Reviewed-by: Christoph Hellwig <hch@lst.de>
## fs/xfs/xfs_file.c ##
@@
9: 67aeb55c4031 ! 10: 21b92f51fd5e xfs: don't report dio_mem_align and dio_offset_align for fsverity files
@@ Commit message
to the buffered IO is used in this case. The zero alignment values also
mean that DIO is not supported on this file, see statx(2).
+ Signed-off-by: Andrey Albershteyn <aalbersh@kernel.org>
Acked-by: Eric Biggers <ebiggers@kernel.org>
Reviewed-by: "Darrick J. Wong" <djwong@kernel.org>
- Signed-off-by: Andrey Albershteyn <aalbersh@kernel.org>
## fs/xfs/xfs_iops.c ##
@@
10: 4dae04bdd7f3 ! 11: 929a7172c341 xfs: handle fsverity I/O in write/read path
@@ Commit message
Introduce a new inode flag meaning that merkle tree is being build on
the inode.
+ Signed-off-by: Andrey Albershteyn <aalbersh@kernel.org>
Reviewed-by: "Darrick J. Wong" <djwong@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
- Signed-off-by: Andrey Albershteyn <aalbersh@kernel.org>
## fs/xfs/Makefile ##
@@ fs/xfs/Makefile: xfs-$(CONFIG_XFS_POSIX_ACL) += xfs_acl.o
@@ fs/xfs/libxfs/xfs_bmap.c: xfs_bmapi_convert_one_delalloc(
*/
if (!isnullstartblock(bma.got.br_startblock)) {
+ if (xfs_iflags_test(ip, XFS_VERITY_CONSTRUCTION) &&
-+ XFS_FSB_TO_B(mp, bma.got.br_startoff) >=
-+ xfs_fsverity_metadata_offset(ip))
++ offset >= xfs_fsverity_metadata_offset(ip))
+ flags |= IOMAP_F_FSVERITY;
xfs_bmbt_to_iomap(ip, iomap, &bma.got, 0, flags,
xfs_iomap_inode_sequence(ip, flags));
@@ fs/xfs/libxfs/xfs_bmap.c: xfs_bmapi_convert_one_delalloc(
XFS_STATS_INC(mp, xs_xstrat_quick);
+ if (xfs_iflags_test(ip, XFS_VERITY_CONSTRUCTION) &&
-+ XFS_FSB_TO_B(mp, bma.got.br_startoff) >=
-+ xfs_fsverity_metadata_offset(ip))
++ offset >= xfs_fsverity_metadata_offset(ip))
+ flags |= IOMAP_F_FSVERITY;
+
ASSERT(!isnullstartblock(bma.got.br_startblock));
@@ fs/xfs/xfs_iomap.c: xfs_direct_write_iomap_begin(
/*
* COW writes may allocate delalloc space or convert unwritten COW
* extents, so we need to make sure to take the lock exclusively here.
+@@ fs/xfs/xfs_iomap.c: xfs_direct_write_iomap_begin(
+ trace_xfs_iomap_found(ip, offset, length - offset, XFS_COW_FORK, &cmap);
+ if (imap.br_startblock != HOLESTARTBLOCK) {
+ seq = xfs_iomap_inode_sequence(ip, 0);
+- error = xfs_bmbt_to_iomap(ip, srcmap, &imap, flags, 0, seq);
++ error = xfs_bmbt_to_iomap(ip, srcmap, &imap, flags,
++ iomap_flags & IOMAP_F_FSVERITY, seq);
+ if (error)
+ goto out_unlock;
+ }
@@ fs/xfs/xfs_iomap.c: xfs_zoned_direct_write_iomap_begin(
return error;
}
@@ fs/xfs/xfs_iomap.c: xfs_buffered_write_iomap_begin(
/* we can't use delayed allocations when using extent size hints */
if (xfs_get_extsz_hint(ip))
+@@ fs/xfs/xfs_iomap.c: xfs_buffered_write_iomap_begin(
+
+ found_cow:
+ if (imap.br_startoff <= offset_fsb) {
+- error = xfs_bmbt_to_iomap(ip, srcmap, &imap, flags, 0,
++ error = xfs_bmbt_to_iomap(ip, srcmap, &imap, flags,
++ iomap_flags & IOMAP_F_FSVERITY,
+ xfs_iomap_inode_sequence(ip, 0));
+ if (error)
+ goto out_unlock;
@@ fs/xfs/xfs_iomap.c: xfs_read_iomap_begin(
bool shared = false;
unsigned int lockmode = XFS_ILOCK_SHARED;
11: 79f81266cd22 ! 12: db144b392a91 xfs: use read ioend for fsverity data verification
@@ Commit message
Add a simple helper to check that this is not fsverity metadata but file
data that needs verification.
- Reviewed-by: "Darrick J. Wong" <djwong@kernel.org>
Signed-off-by: Andrey Albershteyn <aalbersh@kernel.org>
## fs/xfs/xfs_aops.c ##
@@ fs/xfs/xfs_fsverity.c
#include <linux/iomap.h>
+struct kmem_cache *xfs_fsverity_ioend_cache;
++mempool_t xfs_fsverity_ioend_pool;
++
++#define XFS_FSVERITY_IOEND_POOL_MIN 128
++
++/*
++ * Back the fsverity ioend allocations with a mempool so that read I/O
++ * completion always makes forward progress and cannot deadlock
++ */
++int
++xfs_fsverity_init(void)
++{
++ return mempool_init_slab_pool(&xfs_fsverity_ioend_pool,
++ XFS_FSVERITY_IOEND_POOL_MIN, xfs_fsverity_ioend_cache);
++}
++
++void
++xfs_fsverity_exit(void)
++{
++ mempool_exit(&xfs_fsverity_ioend_pool);
++}
+
loff_t
xfs_fsverity_metadata_offset(
@@ fs/xfs/xfs_fsverity.h
#include "xfs_platform.h"
+#include <linux/iomap.h>
++#include <linux/mempool.h>
#ifdef CONFIG_FS_VERITY
++int xfs_fsverity_init(void);
++void xfs_fsverity_exit(void);
loff_t xfs_fsverity_metadata_offset(const struct xfs_inode *ip);
+bool xfs_fsverity_is_file_data(const struct xfs_inode *ip, loff_t offset);
#else
++static inline int xfs_fsverity_init(void)
++{
++ return 0;
++}
++static inline void xfs_fsverity_exit(void)
++{
++}
static inline loff_t xfs_fsverity_metadata_offset(const struct xfs_inode *ip)
{
WARN_ON_ONCE(1);
@@ fs/xfs/xfs_fsverity.h
+};
+
+extern struct kmem_cache *xfs_fsverity_ioend_cache;
++extern mempool_t xfs_fsverity_ioend_pool;
+
#endif /* __XFS_FSVERITY_H__ */
@@ fs/xfs/xfs_ioend.c
+ struct iomap_ioend *ioend = fsv_ioend->ioend;
+ struct bio *bio = &ioend->io_bio;
+
-+ kmem_cache_free(xfs_fsverity_ioend_cache, fsv_ioend);
++ mempool_free(fsv_ioend, &xfs_fsverity_ioend_pool);
+
+ if (!bio->bi_status)
+ fsverity_verify_bio(ioend->io_vi, bio);
@@ fs/xfs/xfs_ioend.c: xfs_end_io_read(
}
+ /*
-+ * If we have fsverity and block device integrity attached to this bio,
-+ * we need to run fsverity verification of data folios from a separate
-+ * fsverity workqueue. This is necessary to avoid deadlocking due to
-+ * fsverity issuing more reads of fsverity metadata which would be
-+ * processed by the same worker in the BIO completion workqueue.
-+ *
-+ * Without block device integrity, fsverity metadata IO will not use
-+ * ioends for completion.
++ * If we have fsverity on this bio, we need to run fsverity verification
++ * of data folios from a separate fsverity workqueue. This is necessary
++ * to avoid deadlocking due to fsverity issuing more reads of fsverity
++ * metadata which would be processed by the same worker in the BIO
++ * completion workqueue.
+ */
+ if (IS_ENABLED(CONFIG_FS_VERITY) && !error && ioend->io_vi &&
+ xfs_fsverity_is_file_data(ip, ioend->io_offset)) {
-+ if (ioend->io_flags & IOMAP_IOEND_INTEGRITY) {
-+ fsv_ioend = kmem_cache_zalloc(xfs_fsverity_ioend_cache,
-+ GFP_KERNEL);
-+ if (!fsv_ioend) {
-+ iomap_finish_ioends(ioend, -ENOMEM);
-+ return;
-+ }
-+ fsv_ioend->ioend = ioend;
-+ INIT_WORK(&fsv_ioend->work, xfs_end_fsverity_io_read);
++ fsv_ioend = mempool_alloc(&xfs_fsverity_ioend_pool,
++ GFP_NOFS);
++ fsv_ioend->ioend = ioend;
++ INIT_WORK(&fsv_ioend->work, xfs_end_fsverity_io_read);
+
-+ fsverity_enqueue_verify_work(&fsv_ioend->work);
-+ return;
-+ }
-+
-+ fsverity_verify_bio(ioend->io_vi, &ioend->io_bio);
-+ error = blk_status_to_errno(ioend->io_bio.bi_status);
++ fsverity_enqueue_verify_work(&fsv_ioend->work);
++ return;
+ }
+
iomap_finish_ioends(ioend, error);
@@ fs/xfs/xfs_super.c: xfs_init_caches(void)
+ sizeof(struct xfs_fsverity_ioend),
+ 0, 0, NULL);
+ if (!xfs_fsverity_ioend_cache)
-+ goto out_destroy_fsverity_ioend_cache;
++ goto out_destroy_parent_args_cache;
+#endif
+
return 0;
+#ifdef CONFIG_FS_VERITY
-+ out_destroy_fsverity_ioend_cache:
-+ kmem_cache_destroy(xfs_fsverity_ioend_cache);
++ out_destroy_parent_args_cache:
++ kmem_cache_destroy(xfs_parent_args_cache);
+#endif
out_destroy_xmi_cache:
kmem_cache_destroy(xfs_xmi_cache);
@@ fs/xfs/xfs_super.c: xfs_destroy_caches(void)
kmem_cache_destroy(xfs_parent_args_cache);
kmem_cache_destroy(xfs_xmd_cache);
kmem_cache_destroy(xfs_xmi_cache);
+@@ fs/xfs/xfs_super.c: init_xfs_fs(void)
+ if (error)
+ goto out;
+
+- error = xfs_init_workqueues();
++ error = xfs_fsverity_init();
+ if (error)
+ goto out_destroy_caches;
+
++ error = xfs_init_workqueues();
++ if (error)
++ goto out_fsverity_exit;
++
+ error = xfs_mru_cache_init();
+ if (error)
+ goto out_destroy_wq;
+@@ fs/xfs/xfs_super.c: init_xfs_fs(void)
+ xfs_mru_cache_uninit();
+ out_destroy_wq:
+ xfs_destroy_workqueues();
++ out_fsverity_exit:
++ xfs_fsverity_exit();
+ out_destroy_caches:
+ xfs_destroy_caches();
+ out:
+@@ fs/xfs/xfs_super.c: exit_xfs_fs(void)
+ xfs_cleanup_procfs();
+ xfs_mru_cache_uninit();
+ xfs_destroy_workqueues();
++ xfs_fsverity_exit();
+ xfs_destroy_caches();
+ xfs_uuid_table_free();
+ }
12: 7b7e33fef0ab ! 13: 5f00c1287b5e xfs: add XFS_BMAPI_UNWRITTEN to unmap unwritten extents in __xfs_bunmapi()
@@ Commit message
written ones in place. This will be used in following patch to clean up
unwritten extents on fsverity inodes.
- Reviewed-by: "Darrick J. Wong" <djwong@kernel.org>
Signed-off-by: Andrey Albershteyn <aalbersh@kernel.org>
+ Reviewed-by: "Darrick J. Wong" <djwong@kernel.org>
## fs/xfs/libxfs/xfs_bmap.c ##
@@ fs/xfs/libxfs/xfs_bmap.c: __xfs_bunmapi(
@@ fs/xfs/libxfs/xfs_bmap.c: __xfs_bunmapi(
del.br_blockcount = end + 1 - del.br_startoff;
+ if ((flags & XFS_BMAPI_UNWRITTEN) &&
-+ del.br_state != XFS_EXT_UNWRITTEN)
++ del.br_state != XFS_EXT_UNWRITTEN)
+ goto skip;
+
if (!isrt || (flags & XFS_BMAPI_REMAP))
13: 44817f70a46b ! 14: 9a82d542d940 xfs: don't remove written extents past EOF on fsverity inodes
@@ Commit message
undergoing merkle tree construction need to be skipped in case reclaim
takes place.
- Reviewed-by: "Darrick J. Wong" <djwong@kernel.org>
Signed-off-by: Andrey Albershteyn <aalbersh@kernel.org>
+ Reviewed-by: "Darrick J. Wong" <djwong@kernel.org>
## fs/xfs/xfs_bmap_util.c ##
@@
@@ fs/xfs/xfs_bmap_util.c: xfs_can_free_eofblocks(
return false;
+ /*
-+ * Don't clean fsverity inodes which have merkle tree being built, the
++ * Don't clean fsverity inodes as they already have been cleaned up and
++ * are read-only. Skip inodes which have merkle tree being built, the
+ * merkle tree is written beyond EOF
+ */
-+ if (xfs_iflags_test(ip, XFS_VERITY_CONSTRUCTION))
++ if (fsverity_active(VFS_IC(ip)) ||
++ xfs_iflags_test(ip, XFS_VERITY_CONSTRUCTION))
+ return false;
+
/*
@@ fs/xfs/xfs_bmap_util.c: xfs_free_eofblocks(
xfs_ilock(ip, XFS_ILOCK_EXCL);
xfs_trans_ijoin(tp, ip, 0);
++ /*
++ * While fs-verity writes metadata after EOF, it can leave unwritten
++ * preallocations. Clear all that out.
++ */
+ if (has_verity)
+ bmapi_flags |= XFS_BMAPI_UNWRITTEN;
+
14: 6c1468facf03 ! 15: 420fb1a97664 xfs: add fs-verity support
@@ Commit message
Pro-actively remove any unwritten extents as we use last extent to
locate descriptor.
- Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Andrey Albershteyn <aalbersh@kernel.org>
+ Reviewed-by: Christoph Hellwig <hch@lst.de>
## fs/xfs/xfs_fsverity.c ##
@@
@@ fs/xfs/xfs_fsverity.c
+#include <linux/pagemap.h>
struct kmem_cache *xfs_fsverity_ioend_cache;
-
+ mempool_t xfs_fsverity_ioend_pool;
@@ fs/xfs/xfs_fsverity.c: xfs_fsverity_is_file_data(
return fsverity_active(VFS_IC(ip)) &&
offset < xfs_fsverity_metadata_offset(ip);
@@ fs/xfs/xfs_fsverity.c: xfs_fsverity_is_file_data(
+ uint32_t blocksize = i_blocksize(VFS_I(ip));
+ xfs_fileoff_t last_block_offset;
+
-+ ASSERT(inode->i_flags & S_VERITY);
-+ xfs_ilock(ip, XFS_ILOCK_SHARED);
++ xfs_ilock(ip, XFS_ILOCK_EXCL);
++ /*
++ * Serialize reading of inode->i_flags with xfs_scrub clearing of this
++ * flag if inode is corrupted.
++ */
++ if (!(inode->i_flags & S_VERITY)) {
++ xfs_iunlock(ip, XFS_ILOCK_EXCL);
++ return -ENODATA;
++ }
+ error = xfs_bmap_last_extent(NULL, ip, XFS_DATA_FORK, &rec, &is_empty);
-+ xfs_iunlock(ip, XFS_ILOCK_SHARED);
++ xfs_iunlock(ip, XFS_ILOCK_EXCL);
+ if (error)
+ return error;
+
@@ fs/xfs/xfs_fsverity.c: xfs_fsverity_is_file_data(
+ return error;
+ }
+
-+ xfs_ilock(ip, XFS_ILOCK_EXCL);
-+ xfs_trans_ijoin(tp, ip, 0);
-+
+ truncate_inode_pages(VFS_I(ip)->i_mapping, XFS_ISIZE(ip));
+
++ xfs_ilock(ip, XFS_ILOCK_EXCL);
++ xfs_trans_ijoin(tp, ip, 0);
++
+ /*
+ * We remove post EOF data, no need to update i_size as fsverity
+ * didn't move i_size in the first place
@@ fs/xfs/xfs_fsverity.c: xfs_fsverity_is_file_data(
+ return error;
+}
+
++static int
++xfs_fsverity_reset_inode(
++ struct xfs_inode *ip)
++{
++ int error;
++ struct xfs_mount *mp = ip->i_mount;
++ struct xfs_trans *tp;
++
++ error = xfs_fsverity_delete_metadata(ip);
++ if (error)
++ return error;
++
++ /*
++ * First, let's clean in-memory fsverity flag and then reset it on the
++ * disk
++ */
++ inode_set_flags(VFS_I(ip), 0, S_VERITY);
++
++ /*
++ * Set fsverity inode flag
++ */
++ error = xfs_trans_alloc_inode(ip, &M_RES(mp)->tr_ichange,
++ 0, 0, false, &tp);
++ if (error)
++ return error;
++
++ ip->i_diflags2 &= ~XFS_DIFLAG2_VERITY;
++
++ xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
++ xfs_trans_set_sync(tp);
++
++ error = xfs_trans_commit(tp);
++ xfs_iunlock(ip, XFS_ILOCK_EXCL);
++ return error;
++}
+
+/*
+ * Prepare to enable fsverity by clearing old metadata.
@@ fs/xfs/xfs_fsverity.c: xfs_fsverity_is_file_data(
+ if (IS_DAX(inode) || ip->i_diflags2 & XFS_DIFLAG2_DAX)
+ return -EINVAL;
+
++ /*
++ * fs-verity stores the Merkle tree past EOF in units of the filesystem
++ * block size, so it cannot support realtime files whose allocation unit
++ * (extent size) is larger than the block size.
++ */
++ if (xfs_inode_has_bigrtalloc(ip))
++ return -EINVAL;
++
+ if (inode->i_size > XFS_FSVERITY_LARGEST_FILE)
+ return -EFBIG;
+
@@ fs/xfs/xfs_fsverity.c: xfs_fsverity_is_file_data(
+ xfs_assert_ilocked(ip, XFS_IOLOCK_EXCL);
+
+ /* fs-verity failed, just cleanup */
-+ if (desc == NULL) {
-+ error = xfs_fsverity_delete_metadata(ip);
++ if (desc == NULL)
+ goto out;
-+ }
+
+ error = xfs_fsverity_write_descriptor(file, desc, desc_size,
+ merkle_tree_size);
@@ fs/xfs/xfs_fsverity.c: xfs_fsverity_is_file_data(
+ if (error) {
+ int error2;
+
-+ error2 = xfs_fsverity_delete_metadata(ip);
++ error2 = xfs_fsverity_reset_inode(ip);
+ if (error2)
+ xfs_alert(ip->i_mount,
+"ino 0x%llx failed to clean up new fsverity metadata, err %d",
@@ fs/xfs/xfs_fsverity.c: xfs_fsverity_is_file_data(
+ generic_readahead_merkle_tree(inode, index, nr_pages);
+}
+
-+/*
-+ * Write a merkle tree block.
-+ */
-+static int
-+xfs_fsverity_write_merkle(
-+ struct file *file,
++static inline bool
++xfs_fsverity_is_hashes_of_zeroed_blocks(
++ struct xfs_inode *ip,
+ const void *buf,
-+ u64 pos,
+ unsigned int size,
+ const u8 *zero_digest,
+ unsigned int digest_size)
+{
-+ struct inode *inode = file_inode(file);
-+ struct xfs_inode *ip = XFS_I(inode);
-+ loff_t position = pos +
-+ xfs_fsverity_metadata_offset(ip);
-+
-+ if (position + size > inode->i_sb->s_maxbytes)
-+ return -EFBIG;
-+
+ /*
+ * If this is a block full of hashes of zeroed blocks, don't bother
+ * storing the block. We can synthesize them later.
@@ fs/xfs/xfs_fsverity.c: xfs_fsverity_is_file_data(
+ *
+ * Iomap won't know about these empty blocks.
+ */
-+ if (size == ip->i_mount->m_sb.sb_blocksize &&
-+ /*
-+ * First digest is zero_digest
-+ */
-+ memcmp(buf, zero_digest, digest_size) == 0 &&
-+ /*
-+ * Every digest is same as previous, thus all are
-+ * zero_digest
-+ */
-+ memcmp(buf + digest_size, buf, size - digest_size) == 0)
++ if (size != ip->i_mount->m_sb.sb_blocksize)
++ return false;
++ /*
++ * First digest is zero_digest
++ */
++ if (memcmp(buf, zero_digest, digest_size))
++ return false;
++ /*
++ * Every digest is same as previous, thus all are
++ * zero_digest
++ */
++ return memcmp(buf + digest_size, buf, size - digest_size) == 0;
++}
++
++/*
++ * Write a merkle tree block.
++ */
++static int
++xfs_fsverity_write_merkle(
++ struct file *file,
++ const void *buf,
++ u64 pos,
++ unsigned int size,
++ const u8 *zero_digest,
++ unsigned int digest_size)
++{
++ struct inode *inode = file_inode(file);
++ struct xfs_inode *ip = XFS_I(inode);
++ loff_t position = pos +
++ xfs_fsverity_metadata_offset(ip);
++
++ if (position + size > inode->i_sb->s_maxbytes)
++ return -EFBIG;
++
++ if (xfs_fsverity_is_hashes_of_zeroed_blocks(ip, buf, size, zero_digest,
++ digest_size))
+ return 0;
+
+ return iomap_fsverity_write(file, position, size, buf,
@@ fs/xfs/xfs_fsverity.h
#include "xfs_platform.h"
#include <linux/iomap.h>
+#include <linux/fsverity.h>
+ #include <linux/mempool.h>
#ifdef CONFIG_FS_VERITY
+extern const struct fsverity_operations xfs_fsverity_ops;
+ int xfs_fsverity_init(void);
+ void xfs_fsverity_exit(void);
loff_t xfs_fsverity_metadata_offset(const struct xfs_inode *ip);
- bool xfs_fsverity_is_file_data(const struct xfs_inode *ip, loff_t offset);
- #else
## fs/xfs/xfs_message.c ##
@@ fs/xfs/xfs_message.c: xfs_warn_experimental(
15: 78214f0c18ed = 16: 00314b4a38e2 xfs: initialize fs-verity on file open
16: 1cda98e462f0 = 17: d37e9d9a991e xfs: add fs-verity ioctls
17: c772780887b6 = 18: c21e90b7ac09 xfs: advertise fs-verity being available on filesystem
18: 2a1811e69360 ! 19: 6efa9e6690ee xfs: check and repair the verity inode flag state
@@ Commit message
opening the file, so clearing the flag will not compromise that model.
Signed-off-by: Darrick J. Wong <djwong@kernel.org>
- Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Andrey Albershteyn <aalbersh@kernel.org>
+ Reviewed-by: Christoph Hellwig <hch@lst.de>
## fs/xfs/scrub/common.c ##
@@
@@ fs/xfs/scrub/common.c: xchk_inode_count_blocks(
+ break;
+ case -ENODATA:
+ case -EMSGSIZE:
-+ case -EINVAL:
+ case -EFSCORRUPTED:
-+ case -EFBIG:
+ case -ERANGE:
+ case -EBADMSG:
+ /*
19: 942e4a193836 = 20: e01d0c1aa284 xfs: introduce health state for corrupted fsverity metadata
20: 94fdc1d0ed15 = 21: 0ebd5899bc53 xfs: enable ro-compat fs-verity flag
--
2.54.0
WARNING: multiple messages have this Message-ID (diff)
From: Andrey Albershteyn via Linux-f2fs-devel <linux-f2fs-devel@lists.sourceforge.net>
To: djwong@kernel.org, ebiggers@kernel.org, hch@lst.de,
Carlos Maiolino <cem@kernel.org>
Cc: fsverity@lists.linux.dev,
Andrey Albershteyn <aalbersh@kernel.org>,
david@fromorbit.com, linux-unionfs@vger.kernel.org,
linux-f2fs-devel@lists.sourceforge.net,
linux-xfs@vger.kernel.org, linux-fsdevel@vger.kernel.org,
linux-ext4@vger.kernel.org, linux-btrfs@vger.kernel.org
Subject: [f2fs-dev] [PATCH v17 00/21] fs-verity support for XFS with post EOF merkle tree
Date: Sat, 3 Oct 2026 00:36:41 +0200 [thread overview]
Message-ID: <20261002223705.2175542-1-aalbersh@kernel.org> (raw)
Hi all,
This is next revision of fsverity for XFS.
Patches without review:
[PATCH v17 12/21] xfs: use read ioend for fsverity data verification
This series based on block/for-next (has lazy-bounce series)
block/for-next:
https://git.kernel.org/pub/scm/linux/kernel/git/axboe/linux.git/log/?h=for-next
kernel:
https://git.kernel.org/pub/scm/linux/kernel/git/aalbersh/xfs-linux.git/log/?h=fsverity
xfsprogs:
https://git.kernel.org/pub/scm/linux/kernel/git/aalbersh/xfsprogs-dev.git/log/?h=fsverity
xfstests:
https://git.kernel.org/pub/scm/linux/kernel/git/aalbersh/xfstests-dev.git/log/?h=fsverity
v16:
https://lore.kernel.org/fsverity/arJC542mXklAeswE@aalbersh-thinkpadx1carbongen13.rmtcz.csb/T/#t
v15:
https://lore.kernel.org/fsverity/20260817070240.GA17371@lst.de/T/#t
v14:
https://lore.kernel.org/fsverity/anmFWhPNOqe4uyht@aalbersh-thinkpadx1carbongen13.rmtcz.csb/T/#t
v13:
https://lore.kernel.org/fsverity/20260721184346.416657-1-aalbersh@kernel.org/T/#t
v12:
https://lore.kernel.org/fsverity/al8xgOwueDOzGakK@aalbersh-thinkpadx1carbongen13.rmtcz.csb/T/#t
v11:
https://lore.kernel.org/all/20260710085256.3464201-1-aalbersh@kernel.org/
v10:
https://lore.kernel.org/fsverity/20260520123722.405752-1-aalbersh@kernel.org/#r
v9:
https://lore.kernel.org/fsverity/20260428083332.768693-1-aalbersh@kernel.org/#r
To: djwong@kernel.org
To: ebiggers@kernel.org
To: hch@lst.de
To: Carlos Maiolino <cem@kernel.org>
Cc: fsverity@lists.linux.dev
Cc: linux-fsdevel@vger.kernel.org
Cc: linux-xfs@vger.kernel.org
Cc: linux-unionfs@vger.kernel.org
Cc: linux-ext4@vger.kernel.org
Cc: linux-f2fs-devel@lists.sourceforge.net
Cc: linux-btrfs@vger.kernel.org
Cc: david@fromorbit.com
---
Changes in v17:
- Add mempool for fsverity ioends cache
- Add xfs_fsverity_reset_inode() as a common clean up function
- Changed ILOCK_SHARED to ILOCK_EXCL for xfs_bmap_last_extent()
- Swap order of truncate_inode_pages() and ilock() due to ABBA
- Add xfs_fsverity_is_hashes_of_zeroed_blocks() helper
- Removed EINVAL and EFBIG from scrub as ambiguous
Changes in v16:
- Rebase to block/for-next
- Removed work_struct from ioend in favor of kmem_cache structs
- Minor adjustments from v15 review
- Skip written extents in lower level of __xfs_bunmapi()
Changes in v15:
- Pull BIO in task context patches
- Drop flag argument in xfs_free_eofblocks()
- Call xfs_free_eofblocks() on fsverity inodes
- Comments and commit messages updates
- Rebased to v7.2-rc7
- Dropped patch for fsverity_fill_zerohash() with highmem optimization
Changes in v14:
- Rebase to lazy-bounce@hch-misc
- Adjust read ioends to BIO in task context flow
- MMAPLOCK/sb_internal deadlock fix reported by sashiko
- Add missing delalloc clean up in verity_end_enable
- Use xfs_free_eofblocks() instead of writing own clean up routine
- Modify xfs_free_eofblocks() to be able to clean unwritten only
- Dropped fix patch for truncate/set_size check
- Various minor code and #include rearrangements for bisecting
Changes in v13:
- Hoisted statx reporting to common code
- Added read ioend sorted for worker self-deadlock fix
- Adjusted fsverity flags in zoned write path
Changes in v12:
- Refactored xfs_fsverity_cancel_unwritten()
- Switched to using inode_set_flags()
- Add a lock for COW fork reading
- Add pagecache truncation in cleanup path
- Added ERANGE and EBADMSG to fsverity scrub handling
- Add missing XFS_FSVERITY_CONSTRUCTION in various xfs_iomap
- Rebase to -rc3
Changes in v11:
- Drop wrong overlayfs patch
- Drop already merged iomap and fsverity patches
- Update to I_INO() use instead of ip->i_ino
- Sashiko.dev fixes. See list of issues below.
Changes in v10:
- Rebase to v7.1-rc3 with relevant adjustments
- Initialize ioend->io_vi to NULL to not get write work onto verity wq
- Range diff below
Changes in v9:
- Fix fsverity_fill_zerohash() parameter names
- A few fixes found by sashiko.dev:
- Replace ip->i_mount->m_attr_geo->blksize with m_sb.sb_blocksize
- Don't call xfs_trans_cancel() after xfs_trans_commit() in
xfs_fsverity_end_enable()
- Call xfs_fsverity_delete_metadata() if verity enable failed
- Change start/end type from xfs_fileoff_t to loff_t
- Return xfs_trans_commit() error from
xfs_fsverity_cancel_unwritten()
Changes in v8:
- Return fsverity_ensure_verity_info() errors from
ovl_ensure_verity_loaded()
Changes in v7:
- Move kerneldoc to fsverity_ensure_verity_info() definition
- Drop patch adding XFS traces
- Fix overly long line in the comment
- Make order of fserror and fsverity_error consistent
- Add overlay patch converting to fsverity_ensure_verity_info()
Changes in v6:
- Removed stub for fsverity_ensure_verity_info() as it's optimized out
- Rename fsverity_folio_zero_hash() to fsverify_fill_zerohash()
- Merge patches 8 to 10 into one
- Merge patch gerating zero_hash and fsverity_fill_zerohash() into one
- Add kerneldoc to fsverity_ensure_verity_info()
- Add comments to iomap_block_needs_zeroing()
Changes in v5:
- Add fserror_report_data_lost() for data blocks in page spanning EOF
- Issue fsverity metadata readahead in data readahead
- iomap_fsverity_write() return type fix
- Use of S_ISREG(mode)
- Make 65536 #define instead of open-coded
- Use transaction per unwritten extent removal
- Fetch fsverity_info for all fsverity metadata
- Revert fsverity_folio_zero_hash() stub as used in iomap
- Extend cancel_unwritten to whole file range to remove cow leftovers
- Drop delayed allocation on the COW fork on fsverity completion
Changes in v4:
- Use fserror interface in fsverity instead of fs callback
- Hoist pagecache_read from f2fs/ext4 to fsverity
- Refactor iomap code
- Fetch fsverity_info only for file data and merkle tree holes
- Do not disable preallocation, remove unwritten extents instead
- Offload fsverity hash I/O to fsverity workqueue in read path
- Store merkle tree at round_up(i_size, 64k)
- Add a spacing between merkle tree and fsverity descriptor as next 64k
aligned block
- Squash helpers into first user commits
- Squash on-disk format changes into single commit
- Drop different offset for pagecache/on-disk
- Don't zero out pages in higher order folios in write path
- Link to v3: https://lore.kernel.org/fsverity/20260217231937.1183679-1-aalbersh@kernel.org/T/#t
Changes in v3:
- Different on-disk and pagecache offset
- Use read path ioends
- Switch to hashtable fsverity info
- Synthesize merkle tree blocks full of zeroes
- Other minor refactors
- Link to v2: https://lore.kernel.org/fsverity/20260114164210.GO15583@frogsfrogsfrogs/T/#t
Changes in v2:
- Move to VFS interface for merkle tree block reading
- Drop patchset for per filesystem workqueues
- Change how offsets of the descriptor and tree metadata is calculated
- Store fs-verity descriptor in data fork side by side with merkle tree
- Simplify iomap changes, remove interface for post eof read/write
- Get rid of extended attribute implementation
- Link to v1: https://lore.kernel.org/r/20250728-fsverity-v1-0-9e5443af0e34@kernel.org
Andrey Albershteyn (19):
fsverity: report validation errors through fserror to fsnotify
fsverity: expose ensure_fsverity_info()
fsverity: pass digest size and hash of the all-zeroes block to ->write
fsverity: hoist pagecache_read from f2fs/ext4 to fsverity
fsverity: don't allow setting DAX file attribute on fsverity files
fsverity: hoist statx reporting of fs-verity flag
xfs: introduce fsverity on-disk changes
xfs: don't allow to enable DAX on fs-verity sealed inode
xfs: disable direct read path for fs-verity files
xfs: don't report dio_mem_align and dio_offset_align for fsverity
files
xfs: handle fsverity I/O in write/read path
xfs: use read ioend for fsverity data verification
xfs: add XFS_BMAPI_UNWRITTEN to unmap unwritten extents in
__xfs_bunmapi()
xfs: don't remove written extents past EOF on fsverity inodes
xfs: add fs-verity support
xfs: initialize fs-verity on file open
xfs: add fs-verity ioctls
xfs: introduce health state for corrupted fsverity metadata
xfs: enable ro-compat fs-verity flag
Darrick J. Wong (2):
xfs: advertise fs-verity being available on filesystem
xfs: check and repair the verity inode flag state
fs/btrfs/inode.c | 3 -
fs/btrfs/verity.c | 6 +-
fs/ext4/inode.c | 5 +-
fs/ext4/verity.c | 36 +--
fs/f2fs/file.c | 5 +-
fs/f2fs/verity.c | 34 +--
fs/file_attr.c | 11 +-
fs/stat.c | 6 +-
fs/verity/enable.c | 4 +-
fs/verity/open.c | 26 +-
fs/verity/pagecache.c | 33 +++
fs/verity/verify.c | 4 +
fs/xfs/Makefile | 1 +
fs/xfs/libxfs/xfs_bmap.c | 15 +-
fs/xfs/libxfs/xfs_bmap.h | 6 +-
fs/xfs/libxfs/xfs_format.h | 35 ++-
fs/xfs/libxfs/xfs_fs.h | 2 +
fs/xfs/libxfs/xfs_health.h | 4 +-
fs/xfs/libxfs/xfs_inode_buf.c | 8 +
fs/xfs/libxfs/xfs_inode_util.c | 5 +-
fs/xfs/libxfs/xfs_sb.c | 4 +
fs/xfs/scrub/common.c | 53 ++++
fs/xfs/scrub/common.h | 2 +
fs/xfs/scrub/inode.c | 7 +
fs/xfs/scrub/inode_repair.c | 36 +++
fs/xfs/xfs_aops.c | 49 +++-
fs/xfs/xfs_bmap_util.c | 31 ++-
fs/xfs/xfs_file.c | 71 +++--
fs/xfs/xfs_fsverity.c | 489 +++++++++++++++++++++++++++++++++
fs/xfs/xfs_fsverity.h | 47 ++++
fs/xfs/xfs_health.c | 1 +
fs/xfs/xfs_inode.h | 6 +
fs/xfs/xfs_ioctl.c | 14 +
fs/xfs/xfs_ioend.c | 53 +++-
fs/xfs/xfs_ioend.h | 4 +-
fs/xfs/xfs_iomap.c | 37 ++-
fs/xfs/xfs_iomap.h | 5 +-
fs/xfs/xfs_iops.c | 12 +-
fs/xfs/xfs_message.c | 4 +
fs/xfs/xfs_message.h | 1 +
fs/xfs/xfs_mount.h | 4 +
fs/xfs/xfs_super.c | 31 ++-
include/linux/fsverity.h | 10 +-
43 files changed, 1079 insertions(+), 141 deletions(-)
create mode 100644 fs/xfs/xfs_fsverity.c
create mode 100644 fs/xfs/xfs_fsverity.h
Range-diff against v16:
-: ------------ > 1: c14aea60fb61 fsverity: report validation errors through fserror to fsnotify
1: d234049f2fc6 ! 2: ba2ec9993a12 fsverity: expose ensure_fsverity_info()
@@ Commit message
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
Acked-by: Eric Biggers <ebiggers@kernel.org>
- Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Andrey Albershteyn <aalbersh@kernel.org>
+ Reviewed-by: Christoph Hellwig <hch@lst.de>
## fs/verity/open.c ##
@@ fs/verity/open.c: int fsverity_get_descriptor(struct inode *inode,
2: ce8681774085 ! 3: 68694ea8ba0d fsverity: pass digest size and hash of the all-zeroes block to ->write
@@ Commit message
hashes of zeroed data blocks. XFS will use this to decide if it want to
store tree block full of these hashes.
+ Signed-off-by: Andrey Albershteyn <aalbersh@kernel.org>
Reviewed-by: "Darrick J. Wong" <djwong@kernel.org>
Acked-by: Eric Biggers <ebiggers@kernel.org>
Acked-by: David Sterba <dsterba@suse.com>
- Signed-off-by: Andrey Albershteyn <aalbersh@kernel.org>
## fs/btrfs/verity.c ##
@@ fs/btrfs/verity.c: static struct page *btrfs_read_merkle_tree_page(struct inode *inode,
3: 363bb4311e70 = 4: 5732f007e676 fsverity: hoist pagecache_read from f2fs/ext4 to fsverity
4: 159c890b697c ! 5: 9928ceefe211 fsverity: don't allow setting DAX file attribute on fsverity files
@@ Commit message
Note, that the only other filesystem supporting DAX and fsverity is
ext4, and ext4 does check for this case.
+ Signed-off-by: Andrey Albershteyn <aalbersh@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: "Darrick J. Wong" <djwong@kernel.org>
Reviewed-by: Eric Biggers <ebiggers@kernel.org>
- Signed-off-by: Andrey Albershteyn <aalbersh@kernel.org>
## fs/file_attr.c ##
@@ fs/file_attr.c: static int fileattr_set_prepare(struct inode *inode,
5: 4989457dc89c ! 6: 8f866da8730c fsverity: hoist statx reporting of fs-verity flag
@@ Commit message
Fixes: 146054090b08 ("btrfs: initial fsverity support")
Cc: stable@vger.kernel.org
+ Signed-off-by: Andrey Albershteyn <aalbersh@kernel.org>
Acked-by: Eric Biggers <ebiggers@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: "Darrick J. Wong" <djwong@kernel.org>
- Signed-off-by: Andrey Albershteyn <aalbersh@kernel.org>
## fs/btrfs/inode.c ##
@@ fs/btrfs/inode.c: static int btrfs_getattr(struct mnt_idmap *idmap,
6: 95e50d365df7 = 7: d93e466c36fd xfs: introduce fsverity on-disk changes
7: bf0fbecea27a = 8: 4bcf1275fa38 xfs: don't allow to enable DAX on fs-verity sealed inode
8: ac7fa296202d ! 9: 082d5f39ae5a xfs: disable direct read path for fs-verity files
@@ Commit message
through the DIO path.
Signed-off-by: Darrick J. Wong <djwong@kernel.org>
- Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Andrey Albershteyn <aalbersh@kernel.org>
+ Reviewed-by: Christoph Hellwig <hch@lst.de>
## fs/xfs/xfs_file.c ##
@@
9: 67aeb55c4031 ! 10: 21b92f51fd5e xfs: don't report dio_mem_align and dio_offset_align for fsverity files
@@ Commit message
to the buffered IO is used in this case. The zero alignment values also
mean that DIO is not supported on this file, see statx(2).
+ Signed-off-by: Andrey Albershteyn <aalbersh@kernel.org>
Acked-by: Eric Biggers <ebiggers@kernel.org>
Reviewed-by: "Darrick J. Wong" <djwong@kernel.org>
- Signed-off-by: Andrey Albershteyn <aalbersh@kernel.org>
## fs/xfs/xfs_iops.c ##
@@
10: 4dae04bdd7f3 ! 11: 929a7172c341 xfs: handle fsverity I/O in write/read path
@@ Commit message
Introduce a new inode flag meaning that merkle tree is being build on
the inode.
+ Signed-off-by: Andrey Albershteyn <aalbersh@kernel.org>
Reviewed-by: "Darrick J. Wong" <djwong@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
- Signed-off-by: Andrey Albershteyn <aalbersh@kernel.org>
## fs/xfs/Makefile ##
@@ fs/xfs/Makefile: xfs-$(CONFIG_XFS_POSIX_ACL) += xfs_acl.o
@@ fs/xfs/libxfs/xfs_bmap.c: xfs_bmapi_convert_one_delalloc(
*/
if (!isnullstartblock(bma.got.br_startblock)) {
+ if (xfs_iflags_test(ip, XFS_VERITY_CONSTRUCTION) &&
-+ XFS_FSB_TO_B(mp, bma.got.br_startoff) >=
-+ xfs_fsverity_metadata_offset(ip))
++ offset >= xfs_fsverity_metadata_offset(ip))
+ flags |= IOMAP_F_FSVERITY;
xfs_bmbt_to_iomap(ip, iomap, &bma.got, 0, flags,
xfs_iomap_inode_sequence(ip, flags));
@@ fs/xfs/libxfs/xfs_bmap.c: xfs_bmapi_convert_one_delalloc(
XFS_STATS_INC(mp, xs_xstrat_quick);
+ if (xfs_iflags_test(ip, XFS_VERITY_CONSTRUCTION) &&
-+ XFS_FSB_TO_B(mp, bma.got.br_startoff) >=
-+ xfs_fsverity_metadata_offset(ip))
++ offset >= xfs_fsverity_metadata_offset(ip))
+ flags |= IOMAP_F_FSVERITY;
+
ASSERT(!isnullstartblock(bma.got.br_startblock));
@@ fs/xfs/xfs_iomap.c: xfs_direct_write_iomap_begin(
/*
* COW writes may allocate delalloc space or convert unwritten COW
* extents, so we need to make sure to take the lock exclusively here.
+@@ fs/xfs/xfs_iomap.c: xfs_direct_write_iomap_begin(
+ trace_xfs_iomap_found(ip, offset, length - offset, XFS_COW_FORK, &cmap);
+ if (imap.br_startblock != HOLESTARTBLOCK) {
+ seq = xfs_iomap_inode_sequence(ip, 0);
+- error = xfs_bmbt_to_iomap(ip, srcmap, &imap, flags, 0, seq);
++ error = xfs_bmbt_to_iomap(ip, srcmap, &imap, flags,
++ iomap_flags & IOMAP_F_FSVERITY, seq);
+ if (error)
+ goto out_unlock;
+ }
@@ fs/xfs/xfs_iomap.c: xfs_zoned_direct_write_iomap_begin(
return error;
}
@@ fs/xfs/xfs_iomap.c: xfs_buffered_write_iomap_begin(
/* we can't use delayed allocations when using extent size hints */
if (xfs_get_extsz_hint(ip))
+@@ fs/xfs/xfs_iomap.c: xfs_buffered_write_iomap_begin(
+
+ found_cow:
+ if (imap.br_startoff <= offset_fsb) {
+- error = xfs_bmbt_to_iomap(ip, srcmap, &imap, flags, 0,
++ error = xfs_bmbt_to_iomap(ip, srcmap, &imap, flags,
++ iomap_flags & IOMAP_F_FSVERITY,
+ xfs_iomap_inode_sequence(ip, 0));
+ if (error)
+ goto out_unlock;
@@ fs/xfs/xfs_iomap.c: xfs_read_iomap_begin(
bool shared = false;
unsigned int lockmode = XFS_ILOCK_SHARED;
11: 79f81266cd22 ! 12: db144b392a91 xfs: use read ioend for fsverity data verification
@@ Commit message
Add a simple helper to check that this is not fsverity metadata but file
data that needs verification.
- Reviewed-by: "Darrick J. Wong" <djwong@kernel.org>
Signed-off-by: Andrey Albershteyn <aalbersh@kernel.org>
## fs/xfs/xfs_aops.c ##
@@ fs/xfs/xfs_fsverity.c
#include <linux/iomap.h>
+struct kmem_cache *xfs_fsverity_ioend_cache;
++mempool_t xfs_fsverity_ioend_pool;
++
++#define XFS_FSVERITY_IOEND_POOL_MIN 128
++
++/*
++ * Back the fsverity ioend allocations with a mempool so that read I/O
++ * completion always makes forward progress and cannot deadlock
++ */
++int
++xfs_fsverity_init(void)
++{
++ return mempool_init_slab_pool(&xfs_fsverity_ioend_pool,
++ XFS_FSVERITY_IOEND_POOL_MIN, xfs_fsverity_ioend_cache);
++}
++
++void
++xfs_fsverity_exit(void)
++{
++ mempool_exit(&xfs_fsverity_ioend_pool);
++}
+
loff_t
xfs_fsverity_metadata_offset(
@@ fs/xfs/xfs_fsverity.h
#include "xfs_platform.h"
+#include <linux/iomap.h>
++#include <linux/mempool.h>
#ifdef CONFIG_FS_VERITY
++int xfs_fsverity_init(void);
++void xfs_fsverity_exit(void);
loff_t xfs_fsverity_metadata_offset(const struct xfs_inode *ip);
+bool xfs_fsverity_is_file_data(const struct xfs_inode *ip, loff_t offset);
#else
++static inline int xfs_fsverity_init(void)
++{
++ return 0;
++}
++static inline void xfs_fsverity_exit(void)
++{
++}
static inline loff_t xfs_fsverity_metadata_offset(const struct xfs_inode *ip)
{
WARN_ON_ONCE(1);
@@ fs/xfs/xfs_fsverity.h
+};
+
+extern struct kmem_cache *xfs_fsverity_ioend_cache;
++extern mempool_t xfs_fsverity_ioend_pool;
+
#endif /* __XFS_FSVERITY_H__ */
@@ fs/xfs/xfs_ioend.c
+ struct iomap_ioend *ioend = fsv_ioend->ioend;
+ struct bio *bio = &ioend->io_bio;
+
-+ kmem_cache_free(xfs_fsverity_ioend_cache, fsv_ioend);
++ mempool_free(fsv_ioend, &xfs_fsverity_ioend_pool);
+
+ if (!bio->bi_status)
+ fsverity_verify_bio(ioend->io_vi, bio);
@@ fs/xfs/xfs_ioend.c: xfs_end_io_read(
}
+ /*
-+ * If we have fsverity and block device integrity attached to this bio,
-+ * we need to run fsverity verification of data folios from a separate
-+ * fsverity workqueue. This is necessary to avoid deadlocking due to
-+ * fsverity issuing more reads of fsverity metadata which would be
-+ * processed by the same worker in the BIO completion workqueue.
-+ *
-+ * Without block device integrity, fsverity metadata IO will not use
-+ * ioends for completion.
++ * If we have fsverity on this bio, we need to run fsverity verification
++ * of data folios from a separate fsverity workqueue. This is necessary
++ * to avoid deadlocking due to fsverity issuing more reads of fsverity
++ * metadata which would be processed by the same worker in the BIO
++ * completion workqueue.
+ */
+ if (IS_ENABLED(CONFIG_FS_VERITY) && !error && ioend->io_vi &&
+ xfs_fsverity_is_file_data(ip, ioend->io_offset)) {
-+ if (ioend->io_flags & IOMAP_IOEND_INTEGRITY) {
-+ fsv_ioend = kmem_cache_zalloc(xfs_fsverity_ioend_cache,
-+ GFP_KERNEL);
-+ if (!fsv_ioend) {
-+ iomap_finish_ioends(ioend, -ENOMEM);
-+ return;
-+ }
-+ fsv_ioend->ioend = ioend;
-+ INIT_WORK(&fsv_ioend->work, xfs_end_fsverity_io_read);
++ fsv_ioend = mempool_alloc(&xfs_fsverity_ioend_pool,
++ GFP_NOFS);
++ fsv_ioend->ioend = ioend;
++ INIT_WORK(&fsv_ioend->work, xfs_end_fsverity_io_read);
+
-+ fsverity_enqueue_verify_work(&fsv_ioend->work);
-+ return;
-+ }
-+
-+ fsverity_verify_bio(ioend->io_vi, &ioend->io_bio);
-+ error = blk_status_to_errno(ioend->io_bio.bi_status);
++ fsverity_enqueue_verify_work(&fsv_ioend->work);
++ return;
+ }
+
iomap_finish_ioends(ioend, error);
@@ fs/xfs/xfs_super.c: xfs_init_caches(void)
+ sizeof(struct xfs_fsverity_ioend),
+ 0, 0, NULL);
+ if (!xfs_fsverity_ioend_cache)
-+ goto out_destroy_fsverity_ioend_cache;
++ goto out_destroy_parent_args_cache;
+#endif
+
return 0;
+#ifdef CONFIG_FS_VERITY
-+ out_destroy_fsverity_ioend_cache:
-+ kmem_cache_destroy(xfs_fsverity_ioend_cache);
++ out_destroy_parent_args_cache:
++ kmem_cache_destroy(xfs_parent_args_cache);
+#endif
out_destroy_xmi_cache:
kmem_cache_destroy(xfs_xmi_cache);
@@ fs/xfs/xfs_super.c: xfs_destroy_caches(void)
kmem_cache_destroy(xfs_parent_args_cache);
kmem_cache_destroy(xfs_xmd_cache);
kmem_cache_destroy(xfs_xmi_cache);
+@@ fs/xfs/xfs_super.c: init_xfs_fs(void)
+ if (error)
+ goto out;
+
+- error = xfs_init_workqueues();
++ error = xfs_fsverity_init();
+ if (error)
+ goto out_destroy_caches;
+
++ error = xfs_init_workqueues();
++ if (error)
++ goto out_fsverity_exit;
++
+ error = xfs_mru_cache_init();
+ if (error)
+ goto out_destroy_wq;
+@@ fs/xfs/xfs_super.c: init_xfs_fs(void)
+ xfs_mru_cache_uninit();
+ out_destroy_wq:
+ xfs_destroy_workqueues();
++ out_fsverity_exit:
++ xfs_fsverity_exit();
+ out_destroy_caches:
+ xfs_destroy_caches();
+ out:
+@@ fs/xfs/xfs_super.c: exit_xfs_fs(void)
+ xfs_cleanup_procfs();
+ xfs_mru_cache_uninit();
+ xfs_destroy_workqueues();
++ xfs_fsverity_exit();
+ xfs_destroy_caches();
+ xfs_uuid_table_free();
+ }
12: 7b7e33fef0ab ! 13: 5f00c1287b5e xfs: add XFS_BMAPI_UNWRITTEN to unmap unwritten extents in __xfs_bunmapi()
@@ Commit message
written ones in place. This will be used in following patch to clean up
unwritten extents on fsverity inodes.
- Reviewed-by: "Darrick J. Wong" <djwong@kernel.org>
Signed-off-by: Andrey Albershteyn <aalbersh@kernel.org>
+ Reviewed-by: "Darrick J. Wong" <djwong@kernel.org>
## fs/xfs/libxfs/xfs_bmap.c ##
@@ fs/xfs/libxfs/xfs_bmap.c: __xfs_bunmapi(
@@ fs/xfs/libxfs/xfs_bmap.c: __xfs_bunmapi(
del.br_blockcount = end + 1 - del.br_startoff;
+ if ((flags & XFS_BMAPI_UNWRITTEN) &&
-+ del.br_state != XFS_EXT_UNWRITTEN)
++ del.br_state != XFS_EXT_UNWRITTEN)
+ goto skip;
+
if (!isrt || (flags & XFS_BMAPI_REMAP))
13: 44817f70a46b ! 14: 9a82d542d940 xfs: don't remove written extents past EOF on fsverity inodes
@@ Commit message
undergoing merkle tree construction need to be skipped in case reclaim
takes place.
- Reviewed-by: "Darrick J. Wong" <djwong@kernel.org>
Signed-off-by: Andrey Albershteyn <aalbersh@kernel.org>
+ Reviewed-by: "Darrick J. Wong" <djwong@kernel.org>
## fs/xfs/xfs_bmap_util.c ##
@@
@@ fs/xfs/xfs_bmap_util.c: xfs_can_free_eofblocks(
return false;
+ /*
-+ * Don't clean fsverity inodes which have merkle tree being built, the
++ * Don't clean fsverity inodes as they already have been cleaned up and
++ * are read-only. Skip inodes which have merkle tree being built, the
+ * merkle tree is written beyond EOF
+ */
-+ if (xfs_iflags_test(ip, XFS_VERITY_CONSTRUCTION))
++ if (fsverity_active(VFS_IC(ip)) ||
++ xfs_iflags_test(ip, XFS_VERITY_CONSTRUCTION))
+ return false;
+
/*
@@ fs/xfs/xfs_bmap_util.c: xfs_free_eofblocks(
xfs_ilock(ip, XFS_ILOCK_EXCL);
xfs_trans_ijoin(tp, ip, 0);
++ /*
++ * While fs-verity writes metadata after EOF, it can leave unwritten
++ * preallocations. Clear all that out.
++ */
+ if (has_verity)
+ bmapi_flags |= XFS_BMAPI_UNWRITTEN;
+
14: 6c1468facf03 ! 15: 420fb1a97664 xfs: add fs-verity support
@@ Commit message
Pro-actively remove any unwritten extents as we use last extent to
locate descriptor.
- Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Andrey Albershteyn <aalbersh@kernel.org>
+ Reviewed-by: Christoph Hellwig <hch@lst.de>
## fs/xfs/xfs_fsverity.c ##
@@
@@ fs/xfs/xfs_fsverity.c
+#include <linux/pagemap.h>
struct kmem_cache *xfs_fsverity_ioend_cache;
-
+ mempool_t xfs_fsverity_ioend_pool;
@@ fs/xfs/xfs_fsverity.c: xfs_fsverity_is_file_data(
return fsverity_active(VFS_IC(ip)) &&
offset < xfs_fsverity_metadata_offset(ip);
@@ fs/xfs/xfs_fsverity.c: xfs_fsverity_is_file_data(
+ uint32_t blocksize = i_blocksize(VFS_I(ip));
+ xfs_fileoff_t last_block_offset;
+
-+ ASSERT(inode->i_flags & S_VERITY);
-+ xfs_ilock(ip, XFS_ILOCK_SHARED);
++ xfs_ilock(ip, XFS_ILOCK_EXCL);
++ /*
++ * Serialize reading of inode->i_flags with xfs_scrub clearing of this
++ * flag if inode is corrupted.
++ */
++ if (!(inode->i_flags & S_VERITY)) {
++ xfs_iunlock(ip, XFS_ILOCK_EXCL);
++ return -ENODATA;
++ }
+ error = xfs_bmap_last_extent(NULL, ip, XFS_DATA_FORK, &rec, &is_empty);
-+ xfs_iunlock(ip, XFS_ILOCK_SHARED);
++ xfs_iunlock(ip, XFS_ILOCK_EXCL);
+ if (error)
+ return error;
+
@@ fs/xfs/xfs_fsverity.c: xfs_fsverity_is_file_data(
+ return error;
+ }
+
-+ xfs_ilock(ip, XFS_ILOCK_EXCL);
-+ xfs_trans_ijoin(tp, ip, 0);
-+
+ truncate_inode_pages(VFS_I(ip)->i_mapping, XFS_ISIZE(ip));
+
++ xfs_ilock(ip, XFS_ILOCK_EXCL);
++ xfs_trans_ijoin(tp, ip, 0);
++
+ /*
+ * We remove post EOF data, no need to update i_size as fsverity
+ * didn't move i_size in the first place
@@ fs/xfs/xfs_fsverity.c: xfs_fsverity_is_file_data(
+ return error;
+}
+
++static int
++xfs_fsverity_reset_inode(
++ struct xfs_inode *ip)
++{
++ int error;
++ struct xfs_mount *mp = ip->i_mount;
++ struct xfs_trans *tp;
++
++ error = xfs_fsverity_delete_metadata(ip);
++ if (error)
++ return error;
++
++ /*
++ * First, let's clean in-memory fsverity flag and then reset it on the
++ * disk
++ */
++ inode_set_flags(VFS_I(ip), 0, S_VERITY);
++
++ /*
++ * Set fsverity inode flag
++ */
++ error = xfs_trans_alloc_inode(ip, &M_RES(mp)->tr_ichange,
++ 0, 0, false, &tp);
++ if (error)
++ return error;
++
++ ip->i_diflags2 &= ~XFS_DIFLAG2_VERITY;
++
++ xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
++ xfs_trans_set_sync(tp);
++
++ error = xfs_trans_commit(tp);
++ xfs_iunlock(ip, XFS_ILOCK_EXCL);
++ return error;
++}
+
+/*
+ * Prepare to enable fsverity by clearing old metadata.
@@ fs/xfs/xfs_fsverity.c: xfs_fsverity_is_file_data(
+ if (IS_DAX(inode) || ip->i_diflags2 & XFS_DIFLAG2_DAX)
+ return -EINVAL;
+
++ /*
++ * fs-verity stores the Merkle tree past EOF in units of the filesystem
++ * block size, so it cannot support realtime files whose allocation unit
++ * (extent size) is larger than the block size.
++ */
++ if (xfs_inode_has_bigrtalloc(ip))
++ return -EINVAL;
++
+ if (inode->i_size > XFS_FSVERITY_LARGEST_FILE)
+ return -EFBIG;
+
@@ fs/xfs/xfs_fsverity.c: xfs_fsverity_is_file_data(
+ xfs_assert_ilocked(ip, XFS_IOLOCK_EXCL);
+
+ /* fs-verity failed, just cleanup */
-+ if (desc == NULL) {
-+ error = xfs_fsverity_delete_metadata(ip);
++ if (desc == NULL)
+ goto out;
-+ }
+
+ error = xfs_fsverity_write_descriptor(file, desc, desc_size,
+ merkle_tree_size);
@@ fs/xfs/xfs_fsverity.c: xfs_fsverity_is_file_data(
+ if (error) {
+ int error2;
+
-+ error2 = xfs_fsverity_delete_metadata(ip);
++ error2 = xfs_fsverity_reset_inode(ip);
+ if (error2)
+ xfs_alert(ip->i_mount,
+"ino 0x%llx failed to clean up new fsverity metadata, err %d",
@@ fs/xfs/xfs_fsverity.c: xfs_fsverity_is_file_data(
+ generic_readahead_merkle_tree(inode, index, nr_pages);
+}
+
-+/*
-+ * Write a merkle tree block.
-+ */
-+static int
-+xfs_fsverity_write_merkle(
-+ struct file *file,
++static inline bool
++xfs_fsverity_is_hashes_of_zeroed_blocks(
++ struct xfs_inode *ip,
+ const void *buf,
-+ u64 pos,
+ unsigned int size,
+ const u8 *zero_digest,
+ unsigned int digest_size)
+{
-+ struct inode *inode = file_inode(file);
-+ struct xfs_inode *ip = XFS_I(inode);
-+ loff_t position = pos +
-+ xfs_fsverity_metadata_offset(ip);
-+
-+ if (position + size > inode->i_sb->s_maxbytes)
-+ return -EFBIG;
-+
+ /*
+ * If this is a block full of hashes of zeroed blocks, don't bother
+ * storing the block. We can synthesize them later.
@@ fs/xfs/xfs_fsverity.c: xfs_fsverity_is_file_data(
+ *
+ * Iomap won't know about these empty blocks.
+ */
-+ if (size == ip->i_mount->m_sb.sb_blocksize &&
-+ /*
-+ * First digest is zero_digest
-+ */
-+ memcmp(buf, zero_digest, digest_size) == 0 &&
-+ /*
-+ * Every digest is same as previous, thus all are
-+ * zero_digest
-+ */
-+ memcmp(buf + digest_size, buf, size - digest_size) == 0)
++ if (size != ip->i_mount->m_sb.sb_blocksize)
++ return false;
++ /*
++ * First digest is zero_digest
++ */
++ if (memcmp(buf, zero_digest, digest_size))
++ return false;
++ /*
++ * Every digest is same as previous, thus all are
++ * zero_digest
++ */
++ return memcmp(buf + digest_size, buf, size - digest_size) == 0;
++}
++
++/*
++ * Write a merkle tree block.
++ */
++static int
++xfs_fsverity_write_merkle(
++ struct file *file,
++ const void *buf,
++ u64 pos,
++ unsigned int size,
++ const u8 *zero_digest,
++ unsigned int digest_size)
++{
++ struct inode *inode = file_inode(file);
++ struct xfs_inode *ip = XFS_I(inode);
++ loff_t position = pos +
++ xfs_fsverity_metadata_offset(ip);
++
++ if (position + size > inode->i_sb->s_maxbytes)
++ return -EFBIG;
++
++ if (xfs_fsverity_is_hashes_of_zeroed_blocks(ip, buf, size, zero_digest,
++ digest_size))
+ return 0;
+
+ return iomap_fsverity_write(file, position, size, buf,
@@ fs/xfs/xfs_fsverity.h
#include "xfs_platform.h"
#include <linux/iomap.h>
+#include <linux/fsverity.h>
+ #include <linux/mempool.h>
#ifdef CONFIG_FS_VERITY
+extern const struct fsverity_operations xfs_fsverity_ops;
+ int xfs_fsverity_init(void);
+ void xfs_fsverity_exit(void);
loff_t xfs_fsverity_metadata_offset(const struct xfs_inode *ip);
- bool xfs_fsverity_is_file_data(const struct xfs_inode *ip, loff_t offset);
- #else
## fs/xfs/xfs_message.c ##
@@ fs/xfs/xfs_message.c: xfs_warn_experimental(
15: 78214f0c18ed = 16: 00314b4a38e2 xfs: initialize fs-verity on file open
16: 1cda98e462f0 = 17: d37e9d9a991e xfs: add fs-verity ioctls
17: c772780887b6 = 18: c21e90b7ac09 xfs: advertise fs-verity being available on filesystem
18: 2a1811e69360 ! 19: 6efa9e6690ee xfs: check and repair the verity inode flag state
@@ Commit message
opening the file, so clearing the flag will not compromise that model.
Signed-off-by: Darrick J. Wong <djwong@kernel.org>
- Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Andrey Albershteyn <aalbersh@kernel.org>
+ Reviewed-by: Christoph Hellwig <hch@lst.de>
## fs/xfs/scrub/common.c ##
@@
@@ fs/xfs/scrub/common.c: xchk_inode_count_blocks(
+ break;
+ case -ENODATA:
+ case -EMSGSIZE:
-+ case -EINVAL:
+ case -EFSCORRUPTED:
-+ case -EFBIG:
+ case -ERANGE:
+ case -EBADMSG:
+ /*
19: 942e4a193836 = 20: e01d0c1aa284 xfs: introduce health state for corrupted fsverity metadata
20: 94fdc1d0ed15 = 21: 0ebd5899bc53 xfs: enable ro-compat fs-verity flag
--
2.54.0
_______________________________________________
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
next reply other threads:[~2026-10-02 22:37 UTC|newest]
Thread overview: 96+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-02 22:36 Andrey Albershteyn [this message]
2026-10-02 22:36 ` [f2fs-dev] [PATCH v17 00/21] fs-verity support for XFS with post EOF merkle tree Andrey Albershteyn via Linux-f2fs-devel
2026-10-02 22:36 ` [PATCH v17 01/21] fsverity: report validation errors through fserror to fsnotify Andrey Albershteyn
2026-10-02 22:36 ` [f2fs-dev] " Andrey Albershteyn via Linux-f2fs-devel
2026-10-03 1:34 ` sashiko-bot
2026-10-03 1:34 ` sashiko-bot--- via Linux-f2fs-devel
2026-10-02 22:36 ` [PATCH v17 02/21] fsverity: expose ensure_fsverity_info() Andrey Albershteyn
2026-10-02 22:36 ` [f2fs-dev] " Andrey Albershteyn via Linux-f2fs-devel
2026-10-03 1:34 ` sashiko-bot
2026-10-03 1:34 ` sashiko-bot--- via Linux-f2fs-devel
2026-10-02 22:36 ` [PATCH v17 03/21] fsverity: pass digest size and hash of the all-zeroes block to ->write Andrey Albershteyn
2026-10-02 22:36 ` [f2fs-dev] " Andrey Albershteyn via Linux-f2fs-devel
2026-10-03 1:34 ` sashiko-bot
2026-10-03 1:34 ` sashiko-bot--- via Linux-f2fs-devel
2026-10-02 22:36 ` [PATCH v17 04/21] fsverity: hoist pagecache_read from f2fs/ext4 to fsverity Andrey Albershteyn
2026-10-02 22:36 ` [f2fs-dev] " Andrey Albershteyn via Linux-f2fs-devel
2026-10-03 1:34 ` sashiko-bot
2026-10-03 1:34 ` sashiko-bot--- via Linux-f2fs-devel
2026-10-02 22:36 ` [PATCH v17 05/21] fsverity: don't allow setting DAX file attribute on fsverity files Andrey Albershteyn
2026-10-02 22:36 ` [f2fs-dev] " Andrey Albershteyn via Linux-f2fs-devel
2026-10-03 1:34 ` sashiko-bot
2026-10-02 22:36 ` [PATCH v17 06/21] fsverity: hoist statx reporting of fs-verity flag Andrey Albershteyn
2026-10-02 22:36 ` [f2fs-dev] " Andrey Albershteyn via Linux-f2fs-devel
2026-10-03 1:34 ` sashiko-bot
2026-10-02 22:36 ` [PATCH v17 07/21] xfs: introduce fsverity on-disk changes Andrey Albershteyn
2026-10-02 22:36 ` [f2fs-dev] " Andrey Albershteyn via Linux-f2fs-devel
2026-10-03 1:34 ` sashiko-bot
2026-10-02 22:36 ` [PATCH v17 08/21] xfs: don't allow to enable DAX on fs-verity sealed inode Andrey Albershteyn
2026-10-02 22:36 ` [f2fs-dev] " Andrey Albershteyn via Linux-f2fs-devel
2026-10-03 1:34 ` sashiko-bot
2026-10-02 22:36 ` [PATCH v17 09/21] xfs: disable direct read path for fs-verity files Andrey Albershteyn
2026-10-02 22:36 ` [f2fs-dev] " Andrey Albershteyn via Linux-f2fs-devel
2026-10-03 1:34 ` sashiko-bot
2026-10-03 1:34 ` sashiko-bot--- via Linux-f2fs-devel
2026-10-02 22:36 ` [PATCH v17 10/21] xfs: don't report dio_mem_align and dio_offset_align for fsverity files Andrey Albershteyn
2026-10-02 22:36 ` [f2fs-dev] " Andrey Albershteyn via Linux-f2fs-devel
2026-10-03 1:34 ` sashiko-bot
2026-10-03 1:34 ` sashiko-bot--- via Linux-f2fs-devel
2026-10-02 22:36 ` [PATCH v17 11/21] xfs: handle fsverity I/O in write/read path Andrey Albershteyn
2026-10-02 22:36 ` [f2fs-dev] " Andrey Albershteyn via Linux-f2fs-devel
2026-10-03 1:34 ` sashiko-bot
2026-10-03 1:34 ` sashiko-bot--- via Linux-f2fs-devel
2026-10-02 22:36 ` [PATCH v17 12/21] xfs: use read ioend for fsverity data verification Andrey Albershteyn
2026-10-02 22:36 ` [f2fs-dev] " Andrey Albershteyn via Linux-f2fs-devel
2026-10-03 1:34 ` sashiko-bot
2026-10-03 1:34 ` sashiko-bot--- via Linux-f2fs-devel
2026-10-02 22:36 ` [PATCH v17 13/21] xfs: add XFS_BMAPI_UNWRITTEN to unmap unwritten extents in __xfs_bunmapi() Andrey Albershteyn
2026-10-02 22:36 ` [f2fs-dev] " Andrey Albershteyn via Linux-f2fs-devel
2026-10-03 1:34 ` sashiko-bot
2026-10-03 1:34 ` sashiko-bot--- via Linux-f2fs-devel
2026-10-02 22:36 ` [PATCH v17 14/21] xfs: don't remove written extents past EOF on fsverity inodes Andrey Albershteyn
2026-10-02 22:36 ` [f2fs-dev] " Andrey Albershteyn via Linux-f2fs-devel
2026-10-03 1:34 ` sashiko-bot
2026-10-03 1:34 ` sashiko-bot--- via Linux-f2fs-devel
2026-10-02 22:36 ` [PATCH v17 15/21] xfs: add fs-verity support Andrey Albershteyn
2026-10-02 22:36 ` [f2fs-dev] " Andrey Albershteyn via Linux-f2fs-devel
2026-10-03 1:34 ` sashiko-bot
2026-10-03 1:34 ` sashiko-bot--- via Linux-f2fs-devel
2026-10-05 17:18 ` Andrey Albershteyn
2026-10-05 17:18 ` [f2fs-dev] " Andrey Albershteyn via Linux-f2fs-devel
2026-10-05 21:12 ` Darrick J. Wong
2026-10-05 21:12 ` [f2fs-dev] " Darrick J. Wong via Linux-f2fs-devel
2026-10-06 9:03 ` Andrey Albershteyn
2026-10-06 9:03 ` [f2fs-dev] " Andrey Albershteyn via Linux-f2fs-devel
2026-10-02 22:36 ` [PATCH v17 16/21] xfs: initialize fs-verity on file open Andrey Albershteyn
2026-10-02 22:36 ` [f2fs-dev] " Andrey Albershteyn via Linux-f2fs-devel
2026-10-03 1:34 ` sashiko-bot
2026-10-03 1:34 ` sashiko-bot--- via Linux-f2fs-devel
2026-10-02 22:36 ` [PATCH v17 17/21] xfs: add fs-verity ioctls Andrey Albershteyn
2026-10-02 22:36 ` [f2fs-dev] " Andrey Albershteyn via Linux-f2fs-devel
2026-10-03 1:34 ` sashiko-bot
2026-10-03 1:34 ` sashiko-bot--- via Linux-f2fs-devel
2026-10-02 22:36 ` [PATCH v17 18/21] xfs: advertise fs-verity being available on filesystem Andrey Albershteyn
2026-10-02 22:36 ` [f2fs-dev] " Andrey Albershteyn via Linux-f2fs-devel
2026-10-03 1:34 ` sashiko-bot
2026-10-03 1:34 ` sashiko-bot--- via Linux-f2fs-devel
2026-10-02 22:37 ` [PATCH v17 19/21] xfs: check and repair the verity inode flag state Andrey Albershteyn
2026-10-02 22:37 ` [f2fs-dev] " Andrey Albershteyn via Linux-f2fs-devel
2026-10-03 1:34 ` sashiko-bot
2026-10-03 1:34 ` sashiko-bot--- via Linux-f2fs-devel
2026-10-02 22:37 ` [PATCH v17 20/21] xfs: introduce health state for corrupted fsverity metadata Andrey Albershteyn
2026-10-02 22:37 ` [f2fs-dev] " Andrey Albershteyn via Linux-f2fs-devel
2026-10-03 1:34 ` sashiko-bot
2026-10-03 1:34 ` sashiko-bot--- via Linux-f2fs-devel
2026-10-02 22:37 ` [PATCH v17 21/21] xfs: enable ro-compat fs-verity flag Andrey Albershteyn
2026-10-02 22:37 ` [f2fs-dev] " Andrey Albershteyn via Linux-f2fs-devel
2026-10-03 1:34 ` sashiko-bot
2026-10-03 1:34 ` sashiko-bot--- via Linux-f2fs-devel
2026-10-02 23:25 ` [PATCH v17 00/21] fs-verity support for XFS with post EOF merkle tree Eric Biggers
2026-10-02 23:25 ` [f2fs-dev] " Eric Biggers via Linux-f2fs-devel
2026-10-03 12:07 ` Carlos Maiolino
2026-10-03 12:07 ` [f2fs-dev] " Carlos Maiolino via Linux-f2fs-devel
2026-10-05 11:26 ` Andrey Albershteyn
2026-10-05 11:26 ` [f2fs-dev] " Andrey Albershteyn via Linux-f2fs-devel
2026-10-05 13:30 ` Eric Biggers
2026-10-05 13:30 ` [f2fs-dev] " Eric Biggers via Linux-f2fs-devel
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=20261002223705.2175542-1-aalbersh@kernel.org \
--to=aalbersh@kernel.org \
--cc=cem@kernel.org \
--cc=david@fromorbit.com \
--cc=djwong@kernel.org \
--cc=ebiggers@kernel.org \
--cc=fsverity@lists.linux.dev \
--cc=hch@lst.de \
--cc=linux-btrfs@vger.kernel.org \
--cc=linux-ext4@vger.kernel.org \
--cc=linux-f2fs-devel@lists.sourceforge.net \
--cc=linux-fsdevel@vger.kernel.org \
--cc=linux-unionfs@vger.kernel.org \
--cc=linux-xfs@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 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.