From: John Garry john.g.garry@oracle.com
maillist inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I9VTE3 CVE: NA
Reference: https://lore.kernel.org/all/20240326133813.3224593-1-john.g.garry@oracle.com...
--------------------------------
Support atomic writes by producing a single BIO with REQ_ATOMIC flag set.
We rely on the FS to guarantee extent alignment, such that an atomic write should never straddle two or more extents. The FS should also check for validity of an atomic write length/alignment.
Signed-off-by: John Garry john.g.garry@oracle.com Signed-off-by: Long Li leo.lilong@huawei.com --- fs/iomap/direct-io.c | 10 ++++++++++ 1 file changed, 10 insertions(+)
diff --git a/fs/iomap/direct-io.c b/fs/iomap/direct-io.c index 6cdacdd141f6..063ea9eb8afb 100644 --- a/fs/iomap/direct-io.c +++ b/fs/iomap/direct-io.c @@ -234,6 +234,7 @@ static loff_t iomap_dio_bio_actor(struct inode *inode, loff_t pos, loff_t length, struct iomap_dio *dio, struct iomap *iomap) { + bool is_atomic = dio->iocb->ki_flags & IOCB_ATOMIC; unsigned int blkbits = blksize_bits(bdev_logical_block_size(iomap->bdev)); unsigned int zeroing_size, pad; unsigned int align = iov_iter_alignment(dio->submit.iter); @@ -307,6 +308,7 @@ iomap_dio_bio_actor(struct inode *inode, loff_t pos, loff_t length, bio->bi_iter.bi_sector = iomap_sector(iomap, pos); bio->bi_write_hint = dio->iocb->ki_hint; bio->bi_ioprio = dio->iocb->ki_ioprio; + bio->bi_private = dio; bio->bi_end_io = iomap_dio_bio_end_io;
@@ -323,8 +325,16 @@ iomap_dio_bio_actor(struct inode *inode, loff_t pos, loff_t length, }
n = bio->bi_iter.bi_size; + if (is_atomic && (n != orig_count)) { + /* This bio should have covered the complete length */ + ret = -EINVAL; + bio_put(bio); + goto out; + } if (dio->flags & IOMAP_DIO_WRITE) { bio->bi_opf = REQ_OP_WRITE | REQ_SYNC | REQ_IDLE; + if (is_atomic) + bio->bi_opf |= REQ_ATOMIC; if (use_fua) bio->bi_opf |= REQ_FUA; else