diff mbox series

block: Don't allow an atomic write be truncated in blkdev_write_iter()

Message ID 20241127092318.632790-1-john.g.garry@oracle.com (mailing list archive)
State New
Headers show
Series block: Don't allow an atomic write be truncated in blkdev_write_iter() | expand

Commit Message

John Garry Nov. 27, 2024, 9:23 a.m. UTC
A write which goes past the end of the bdev in blkdev_write_iter() will
be truncated. Truncating cannot tolerated for an atomic write, so error
that condition.

Fixes: caf336f81b3a ("block: Add fops atomic write support")
Signed-off-by: John Garry <john.g.garry@oracle.com>

Comments

Christoph Hellwig Nov. 27, 2024, 9:31 a.m. UTC | #1
Looks good:

Reviewed-by: Christoph Hellwig <hch@lst.de>
Jens Axboe Nov. 27, 2024, 10:05 p.m. UTC | #2
On Wed, 27 Nov 2024 09:23:18 +0000, John Garry wrote:
> A write which goes past the end of the bdev in blkdev_write_iter() will
> be truncated. Truncating cannot tolerated for an atomic write, so error
> that condition.
> 
> 

Applied, thanks!

[1/1] block: Don't allow an atomic write be truncated in blkdev_write_iter()
      commit: 2cbd51f1f8739fd2fdf4bae1386bcf75ce0176ba

Best regards,
diff mbox series

Patch

diff --git a/block/fops.c b/block/fops.c
index 2d01c9007681..13a67940d040 100644
--- a/block/fops.c
+++ b/block/fops.c
@@ -677,6 +677,7 @@  static ssize_t blkdev_write_iter(struct kiocb *iocb, struct iov_iter *from)
 	struct file *file = iocb->ki_filp;
 	struct inode *bd_inode = bdev_file_inode(file);
 	struct block_device *bdev = I_BDEV(bd_inode);
+	bool atomic = iocb->ki_flags & IOCB_ATOMIC;
 	loff_t size = bdev_nr_bytes(bdev);
 	size_t shorted = 0;
 	ssize_t ret;
@@ -696,7 +697,7 @@  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) {
+	if (atomic) {
 		ret = generic_atomic_write_valid(iocb, from);
 		if (ret)
 			return ret;
@@ -704,6 +705,8 @@  static ssize_t blkdev_write_iter(struct kiocb *iocb, struct iov_iter *from)
 
 	size -= iocb->ki_pos;
 	if (iov_iter_count(from) > size) {
+		if (atomic)
+			return -EINVAL;
 		shorted = iov_iter_count(from) - size;
 		iov_iter_truncate(from, size);
 	}