Linux EXT4 FS development
 help / color / mirror / Atom feed
From: Andrey Albershteyn <aalbersh@kernel.org>
To: linux-xfs@vger.kernel.org, fsverity@lists.linux.dev,
	linux-fsdevel@vger.kernel.org, ebiggers@kernel.org
Cc: Andrey Albershteyn <aalbersh@kernel.org>,
	hch@lst.de, linux-ext4@vger.kernel.org,
	linux-f2fs-devel@lists.sourceforge.net,
	linux-btrfs@vger.kernel.org, djwong@kernel.org
Subject: [PATCH v13 14/23] xfs: always prioritize fsverity metadata ioends in ioend completion
Date: Tue, 21 Jul 2026 20:40:51 +0200	[thread overview]
Message-ID: <20260721184346.416657-15-aalbersh@kernel.org> (raw)
In-Reply-To: <20260721184346.416657-1-aalbersh@kernel.org>

When both block device integrity checksums and fsverity are used, all
read ioends end up in the ioend processing. This means that fsverity
data and metadata ioends could both get on ioend queue ip->i_ioend_list.

Then, when worker pick ups the work, it will process all ioends in the
queue. Before, processing ioends are sorted based on file offset,
meaning data ioend first, metadata second. Metadata ioend already
holding folio lock, if data ioend needs this exact folio the worker will
self deadlock.

Fix this by prioritizing fsverity metadata while sorting read ioends.

Signed-off-by: Andrey Albershteyn <aalbersh@kernel.org>
---
 fs/iomap/ioend.c      |  8 ++++----
 fs/xfs/xfs_aops.c     | 32 +++++++++++++++++++++++++++++++-
 include/linux/iomap.h |  5 ++++-
 3 files changed, 39 insertions(+), 6 deletions(-)

diff --git a/fs/iomap/ioend.c b/fs/iomap/ioend.c
index 0565328764c1..8e46b7f1aa6a 100644
--- a/fs/iomap/ioend.c
+++ b/fs/iomap/ioend.c
@@ -4,7 +4,6 @@
  */
 #include <linux/bio-integrity.h>
 #include <linux/iomap.h>
-#include <linux/list_sort.h>
 #include <linux/pagemap.h>
 #include <linux/writeback.h>
 #include <linux/fserror.h>
@@ -425,7 +424,7 @@ void iomap_ioend_try_merge(struct iomap_ioend *ioend,
 }
 EXPORT_SYMBOL_GPL(iomap_ioend_try_merge);
 
