Merge branch 'for-6.13/block-atomic' into for-6.13/block

Merge in block/fs prep patches for the atomic write support.

* for-6.13/block-atomic:
  block: Add bdev atomic write limits helpers
  fs/block: Check for IOCB_DIRECT in generic_atomic_write_valid()
  block/fs: Pass an iocb to generic_atomic_write_valid()
This commit is contained in:
Jens Axboe 2024-10-22 08:21:51 -06:00
commit fdad1a20cd
4 changed files with 38 additions and 17 deletions

View File

@ -35,13 +35,10 @@ static blk_opf_t dio_bio_write_op(struct kiocb *iocb)
return opf; return opf;
} }
static bool blkdev_dio_invalid(struct block_device *bdev, loff_t pos, static bool blkdev_dio_invalid(struct block_device *bdev, struct kiocb *iocb,
struct iov_iter *iter, bool is_atomic) struct iov_iter *iter)
{ {
if (is_atomic && !generic_atomic_write_valid(iter, pos)) return iocb->ki_pos & (bdev_logical_block_size(bdev) - 1) ||
return true;
return pos & (bdev_logical_block_size(bdev) - 1) ||
!bdev_iter_is_aligned(bdev, iter); !bdev_iter_is_aligned(bdev, iter);
} }
@ -368,13 +365,12 @@ static ssize_t __blkdev_direct_IO_async(struct kiocb *iocb,
static ssize_t blkdev_direct_IO(struct kiocb *iocb, struct iov_iter *iter) static ssize_t blkdev_direct_IO(struct kiocb *iocb, struct iov_iter *iter)
{ {
struct block_device *bdev = I_BDEV(iocb->ki_filp->f_mapping->host); struct block_device *bdev = I_BDEV(iocb->ki_filp->f_mapping->host);
bool is_atomic = iocb->ki_flags & IOCB_ATOMIC;
unsigned int nr_pages; unsigned int nr_pages;
if (!iov_iter_count(iter)) if (!iov_iter_count(iter))
return 0; return 0;
if (blkdev_dio_invalid(bdev, iocb->ki_pos, iter, is_atomic)) if (blkdev_dio_invalid(bdev, iocb, iter))
return -EINVAL; return -EINVAL;
nr_pages = bio_iov_vecs_to_alloc(iter, BIO_MAX_VECS + 1); nr_pages = bio_iov_vecs_to_alloc(iter, BIO_MAX_VECS + 1);
@ -383,7 +379,7 @@ static ssize_t blkdev_direct_IO(struct kiocb *iocb, struct iov_iter *iter)
return __blkdev_direct_IO_simple(iocb, iter, bdev, return __blkdev_direct_IO_simple(iocb, iter, bdev,
nr_pages); nr_pages);
return __blkdev_direct_IO_async(iocb, iter, bdev, nr_pages); return __blkdev_direct_IO_async(iocb, iter, bdev, nr_pages);
} else if (is_atomic) { } else if (iocb->ki_flags & IOCB_ATOMIC) {
return -EINVAL; return -EINVAL;
} }
return __blkdev_direct_IO(iocb, iter, bdev, bio_max_segs(nr_pages)); return __blkdev_direct_IO(iocb, iter, bdev, bio_max_segs(nr_pages));
@ -625,7 +621,7 @@ static int blkdev_open(struct inode *inode, struct file *filp)
if (!bdev) if (!bdev)
return -ENXIO; return -ENXIO;
if (bdev_can_atomic_write(bdev) && filp->f_flags & O_DIRECT) if (bdev_can_atomic_write(bdev))
filp->f_mode |= FMODE_CAN_ATOMIC_WRITE; filp->f_mode |= FMODE_CAN_ATOMIC_WRITE;
ret = bdev_open(bdev, mode, filp->private_data, NULL, filp); ret = bdev_open(bdev, mode, filp->private_data, NULL, filp);
@ -700,6 +696,12 @@ static ssize_t blkdev_write_iter(struct kiocb *iocb, struct iov_iter *from)
if ((iocb->ki_flags & (IOCB_NOWAIT | IOCB_DIRECT)) == IOCB_NOWAIT) if ((iocb->ki_flags & (IOCB_NOWAIT | IOCB_DIRECT)) == IOCB_NOWAIT)
return -EOPNOTSUPP; return -EOPNOTSUPP;
if (iocb->ki_flags & IOCB_ATOMIC) {
ret = generic_atomic_write_valid(iocb, from);
if (ret)
return ret;
}
size -= iocb->ki_pos; size -= iocb->ki_pos;
if (iov_iter_count(from) > size) { if (iov_iter_count(from) > size) {
shorted = iov_iter_count(from) - size; shorted = iov_iter_count(from) - size;

View File

@ -1830,18 +1830,21 @@ int generic_file_rw_checks(struct file *file_in, struct file *file_out)
return 0; return 0;
} }
bool generic_atomic_write_valid(struct iov_iter *iter, loff_t pos) int generic_atomic_write_valid(struct kiocb *iocb, struct iov_iter *iter)
{ {
size_t len = iov_iter_count(iter); size_t len = iov_iter_count(iter);
if (!iter_is_ubuf(iter)) if (!iter_is_ubuf(iter))
return false; return -EINVAL;
if (!is_power_of_2(len)) if (!is_power_of_2(len))
return false; return -EINVAL;
if (!IS_ALIGNED(pos, len)) if (!IS_ALIGNED(iocb->ki_pos, len))
return false; return -EINVAL;
return true; if (!(iocb->ki_flags & IOCB_DIRECT))
return -EOPNOTSUPP;
return 0;
} }

View File

@ -1682,6 +1682,22 @@ static inline bool bdev_can_atomic_write(struct block_device *bdev)
return true; return true;
} }
static inline unsigned int
bdev_atomic_write_unit_min_bytes(struct block_device *bdev)
{
if (!bdev_can_atomic_write(bdev))
return 0;
return queue_atomic_write_unit_min_bytes(bdev_get_queue(bdev));
}
static inline unsigned int
bdev_atomic_write_unit_max_bytes(struct block_device *bdev)
{
if (!bdev_can_atomic_write(bdev))
return 0;
return queue_atomic_write_unit_max_bytes(bdev_get_queue(bdev));
}
#define DEFINE_IO_COMP_BATCH(name) struct io_comp_batch name = { } #define DEFINE_IO_COMP_BATCH(name) struct io_comp_batch name = { }
#endif /* _LINUX_BLKDEV_H */ #endif /* _LINUX_BLKDEV_H */

View File

@ -3726,6 +3726,6 @@ static inline bool vfs_empty_path(int dfd, const char __user *path)
return !c; return !c;
} }
bool generic_atomic_write_valid(struct iov_iter *iter, loff_t pos); int generic_atomic_write_valid(struct kiocb *iocb, struct iov_iter *iter);
#endif /* _LINUX_FS_H */ #endif /* _LINUX_FS_H */