All of lore.kernel.org
 help / color / mirror / Atom feed
From: Chris Mason <mason@kernel.org>
To: mason@kernel.org, tytso@mit.edu, cem@kernel.org,
	david@fromorbit.com, jack@suse.cz, djwong@kernel.org,
	josef@toxicpanda.com, hch@lst.de, linux-xfs@vger.kernel.org,
	linux-fsdevel@vger.kernel.org, linux-ext4@vger.kernel.org,
	tz2294@columbia.edu, brauner@kernel.org
Subject: [PATCH v9 12/14] xfs: restart faults racing with realtime flag changes
Date: Thu, 12 Nov 2026 16:46:16 -0500	[thread overview]
Message-ID: <20261112214604.67875-13-mason@kernel.org> (raw)
In-Reply-To: <20261112214604.67875-1-mason@kernel.org>

On a zoned XFS, a store through a shared mapping can dereference a NULL
pointer if the realtime flag of the file is set as the write fault
starts.

xfs_write_fault() reserves zoned space only for a zoned inode. The
reservation can wait for garbage collection, which takes the MMAPLOCK,
so it comes ahead of that lock, and so does the test for a zoned inode.
FS_IOC_FSSETXATTR can set the flag of a file with no blocks right after
the test:

    write fault                           FS_IOC_FSSETXATTR
    ===========                           =================
    xfs_write_fault()
      sees that the inode is not zoned
                                          sets the realtime flag
      takes the MMAPLOCK
    xfs_buffered_write_iomap_begin()
      sees that the inode is zoned
      /* ac is NULL */

The fix used here is to test again under the MMAPLOCK, which keeps the
ioctl out since "xfs: take the MMAPLOCK in xfs_fileattr_set()", and to
start the fault over if the flag has changed.

Fixes: 058dd70c65ab ("xfs: implement buffered writes to zoned RT devices")
Signed-off-by: Chris Mason <mason@kernel.org>
---

Notes:
    v8->v9:
    - The flag is tested once, in __xfs_write_fault() under the MMAPLOCK.
      The four tests under the ILOCK are gone, and so is the -EINVAL for
      callers that are no faults (Christoph Hellwig).
    - Was 11/15.
    
    v7->v8:
    - Only a page fault gets -EAGAIN. Any other caller that gets to one of
      the tests fails with -EINVAL, as a write and an fallocate do. pNFS can
      get there: xfs_fs_map_blocks() tests the flag before it takes its
      locks (Christoph Hellwig).
    - The warning now says "during block mapping".
    - The helper reads the inode number with I_INO(), and its comment no
      longer says that the flag is stable once the inode has blocks.
    - Was 11/11.
    
    v6->v7:
    - xfs_direct_write_iomap_begin() tests the flag too, as soon as it holds
      the ILOCK. It could allocate blocks for a COW fork extent before it
      got to the test in xfs_iomap_write_direct().
    - The assert on the extent size hint in
      xfs_zoned_buffered_write_iomap_begin() moved below the test of the
      flag.
    - Dropped the Reviewed-by of Christoph Hellwig, since the patch changed.
    - Was 10/10.

 fs/xfs/xfs_file.c | 15 +++++++++++++--
 1 file changed, 13 insertions(+), 2 deletions(-)

diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c
index 78c9668c806b..6ff544c0934d 100644
--- a/fs/xfs/xfs_file.c
+++ b/fs/xfs/xfs_file.c
@@ -2076,11 +2076,22 @@ __xfs_write_fault(
 		lock_mode = XFS_MMAPLOCK_EXCL;
 	}
 
-	if (IS_DAX(inode))
+	/*
+	 * The caller picked the zoned or the regular path with no lock held.
+	 * The realtime flag cannot change under the MMAPLOCK, so look at it
+	 * again, and start over if it has changed.
+	 */
+	if (xfs_is_zoned_inode(ip) != !!ac) {
+		xfs_warn_ratelimited(ip->i_mount,
+			"RT flag modifying during page fault for inode 0x%llx.",
+			inode->i_ino);
+		ret = VM_FAULT_NOPAGE;
+	} else if (IS_DAX(inode)) {
 		ret = xfs_dax_fault_locked(vmf, order, true);
-	else
+	} else {
 		ret = iomap_page_mkwrite(vmf, &xfs_buffered_write_iomap_ops,
 				ac);
+	}
 	xfs_iunlock(ip, lock_mode);
 
 	sb_end_pagefault(inode->i_sb);
-- 
2.55.0


  parent reply	other threads:[~2026-11-12 21:46 UTC|newest]

Thread overview: 33+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-11-12 21:46 [PATCH v9 00/14] reflink and atomic write bugs Chris Mason
2026-11-12 21:46 ` [PATCH v9 01/14] xfs: don't skip the flush before shifting extents Chris Mason
2026-11-12 21:55   ` sashiko-bot
2026-11-12 21:46 ` [PATCH v9 02/14] xfs: flush the shifted range before changing the file Chris Mason
2026-11-12 21:54   ` sashiko-bot
2026-11-12 21:46 ` [PATCH v9 03/14] xfs: don't change the block map under a dirty folio Chris Mason
2026-11-12 22:03   ` sashiko-bot
2026-11-12 21:46 ` [PATCH v9 04/14] iomap: don't punch delalloc under a dirty EOF block Chris Mason
2026-11-12 21:54   ` sashiko-bot
2026-11-12 21:46 ` [PATCH v9 05/14] fs: validate atomic writes after O_APPEND and limits Chris Mason
2026-11-12 22:16   ` sashiko-bot
2026-11-12 21:46 ` [PATCH v9 06/14] xfs: recheck direct write alignment after write checks Chris Mason
2026-11-12 22:22   ` sashiko-bot
2026-11-12 21:46 ` [PATCH v9 07/14] xfs: test for reflink after the dio " Chris Mason
2026-11-12 21:54   ` sashiko-bot
2026-11-12 21:46 ` [PATCH v9 08/14] xfs: refuse writes to files racing with realtime inode flag changes Chris Mason
2026-11-12 22:11   ` sashiko-bot
2026-11-12 21:46 ` [PATCH v9 09/14] xfs: test for always COW after the dio write checks Chris Mason
2026-11-12 21:53   ` sashiko-bot
2026-11-12 21:46 ` [PATCH v9 10/14] xfs: refuse fallocate racing with realtime flag changes Chris Mason
2026-11-12 22:11   ` sashiko-bot
2026-11-12 21:46 ` [PATCH v9 11/14] xfs: take the MMAPLOCK in xfs_fileattr_set() Chris Mason
2026-11-12 22:13   ` sashiko-bot
2026-11-12 23:49   ` Christoph Hellwig
2026-11-12 21:46 ` Chris Mason [this message]
2026-11-12 22:08   ` [PATCH v9 12/14] xfs: restart faults racing with realtime flag changes sashiko-bot
2026-11-12 23:50   ` Christoph Hellwig
2026-11-12 21:46 ` [PATCH v9 13/14] xfs: don't enable DAX on zoned inodes Chris Mason
2026-11-12 22:03   ` sashiko-bot
2026-11-12 23:50   ` Christoph Hellwig
2026-11-12 21:46 ` [PATCH v9 14/14] xfs: test for realtime and reflink under the pNFS locks Chris Mason
2026-11-12 22:02   ` sashiko-bot
2026-11-12 23:51   ` Christoph Hellwig

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=20261112214604.67875-13-mason@kernel.org \
    --to=mason@kernel.org \
    --cc=brauner@kernel.org \
    --cc=cem@kernel.org \
    --cc=david@fromorbit.com \
    --cc=djwong@kernel.org \
    --cc=hch@lst.de \
    --cc=jack@suse.cz \
    --cc=josef@toxicpanda.com \
    --cc=linux-ext4@vger.kernel.org \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=linux-xfs@vger.kernel.org \
    --cc=tytso@mit.edu \
    --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 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.