]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
xfs: ignore HW which cannot atomic write a single block
authorDarrick J. Wong <djwong@kernel.org>
Wed, 7 May 2025 21:18:26 +0000 (14:18 -0700)
committerDarrick J. Wong <djwong@kernel.org>
Wed, 7 May 2025 21:25:31 +0000 (14:25 -0700)
Currently only HW which can write at least 1x block is supported.

For supporting atomic writes > 1x block, a CoW-based method will also be
used and this will not be resticted to using HW which can write >= 1x
block.

However for deciding if HW-based atomic writes can be used, we need to
start adding checks for write length < HW min, which complicates the
code.  Indeed, a statx field similar to unit_max_opt should also be
added for this minimum, which is undesirable.

HW which can only write > 1x blocks would be uncommon and quite weird,
so let's just not support it.

Signed-off-by: "Darrick J. Wong" <djwong@kernel.org>
Signed-off-by: John Garry <john.g.garry@oracle.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
fs/xfs/xfs_buf.c
fs/xfs/xfs_buf.h
fs/xfs/xfs_inode.h

index e2374c503e790e6a1a29e119828e85effd8b7e05..d52d9587b42c66b6ad8fd6c12fd7b26b7be53348 100644 (file)
@@ -1722,11 +1722,23 @@ static inline void
 xfs_configure_buftarg_atomic_writes(
        struct xfs_buftarg      *btp)
 {
+       struct xfs_mount        *mp = btp->bt_mount;
        unsigned int            min_bytes, max_bytes;
 
        min_bytes = bdev_atomic_write_unit_min_bytes(btp->bt_bdev);
        max_bytes = bdev_atomic_write_unit_max_bytes(btp->bt_bdev);
 
+       /*
+        * Ignore atomic write geometry that is nonsense or doesn't even cover
+        * a single fsblock.
+        */
+       if (min_bytes > max_bytes ||
+           min_bytes > mp->m_sb.sb_blocksize ||
+           max_bytes < mp->m_sb.sb_blocksize) {
+               min_bytes = 0;
+               max_bytes = 0;
+       }
+
        btp->bt_bdev_awu_min = min_bytes;
        btp->bt_bdev_awu_max = max_bytes;
 }
index a7026fb255c4c7f80229ba5b433cc9d782bd2893..9d2ab567cf814f103eccbf5bbdae938f878625a4 100644 (file)
@@ -112,7 +112,7 @@ struct xfs_buftarg {
        struct percpu_counter   bt_readahead_count;
        struct ratelimit_state  bt_ioerror_rl;
 
-       /* Atomic write unit values */
+       /* Atomic write unit values, bytes */
        unsigned int            bt_bdev_awu_min;
        unsigned int            bt_bdev_awu_max;
 
index d3471a7418b938152d758ea830533012098ce226..d7e2b902ef5c97242a2ccf765b6c0378374de111 100644 (file)
@@ -358,15 +358,7 @@ static inline bool xfs_inode_has_bigrtalloc(const struct xfs_inode *ip)
 
 static inline bool xfs_inode_can_hw_atomic_write(const struct xfs_inode *ip)
 {
-       struct xfs_mount        *mp = ip->i_mount;
-       struct xfs_buftarg      *target = xfs_inode_buftarg(ip);
-
-       if (mp->m_sb.sb_blocksize < target->bt_bdev_awu_min)
-               return false;
-       if (mp->m_sb.sb_blocksize > target->bt_bdev_awu_max)
-               return false;
-
-       return true;
+       return xfs_inode_buftarg(ip)->bt_bdev_awu_max > 0;
 }
 
 /*