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;
}
static bool blkdev_dio_invalid(struct block_device *bdev, loff_t pos,
struct iov_iter *iter, bool is_atomic)
static bool blkdev_dio_invalid(struct block_device *bdev, struct kiocb *iocb,
struct iov_iter *iter)
{
if (is_atomic && !generic_atomic_write_valid(iter, pos))
return true;
return pos & (bdev_logical_block_size(bdev) - 1) ||
return iocb->ki_pos & (bdev_logical_block_size(bdev) - 1) ||
!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)
{
struct block_device *bdev = I_BDEV(iocb->ki_filp->f_mapping->host);
bool is_atomic = iocb->ki_flags & IOCB_ATOMIC;
unsigned int nr_pages;
if (!iov_iter_count(iter))
return 0;
if (blkdev_dio_invalid(bdev, iocb->ki_pos, iter, is_atomic))
if (blkdev_dio_invalid(bdev, iocb, iter))
return -EINVAL;
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,
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 __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)
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;
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)
return -EOPNOTSUPP;
if (iocb->ki_flags & IOCB_ATOMIC) {
ret = generic_atomic_write_valid(iocb, from);
if (ret)
return ret;
}
size -= iocb->ki_pos;
if (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;
}
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);
if (!iter_is_ubuf(iter))
return false;
return -EINVAL;
if (!is_power_of_2(len))
return false;
return -EINVAL;
if (!IS_ALIGNED(pos, len))
return false;
if (!IS_ALIGNED(iocb->ki_pos, len))
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;
}
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 = { }
#endif /* _LINUX_BLKDEV_H */

View File

@ -3726,6 +3726,6 @@ static inline bool vfs_empty_path(int dfd, const char __user *path)
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 */