-static int iomap_ioend_compare(void *priv, const struct list_head *a,
+int iomap_ioend_compare(void *priv, const struct list_head *a,
 		const struct list_head *b)
 {
 	struct iomap_ioend *ia = container_of(a, struct iomap_ioend, io_list);
@@ -437,10 +436,11 @@ static int iomap_ioend_compare(void *priv, const struct list_head *a,
 		return 1;
 	return 0;
 }
+EXPORT_SYMBOL_GPL(iomap_ioend_compare);
 
-void iomap_sort_ioends(struct list_head *ioend_list)
+void iomap_sort_ioends(struct list_head *ioend_list, list_cmp_func_t cmp)
 {
-	list_sort(NULL, ioend_list, iomap_ioend_compare);
+	list_sort(NULL, ioend_list, cmp);
 }
 EXPORT_SYMBOL_GPL(iomap_sort_ioends);
 
diff --git a/fs/xfs/xfs_aops.c b/fs/xfs/xfs_aops.c
index 34d0ff7c7086..c7843a8776b0 100644
--- a/fs/xfs/xfs_aops.c
+++ b/fs/xfs/xfs_aops.c
@@ -182,6 +182,32 @@ xfs_end_ioend_write(
 	memalloc_nofs_restore(nofs_flag);
 }
 
+/*
+ * Prioritize fsverity metadata over file data. Sort based on i_size as fsverity
+ * metadata is always beyond EOF
+ */
+static int
+xfs_read_ioend_compare(
+	void			*priv,
+	const struct list_head	*a,
+	const struct list_head	*b)
+{
+	struct iomap_ioend	*ia = container_of(a, struct iomap_ioend,
+			io_list);
+	struct iomap_ioend	*ib = container_of(b, struct iomap_ioend,
+			io_list);
+	loff_t			i_size = i_size_read(ia->io_inode);
+
+	if (!IS_VERITY(ia->io_inode))
+		return iomap_ioend_compare(priv, a, b);
+
+	if (ia->io_offset > i_size && ib->io_offset < i_size)
+		return -1;
+	if (ia->io_offset < i_size && ib->io_offset > i_size)
+		return 1;
+	return 0;
+}
+
 /*
  * Finish all pending IO completions that require transactional modifications.
  *
@@ -210,7 +236,11 @@ xfs_end_io(
 	list_replace_init(&ip->i_ioend_list, &tmp);
 	spin_unlock_irqrestore(&ip->i_ioend_lock, flags);
 
-	iomap_sort_ioends(&tmp);
+	ioend = list_first_entry_or_null(&tmp, struct iomap_ioend, io_list);
+	if (bio_op(&ioend->io_bio) == REQ_OP_READ)
+		iomap_sort_ioends(&tmp, xfs_read_ioend_compare);
+	else
+		iomap_sort_ioends(&tmp, iomap_ioend_compare);
 	while ((ioend = list_first_entry_or_null(&tmp, struct iomap_ioend,
 			io_list))) {
 		list_del_init(&ioend->io_list);
diff --git a/include/linux/iomap.h b/include/linux/iomap.h
index 56b43d594e6e..36fc931382a8 100644
--- a/include/linux/iomap.h
+++ b/include/linux/iomap.h
@@ -10,6 +10,7 @@
 #include <linux/mm_types.h>
 #include <linux/blkdev.h>
 #include <linux/folio_batch.h>
+#include <linux/list_sort.h>
 
 struct address_space;
 struct fiemap_extent_info;
@@ -488,7 +489,9 @@ struct iomap_ioend *iomap_split_ioend(struct iomap_ioend *ioend,
 void iomap_finish_ioends(struct iomap_ioend *ioend, int error);
 void iomap_ioend_try_merge(struct iomap_ioend *ioend,
 		struct list_head *more_ioends);
-void iomap_sort_ioends(struct list_head *ioend_list);
+int iomap_ioend_compare(void *priv, const struct list_head *a,
+		const struct list_head *b);
+void iomap_sort_ioends(struct list_head *ioend_list, list_cmp_func_t cmp);
 ssize_t iomap_add_to_ioend(struct iomap_writepage_ctx *wpc, struct folio *folio,
 		loff_t pos, loff_t end_pos, unsigned int dirty_len);
 int iomap_ioend_writeback_submit(struct iomap_writepage_ctx *wpc, int error);
-- 
2.54.0


  parent reply	other threads:[~2026-07-21 18:44 UTC|newest]

Thread overview: 24+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-07-21 18:40 [PATCH v13 00/23] fs-verity support for XFS with post EOF merkle tree Andrey Albershteyn
2026-07-21 18:40 ` [PATCH v13 01/23] fsverity: report validation errors through fserror to fsnotify Andrey Albershteyn
2026-07-21 18:40 ` [PATCH v13 02/23] fsverity: expose ensure_fsverity_info() Andrey Albershteyn
2026-07-21 18:40 ` [PATCH v13 03/23] fsverity: pass digest size and hash of the all-zeroes block to ->write Andrey Albershteyn
2026-07-21 18:40 ` [PATCH v13 04/23] fsverity: hoist pagecache_read from f2fs/ext4 to fsverity Andrey Albershteyn
2026-07-21 18:40 ` [PATCH v13 05/23] fsverity: improve flushing performance of fsverity_fill_zerohash Andrey Albershteyn
2026-07-21 18:40 ` [PATCH v13 06/23] fsverity: don't allow setting DAX file attribute on fsverity files Andrey Albershteyn
2026-07-21 18:40 ` [PATCH v13 07/23] fs,fsverity: remove check for fsverity being enabled in setattr_prepare() Andrey Albershteyn
2026-07-21 18:40 ` [PATCH v13 08/23] fsverity: hoist statx reporting of fs-verity flag Andrey Albershteyn
2026-07-21 18:40 ` [PATCH v13 09/23] xfs: introduce fsverity on-disk changes Andrey Albershteyn
2026-07-21 18:40 ` [PATCH v13 10/23] xfs: don't allow to enable DAX on fs-verity sealed inode Andrey Albershteyn
2026-07-21 18:40 ` [PATCH v13 11/23] xfs: disable direct read path for fs-verity files Andrey Albershteyn
2026-07-21 18:40 ` [PATCH v13 12/23] xfs: don't report dio_mem_align and dio_offset_align for fsverity files Andrey Albershteyn
2026-07-21 18:40 ` [PATCH v13 13/23] xfs: handle fsverity I/O in write/read path Andrey Albershteyn
2026-07-21 18:40 ` Andrey Albershteyn [this message]
2026-07-21 18:40 ` [PATCH v13 15/23] xfs: use read ioend for fsverity data verification Andrey Albershteyn
2026-07-21 18:40 ` [PATCH v13 16/23] xfs: add fs-verity support Andrey Albershteyn
2026-07-21 18:40 ` [PATCH v13 17/23] xfs: remove unwritten extents after preallocations in fsverity metadata Andrey Albershteyn
2026-07-21 18:40 ` [PATCH v13 18/23] xfs: initialize fs-verity on file open Andrey Albershteyn
2026-07-21 18:40 ` [PATCH v13 19/23] xfs: add fs-verity ioctls Andrey Albershteyn
2026-07-21 18:40 ` [PATCH v13 20/23] xfs: advertise fs-verity being available on filesystem Andrey Albershteyn
2026-07-21 18:40 ` [PATCH v13 21/23] xfs: check and repair the verity inode flag state Andrey Albershteyn
2026-07-21 18:40 ` [PATCH v13 22/23] xfs: introduce health state for corrupted fsverity metadata Andrey Albershteyn
2026-07-21 18:41 ` [PATCH v13 23/23] 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=20260721184346.416657-15-aalbersh@kernel.org \
    --to=aalbersh@kernel.org \
    --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-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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox