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 10/14] xfs: refuse fallocate racing with realtime flag changes
Date: Thu, 12 Nov 2026 16:46:14 -0500	[thread overview]
Message-ID: <20261112214604.67875-11-mason@kernel.org> (raw)
In-Reply-To: <20261112214604.67875-1-mason@kernel.org>

On a zoned XFS, fallocate() can dereference a NULL pointer if the
realtime flag of the file is set during the call.

xfs_file_fallocate() reserves zoned space only for a zoned inode, and
tests for that before it takes the iolock. FS_IOC_FSSETXATTR can change
the realtime flag of a file with no blocks in that gap.
xfs_falloc_force_zero() then sees a zoned inode and reads the
reservation, which is NULL:

    fallocate(FALLOC_FL_ZERO_RANGE)     FS_IOC_FSSETXATTR
    ===============================     =================
                                        takes the iolock
    sees that the inode is not zoned
    waits for the iolock
                                        sets the realtime flag
                                        drops the iolock
    xfs_falloc_force_zero()
      sees that the inode is zoned
      /* ac is NULL */

The fix used here is to test again under the iolock, and to fail the
call with -EINVAL if the answer has changed, as the write path does.

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

Notes:
    v7->v9: no change
    
    v6->v7:
    - No change.
    - Was 9/10.

 fs/xfs/xfs_file.c | 41 ++++++++++++++++++++++++++++++++---------
 1 file changed, 32 insertions(+), 9 deletions(-)

diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c
index 5fa8b07a779d..78c9668c806b 100644
--- a/fs/xfs/xfs_file.c
+++ b/fs/xfs/xfs_file.c
@@ -1573,6 +1573,21 @@ xfs_falloc_allocate_range(
 		 FALLOC_FL_ZERO_RANGE |	FALLOC_FL_INSERT_RANGE |	\
 		 FALLOC_FL_UNSHARE_RANGE | FALLOC_FL_WRITE_ZEROES)
 
+/*
+ * For zoned file systems, zeroing the first and last block of a hole punch
+ * requires allocating a new block to rewrite the remaining data and new zeroes
+ * out of place, which needs a space reservation.
+ */
+static inline bool
+xfs_falloc_needs_zoned_resv(
+	struct xfs_inode	*ip,
+	int			mode)
+{
+	return xfs_is_zoned_inode(ip) &&
+		(mode & (FALLOC_FL_PUNCH_HOLE | FALLOC_FL_ZERO_RANGE |
+			 FALLOC_FL_COLLAPSE_RANGE));
+}
+
 STATIC long
 __xfs_file_fallocate(
 	struct file		*file,
@@ -1591,6 +1606,19 @@ __xfs_file_fallocate(
 	if (error)
 		goto out_unlock;
 
+	/*
+	 * The caller looked at the realtime flag before we took the IOLOCK, to
+	 * decide if it has to reserve space.  Bail out if the flag has changed
+	 * since.
+	 */
+	if (xfs_falloc_needs_zoned_resv(ip, mode) != !!ac) {
+		xfs_warn_ratelimited(ip->i_mount,
+			"RT flag modifying during fallocate for inode 0x%llx.",
+			inode->i_ino);
+		error = -EINVAL;
+		goto out_unlock;
+	}
+
 	/*
 	 * Must wait for all AIO to complete before we continue as AIO can
 	 * change the file size on completion without holding any locks we
@@ -1686,16 +1714,11 @@ xfs_file_fallocate(
 		return -EOPNOTSUPP;
 
 	/*
-	 * For zoned file systems, zeroing the first and last block of a hole
-	 * punch requires allocating a new block to rewrite the remaining data
-	 * and new zeroes out of place.  Get a reservations for those before
-	 * taking the iolock.  Dip into the reserved pool because we are
-	 * expected to be able to punch a hole even on a completely full
-	 * file system.
+	 * Get the reservation before taking the iolock.  Dip into the reserved
+	 * pool because we are expected to be able to punch a hole even on a
+	 * completely full file system.
 	 */
-	if (xfs_is_zoned_inode(XFS_I(inode)) &&
-	    (mode & (FALLOC_FL_PUNCH_HOLE | FALLOC_FL_ZERO_RANGE |
-		     FALLOC_FL_COLLAPSE_RANGE)))
+	if (xfs_falloc_needs_zoned_resv(XFS_I(inode), mode))
 		return xfs_file_zoned_fallocate(file, mode, offset, len);
 	return __xfs_file_fallocate(file, mode, offset, len, NULL);
 }
-- 
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 ` Chris Mason [this message]
2026-11-12 22:11   ` [PATCH v9 10/14] xfs: refuse fallocate racing with realtime flag changes 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 ` [PATCH v9 12/14] xfs: restart faults racing with realtime flag changes Chris Mason
2026-11-12 22:08   ` 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-11-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.