|
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 |
|
@@ -386,6 +387,27 @@ static ssize_t blkdev_direct_IO(struct kiocb *iocb, struct iov_iter *iter) |
386 | 387 | return __blkdev_direct_IO(iocb, iter, bio_max_segs(nr_pages)); |
387 | 388 | } |
388 | 389 |
|
| 390 | +static int blkdev_iomap_begin(struct inode *inode, loff_t offset, loff_t length, |
| 391 | + unsigned int flags, struct iomap *iomap, struct iomap *srcmap) |
| 392 | +{ |
| 393 | + struct block_device *bdev = I_BDEV(inode); |
| 394 | + loff_t isize = i_size_read(inode); |
| 395 | + |
| 396 | + iomap->bdev = bdev; |
| 397 | + iomap->offset = ALIGN_DOWN(offset, bdev_logical_block_size(bdev)); |
| 398 | + if (iomap->offset >= isize) |
| 399 | + return -EIO; |
| 400 | + iomap->type = IOMAP_MAPPED; |
| 401 | + iomap->addr = iomap->offset; |
| 402 | + iomap->length = isize - iomap->offset; |
| 403 | + iomap->flags |= IOMAP_F_BUFFER_HEAD; |
| 404 | + return 0; |
| 405 | +} |
| 406 | + |
| 407 | +static const struct iomap_ops blkdev_iomap_ops = { |
| 408 | + .iomap_begin = blkdev_iomap_begin, |
| 409 | +}; |
| 410 | + |
389 | 411 | static int blkdev_writepage(struct page *page, struct writeback_control *wbc) |
390 | 412 | { |
391 | 413 | return block_write_full_page(page, blkdev_get_block, wbc); |
@@ -556,6 +578,11 @@ blkdev_direct_write(struct kiocb *iocb, struct iov_iter *from) |
556 | 578 | return written; |
557 | 579 | } |
558 | 580 |
|
| 581 | +static ssize_t blkdev_buffered_write(struct kiocb *iocb, struct iov_iter *from) |
| 582 | +{ |
| 583 | + return iomap_file_buffered_write(iocb, from, &blkdev_iomap_ops); |
| 584 | +} |
| 585 | + |
559 | 586 | /* |
560 | 587 | * Write data to the block device. Only intended for the block device itself |
561 | 588 | * and the raw driver which basically is a fake block device. |
@@ -605,9 +632,9 @@ static ssize_t blkdev_write_iter(struct kiocb *iocb, struct iov_iter *from) |
605 | 632 | ret = blkdev_direct_write(iocb, from); |
606 | 633 | if (ret >= 0 && iov_iter_count(from)) |
607 | 634 | ret = direct_write_fallback(iocb, from, ret, |
608 | | - generic_perform_write(iocb, from)); |
| 635 | + blkdev_buffered_write(iocb, from)); |
609 | 636 | } else { |
610 | | - ret = generic_perform_write(iocb, from); |
| 637 | + ret = blkdev_buffered_write(iocb, from); |
611 | 638 | } |
612 | 639 |
|
613 | 640 | if (ret > 0) |
|
0 commit comments