Skip to content

Commit 8caec6c

Browse files
Christoph Hellwigbrauner
authored andcommitted
xfs: support sub-block aligned vectors in always COW mode
Now that the block layer and iomap have grown support to indicate the bio sector size explicitly instead of assuming the device sector size, we can ask for logical block size alignment and thus support direct I/O writes where the overall size is logical block size aligned, but the boundaries between vectors might not be. Signed-off-by: Christoph Hellwig <hch@lst.de> Link: https://patch.msgid.link/20251031131045.1613229-3-hch@lst.de Reviewed-by: Darrick J. Wong <djwong@kernel.org> Signed-off-by: Christian Brauner <brauner@kernel.org>
1 parent 001397f commit 8caec6c

1 file changed

Lines changed: 11 additions & 10 deletions

File tree

fs/xfs/xfs_file.c

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -676,8 +676,17 @@ xfs_file_dio_write_aligned(
676676
struct xfs_zone_alloc_ctx *ac)
677677
{
678678
unsigned int iolock = XFS_IOLOCK_SHARED;
679+
unsigned int dio_flags = 0;
679680
ssize_t ret;
680681

682+
/*
683+
* For always COW inodes, each bio must be aligned to the file system
684+
* block size and not just the device sector size because we need to
685+
* allocate a block-aligned amount of space for each write.
686+
*/
687+
if (xfs_is_always_cow_inode(ip))
688+
dio_flags |= IOMAP_DIO_FSBLOCK_ALIGNED;
689+
681690
ret = xfs_ilock_iocb_for_write(iocb, &iolock);
682691
if (ret)
683692
return ret;
@@ -695,7 +704,7 @@ xfs_file_dio_write_aligned(
695704
iolock = XFS_IOLOCK_SHARED;
696705
}
697706
trace_xfs_file_direct_write(iocb, from);
698-
ret = iomap_dio_rw(iocb, from, ops, dops, 0, ac, 0);
707+
ret = iomap_dio_rw(iocb, from, ops, dops, dio_flags, ac, 0);
699708
out_unlock:
700709
xfs_iunlock(ip, iolock);
701710
return ret;
@@ -892,15 +901,7 @@ xfs_file_dio_write(
892901
if ((iocb->ki_pos | count) & target->bt_logical_sectormask)
893902
return -EINVAL;
894903

895-
/*
896-
* For always COW inodes we also must check the alignment of each
897-
* individual iovec segment, as they could end up with different
898-
* I/Os due to the way bio_iov_iter_get_pages works, and we'd
899-
* then overwrite an already written block.
900-
*/
901-
if (((iocb->ki_pos | count) & ip->i_mount->m_blockmask) ||
902-
(xfs_is_always_cow_inode(ip) &&
903-
(iov_iter_alignment(from) & ip->i_mount->m_blockmask)))
904+
if ((iocb->ki_pos | count) & ip->i_mount->m_blockmask)
904905
return xfs_file_dio_write_unaligned(ip, iocb, from);
905906
if (xfs_is_zoned_inode(ip))
906907
return xfs_file_dio_write_zoned(ip, iocb, from);

0 commit comments

Comments
 (0)