For write/writeback set IOMAP_F_FSVERITY flag telling iomap to not update inode size as this is not file data and not skip folio beyond EOF. In read path let iomap know that we are reading fsverity metadata. So, treat holes in the tree as request to synthesize tree blocks and hole after descriptor as end of the fsverity region. Signed-off-by: Andrey Albershteyn --- fs/xfs/libxfs/xfs_bmap.c | 3 +++ fs/xfs/xfs_aops.c | 18 +++++++++++++++++- fs/xfs/xfs_iomap.c | 12 ++++++++++-- 3 files changed, 30 insertions(+), 3 deletions(-) diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c index 53ef4b7e504d..99a3ff2ee928 100644 --- a/fs/xfs/libxfs/xfs_bmap.c +++ b/fs/xfs/libxfs/xfs_bmap.c @@ -4451,6 +4451,9 @@ xfs_bmapi_convert_one_delalloc( XFS_STATS_ADD(mp, xs_xstrat_bytes, XFS_FSB_TO_B(mp, bma.length)); XFS_STATS_INC(mp, xs_xstrat_quick); + if (xfs_iflags_test(ip, XFS_VERITY_CONSTRUCTION)) + flags |= IOMAP_F_FSVERITY; + ASSERT(!isnullstartblock(bma.got.br_startblock)); xfs_bmbt_to_iomap(ip, iomap, &bma.got, 0, flags, xfs_iomap_inode_sequence(ip, flags)); diff --git a/fs/xfs/xfs_aops.c b/fs/xfs/xfs_aops.c index 36c4b2b4b07a..f95dc51eb044 100644 --- a/fs/xfs/xfs_aops.c +++ b/fs/xfs/xfs_aops.c @@ -22,6 +22,7 @@ #include "xfs_icache.h" #include "xfs_zone_alloc.h" #include "xfs_rtgroup.h" +#include "xfs_fsverity.h" #include struct xfs_writepage_ctx { @@ -339,12 +340,16 @@ xfs_map_blocks( int retries = 0; int error = 0; unsigned int *seq; + unsigned int iomap_flags = 0; if (xfs_is_shutdown(mp)) return -EIO; XFS_ERRORTAG_DELAY(mp, XFS_ERRTAG_WB_DELAY_MS); + if (xfs_iflags_test(ip, XFS_VERITY_CONSTRUCTION)) + iomap_flags |= IOMAP_F_FSVERITY; + /* * COW fork blocks can overlap data fork blocks even if the blocks * aren't shared. COW I/O always takes precedent, so we must always @@ -432,7 +437,7 @@ xfs_map_blocks( isnullstartblock(imap.br_startblock)) goto allocate_blocks; - xfs_bmbt_to_iomap(ip, &wpc->iomap, &imap, 0, 0, XFS_WPC(wpc)->data_seq); + xfs_bmbt_to_iomap(ip, &wpc->iomap, &imap, 0, iomap_flags, XFS_WPC(wpc)->data_seq); trace_xfs_map_blocks_found(ip, offset, count, whichfork, &imap); return 0; allocate_blocks: @@ -705,6 +710,17 @@ xfs_vm_writepages( }, }; + if (xfs_iflags_test(ip, XFS_VERITY_CONSTRUCTION)) { + wbc->range_start = fsverity_metadata_offset(VFS_I(ip)); + wbc->range_end = LLONG_MAX; + wbc->nr_to_write = LONG_MAX; + /* + * Set IOMAP_F_FSVERITY to skip initial EOF check + * The following iomap->flags would be set in + * xfs_map_blocks() + */ + wpc.ctx.iomap.flags |= IOMAP_F_FSVERITY; + } return iomap_writepages(&wpc.ctx); } } diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c index 52c41ef36d6d..6b14221ecee2 100644 --- a/fs/xfs/xfs_iomap.c +++ b/fs/xfs/xfs_iomap.c @@ -32,6 +32,7 @@ #include "xfs_rtbitmap.h" #include "xfs_icache.h" #include "xfs_zone_alloc.h" +#include #define XFS_ALLOC_ALIGN(mp, off) \ (((off) >> mp->m_allocsize_log) << mp->m_allocsize_log) @@ -1789,6 +1790,9 @@ xfs_buffered_write_iomap_begin( return xfs_direct_write_iomap_begin(inode, offset, count, flags, iomap, srcmap); + if (xfs_iflags_test(ip, XFS_VERITY_CONSTRUCTION)) + iomap_flags |= IOMAP_F_FSVERITY; + error = xfs_qm_dqattach(ip); if (error) return error; @@ -2114,12 +2118,16 @@ xfs_read_iomap_begin( bool shared = false; unsigned int lockmode = XFS_ILOCK_SHARED; u64 seq; + unsigned int iomap_flags = 0; ASSERT(!(flags & (IOMAP_WRITE | IOMAP_ZERO))); if (xfs_is_shutdown(mp)) return -EIO; + if (fsverity_active(inode) && offset >= XFS_FSVERITY_REGION_START) + iomap_flags |= IOMAP_F_FSVERITY; + error = xfs_ilock_for_iomap(ip, flags, &lockmode); if (error) return error; @@ -2133,8 +2141,8 @@ xfs_read_iomap_begin( if (error) return error; trace_xfs_iomap_found(ip, offset, length, XFS_DATA_FORK, &imap); - return xfs_bmbt_to_iomap(ip, iomap, &imap, flags, - shared ? IOMAP_F_SHARED : 0, seq); + iomap_flags |= shared ? IOMAP_F_SHARED : 0; + return xfs_bmbt_to_iomap(ip, iomap, &imap, flags, iomap_flags, seq); } const struct iomap_ops xfs_read_iomap_ops = { -- 2.51.2