diff options
| author | Christoph Hellwig <hch@lst.de> | 2023-10-27 10:58:24 +0300 |
|---|---|---|
| committer | Christoph Hellwig <hch@lst.de> | 2025-03-03 18:16:44 +0300 |
| commit | 6fff175279e4682b4eff25182808e0b1c90347cf (patch) | |
| tree | e479e6c1994ad90546ca61bb3c91ea766531a54a | |
| parent | 8ae4c8cec0bb4f437c16ba5f4b4d63a1f3a87062 (diff) | |
| download | linux-6fff175279e4682b4eff25182808e0b1c90347cf.tar.xz | |
xfs: refine the unaligned check for always COW inodes in xfs_file_dio_write
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. The existing always_cow sysctl based code doesn't catch this
because nothing enforces that blocks aren't rewritten, but for zoned XFS
on sequential write required zones this is a hard error.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: "Darrick J. Wong" <djwong@kernel.org>
| -rw-r--r-- | fs/xfs/xfs_file.c | 11 |
1 files changed, 10 insertions, 1 deletions
diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c index a81c3e943f20..d66eea31b60a 100644 --- a/fs/xfs/xfs_file.c +++ b/fs/xfs/xfs_file.c @@ -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); } |
