diff options
-rw-r--r-- | fs/btrfs/inode.c | 8 | ||||
-rw-r--r-- | fs/direct-io.c | 34 | ||||
-rw-r--r-- | include/linux/fs.h | 2 |
3 files changed, 25 insertions, 19 deletions
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 8b1212e8f7a8..348ad81903bd 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -8433,14 +8433,14 @@ out_err: | |||
8433 | return 0; | 8433 | return 0; |
8434 | } | 8434 | } |
8435 | 8435 | ||
8436 | static void btrfs_submit_direct(int rw, struct bio *dio_bio, | 8436 | static void btrfs_submit_direct(struct bio *dio_bio, struct inode *inode, |
8437 | struct inode *inode, loff_t file_offset) | 8437 | loff_t file_offset) |
8438 | { | 8438 | { |
8439 | struct btrfs_dio_private *dip = NULL; | 8439 | struct btrfs_dio_private *dip = NULL; |
8440 | struct bio *io_bio = NULL; | 8440 | struct bio *io_bio = NULL; |
8441 | struct btrfs_io_bio *btrfs_bio; | 8441 | struct btrfs_io_bio *btrfs_bio; |
8442 | int skip_sum; | 8442 | int skip_sum; |
8443 | int write = rw & REQ_WRITE; | 8443 | bool write = (bio_op(dio_bio) == REQ_OP_WRITE); |
8444 | int ret = 0; | 8444 | int ret = 0; |
8445 | 8445 | ||
8446 | skip_sum = BTRFS_I(inode)->flags & BTRFS_INODE_NODATASUM; | 8446 | skip_sum = BTRFS_I(inode)->flags & BTRFS_INODE_NODATASUM; |
@@ -8491,7 +8491,7 @@ static void btrfs_submit_direct(int rw, struct bio *dio_bio, | |||
8491 | dio_data->unsubmitted_oe_range_end; | 8491 | dio_data->unsubmitted_oe_range_end; |
8492 | } | 8492 | } |
8493 | 8493 | ||
8494 | ret = btrfs_submit_direct_hook(rw, dip, skip_sum); | 8494 | ret = btrfs_submit_direct_hook(dio_bio->bi_rw, dip, skip_sum); |
8495 | if (!ret) | 8495 | if (!ret) |
8496 | return; | 8496 | return; |
8497 | 8497 | ||
diff --git a/fs/direct-io.c b/fs/direct-io.c index 1bcdd5dde00d..7c3ce73cb617 100644 --- a/fs/direct-io.c +++ b/fs/direct-io.c | |||
@@ -108,7 +108,8 @@ struct dio_submit { | |||
108 | /* dio_state communicated between submission path and end_io */ | 108 | /* dio_state communicated between submission path and end_io */ |
109 | struct dio { | 109 | struct dio { |
110 | int flags; /* doesn't change */ | 110 | int flags; /* doesn't change */ |
111 | int rw; | 111 | int op; |
112 | int op_flags; | ||
112 | blk_qc_t bio_cookie; | 113 | blk_qc_t bio_cookie; |
113 | struct block_device *bio_bdev; | 114 | struct block_device *bio_bdev; |
114 | struct inode *inode; | 115 | struct inode *inode; |
@@ -163,7 +164,7 @@ static inline int dio_refill_pages(struct dio *dio, struct dio_submit *sdio) | |||
163 | ret = iov_iter_get_pages(sdio->iter, dio->pages, LONG_MAX, DIO_PAGES, | 164 | ret = iov_iter_get_pages(sdio->iter, dio->pages, LONG_MAX, DIO_PAGES, |
164 | &sdio->from); | 165 | &sdio->from); |
165 | 166 | ||
166 | if (ret < 0 && sdio->blocks_available && (dio->rw & WRITE)) { | 167 | if (ret < 0 && sdio->blocks_available && (dio->op == REQ_OP_WRITE)) { |
167 | struct page *page = ZERO_PAGE(0); | 168 | struct page *page = ZERO_PAGE(0); |
168 | /* | 169 | /* |
169 | * A memory fault, but the filesystem has some outstanding | 170 | * A memory fault, but the filesystem has some outstanding |
@@ -242,7 +243,8 @@ static ssize_t dio_complete(struct dio *dio, ssize_t ret, bool is_async) | |||
242 | transferred = dio->result; | 243 | transferred = dio->result; |
243 | 244 | ||
244 | /* Check for short read case */ | 245 | /* Check for short read case */ |
245 | if ((dio->rw == READ) && ((offset + transferred) > dio->i_size)) | 246 | if ((dio->op == REQ_OP_READ) && |
247 | ((offset + transferred) > dio->i_size)) | ||
246 | transferred = dio->i_size - offset; | 248 | transferred = dio->i_size - offset; |
247 | } | 249 | } |
248 | 250 | ||
@@ -273,7 +275,7 @@ static ssize_t dio_complete(struct dio *dio, ssize_t ret, bool is_async) | |||
273 | */ | 275 | */ |
274 | dio->iocb->ki_pos += transferred; | 276 | dio->iocb->ki_pos += transferred; |
275 | 277 | ||
276 | if (dio->rw & WRITE) | 278 | if (dio->op == REQ_OP_WRITE) |
277 | ret = generic_write_sync(dio->iocb, transferred); | 279 | ret = generic_write_sync(dio->iocb, transferred); |
278 | dio->iocb->ki_complete(dio->iocb, ret, 0); | 280 | dio->iocb->ki_complete(dio->iocb, ret, 0); |
279 | } | 281 | } |
@@ -375,7 +377,7 @@ dio_bio_alloc(struct dio *dio, struct dio_submit *sdio, | |||
375 | 377 | ||
376 | bio->bi_bdev = bdev; | 378 | bio->bi_bdev = bdev; |
377 | bio->bi_iter.bi_sector = first_sector; | 379 | bio->bi_iter.bi_sector = first_sector; |
378 | bio->bi_rw = dio->rw; | 380 | bio_set_op_attrs(bio, dio->op, dio->op_flags); |
379 | if (dio->is_async) | 381 | if (dio->is_async) |
380 | bio->bi_end_io = dio_bio_end_aio; | 382 | bio->bi_end_io = dio_bio_end_aio; |
381 | else | 383 | else |
@@ -403,14 +405,13 @@ static inline void dio_bio_submit(struct dio *dio, struct dio_submit *sdio) | |||
403 | dio->refcount++; | 405 | dio->refcount++; |
404 | spin_unlock_irqrestore(&dio->bio_lock, flags); | 406 | spin_unlock_irqrestore(&dio->bio_lock, flags); |
405 | 407 | ||
406 | if (dio->is_async && dio->rw == READ && dio->should_dirty) | 408 | if (dio->is_async && dio->op == REQ_OP_READ && dio->should_dirty) |
407 | bio_set_pages_dirty(bio); | 409 | bio_set_pages_dirty(bio); |
408 | 410 | ||
409 | dio->bio_bdev = bio->bi_bdev; | 411 | dio->bio_bdev = bio->bi_bdev; |
410 | 412 | ||
411 | if (sdio->submit_io) { | 413 | if (sdio->submit_io) { |
412 | sdio->submit_io(dio->rw, bio, dio->inode, | 414 | sdio->submit_io(bio, dio->inode, sdio->logical_offset_in_bio); |
413 | sdio->logical_offset_in_bio); | ||
414 | dio->bio_cookie = BLK_QC_T_NONE; | 415 | dio->bio_cookie = BLK_QC_T_NONE; |
415 | } else | 416 | } else |
416 | dio->bio_cookie = submit_bio(bio); | 417 | dio->bio_cookie = submit_bio(bio); |
@@ -479,14 +480,14 @@ static int dio_bio_complete(struct dio *dio, struct bio *bio) | |||
479 | if (bio->bi_error) | 480 | if (bio->bi_error) |
480 | dio->io_error = -EIO; | 481 | dio->io_error = -EIO; |
481 | 482 | ||
482 | if (dio->is_async && dio->rw == READ && dio->should_dirty) { | 483 | if (dio->is_async && dio->op == REQ_OP_READ && dio->should_dirty) { |
483 | err = bio->bi_error; | 484 | err = bio->bi_error; |
484 | bio_check_pages_dirty(bio); /* transfers ownership */ | 485 | bio_check_pages_dirty(bio); /* transfers ownership */ |
485 | } else { | 486 | } else { |
486 | bio_for_each_segment_all(bvec, bio, i) { | 487 | bio_for_each_segment_all(bvec, bio, i) { |
487 | struct page *page = bvec->bv_page; | 488 | struct page *page = bvec->bv_page; |
488 | 489 | ||
489 | if (dio->rw == READ && !PageCompound(page) && | 490 | if (dio->op == REQ_OP_READ && !PageCompound(page) && |
490 | dio->should_dirty) | 491 | dio->should_dirty) |
491 | set_page_dirty_lock(page); | 492 | set_page_dirty_lock(page); |
492 | put_page(page); | 493 | put_page(page); |
@@ -639,7 +640,7 @@ static int get_more_blocks(struct dio *dio, struct dio_submit *sdio, | |||
639 | * which may decide to handle it or also return an unmapped | 640 | * which may decide to handle it or also return an unmapped |
640 | * buffer head. | 641 | * buffer head. |
641 | */ | 642 | */ |
642 | create = dio->rw & WRITE; | 643 | create = dio->op == REQ_OP_WRITE; |
643 | if (dio->flags & DIO_SKIP_HOLES) { | 644 | if (dio->flags & DIO_SKIP_HOLES) { |
644 | if (fs_startblk <= ((i_size_read(dio->inode) - 1) >> | 645 | if (fs_startblk <= ((i_size_read(dio->inode) - 1) >> |
645 | i_blkbits)) | 646 | i_blkbits)) |
@@ -789,7 +790,7 @@ submit_page_section(struct dio *dio, struct dio_submit *sdio, struct page *page, | |||
789 | { | 790 | { |
790 | int ret = 0; | 791 | int ret = 0; |
791 | 792 | ||
792 | if (dio->rw & WRITE) { | 793 | if (dio->op == REQ_OP_WRITE) { |
793 | /* | 794 | /* |
794 | * Read accounting is performed in submit_bio() | 795 | * Read accounting is performed in submit_bio() |
795 | */ | 796 | */ |
@@ -989,7 +990,7 @@ do_holes: | |||
989 | loff_t i_size_aligned; | 990 | loff_t i_size_aligned; |
990 | 991 | ||
991 | /* AKPM: eargh, -ENOTBLK is a hack */ | 992 | /* AKPM: eargh, -ENOTBLK is a hack */ |
992 | if (dio->rw & WRITE) { | 993 | if (dio->op == REQ_OP_WRITE) { |
993 | put_page(page); | 994 | put_page(page); |
994 | return -ENOTBLK; | 995 | return -ENOTBLK; |
995 | } | 996 | } |
@@ -1203,7 +1204,12 @@ do_blockdev_direct_IO(struct kiocb *iocb, struct inode *inode, | |||
1203 | dio->is_async = true; | 1204 | dio->is_async = true; |
1204 | 1205 | ||
1205 | dio->inode = inode; | 1206 | dio->inode = inode; |
1206 | dio->rw = iov_iter_rw(iter) == WRITE ? WRITE_ODIRECT : READ; | 1207 | if (iov_iter_rw(iter) == WRITE) { |
1208 | dio->op = REQ_OP_WRITE; | ||
1209 | dio->op_flags = WRITE_ODIRECT; | ||
1210 | } else { | ||
1211 | dio->op = REQ_OP_READ; | ||
1212 | } | ||
1207 | 1213 | ||
1208 | /* | 1214 | /* |
1209 | * For AIO O_(D)SYNC writes we need to defer completions to a workqueue | 1215 | * For AIO O_(D)SYNC writes we need to defer completions to a workqueue |
diff --git a/include/linux/fs.h b/include/linux/fs.h index 62ca2f9cad95..af6f3c7e4822 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h | |||
@@ -2824,7 +2824,7 @@ extern int generic_file_open(struct inode * inode, struct file * filp); | |||
2824 | extern int nonseekable_open(struct inode * inode, struct file * filp); | 2824 | extern int nonseekable_open(struct inode * inode, struct file * filp); |
2825 | 2825 | ||
2826 | #ifdef CONFIG_BLOCK | 2826 | #ifdef CONFIG_BLOCK |
2827 | typedef void (dio_submit_t)(int rw, struct bio *bio, struct inode *inode, | 2827 | typedef void (dio_submit_t)(struct bio *bio, struct inode *inode, |
2828 | loff_t file_offset); | 2828 | loff_t file_offset); |
2829 | 2829 | ||
2830 | enum { | 2830 | enum { |