From: Andrey Albershteyn <aalbersh@kernel.org>
To: djwong@kernel.org, ebiggers@kernel.org, hch@lst.de,
Jens Axboe <axboe@kernel.dk>, 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-block@vger.kernel.org, linux-ext4@vger.kernel.org,
linux-f2fs-devel@lists.sourceforge.net,
linux-btrfs@vger.kernel.org, david@fromorbit.com,
Tal Zussman <tz2294@columbia.edu>
Subject: [PATCH v15 18/25] xfs: make xfs_free_eofblocks() work with fsverity inodes
Date: Fri, 14 Aug 2026 11:24:35 +0200 [thread overview]
Message-ID: <20260814092448.1818082-19-aalbersh@kernel.org> (raw)
In-Reply-To: <20260814092448.1818082-1-aalbersh@kernel.org>
xfs_free_eofblocks() removes any preallocations and unwritten extents
beyond EOF. This is undesired for fsverity as it stores metadata beyond
EOF. However, while merkle tree is being built delayed preallocation and
unwritten extents are used. After metadata construction is done,
fsverity inodes becomes read-only and won't be changed anymore, none of
these unwritten extents or preallocations in post EOF region will be
used.
Add XFS_BMAPI_UNWRITTEN and change xfs_bunmapi_range to remove only
unwritten extents sitting beyond EOF and set it for fsverity inodes.
The xfs_free_eofblocks() will be called on fsverity inode as usual.
However, inodes which are undergoing merkle tree construction need to
be skipped in case reclaim takes place.
Signed-off-by: Andrey Albershteyn <aalbersh@kernel.org>
---
fs/xfs/libxfs/xfs_bmap.c | 55 +++++++++++++++++++++++++++++-----------
fs/xfs/libxfs/xfs_bmap.h | 6 ++++-
fs/xfs/xfs_bmap_util.c | 25 +++++++++++++++---
3 files changed, 67 insertions(+), 19 deletions(-)
diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c
index cc48f6e20e80..a2d9cef952c4 100644
--- a/fs/xfs/libxfs/xfs_bmap.c
+++ b/fs/xfs/libxfs/xfs_bmap.c
@@ -6144,15 +6144,12 @@ xfs_bmap_validate_extent(
XFS_IS_REALTIME_INODE(ip), whichfork, irec);
}
-/*
- * Used in xfs_itruncate_extents(). This is the maximum number of extents
- * freed from a file in a single transaction.
- */
-#define XFS_ITRUNC_MAX_EXTENTS 2
-
/*
* Unmap every extent in part of an inode's fork. We don't do any higher level
* invalidation work at all.
+ *
+ * The XFS_BMAPI_UNWRITTEN could be passed to remove only unwritten extents,
+ * leaving out normal extents in place.
*/
int
xfs_bunmapi_range(
@@ -6162,23 +6159,51 @@ xfs_bunmapi_range(
xfs_fileoff_t startoff,
xfs_fileoff_t endoff)
{
- xfs_filblks_t unmap_len = endoff - startoff + 1;
+ xfs_filblks_t unmap_len;
int error = 0;
+ int nimaps = 1;
+ int done = 0;
+ struct xfs_bmbt_irec imap;
+ int read_flags =
+ flags & (XFS_BMAPI_ATTRFORK | XFS_BMAPI_ENTIRE);
xfs_assert_ilocked(ip, XFS_ILOCK_EXCL);
- while (unmap_len > 0) {
- ASSERT((*tpp)->t_highest_agno == NULLAGNUMBER);
- error = __xfs_bunmapi(*tpp, ip, startoff, &unmap_len, flags,
- XFS_ITRUNC_MAX_EXTENTS);
+ while (startoff < endoff) {
+ nimaps = 1;
+
+ error = xfs_bmapi_read(ip, startoff, endoff - startoff + 1,
+ &imap, &nimaps, read_flags);
if (error)
goto out;
- /* free the just unmapped extents */
- error = xfs_defer_finish(tpp);
- if (error)
+ if (nimaps == 0)
goto out;
- cond_resched();
+
+ if ((flags & XFS_BMAPI_UNWRITTEN) &&
+ imap.br_state != XFS_EXT_UNWRITTEN) {
+ startoff = imap.br_startoff + imap.br_blockcount;
+ continue;
+ }
+
+ unmap_len = min(endoff - imap.br_startoff + 1,
+ imap.br_blockcount);
+ done = 0;
+ while (!done) {
+ ASSERT((*tpp)->t_highest_agno == NULLAGNUMBER);
+ error = xfs_bunmapi(*tpp, ip, imap.br_startoff,
+ unmap_len, flags, nimaps, &done);
+ if (error)
+ goto out;
+
+ /* free the just unmapped extent */
+ error = xfs_defer_finish(tpp);
+ if (error)
+ goto out;
+ cond_resched();
+ }
+
+ startoff = imap.br_startoff + unmap_len;
}
out:
return error;
diff --git a/fs/xfs/libxfs/xfs_bmap.h b/fs/xfs/libxfs/xfs_bmap.h
index d5f2729305fa..0f36431d9936 100644
--- a/fs/xfs/libxfs/xfs_bmap.h
+++ b/fs/xfs/libxfs/xfs_bmap.h
@@ -90,6 +90,9 @@ struct xfs_bmalloca {
/* Try to align allocations to the extent size hint */
#define XFS_BMAPI_EXTSZALIGN (1u << 11)
+/* Process unwritten extents only. Used for unmapping */
+#define XFS_BMAPI_UNWRITTEN (1u << 12)
+
#define XFS_BMAPI_FLAGS \
{ XFS_BMAPI_ENTIRE, "ENTIRE" }, \
{ XFS_BMAPI_METADATA, "METADATA" }, \
@@ -102,7 +105,8 @@ struct xfs_bmalloca {
{ XFS_BMAPI_COWFORK, "COWFORK" }, \
{ XFS_BMAPI_NODISCARD, "NODISCARD" }, \
{ XFS_BMAPI_NORMAP, "NORMAP" },\
- { XFS_BMAPI_EXTSZALIGN, "EXTSZALIGN" }
+ { XFS_BMAPI_EXTSZALIGN, "EXTSZALIGN" }, \
+ { XFS_BMAPI_UNWRITTEN, "UNWRITTEN" }
static inline int xfs_bmapi_aflag(int w)
diff --git a/fs/xfs/xfs_bmap_util.c b/fs/xfs/xfs_bmap_util.c
index c88b9ade7389..36ac18df5743 100644
--- a/fs/xfs/xfs_bmap_util.c
+++ b/fs/xfs/xfs_bmap_util.c
@@ -31,6 +31,7 @@
#include "xfs_rtbitmap.h"
#include "xfs_rtgroup.h"
#include "xfs_zone_alloc.h"
+#include <linux/fsverity.h>
/* Kernel only BMAP related definitions and functions */
@@ -553,6 +554,13 @@ xfs_can_free_eofblocks(
if (last_fsb <= end_fsb)
return false;
+ /*
+ * Don't clean fsverity inodes which have merkle tree being built, the
+ * merkle tree is written beyond EOF
+ */
+ if (xfs_iflags_test(ip, XFS_VERITY_CONSTRUCTION))
+ return false;
+
/*
* Check if there is an post-EOF extent to free. If there are any
* delalloc blocks attached to the inode (data fork delalloc
@@ -579,6 +587,9 @@ xfs_free_eofblocks(
struct xfs_trans *tp;
struct xfs_mount *mp = ip->i_mount;
int error;
+ int bmapi_flags = XFS_BMAPI_NODISCARD;
+ bool has_verity =
+ ip->i_diflags2 & XFS_DIFLAG2_VERITY;
/* Attach the dquots to the inode up front. */
error = xfs_qm_dqattach(ip);
@@ -593,15 +604,20 @@ xfs_free_eofblocks(
*
* Note that this means we also leave speculative preallocations in
* place for preallocated files.
+ *
+ * Clean up delalloc reservations for fsverity too as those won't be
+ * used
*/
- if (ip->i_diflags & (XFS_DIFLAG_PREALLOC | XFS_DIFLAG_APPEND)) {
+ if (ip->i_diflags & (XFS_DIFLAG_PREALLOC | XFS_DIFLAG_APPEND) ||
+ has_verity) {
if (ip->i_delayed_blks) {
xfs_bmap_punch_delalloc_range(ip, XFS_DATA_FORK,
round_up(XFS_ISIZE(ip), mp->m_sb.sb_blocksize),
LLONG_MAX, NULL);
}
xfs_inode_clear_eofblocks_tag(ip);
- return 0;
+ if (!has_verity)
+ return 0;
}
error = xfs_trans_alloc(mp, &M_RES(mp)->tr_itruncate, 0, 0, 0, &tp);
@@ -613,6 +629,9 @@ xfs_free_eofblocks(
xfs_ilock(ip, XFS_ILOCK_EXCL);
xfs_trans_ijoin(tp, ip, 0);
+ if (has_verity)
+ bmapi_flags |= XFS_BMAPI_UNWRITTEN;
+
/*
* Do not update the on-disk file size. If we update the on-disk file
* size and then the system crashes before the contents of the file are
@@ -620,7 +639,7 @@ xfs_free_eofblocks(
* bug).
*/
error = xfs_itruncate_extents_flags(&tp, ip, XFS_DATA_FORK,
- XFS_ISIZE(ip), XFS_BMAPI_NODISCARD);
+ XFS_ISIZE(ip), bmapi_flags);
if (error)
goto err_cancel;
--
2.54.0
next prev parent reply other threads:[~2026-08-14 9:27 UTC|newest]
Thread overview: 26+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-14 9:24 [PATCH v15 00/25] fs-verity support for XFS with post EOF merkle tree Andrey Albershteyn
2026-08-14 9:24 ` [PATCH v15 01/25] fsverity: report validation errors through fserror to fsnotify Andrey Albershteyn
2026-08-14 9:24 ` [PATCH v15 02/25] fsverity: expose ensure_fsverity_info() Andrey Albershteyn
2026-08-14 9:24 ` [PATCH v15 03/25] fsverity: pass digest size and hash of the all-zeroes block to ->write Andrey Albershteyn
2026-08-14 9:24 ` [PATCH v15 04/25] fsverity: hoist pagecache_read from f2fs/ext4 to fsverity Andrey Albershteyn
2026-08-14 9:24 ` [PATCH v15 05/25] fsverity: don't allow setting DAX file attribute on fsverity files Andrey Albershteyn
2026-08-14 9:24 ` [PATCH v15 06/25] fsverity: hoist statx reporting of fs-verity flag Andrey Albershteyn
2026-08-14 9:24 ` [PATCH v15 07/25] block: add task-context bio completion infrastructure Andrey Albershteyn
2026-08-14 9:24 ` [PATCH v15 08/25] block: don't delay bio task completions Andrey Albershteyn
2026-08-14 9:24 ` [PATCH v15 09/25] iomap: add a iomap_ioend_flags helper Andrey Albershteyn
2026-08-14 9:24 ` [PATCH v15 10/25] iomap: add a IOMAP_IOEND_INTEGRITY flag Andrey Albershteyn
2026-08-14 9:24 ` [PATCH v15 11/25] xfs: use BIO_COMPLETE_IN_TASK for bounce buffered read I/Os Andrey Albershteyn
2026-08-14 9:24 ` [PATCH v15 12/25] xfs: introduce fsverity on-disk changes Andrey Albershteyn
2026-08-14 9:24 ` [PATCH v15 13/25] xfs: don't allow to enable DAX on fs-verity sealed inode Andrey Albershteyn
2026-08-14 9:24 ` [PATCH v15 14/25] xfs: disable direct read path for fs-verity files Andrey Albershteyn
2026-08-14 9:24 ` [PATCH v15 15/25] xfs: don't report dio_mem_align and dio_offset_align for fsverity files Andrey Albershteyn
2026-08-14 9:24 ` [PATCH v15 16/25] xfs: handle fsverity I/O in write/read path Andrey Albershteyn
2026-08-14 9:24 ` [PATCH v15 17/25] xfs: use read ioend for fsverity data verification Andrey Albershteyn
2026-08-14 9:24 ` Andrey Albershteyn [this message]
2026-08-14 9:24 ` [PATCH v15 19/25] xfs: add fs-verity support Andrey Albershteyn
2026-08-14 9:24 ` [PATCH v15 20/25] xfs: initialize fs-verity on file open Andrey Albershteyn
2026-08-14 9:24 ` [PATCH v15 21/25] xfs: add fs-verity ioctls Andrey Albershteyn
2026-08-14 9:24 ` [PATCH v15 22/25] xfs: advertise fs-verity being available on filesystem Andrey Albershteyn
2026-08-14 9:24 ` [PATCH v15 23/25] xfs: check and repair the verity inode flag state Andrey Albershteyn
2026-08-14 9:24 ` [PATCH v15 24/25] xfs: introduce health state for corrupted fsverity metadata Andrey Albershteyn
2026-08-14 9:24 ` [PATCH v15 25/25] xfs: enable ro-compat fs-verity flag Andrey Albershteyn
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=20260814092448.1818082-19-aalbersh@kernel.org \
--to=aalbersh@kernel.org \
--cc=axboe@kernel.dk \
--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-block@vger.kernel.org \
--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 \
--cc=tz2294@columbia.edu \
/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