Pull block fixes from Jens Axboe: "Here's the second round of block updates for this merge window. It's a mix of fixes for changes that went in previously in this round, and fixes in general. This pull request contains: - Fixes for loop from Christoph - A bdi vs gendisk lifetime fix from Dan, worth two cookies. - A blk-mq timeout fix, when on frozen queues. From Gabriel. - Writeback fix from Jan, ensuring that __writeback_single_inode() does the right thing. - Fix for bio->bi_rw usage in f2fs from me. - Error path deadlock fix in blk-mq sysfs registration from me. - Floppy O_ACCMODE fix from Jiri. - Fix to the new bio op methods from Mike. One more followup will be coming here, ensuring that we don't propagate the block types outside of block. That, and a rename of bio->bi_rw is coming right after -rc1 is cut. - Various little fixes" * 'for-linus' of git://git.kernel.dk/linux-block: mm/block: convert rw_page users to bio op use loop: make do_req_filebacked more robust loop: don't try to use AIO for discards blk-mq: fix deadlock in blk_mq_register_disk() error path Include: blkdev: Removed duplicate 'struct request;' declaration. Fixup direct bi_rw modifiers block: fix bdi vs gendisk lifetime mismatch blk-mq: Allow timeouts to run while queue is freezing nbd: fix race in ioctl block: fix use-after-free in seq file f2fs: drop bio->bi_rw manual assignment block: add missing group association in bio-cloning functions blkcg: kill unused field nr_undestroyed_grps writeback: Write dirty times for WB_SYNC_ALL writeback floppy: fix open(O_ACCMODE) for ioctl-only open
Unified · Split
| @@ -583,6 +583,8 @@ void __bio_clone_fast(struct bio *bio, struct bio *bio_src) · 582 unmodified lines | ||
| 583 | 583 | bio->bi_rw = bio_src->bi_rw; |
| 584 | 584 | bio->bi_iter = bio_src->bi_iter; |
| 585 | 585 | bio->bi_io_vec = bio_src->bi_io_vec; |
| 586 | + | |
| 587 | + bio_clone_blkcg_association(bio, bio_src); | |
| 586 | 588 | } |
| 587 | 589 | EXPORT_SYMBOL(__bio_clone_fast); |
| 588 | 590 | |
| @@ -687,6 +689,8 @@ integrity_clone: · 98 unmodified lines | ||
| 687 | 689 | } |
| 688 | 690 | } |
| 689 | 691 | |
| 692 | + bio_clone_blkcg_association(bio, bio_src); | |
| 693 | + | |
| 690 | 694 | return bio; |
| 691 | 695 | } |
| 692 | 696 | EXPORT_SYMBOL(bio_clone_bioset); |
| @@ -2004,6 +2008,17 @@ void bio_disassociate_task(struct bio *bio) · 1311 unmodified lines | ||
| 2004 | 2008 | } |
| 2005 | 2009 | } |
| 2006 | 2010 | |
| 2011 | +/** | |
| 2012 | + * bio_clone_blkcg_association - clone blkcg association from src to dst bio | |
| 2013 | + * @dst: destination bio | |
| 2014 | + * @src: source bio | |
| 2015 | + */ | |
| 2016 | +void bio_clone_blkcg_association(struct bio *dst, struct bio *src) | |
| 2017 | +{ | |
| 2018 | + if (src->bi_css) | |
| 2019 | + WARN_ON(bio_associate_blkcg(dst, src->bi_css)); | |
| 2020 | +} | |
| 2021 | + | |
| 2007 | 2022 | #endif /* CONFIG_BLK_CGROUP */ |
| 2008 | 2023 | |
| 2009 | 2024 | static void __init biovec_init_slabs(void) |
| @@ -380,15 +380,13 @@ static int blk_mq_register_hctx(struct blk_mq_hw_ctx *hctx) · 379 unmodified lines | ||
| 380 | 380 | return ret; |
| 381 | 381 | } |
| 382 | 382 | |
| 383 | −void blk_mq_unregister_disk(struct gendisk *disk) | |
| 383 | +static void __blk_mq_unregister_disk(struct gendisk *disk) | |
| 384 | 384 | { |
| 385 | 385 | struct request_queue *q = disk->queue; |
| 386 | 386 | struct blk_mq_hw_ctx *hctx; |
| 387 | 387 | struct blk_mq_ctx *ctx; |
| 388 | 388 | int i, j; |
| 389 | 389 | |
| 390 | − blk_mq_disable_hotplug(); | |
| 391 | − | |
| 392 | 390 | queue_for_each_hw_ctx(q, hctx, i) { |
| 393 | 391 | blk_mq_unregister_hctx(hctx); |
| 394 | 392 | |
| @@ -405,6 +403,12 @@ void blk_mq_unregister_disk(struct gendisk *disk) · 10 unmodified lines | ||
| 405 | 403 | kobject_put(&disk_to_dev(disk)->kobj); |
| 406 | 404 | |
| 407 | 405 | q->mq_sysfs_init_done = false; |
| 406 | +} | |
| 407 | + | |
| 408 | +void blk_mq_unregister_disk(struct gendisk *disk) | |
| 409 | +{ | |
| 410 | + blk_mq_disable_hotplug(); | |
| 411 | + __blk_mq_unregister_disk(disk); | |
| 408 | 412 | blk_mq_enable_hotplug(); |
| 409 | 413 | } |
| 410 | 414 | |
| @@ -450,7 +454,7 @@ int blk_mq_register_disk(struct gendisk *disk) · 39 unmodified lines | ||
| 450 | 454 | } |
| 451 | 455 | |
| 452 | 456 | if (ret) |
| 453 | − blk_mq_unregister_disk(disk); | |
| 457 | + __blk_mq_unregister_disk(disk); | |
| 454 | 458 | else |
| 455 | 459 | q->mq_sysfs_init_done = true; |
| 456 | 460 | out: |
| @@ -672,7 +672,20 @@ static void blk_mq_timeout_work(struct work_struct *work) · 671 unmodified lines | ||
| 672 | 672 | }; |
| 673 | 673 | int i; |
| 674 | 674 | |
| 675 | − if (blk_queue_enter(q, true)) | |
| 675 | + /* A deadlock might occur if a request is stuck requiring a | |
| 676 | + * timeout at the same time a queue freeze is waiting | |
| 677 | + * completion, since the timeout code would not be able to | |
| 678 | + * acquire the queue reference here. | |
| 679 | + * | |
| 680 | + * That's why we don't use blk_queue_enter here; instead, we use | |
| 681 | + * percpu_ref_tryget directly, because we need to be able to | |
| 682 | + * obtain a reference even in the short window between the queue | |
| 683 | + * starting to freeze, by dropping the first reference in | |
| 684 | + * blk_mq_freeze_queue_start, and the moment the last request is | |
| 685 | + * consumed, marked by the instant q_usage_counter reaches | |
| 686 | + * zero. | |
| 687 | + */ | |
| 688 | + if (!percpu_ref_tryget(&q->q_usage_counter)) | |
| 676 | 689 | return; |
| 677 | 690 | |
| 678 | 691 | blk_mq_queue_tag_busy_iter(q, blk_mq_check_expired, &data); |
| @@ -145,11 +145,6 @@ struct throtl_data · 144 unmodified lines | ||
| 145 | 145 | /* Total Number of queued bios on READ and WRITE lists */ |
| 146 | 146 | unsigned int nr_queued[2]; |
| 147 | 147 | |
| 148 | − /* | |
| 149 | − * number of total undestroyed groups | |
| 150 | − */ | |
| 151 | − unsigned int nr_undestroyed_grps; | |
| 152 | − | |
| 153 | 148 | /* Work for dispatching throttled bios */ |
| 154 | 149 | struct work_struct dispatch_work; |
| 155 | 150 | }; |
| @@ -614,7 +614,7 @@ void device_add_disk(struct device *parent, struct gendisk *disk) · 613 unmodified lines | ||
| 614 | 614 | |
| 615 | 615 | /* Register BDI before referencing it from bdev */ |
| 616 | 616 | bdi = &disk->queue->backing_dev_info; |
| 617 | − bdi_register_dev(bdi, disk_devt(disk)); | |
| 617 | + bdi_register_owner(bdi, disk_to_dev(disk)); | |
| 618 | 618 | |
| 619 | 619 | blk_register_region(disk_devt(disk), disk->minors, NULL, |
| 620 | 620 | exact_match, exact_lock, disk); |
| @@ -856,6 +856,7 @@ static void disk_seqf_stop(struct seq_file *seqf, void *v) · 235 unmodified lines | ||
| 856 | 856 | if (iter) { |
| 857 | 857 | class_dev_iter_exit(iter); |
| 858 | 858 | kfree(iter); |
| 859 | + seqf->private = NULL; | |
| 859 | 860 | } |
| 860 | 861 | } |
| 861 | 862 | |
| @@ -300,20 +300,20 @@ static void copy_from_brd(void *dst, struct brd_device *brd, · 299 unmodified lines | ||
| 300 | 300 | * Process a single bvec of a bio. |
| 301 | 301 | */ |
| 302 | 302 | static int brd_do_bvec(struct brd_device *brd, struct page *page, |
| 303 | − unsigned int len, unsigned int off, int rw, | |
| 303 | + unsigned int len, unsigned int off, int op, | |
| 304 | 304 | sector_t sector) |
| 305 | 305 | { |
| 306 | 306 | void *mem; |
| 307 | 307 | int err = 0; |
| 308 | 308 | |
| 309 | − if (rw != READ) { | |
| 309 | + if (op_is_write(op)) { | |
| 310 | 310 | err = copy_to_brd_setup(brd, sector, len); |
| 311 | 311 | if (err) |
| 312 | 312 | goto out; |
| 313 | 313 | } |
| 314 | 314 | |
| 315 | 315 | mem = kmap_atomic(page); |
| 316 | − if (rw == READ) { | |
| 316 | + if (!op_is_write(op)) { | |
| 317 | 317 | copy_from_brd(mem + off, brd, sector, len); |
| 318 | 318 | flush_dcache_page(page); |
| 319 | 319 | } else { |
| @@ -330,7 +330,6 @@ static blk_qc_t brd_make_request(struct request_queue *q, struct bio *bio) · 10 unmodified lines | ||
| 330 | 330 | { |
| 331 | 331 | struct block_device *bdev = bio->bi_bdev; |
| 332 | 332 | struct brd_device *brd = bdev->bd_disk->private_data; |
| 333 | − int rw; | |
| 334 | 333 | struct bio_vec bvec; |
| 335 | 334 | sector_t sector; |
| 336 | 335 | struct bvec_iter iter; |
| @@ -347,14 +346,12 @@ static blk_qc_t brd_make_request(struct request_queue *q, struct bio *bio) · 10 unmodified lines | ||
| 347 | 346 | goto out; |
| 348 | 347 | } |
| 349 | 348 | |
| 350 | − rw = bio_data_dir(bio); | |
| 351 | − | |
| 352 | 349 | bio_for_each_segment(bvec, bio, iter) { |
| 353 | 350 | unsigned int len = bvec.bv_len; |
| 354 | 351 | int err; |
| 355 | 352 | |
| 356 | 353 | err = brd_do_bvec(brd, bvec.bv_page, len, |
| 357 | − bvec.bv_offset, rw, sector); | |
| 354 | + bvec.bv_offset, bio_op(bio), sector); | |
| 358 | 355 | if (err) |
| 359 | 356 | goto io_error; |
| 360 | 357 | sector += len >> SECTOR_SHIFT; |
| @@ -369,11 +366,11 @@ io_error: · 8 unmodified lines | ||
| 369 | 366 | } |
| 370 | 367 | |
| 371 | 368 | static int brd_rw_page(struct block_device *bdev, sector_t sector, |
| 372 | − struct page *page, int rw) | |
| 369 | + struct page *page, int op) | |
| 373 | 370 | { |
| 374 | 371 | struct brd_device *brd = bdev->bd_disk->private_data; |
| 375 | − int err = brd_do_bvec(brd, page, PAGE_SIZE, 0, rw, sector); | |
| 376 | − page_endio(page, rw & WRITE, err); | |
| 372 | + int err = brd_do_bvec(brd, page, PAGE_SIZE, 0, op, sector); | |
| 373 | + page_endio(page, op, err); | |
| 377 | 374 | return err; |
| 378 | 375 | } |
| 379 | 376 | |
| @@ -3663,11 +3663,6 @@ static int floppy_open(struct block_device *bdev, fmode_t mode) · 3662 unmodified lines | ||
| 3663 | 3663 | |
| 3664 | 3664 | opened_bdev[drive] = bdev; |
| 3665 | 3665 | |
| 3666 | − if (!(mode & (FMODE_READ|FMODE_WRITE))) { | |
| 3667 | − res = -EINVAL; | |
| 3668 | − goto out; | |
| 3669 | − } | |
| 3670 | − | |
| 3671 | 3666 | res = -ENXIO; |
| 3672 | 3667 | |
| 3673 | 3668 | if (!floppy_track_buffer) { |
| @@ -3711,13 +3706,15 @@ static int floppy_open(struct block_device *bdev, fmode_t mode) · 37 unmodified lines | ||
| 3711 | 3706 | if (UFDCS->rawcmd == 1) |
| 3712 | 3707 | UFDCS->rawcmd = 2; |
| 3713 | 3708 | |
| 3714 | − UDRS->last_checked = 0; | |
| 3715 | − clear_bit(FD_OPEN_SHOULD_FAIL_BIT, &UDRS->flags); | |
| 3716 | − check_disk_change(bdev); | |
| 3717 | − if (test_bit(FD_DISK_CHANGED_BIT, &UDRS->flags)) | |
| 3718 | − goto out; | |
| 3719 | − if (test_bit(FD_OPEN_SHOULD_FAIL_BIT, &UDRS->flags)) | |
| 3720 | − goto out; | |
| 3709 | + if (mode & (FMODE_READ|FMODE_WRITE)) { | |
| 3710 | + UDRS->last_checked = 0; | |
| 3711 | + clear_bit(FD_OPEN_SHOULD_FAIL_BIT, &UDRS->flags); | |
| 3712 | + check_disk_change(bdev); | |
| 3713 | + if (test_bit(FD_DISK_CHANGED_BIT, &UDRS->flags)) | |
| 3714 | + goto out; | |
| 3715 | + if (test_bit(FD_OPEN_SHOULD_FAIL_BIT, &UDRS->flags)) | |
| 3716 | + goto out; | |
| 3717 | + } | |
| 3721 | 3718 | |
| 3722 | 3719 | res = -EROFS; |
| 3723 | 3720 | |
| @@ -510,14 +510,10 @@ static int lo_rw_aio(struct loop_device *lo, struct loop_cmd *cmd, · 509 unmodified lines | ||
| 510 | 510 | return 0; |
| 511 | 511 | } |
| 512 | 512 | |
| 513 | − | |
| 514 | −static inline int lo_rw_simple(struct loop_device *lo, | |
| 515 | − struct request *rq, loff_t pos, bool rw) | |
| 513 | +static int do_req_filebacked(struct loop_device *lo, struct request *rq) | |
| 516 | 514 | { |
| 517 | 515 | struct loop_cmd *cmd = blk_mq_rq_to_pdu(rq); |
| 518 | − | |
| 519 | − if (cmd->use_aio) | |
| 520 | − return lo_rw_aio(lo, cmd, pos, rw); | |
| 516 | + loff_t pos = ((loff_t) blk_rq_pos(rq) << 9) + lo->lo_offset; | |
| 521 | 517 | |
| 522 | 518 | /* |
| 523 | 519 | * lo_write_simple and lo_read_simple should have been covered |
| @@ -528,37 +524,30 @@ static inline int lo_rw_simple(struct loop_device *lo, · 4 unmodified lines | ||
| 528 | 524 | * of the req at one time. And direct read IO doesn't need to |
| 529 | 525 | * run flush_dcache_page(). |
| 530 | 526 | */ |
| 531 | − if (rw == WRITE) | |
| 532 | − return lo_write_simple(lo, rq, pos); | |
| 533 | − else | |
| 534 | − return lo_read_simple(lo, rq, pos); | |
| 535 | −} | |
| 536 | − | |
| 537 | −static int do_req_filebacked(struct loop_device *lo, struct request *rq) | |
| 538 | −{ | |
| 539 | − loff_t pos; | |
| 540 | − int ret; | |
| 541 | − | |
| 542 | − pos = ((loff_t) blk_rq_pos(rq) << 9) + lo->lo_offset; | |
| 543 | − | |
| 544 | − if (op_is_write(req_op(rq))) { | |
| 545 | − if (req_op(rq) == REQ_OP_FLUSH) | |
| 546 | − ret = lo_req_flush(lo, rq); | |
| 547 | − else if (req_op(rq) == REQ_OP_DISCARD) | |
| 548 | − ret = lo_discard(lo, rq, pos); | |
| 549 | − else if (lo->transfer) | |
| 550 | − ret = lo_write_transfer(lo, rq, pos); | |
| 527 | + switch (req_op(rq)) { | |
| 528 | + case REQ_OP_FLUSH: | |
| 529 | + return lo_req_flush(lo, rq); | |
| 530 | + case REQ_OP_DISCARD: | |
| 531 | + return lo_discard(lo, rq, pos); | |
| 532 | + case REQ_OP_WRITE: | |
| 533 | + if (lo->transfer) | |
| 534 | + return lo_write_transfer(lo, rq, pos); | |
| 535 | + else if (cmd->use_aio) | |
| 536 | + return lo_rw_aio(lo, cmd, pos, WRITE); | |
| 551 | 537 | else |
| 552 | − ret = lo_rw_simple(lo, rq, pos, WRITE); | |
| 553 | − | |
| 554 | − } else { | |
| 538 | + return lo_write_simple(lo, rq, pos); | |
| 539 | + case REQ_OP_READ: | |
| 555 | 540 | if (lo->transfer) |
| 556 | − ret = lo_read_transfer(lo, rq, pos); | |
| 541 | + return lo_read_transfer(lo, rq, pos); | |
| 542 | + else if (cmd->use_aio) | |
| 543 | + return lo_rw_aio(lo, cmd, pos, READ); | |
| 557 | 544 | else |
| 558 | − ret = lo_rw_simple(lo, rq, pos, READ); | |
| 545 | + return lo_read_simple(lo, rq, pos); | |
| 546 | + default: | |
| 547 | + WARN_ON_ONCE(1); | |
| 548 | + return -EIO; | |
| 549 | + break; | |
| 559 | 550 | } |
| 560 | − | |
| 561 | − return ret; | |
| 562 | 551 | } |
| 563 | 552 | |
| 564 | 553 | struct switch_request { |
| @@ -1659,11 +1648,15 @@ static int loop_queue_rq(struct blk_mq_hw_ctx *hctx, · 1094 unmodified lines | ||
| 1659 | 1648 | if (lo->lo_state != Lo_bound) |
| 1660 | 1649 | return -EIO; |
| 1661 | 1650 | |
| 1662 | − if (lo->use_dio && (req_op(cmd->rq) != REQ_OP_FLUSH || | |
| 1663 | − req_op(cmd->rq) == REQ_OP_DISCARD)) | |
| 1664 | − cmd->use_aio = true; | |
| 1665 | − else | |
| 1651 | + switch (req_op(cmd->rq)) { | |
| 1652 | + case REQ_OP_FLUSH: | |
| 1653 | + case REQ_OP_DISCARD: | |
| 1666 | 1654 | cmd->use_aio = false; |
| 1655 | + break; | |
| 1656 | + default: | |
| 1657 | + cmd->use_aio = lo->use_dio; | |
| 1658 | + break; | |
| 1659 | + } | |
| 1667 | 1660 | |
| 1668 | 1661 | queue_kthread_work(&lo->worker, &cmd->work); |
| 1669 | 1662 | |
| @@ -451,14 +451,9 @@ static int nbd_thread_recv(struct nbd_device *nbd, struct block_device *bdev) · 450 unmodified lines | ||
| 451 | 451 | |
| 452 | 452 | sk_set_memalloc(nbd->sock->sk); |
| 453 | 453 | |
| 454 | − nbd->task_recv = current; | |
| 455 | − | |
| 456 | 454 | ret = device_create_file(disk_to_dev(nbd->disk), &pid_attr); |
| 457 | 455 | if (ret) { |
| 458 | 456 | dev_err(disk_to_dev(nbd->disk), "device_create_file failed!\n"); |
| 459 | − | |
| 460 | − nbd->task_recv = NULL; | |
| 461 | − | |
| 462 | 457 | return ret; |
| 463 | 458 | } |
| 464 | 459 | |
| @@ -477,9 +472,6 @@ static int nbd_thread_recv(struct nbd_device *nbd, struct block_device *bdev) · 12 unmodified lines | ||
| 477 | 472 | nbd_size_clear(nbd, bdev); |
| 478 | 473 | |
| 479 | 474 | device_remove_file(disk_to_dev(nbd->disk), &pid_attr); |
| 480 | − | |
| 481 | − nbd->task_recv = NULL; | |
| 482 | − | |
| 483 | 475 | return ret; |
| 484 | 476 | } |
| 485 | 477 | |
| @@ -788,6 +780,8 @@ static int __nbd_ioctl(struct block_device *bdev, struct nbd_device *nbd, · 302 unmodified lines | ||
| 788 | 780 | if (!nbd->sock) |
| 789 | 781 | return -EINVAL; |
| 790 | 782 | |
| 783 | + /* We have to claim the device under the lock */ | |
| 784 | + nbd->task_recv = current; | |
| 791 | 785 | mutex_unlock(&nbd->tx_lock); |
| 792 | 786 | |
| 793 | 787 | nbd_parse_flags(nbd, bdev); |
| @@ -796,6 +790,7 @@ static int __nbd_ioctl(struct block_device *bdev, struct nbd_device *nbd, · 2 unmodified lines | ||
| 796 | 790 | nbd_name(nbd)); |
| 797 | 791 | if (IS_ERR(thread)) { |
| 798 | 792 | mutex_lock(&nbd->tx_lock); |
| 793 | + nbd->task_recv = NULL; | |
| 799 | 794 | return PTR_ERR(thread); |
| 800 | 795 | } |
| 801 | 796 | |
| @@ -805,6 +800,7 @@ static int __nbd_ioctl(struct block_device *bdev, struct nbd_device *nbd, · 3 unmodified lines | ||
| 805 | 800 | kthread_stop(thread); |
| 806 | 801 | |
| 807 | 802 | mutex_lock(&nbd->tx_lock); |
| 803 | + nbd->task_recv = NULL; | |
| 808 | 804 | |
| 809 | 805 | sock_shutdown(nbd); |
| 810 | 806 | nbd_clear_que(nbd); |
| @@ -843,15 +843,15 @@ static void zram_bio_discard(struct zram *zram, u32 index, · 842 unmodified lines | ||
| 843 | 843 | } |
| 844 | 844 | |
| 845 | 845 | static int zram_bvec_rw(struct zram *zram, struct bio_vec *bvec, u32 index, |
| 846 | − int offset, int rw) | |
| 846 | + int offset, int op) | |
| 847 | 847 | { |
| 848 | 848 | unsigned long start_time = jiffies; |
| 849 | 849 | int ret; |
| 850 | 850 | |
| 851 | − generic_start_io_acct(rw, bvec->bv_len >> SECTOR_SHIFT, | |
| 851 | + generic_start_io_acct(op, bvec->bv_len >> SECTOR_SHIFT, | |
| 852 | 852 | &zram->disk->part0); |
| 853 | 853 | |
| 854 | − if (rw == READ) { | |
| 854 | + if (!op_is_write(op)) { | |
| 855 | 855 | atomic64_inc(&zram->stats.num_reads); |
| 856 | 856 | ret = zram_bvec_read(zram, bvec, index, offset); |
| 857 | 857 | } else { |
| @@ -859,10 +859,10 @@ static int zram_bvec_rw(struct zram *zram, struct bio_vec *bvec, u32 index, · 1 unmodified line | ||
| 859 | 859 | ret = zram_bvec_write(zram, bvec, index, offset); |
| 860 | 860 | } |
| 861 | 861 | |
| 862 | − generic_end_io_acct(rw, &zram->disk->part0, start_time); | |
| 862 | + generic_end_io_acct(op, &zram->disk->part0, start_time); | |
| 863 | 863 | |
| 864 | 864 | if (unlikely(ret)) { |
| 865 | − if (rw == READ) | |
| 865 | + if (!op_is_write(op)) | |
| 866 | 866 | atomic64_inc(&zram->stats.failed_reads); |
| 867 | 867 | else |
| 868 | 868 | atomic64_inc(&zram->stats.failed_writes); |
| @@ -873,7 +873,7 @@ static int zram_bvec_rw(struct zram *zram, struct bio_vec *bvec, u32 index, · 4 unmodified lines | ||
| 873 | 873 | |
| 874 | 874 | static void __zram_make_request(struct zram *zram, struct bio *bio) |
| 875 | 875 | { |
| 876 | − int offset, rw; | |
| 876 | + int offset; | |
| 877 | 877 | u32 index; |
| 878 | 878 | struct bio_vec bvec; |
| 879 | 879 | struct bvec_iter iter; |
| @@ -888,7 +888,6 @@ static void __zram_make_request(struct zram *zram, struct bio *bio) · 8 unmodified lines | ||
| 888 | 888 | return; |
| 889 | 889 | } |
| 890 | 890 | |
| 891 | − rw = bio_data_dir(bio); | |
| 892 | 891 | bio_for_each_segment(bvec, bio, iter) { |
| 893 | 892 | int max_transfer_size = PAGE_SIZE - offset; |
| 894 | 893 | |
| @@ -903,15 +902,18 @@ static void __zram_make_request(struct zram *zram, struct bio *bio) · 8 unmodified lines | ||
| 903 | 902 | bv.bv_len = max_transfer_size; |
| 904 | 903 | bv.bv_offset = bvec.bv_offset; |
| 905 | 904 | |
| 906 | − if (zram_bvec_rw(zram, &bv, index, offset, rw) < 0) | |
| 905 | + if (zram_bvec_rw(zram, &bv, index, offset, | |
| 906 | + bio_op(bio)) < 0) | |
| 907 | 907 | goto out; |
| 908 | 908 | |
| 909 | 909 | bv.bv_len = bvec.bv_len - max_transfer_size; |
| 910 | 910 | bv.bv_offset += max_transfer_size; |
| 911 | − if (zram_bvec_rw(zram, &bv, index + 1, 0, rw) < 0) | |
| 911 | + if (zram_bvec_rw(zram, &bv, index + 1, 0, | |
| 912 | + bio_op(bio)) < 0) | |
| 912 | 913 | goto out; |
| 913 | 914 | } else |
| 914 | − if (zram_bvec_rw(zram, &bvec, index, offset, rw) < 0) | |
| 915 | + if (zram_bvec_rw(zram, &bvec, index, offset, | |
| 916 | + bio_op(bio)) < 0) | |
| 915 | 917 | goto out; |
| 916 | 918 | |
| 917 | 919 | update_position(&index, &offset, &bvec); |
| @@ -968,7 +970,7 @@ static void zram_slot_free_notify(struct block_device *bdev, · 50 unmodified lines | ||
| 968 | 970 | } |
| 969 | 971 | |
| 970 | 972 | static int zram_rw_page(struct block_device *bdev, sector_t sector, |
| 971 | − struct page *page, int rw) | |
| 973 | + struct page *page, int op) | |
| 972 | 974 | { |
| 973 | 975 | int offset, err = -EIO; |
| 974 | 976 | u32 index; |
| @@ -992,7 +994,7 @@ static int zram_rw_page(struct block_device *bdev, sector_t sector, · 17 unmodified lines | ||
| 992 | 994 | bv.bv_len = PAGE_SIZE; |
| 993 | 995 | bv.bv_offset = 0; |
| 994 | 996 | |
| 995 | − err = zram_bvec_rw(zram, &bv, index, offset, rw); | |
| 997 | + err = zram_bvec_rw(zram, &bv, index, offset, op); | |
| 996 | 998 | put_zram: |
| 997 | 999 | zram_meta_put(zram); |
| 998 | 1000 | out: |
| @@ -1005,7 +1007,7 @@ out: · 6 unmodified lines | ||
| 1005 | 1007 | * (e.g., SetPageError, set_page_dirty and extra works). |
| 1006 | 1008 | */ |
| 1007 | 1009 | if (err == 0) |
| 1008 | − page_endio(page, rw, 0); | |
| 1010 | + page_endio(page, op, 0); | |
| 1009 | 1011 | return err; |
| 1010 | 1012 | } |
| 1011 | 1013 | |
| @@ -1133,11 +1133,11 @@ static int btt_write_pg(struct btt *btt, struct bio_integrity_payload *bip, · 1132 unmodified lines | ||
| 1133 | 1133 | |
| 1134 | 1134 | static int btt_do_bvec(struct btt *btt, struct bio_integrity_payload *bip, |
| 1135 | 1135 | struct page *page, unsigned int len, unsigned int off, |
| 1136 | − int rw, sector_t sector) | |
| 1136 | + int op, sector_t sector) | |
| 1137 | 1137 | { |
| 1138 | 1138 | int ret; |
| 1139 | 1139 | |
| 1140 | − if (rw == READ) { | |
| 1140 | + if (!op_is_write(op)) { | |
| 1141 | 1141 | ret = btt_read_pg(btt, bip, page, off, sector, len); |
| 1142 | 1142 | flush_dcache_page(page); |
| 1143 | 1143 | } else { |
| @@ -1155,7 +1155,7 @@ static blk_qc_t btt_make_request(struct request_queue *q, struct bio *bio) · 11 unmodified lines | ||
| 1155 | 1155 | struct bvec_iter iter; |
| 1156 | 1156 | unsigned long start; |
| 1157 | 1157 | struct bio_vec bvec; |
| 1158 | − int err = 0, rw; | |
| 1158 | + int err = 0; | |
| 1159 | 1159 | bool do_acct; |
| 1160 | 1160 | |
| 1161 | 1161 | /* |
| @@ -1170,7 +1170,6 @@ static blk_qc_t btt_make_request(struct request_queue *q, struct bio *bio) · 8 unmodified lines | ||
| 1170 | 1170 | } |
| 1171 | 1171 | |
| 1172 | 1172 | do_acct = nd_iostat_start(bio, &start); |
| 1173 | − rw = bio_data_dir(bio); | |
| 1174 | 1173 | bio_for_each_segment(bvec, bio, iter) { |
| 1175 | 1174 | unsigned int len = bvec.bv_len; |
| 1176 | 1175 | |
| @@ -1181,11 +1180,12 @@ static blk_qc_t btt_make_request(struct request_queue *q, struct bio *bio) · 4 unmodified lines | ||
| 1181 | 1180 | BUG_ON(len % btt->sector_size); |
| 1182 | 1181 | |
| 1183 | 1182 | err = btt_do_bvec(btt, bip, bvec.bv_page, len, bvec.bv_offset, |
| 1184 | − rw, iter.bi_sector); | |
| 1183 | + bio_op(bio), iter.bi_sector); | |
| 1185 | 1184 | if (err) { |
| 1186 | 1185 | dev_info(&btt->nd_btt->dev, |
| 1187 | 1186 | "io error in %s sector %lld, len %d,\n", |
| 1188 | − (rw == READ) ? "READ" : "WRITE", | |
| 1187 | + (op_is_write(bio_op(bio))) ? "WRITE" : | |
| 1188 | + "READ", | |
| 1189 | 1189 | (unsigned long long) iter.bi_sector, len); |
| 1190 | 1190 | bio->bi_error = err; |
| 1191 | 1191 | break; |
| @@ -1200,12 +1200,12 @@ out: · 8 unmodified lines | ||
| 1200 | 1200 | } |
| 1201 | 1201 | |
| 1202 | 1202 | static int btt_rw_page(struct block_device *bdev, sector_t sector, |
| 1203 | − struct page *page, int rw) | |
| 1203 | + struct page *page, int op) | |
| 1204 | 1204 | { |
| 1205 | 1205 | struct btt *btt = bdev->bd_disk->private_data; |
| 1206 | 1206 | |
| 1207 | − btt_do_bvec(btt, NULL, page, PAGE_SIZE, 0, rw, sector); | |
| 1208 | − page_endio(page, rw & WRITE, 0); | |
| 1207 | + btt_do_bvec(btt, NULL, page, PAGE_SIZE, 0, op, sector); | |
| 1208 | + page_endio(page, op, 0); | |
| 1209 | 1209 | return 0; |
| 1210 | 1210 | } |
| 1211 | 1211 | |
| @@ -67,7 +67,7 @@ static void pmem_clear_poison(struct pmem_device *pmem, phys_addr_t offset, · 66 unmodified lines | ||
| 67 | 67 | } |
| 68 | 68 | |
| 69 | 69 | static int pmem_do_bvec(struct pmem_device *pmem, struct page *page, |
| 70 | − unsigned int len, unsigned int off, int rw, | |
| 70 | + unsigned int len, unsigned int off, int op, | |
| 71 | 71 | sector_t sector) |
| 72 | 72 | { |
| 73 | 73 | int rc = 0; |
| @@ -79,7 +79,7 @@ static int pmem_do_bvec(struct pmem_device *pmem, struct page *page, · 5 unmodified lines | ||
| 79 | 79 | if (unlikely(is_bad_pmem(&pmem->bb, sector, len))) |
| 80 | 80 | bad_pmem = true; |
| 81 | 81 | |
| 82 | − if (rw == READ) { | |
| 82 | + if (!op_is_write(op)) { | |
| 83 | 83 | if (unlikely(bad_pmem)) |
| 84 | 84 | rc = -EIO; |
| 85 | 85 | else { |
| @@ -134,7 +134,7 @@ static blk_qc_t pmem_make_request(struct request_queue *q, struct bio *bio) · 48 unmodified lines | ||
| 134 | 134 | do_acct = nd_iostat_start(bio, &start); |
| 135 | 135 | bio_for_each_segment(bvec, bio, iter) { |
| 136 | 136 | rc = pmem_do_bvec(pmem, bvec.bv_page, bvec.bv_len, |
| 137 | − bvec.bv_offset, bio_data_dir(bio), | |
| 137 | + bvec.bv_offset, bio_op(bio), | |
| 138 | 138 | iter.bi_sector); |
| 139 | 139 | if (rc) { |
| 140 | 140 | bio->bi_error = rc; |
| @@ -152,12 +152,12 @@ static blk_qc_t pmem_make_request(struct request_queue *q, struct bio *bio) · 11 unmodified lines | ||
| 152 | 152 | } |
| 153 | 153 | |
| 154 | 154 | static int pmem_rw_page(struct block_device *bdev, sector_t sector, |
| 155 | − struct page *page, int rw) | |
| 155 | + struct page *page, int op) | |
| 156 | 156 | { |
| 157 | 157 | struct pmem_device *pmem = bdev->bd_queue->queuedata; |
| 158 | 158 | int rc; |
| 159 | 159 | |
| 160 | − rc = pmem_do_bvec(pmem, page, PAGE_SIZE, 0, rw, sector); | |
| 160 | + rc = pmem_do_bvec(pmem, page, PAGE_SIZE, 0, op, sector); | |
| 161 | 161 | |
| 162 | 162 | /* |
| 163 | 163 | * The ->rw_page interface is subtle and tricky. The core |
| @@ -166,7 +166,7 @@ static int pmem_rw_page(struct block_device *bdev, sector_t sector, · 2 unmodified lines | ||
| 166 | 166 | * caused by double completion. |
| 167 | 167 | */ |
| 168 | 168 | if (rc == 0) |
| 169 | − page_endio(page, rw & WRITE, 0); | |
| 169 | + page_endio(page, op, 0); | |
| 170 | 170 | |
| 171 | 171 | return rc; |
| 172 | 172 | } |
| @@ -416,7 +416,8 @@ int bdev_read_page(struct block_device *bdev, sector_t sector, · 415 unmodified lines | ||
| 416 | 416 | result = blk_queue_enter(bdev->bd_queue, false); |
| 417 | 417 | if (result) |
| 418 | 418 | return result; |
| 419 | − result = ops->rw_page(bdev, sector + get_start_sect(bdev), page, READ); | |
| 419 | + result = ops->rw_page(bdev, sector + get_start_sect(bdev), page, | |
| 420 | + REQ_OP_READ); | |
| 420 | 421 | blk_queue_exit(bdev->bd_queue); |
| 421 | 422 | return result; |
| 422 | 423 | } |
| @@ -445,7 +446,6 @@ int bdev_write_page(struct block_device *bdev, sector_t sector, · 22 unmodified lines | ||
| 445 | 446 | struct page *page, struct writeback_control *wbc) |
| 446 | 447 | { |
| 447 | 448 | int result; |
| 448 | − int rw = (wbc->sync_mode == WB_SYNC_ALL) ? WRITE_SYNC : WRITE; | |
| 449 | 449 | const struct block_device_operations *ops = bdev->bd_disk->fops; |
| 450 | 450 | |
| 451 | 451 | if (!ops->rw_page || bdev_get_integrity(bdev)) |
| @@ -455,7 +455,8 @@ int bdev_write_page(struct block_device *bdev, sector_t sector, · 3 unmodified lines | ||
| 455 | 455 | return result; |
| 456 | 456 | |
| 457 | 457 | set_page_writeback(page); |
| 458 | − result = ops->rw_page(bdev, sector + get_start_sect(bdev), page, rw); | |
| 458 | + result = ops->rw_page(bdev, sector + get_start_sect(bdev), page, | |
| 459 | + REQ_OP_WRITE); | |
| 459 | 460 | if (result) |
| 460 | 461 | end_page_writeback(page); |
| 461 | 462 | else |
| @@ -2049,7 +2049,7 @@ int repair_io_failure(struct inode *inode, u64 start, u64 length, u64 logical, · 2048 unmodified lines | ||
| 2049 | 2049 | return -EIO; |
| 2050 | 2050 | } |
| 2051 | 2051 | bio->bi_bdev = dev->bdev; |
| 2052 | − bio->bi_rw = WRITE_SYNC; | |
| 2052 | + bio_set_op_attrs(bio, REQ_OP_WRITE, WRITE_SYNC); | |
| 2053 | 2053 | bio_add_page(bio, page, length, pg_offset); |
| 2054 | 2054 | |
| 2055 | 2055 | if (btrfsic_submit_bio_wait(bio)) { |
| @@ -2697,12 +2697,6 @@ struct bio *btrfs_bio_clone(struct bio *bio, gfp_t gfp_mask) · 641 unmodified lines | ||
| 2697 | 2697 | btrfs_bio->csum = NULL; |
| 2698 | 2698 | btrfs_bio->csum_allocated = NULL; |
| 2699 | 2699 | btrfs_bio->end_io = NULL; |
| 2700 | − | |
| 2701 | −#ifdef CONFIG_BLK_CGROUP | |
| 2702 | − /* FIXME, put this into bio_clone_bioset */ | |
| 2703 | − if (bio->bi_css) | |
| 2704 | − bio_associate_blkcg(new, bio->bi_css); | |
| 2705 | −#endif | |
| 2706 | 2700 | } |
| 2707 | 2701 | return new; |
| 2708 | 2702 | } |
| @@ -245,7 +245,6 @@ int f2fs_submit_page_bio(struct f2fs_io_info *fio) · 244 unmodified lines | ||
| 245 | 245 | bio_put(bio); |
| 246 | 246 | return -EFAULT; |
| 247 | 247 | } |
| 248 | − bio->bi_rw = fio->op_flags; | |
| 249 | 248 | bio_set_op_attrs(bio, fio->op, fio->op_flags); |
| 250 | 249 | |
| 251 | 250 | __submit_bio(fio->sbi, bio, fio->type); |
| @@ -1327,6 +1327,7 @@ __writeback_single_inode(struct inode *inode, struct writeback_control *wbc) · 1326 unmodified lines | ||
| 1327 | 1327 | dirty = inode->i_state & I_DIRTY; |
| 1328 | 1328 | if (inode->i_state & I_DIRTY_TIME) { |
| 1329 | 1329 | if ((dirty & (I_DIRTY_SYNC | I_DIRTY_DATASYNC)) || |
| 1330 | + wbc->sync_mode == WB_SYNC_ALL || | |
| 1330 | 1331 | unlikely(inode->i_state & I_DIRTY_TIME_EXPIRED) || |
| 1331 | 1332 | unlikely(time_after(jiffies, |
| 1332 | 1333 | (inode->dirtied_time_when + |
| @@ -50,7 +50,7 @@ static void mpage_end_io(struct bio *bio) · 49 unmodified lines | ||
| 50 | 50 | |
| 51 | 51 | bio_for_each_segment_all(bv, bio, i) { |
| 52 | 52 | struct page *page = bv->bv_page; |
| 53 | − page_endio(page, bio_data_dir(bio), bio->bi_error); | |
| 53 | + page_endio(page, bio_op(bio), bio->bi_error); | |
| 54 | 54 | } |
| 55 | 55 | |
| 56 | 56 | bio_put(bio); |
| @@ -163,6 +163,7 @@ struct backing_dev_info { · 162 unmodified lines | ||
| 163 | 163 | wait_queue_head_t wb_waitq; |
| 164 | 164 | |
| 165 | 165 | struct device *dev; |
| 166 | + struct device *owner; | |
| 166 | 167 | |
| 167 | 168 | struct timer_list laptop_mode_wb_timer; |
| 168 | 169 | |
| @@ -24,6 +24,7 @@ __printf(3, 4) · 23 unmodified lines | ||
| 24 | 24 | int bdi_register(struct backing_dev_info *bdi, struct device *parent, |
| 25 | 25 | const char *fmt, ...); |
| 26 | 26 | int bdi_register_dev(struct backing_dev_info *bdi, dev_t dev); |
| 27 | +int bdi_register_owner(struct backing_dev_info *bdi, struct device *owner); | |
| 27 | 28 | void bdi_unregister(struct backing_dev_info *bdi); |
| 28 | 29 | |
| 29 | 30 | int __must_check bdi_setup_and_register(struct backing_dev_info *, char *); |
| @@ -470,11 +470,14 @@ extern unsigned int bvec_nr_vecs(unsigned short idx); · 469 unmodified lines | ||
| 470 | 470 | int bio_associate_blkcg(struct bio *bio, struct cgroup_subsys_state *blkcg_css); |
| 471 | 471 | int bio_associate_current(struct bio *bio); |
| 472 | 472 | void bio_disassociate_task(struct bio *bio); |
| 473 | +void bio_clone_blkcg_association(struct bio *dst, struct bio *src); | |
| 473 | 474 | #else /* CONFIG_BLK_CGROUP */ |
| 474 | 475 | static inline int bio_associate_blkcg(struct bio *bio, |
| 475 | 476 | struct cgroup_subsys_state *blkcg_css) { return 0; } |
| 476 | 477 | static inline int bio_associate_current(struct bio *bio) { return -ENOENT; } |
| 477 | 478 | static inline void bio_disassociate_task(struct bio *bio) { } |
| 479 | +static inline void bio_clone_blkcg_association(struct bio *dst, | |
| 480 | + struct bio *src) { } | |
| 478 | 481 | #endif /* CONFIG_BLK_CGROUP */ |
| 479 | 482 | |
| 480 | 483 | #ifdef CONFIG_HIGHMEM |
| @@ -18,6 +18,17 @@ struct cgroup_subsys_state; · 17 unmodified lines | ||
| 18 | 18 | typedef void (bio_end_io_t) (struct bio *); |
| 19 | 19 | typedef void (bio_destructor_t) (struct bio *); |
| 20 | 20 | |
| 21 | +enum req_op { | |
| 22 | + REQ_OP_READ, | |
| 23 | + REQ_OP_WRITE, | |
| 24 | + REQ_OP_DISCARD, /* request to discard sectors */ | |
| 25 | + REQ_OP_SECURE_ERASE, /* request to securely erase sectors */ | |
| 26 | + REQ_OP_WRITE_SAME, /* write same block many times */ | |
| 27 | + REQ_OP_FLUSH, /* request for cache flush */ | |
| 28 | +}; | |
| 29 | + | |
| 30 | +#define REQ_OP_BITS 3 | |
| 31 | + | |
| 21 | 32 | #ifdef CONFIG_BLOCK |
| 22 | 33 | /* |
| 23 | 34 | * main unit of I/O for the block layer and lower layers (ie drivers and |
| @@ -228,17 +239,6 @@ enum rq_flag_bits { · 204 unmodified lines | ||
| 228 | 239 | #define REQ_HASHED (1ULL << __REQ_HASHED) |
| 229 | 240 | #define REQ_MQ_INFLIGHT (1ULL << __REQ_MQ_INFLIGHT) |
| 230 | 241 | |
| 231 | −enum req_op { | |
| 232 | − REQ_OP_READ, | |
| 233 | − REQ_OP_WRITE, | |
| 234 | − REQ_OP_DISCARD, /* request to discard sectors */ | |
| 235 | − REQ_OP_SECURE_ERASE, /* request to securely erase sectors */ | |
| 236 | − REQ_OP_WRITE_SAME, /* write same block many times */ | |
| 237 | − REQ_OP_FLUSH, /* request for cache flush */ | |
| 238 | −}; | |
| 239 | − | |
| 240 | −#define REQ_OP_BITS 3 | |
| 241 | − | |
| 242 | 242 | typedef unsigned int blk_qc_t; |
| 243 | 243 | #define BLK_QC_T_NONE -1U |
| 244 | 244 | #define BLK_QC_T_SHIFT 16 |
| @@ -47,7 +47,6 @@ struct pr_ops; · 46 unmodified lines | ||
| 47 | 47 | */ |
| 48 | 48 | #define BLKCG_MAX_POLS 2 |
| 49 | 49 | |
| 50 | −struct request; | |
| 51 | 50 | typedef void (rq_end_io_fn)(struct request *, int); |
| 52 | 51 | |
| 53 | 52 | #define BLK_RL_SYNCFULL (1U << 0) |
| @@ -1673,7 +1672,7 @@ struct blk_dax_ctl { · 1619 unmodified lines | ||
| 1673 | 1672 | struct block_device_operations { |
| 1674 | 1673 | int (*open) (struct block_device *, fmode_t); |
| 1675 | 1674 | void (*release) (struct gendisk *, fmode_t); |
| 1676 | − int (*rw_page)(struct block_device *, sector_t, struct page *, int rw); | |
| 1675 | + int (*rw_page)(struct block_device *, sector_t, struct page *, int op); | |
| 1677 | 1676 | int (*ioctl) (struct block_device *, fmode_t, unsigned, unsigned long); |
| 1678 | 1677 | int (*compat_ioctl) (struct block_device *, fmode_t, unsigned, unsigned long); |
| 1679 | 1678 | long (*direct_access)(struct block_device *, sector_t, void **, pfn_t *, |
| @@ -2480,12 +2480,13 @@ extern void init_special_inode(struct inode *, umode_t, dev_t); · 2479 unmodified lines | ||
| 2480 | 2480 | extern void make_bad_inode(struct inode *); |
| 2481 | 2481 | extern bool is_bad_inode(struct inode *); |
| 2482 | 2482 | |
| 2483 | −#ifdef CONFIG_BLOCK | |
| 2484 | 2483 | static inline bool op_is_write(unsigned int op) |
| 2485 | 2484 | { |
| 2486 | 2485 | return op == REQ_OP_READ ? false : true; |
| 2487 | 2486 | } |
| 2488 | 2487 | |
| 2488 | +#ifdef CONFIG_BLOCK | |
| 2489 | + | |
| 2489 | 2490 | /* |
| 2490 | 2491 | * return data direction, READ or WRITE |
| 2491 | 2492 | */ |
| @@ -510,7 +510,7 @@ static inline void wait_on_page_writeback(struct page *page) · 509 unmodified lines | ||
| 510 | 510 | extern void end_page_writeback(struct page *page); |
| 511 | 511 | void wait_for_stable_page(struct page *page); |
| 512 | 512 | |
| 513 | −void page_endio(struct page *page, int rw, int err); | |
| 513 | +void page_endio(struct page *page, int op, int err); | |
| 514 | 514 | |
| 515 | 515 | /* |
| 516 | 516 | * Add an arbitrary waiter to a page's wait queue |
| @@ -825,6 +825,20 @@ int bdi_register_dev(struct backing_dev_info *bdi, dev_t dev) · 824 unmodified lines | ||
| 825 | 825 | } |
| 826 | 826 | EXPORT_SYMBOL(bdi_register_dev); |
| 827 | 827 | |
| 828 | +int bdi_register_owner(struct backing_dev_info *bdi, struct device *owner) | |
| 829 | +{ | |
| 830 | + int rc; | |
| 831 | + | |
| 832 | + rc = bdi_register(bdi, NULL, "%u:%u", MAJOR(owner->devt), | |
| 833 | + MINOR(owner->devt)); | |
| 834 | + if (rc) | |
| 835 | + return rc; | |
| 836 | + bdi->owner = owner; | |
| 837 | + get_device(owner); | |
| 838 | + return 0; | |
| 839 | +} | |
| 840 | +EXPORT_SYMBOL(bdi_register_owner); | |
| 841 | + | |
| 828 | 842 | /* |
| 829 | 843 | * Remove bdi from bdi_list, and ensure that it is no longer visible |
| 830 | 844 | */ |
| @@ -849,6 +863,11 @@ void bdi_unregister(struct backing_dev_info *bdi) · 18 unmodified lines | ||
| 849 | 863 | device_unregister(bdi->dev); |
| 850 | 864 | bdi->dev = NULL; |
| 851 | 865 | } |
| 866 | + | |
| 867 | + if (bdi->owner) { | |
| 868 | + put_device(bdi->owner); | |
| 869 | + bdi->owner = NULL; | |
| 870 | + } | |
| 852 | 871 | } |
| 853 | 872 | |
| 854 | 873 | void bdi_exit(struct backing_dev_info *bdi) |
| @@ -887,9 +887,9 @@ EXPORT_SYMBOL(end_page_writeback); · 886 unmodified lines | ||
| 887 | 887 | * After completing I/O on a page, call this routine to update the page |
| 888 | 888 | * flags appropriately |
| 889 | 889 | */ |
| 890 | −void page_endio(struct page *page, int rw, int err) | |
| 890 | +void page_endio(struct page *page, int op, int err) | |
| 891 | 891 | { |
| 892 | − if (rw == READ) { | |
| 892 | + if (!op_is_write(op)) { | |
| 893 | 893 | if (!err) { |
| 894 | 894 | SetPageUptodate(page); |
| 895 | 895 | } else { |
| @@ -897,7 +897,7 @@ void page_endio(struct page *page, int rw, int err) · 1 unmodified line | ||
| 897 | 897 | SetPageError(page); |
| 898 | 898 | } |
| 899 | 899 | unlock_page(page); |
| 900 | − } else { /* rw == WRITE */ | |
| 900 | + } else { | |
| 901 | 901 | if (err) { |
| 902 | 902 | SetPageError(page); |
| 903 | 903 | if (page->mapping) |