Skip to content

Commit ca3557a

Browse files
committed
Merge patch series "alloc misaligned vectors for zoned XFS v2"
Christoph Hellwig <hch@lst.de> says: This series enables the new block layer support for misaligned individual vectors for zoned XFS. The first patch is the from Qu and supposedly already applied to the vfs iomap 6.19 branch, but I can't find it there. The next two are small fixups for it, and the last one makes use of this new functionality in XFS. * patches from https://patch.msgid.link/20251031131045.1613229-1-hch@lst.de: xfs: support sub-block aligned vectors in always COW mode iomap: add IOMAP_DIO_FSBLOCK_ALIGNED flag Link: https://patch.msgid.link/20251031131045.1613229-1-hch@lst.de Signed-off-by: Christian Brauner <brauner@kernel.org>
2 parents 560507c + 8caec6c commit ca3557a

4 files changed

Lines changed: 38 additions & 15 deletions

File tree

fs/iomap/direct-io.c

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -336,8 +336,18 @@ static int iomap_dio_bio_iter(struct iomap_iter *iter, struct iomap_dio *dio)
336336
int nr_pages, ret = 0;
337337
u64 copied = 0;
338338
size_t orig_count;
339+
unsigned int alignment;
339340

340-
if ((pos | length) & (bdev_logical_block_size(iomap->bdev) - 1))
341+
/*
342+
* File systems that write out of place and always allocate new blocks
343+
* need each bio to be block aligned as that's the unit of allocation.
344+
*/
345+
if (dio->flags & IOMAP_DIO_FSBLOCK_ALIGNED)
346+
alignment = fs_block_size;
347+
else
348+
alignment = bdev_logical_block_size(iomap->bdev);
349+
350+
if ((pos | length) & (alignment - 1))
341351
return -EINVAL;
342352

343353
if (dio->flags & IOMAP_DIO_WRITE) {
@@ -434,7 +444,7 @@ static int iomap_dio_bio_iter(struct iomap_iter *iter, struct iomap_dio *dio)
434444
bio->bi_end_io = iomap_dio_bio_end_io;
435445

436446
ret = bio_iov_iter_get_pages(bio, dio->submit.iter,
437-
bdev_logical_block_size(iomap->bdev) - 1);
447+
alignment - 1);
438448
if (unlikely(ret)) {
439449
/*
440450
* We have to stop part way through an IO. We must fall
@@ -639,6 +649,9 @@ __iomap_dio_rw(struct kiocb *iocb, struct iov_iter *iter,
639649
if (iocb->ki_flags & IOCB_NOWAIT)
640650
iomi.flags |= IOMAP_NOWAIT;
641651

652+
if (dio_flags & IOMAP_DIO_FSBLOCK_ALIGNED)
653+
dio->flags |= IOMAP_DIO_FSBLOCK_ALIGNED;
654+
642655
if (iov_iter_rw(iter) == READ) {
643656
/* reads can always complete inline */
644657
dio->flags |= IOMAP_DIO_INLINE_COMP;

fs/iomap/trace.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -122,9 +122,10 @@ DEFINE_RANGE_EVENT(iomap_zero_iter);
122122

123123

124124
#define IOMAP_DIO_STRINGS \
125-
{IOMAP_DIO_FORCE_WAIT, "DIO_FORCE_WAIT" }, \
126-
{IOMAP_DIO_OVERWRITE_ONLY, "DIO_OVERWRITE_ONLY" }, \
127-
{IOMAP_DIO_PARTIAL, "DIO_PARTIAL" }
125+
{IOMAP_DIO_FORCE_WAIT, "DIO_FORCE_WAIT" }, \
126+
{IOMAP_DIO_OVERWRITE_ONLY, "DIO_OVERWRITE_ONLY" }, \
127+
{IOMAP_DIO_PARTIAL, "DIO_PARTIAL" }, \
128+
{IOMAP_DIO_FSBLOCK_ALIGNED, "DIO_FSBLOCK_ALIGNED" }
128129

129130
DECLARE_EVENT_CLASS(iomap_class,
130131
TP_PROTO(struct inode *inode, struct iomap *iomap),

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);

include/linux/iomap.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -553,6 +553,14 @@ struct iomap_dio_ops {
553553
*/
554554
#define IOMAP_DIO_PARTIAL (1 << 2)
555555

556+
/*
557+
* Ensure each bio is aligned to fs block size.
558+
*
559+
* For filesystems which need to calculate/verify the checksum of each fs
560+
* block. Otherwise they may not be able to handle unaligned bios.
561+
*/
562+
#define IOMAP_DIO_FSBLOCK_ALIGNED (1 << 3)
563+
556564
ssize_t iomap_dio_rw(struct kiocb *iocb, struct iov_iter *iter,
557565
const struct iomap_ops *ops, const struct iomap_dio_ops *dops,
558566
unsigned int dio_flags, void *private, size_t done_before);

0 commit comments

Comments
 (0)