]> www.infradead.org Git - users/hch/xfs.git/commitdiff
xfs: refine the unaligned check for always COW inodes in xfs_file_dio_write
authorChristoph Hellwig <hch@lst.de>
Fri, 27 Oct 2023 07:58:24 +0000 (09:58 +0200)
committerChristoph Hellwig <hch@lst.de>
Tue, 5 Nov 2024 08:29:51 +0000 (09:29 +0100)
For always COW inodes we also must check the alignment of each individual
iovec segment, as they could end up with different I/Os due to the way
bio_iov_iter_get_pages works, and we'd then overwrite an already written
block.

Signed-off-by: Christoph Hellwig <hch@lst.de>
fs/xfs/xfs_file.c

index a9995878f5985b92b8227a0207a6f8698df048b5..a952d3faa06611e650f2c41f600c7a8ac9b39681 100644 (file)
@@ -721,7 +721,16 @@ xfs_file_dio_write(
        /* direct I/O must be aligned to device logical sector size */
        if ((iocb->ki_pos | count) & target->bt_logical_sectormask)
                return -EINVAL;
-       if ((iocb->ki_pos | count) & ip->i_mount->m_blockmask)
+
+       /*
+        * For always COW inodes we also must check the alignment of each
+        * individual iovec segment, as they could end up with different
+        * I/Os due to the way bio_iov_iter_get_pages works, and we'd
+        * then overwrite an already written block.
+        */
+       if (((iocb->ki_pos | count) & ip->i_mount->m_blockmask) ||
+           (xfs_is_always_cow_inode(ip) &&
+            (iov_iter_alignment(from) & ip->i_mount->m_blockmask)))
                return xfs_file_dio_write_unaligned(ip, iocb, from);
        return xfs_file_dio_write_aligned(ip, iocb, from);
 }