Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

block: use iomap for writes to block devices

Use iomap in buffer_head compat mode to write to block devices.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Luis Chamberlain <mcgrof@kernel.org>
Reviewed-by: Pankaj Raghav <p.raghav@samsung.com>
Reviewed-by: Hannes Reinecke <hare@suse.de>
Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
Reviewed-by: Christian Brauner <brauner@kernel.org>
Link: https://lore.kernel.org/r/20230801172201.1923299-6-hch@lst.de
Signed-off-by: Jens Axboe <axboe@kernel.dk>

authored by

Christoph Hellwig and committed by
Jens Axboe
487c607d a05f7bd9

+30 -2
+1
block/Kconfig
··· 5 5 menuconfig BLOCK 6 6 bool "Enable the block layer" if EXPERT 7 7 default y 8 + select FS_IOMAP 8 9 select SBITMAP 9 10 help 10 11 Provide block layer support for the kernel.
+29 -2
block/fops.c
··· 15 15 #include <linux/falloc.h> 16 16 #include <linux/suspend.h> 17 17 #include <linux/fs.h> 18 + #include <linux/iomap.h> 18 19 #include <linux/module.h> 19 20 #include "blk.h" 20 21 ··· 387 386 return __blkdev_direct_IO(iocb, iter, bio_max_segs(nr_pages)); 388 387 } 389 388 389 + static int blkdev_iomap_begin(struct inode *inode, loff_t offset, loff_t length, 390 + unsigned int flags, struct iomap *iomap, struct iomap *srcmap) 391 + { 392 + struct block_device *bdev = I_BDEV(inode); 393 + loff_t isize = i_size_read(inode); 394 + 395 + iomap->bdev = bdev; 396 + iomap->offset = ALIGN_DOWN(offset, bdev_logical_block_size(bdev)); 397 + if (iomap->offset >= isize) 398 + return -EIO; 399 + iomap->type = IOMAP_MAPPED; 400 + iomap->addr = iomap->offset; 401 + iomap->length = isize - iomap->offset; 402 + iomap->flags |= IOMAP_F_BUFFER_HEAD; 403 + return 0; 404 + } 405 + 406 + static const struct iomap_ops blkdev_iomap_ops = { 407 + .iomap_begin = blkdev_iomap_begin, 408 + }; 409 + 390 410 static int blkdev_writepage(struct page *page, struct writeback_control *wbc) 391 411 { 392 412 return block_write_full_page(page, blkdev_get_block, wbc); ··· 578 556 return written; 579 557 } 580 558 559 + static ssize_t blkdev_buffered_write(struct kiocb *iocb, struct iov_iter *from) 560 + { 561 + return iomap_file_buffered_write(iocb, from, &blkdev_iomap_ops); 562 + } 563 + 581 564 /* 582 565 * Write data to the block device. Only intended for the block device itself 583 566 * and the raw driver which basically is a fake block device. ··· 632 605 ret = blkdev_direct_write(iocb, from); 633 606 if (ret >= 0 && iov_iter_count(from)) 634 607 ret = direct_write_fallback(iocb, from, ret, 635 - generic_perform_write(iocb, from)); 608 + blkdev_buffered_write(iocb, from)); 636 609 } else { 637 - ret = generic_perform_write(iocb, from); 610 + ret = blkdev_buffered_write(iocb, from); 638 611 } 639 612 640 613 if (ret > 0)