Commit 3f289dcb authored by Tejun Heo's avatar Tejun Heo Committed by Jens Axboe

block: make bdev_ops->rw_page() take a REQ_OP instead of bool

c11f0c0b ("block/mm: make bdev_ops->rw_page() take a bool for
read/write") replaced @op with boolean @is_write, which limited the
amount of information going into ->rw_page() and more importantly
page_endio(), which removed the need to expose block internals to mm.

Unfortunately, we want to track discards separately and @is_write
isn't enough information.  This patch updates bdev_ops->rw_page() to
take REQ_OP instead but leaves page_endio() to take bool @is_write.
This allows the block part of operations to have enough information
while not leaking it to mm.
Signed-off-by: default avatarTejun Heo <tj@kernel.org>
Cc: Mike Christie <mchristi@redhat.com>
Cc: Minchan Kim <minchan@kernel.org>
Cc: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: default avatarJens Axboe <axboe@kernel.dk>
parent ada94973
...@@ -254,20 +254,20 @@ static void copy_from_brd(void *dst, struct brd_device *brd, ...@@ -254,20 +254,20 @@ static void copy_from_brd(void *dst, struct brd_device *brd,
* Process a single bvec of a bio. * Process a single bvec of a bio.
*/ */
static int brd_do_bvec(struct brd_device *brd, struct page *page, static int brd_do_bvec(struct brd_device *brd, struct page *page,
unsigned int len, unsigned int off, bool is_write, unsigned int len, unsigned int off, unsigned int op,
sector_t sector) sector_t sector)
{ {
void *mem; void *mem;
int err = 0; int err = 0;
if (is_write) { if (op_is_write(op)) {
err = copy_to_brd_setup(brd, sector, len); err = copy_to_brd_setup(brd, sector, len);
if (err) if (err)
goto out; goto out;
} }
mem = kmap_atomic(page); mem = kmap_atomic(page);
if (!is_write) { if (!op_is_write(op)) {
copy_from_brd(mem + off, brd, sector, len); copy_from_brd(mem + off, brd, sector, len);
flush_dcache_page(page); flush_dcache_page(page);
} else { } else {
...@@ -296,7 +296,7 @@ static blk_qc_t brd_make_request(struct request_queue *q, struct bio *bio) ...@@ -296,7 +296,7 @@ static blk_qc_t brd_make_request(struct request_queue *q, struct bio *bio)
int err; int err;
err = brd_do_bvec(brd, bvec.bv_page, len, bvec.bv_offset, err = brd_do_bvec(brd, bvec.bv_page, len, bvec.bv_offset,
op_is_write(bio_op(bio)), sector); bio_op(bio), sector);
if (err) if (err)
goto io_error; goto io_error;
sector += len >> SECTOR_SHIFT; sector += len >> SECTOR_SHIFT;
...@@ -310,15 +310,15 @@ static blk_qc_t brd_make_request(struct request_queue *q, struct bio *bio) ...@@ -310,15 +310,15 @@ static blk_qc_t brd_make_request(struct request_queue *q, struct bio *bio)
} }
static int brd_rw_page(struct block_device *bdev, sector_t sector, static int brd_rw_page(struct block_device *bdev, sector_t sector,
struct page *page, bool is_write) struct page *page, unsigned int op)
{ {
struct brd_device *brd = bdev->bd_disk->private_data; struct brd_device *brd = bdev->bd_disk->private_data;
int err; int err;
if (PageTransHuge(page)) if (PageTransHuge(page))
return -ENOTSUPP; return -ENOTSUPP;
err = brd_do_bvec(brd, page, PAGE_SIZE, 0, is_write, sector); err = brd_do_bvec(brd, page, PAGE_SIZE, 0, op, sector);
page_endio(page, is_write, err); page_endio(page, op_is_write(op), err);
return err; return err;
} }
......
...@@ -1274,17 +1274,17 @@ static void zram_bio_discard(struct zram *zram, u32 index, ...@@ -1274,17 +1274,17 @@ static void zram_bio_discard(struct zram *zram, u32 index,
* Returns 1 if IO request was successfully submitted. * Returns 1 if IO request was successfully submitted.
*/ */
static int zram_bvec_rw(struct zram *zram, struct bio_vec *bvec, u32 index, static int zram_bvec_rw(struct zram *zram, struct bio_vec *bvec, u32 index,
int offset, bool is_write, struct bio *bio) int offset, unsigned int op, struct bio *bio)
{ {
unsigned long start_time = jiffies; unsigned long start_time = jiffies;
int rw_acct = is_write ? REQ_OP_WRITE : REQ_OP_READ; int rw_acct = op_is_write(op) ? REQ_OP_WRITE : REQ_OP_READ;
struct request_queue *q = zram->disk->queue; struct request_queue *q = zram->disk->queue;
int ret; int ret;
generic_start_io_acct(q, rw_acct, bvec->bv_len >> SECTOR_SHIFT, generic_start_io_acct(q, rw_acct, bvec->bv_len >> SECTOR_SHIFT,
&zram->disk->part0); &zram->disk->part0);
if (!is_write) { if (!op_is_write(op)) {
atomic64_inc(&zram->stats.num_reads); atomic64_inc(&zram->stats.num_reads);
ret = zram_bvec_read(zram, bvec, index, offset, bio); ret = zram_bvec_read(zram, bvec, index, offset, bio);
flush_dcache_page(bvec->bv_page); flush_dcache_page(bvec->bv_page);
...@@ -1300,7 +1300,7 @@ static int zram_bvec_rw(struct zram *zram, struct bio_vec *bvec, u32 index, ...@@ -1300,7 +1300,7 @@ static int zram_bvec_rw(struct zram *zram, struct bio_vec *bvec, u32 index,
zram_slot_unlock(zram, index); zram_slot_unlock(zram, index);
if (unlikely(ret < 0)) { if (unlikely(ret < 0)) {
if (!is_write) if (!op_is_write(op))
atomic64_inc(&zram->stats.failed_reads); atomic64_inc(&zram->stats.failed_reads);
else else
atomic64_inc(&zram->stats.failed_writes); atomic64_inc(&zram->stats.failed_writes);
...@@ -1338,7 +1338,7 @@ static void __zram_make_request(struct zram *zram, struct bio *bio) ...@@ -1338,7 +1338,7 @@ static void __zram_make_request(struct zram *zram, struct bio *bio)
bv.bv_len = min_t(unsigned int, PAGE_SIZE - offset, bv.bv_len = min_t(unsigned int, PAGE_SIZE - offset,
unwritten); unwritten);
if (zram_bvec_rw(zram, &bv, index, offset, if (zram_bvec_rw(zram, &bv, index, offset,
op_is_write(bio_op(bio)), bio) < 0) bio_op(bio), bio) < 0)
goto out; goto out;
bv.bv_offset += bv.bv_len; bv.bv_offset += bv.bv_len;
...@@ -1390,7 +1390,7 @@ static void zram_slot_free_notify(struct block_device *bdev, ...@@ -1390,7 +1390,7 @@ static void zram_slot_free_notify(struct block_device *bdev,
} }
static int zram_rw_page(struct block_device *bdev, sector_t sector, static int zram_rw_page(struct block_device *bdev, sector_t sector,
struct page *page, bool is_write) struct page *page, unsigned int op)
{ {
int offset, ret; int offset, ret;
u32 index; u32 index;
...@@ -1414,7 +1414,7 @@ static int zram_rw_page(struct block_device *bdev, sector_t sector, ...@@ -1414,7 +1414,7 @@ static int zram_rw_page(struct block_device *bdev, sector_t sector,
bv.bv_len = PAGE_SIZE; bv.bv_len = PAGE_SIZE;
bv.bv_offset = 0; bv.bv_offset = 0;
ret = zram_bvec_rw(zram, &bv, index, offset, is_write, NULL); ret = zram_bvec_rw(zram, &bv, index, offset, op, NULL);
out: out:
/* /*
* If I/O fails, just return error(ie, non-zero) without * If I/O fails, just return error(ie, non-zero) without
...@@ -1429,7 +1429,7 @@ static int zram_rw_page(struct block_device *bdev, sector_t sector, ...@@ -1429,7 +1429,7 @@ static int zram_rw_page(struct block_device *bdev, sector_t sector,
switch (ret) { switch (ret) {
case 0: case 0:
page_endio(page, is_write, 0); page_endio(page, op_is_write(op), 0);
break; break;
case 1: case 1:
ret = 0; ret = 0;
......
...@@ -1423,11 +1423,11 @@ static int btt_write_pg(struct btt *btt, struct bio_integrity_payload *bip, ...@@ -1423,11 +1423,11 @@ static int btt_write_pg(struct btt *btt, struct bio_integrity_payload *bip,
static int btt_do_bvec(struct btt *btt, struct bio_integrity_payload *bip, static int btt_do_bvec(struct btt *btt, struct bio_integrity_payload *bip,
struct page *page, unsigned int len, unsigned int off, struct page *page, unsigned int len, unsigned int off,
bool is_write, sector_t sector) unsigned int op, sector_t sector)
{ {
int ret; int ret;
if (!is_write) { if (!op_is_write(op)) {
ret = btt_read_pg(btt, bip, page, off, sector, len); ret = btt_read_pg(btt, bip, page, off, sector, len);
flush_dcache_page(page); flush_dcache_page(page);
} else { } else {
...@@ -1464,7 +1464,7 @@ static blk_qc_t btt_make_request(struct request_queue *q, struct bio *bio) ...@@ -1464,7 +1464,7 @@ static blk_qc_t btt_make_request(struct request_queue *q, struct bio *bio)
} }
err = btt_do_bvec(btt, bip, bvec.bv_page, len, bvec.bv_offset, err = btt_do_bvec(btt, bip, bvec.bv_page, len, bvec.bv_offset,
op_is_write(bio_op(bio)), iter.bi_sector); bio_op(bio), iter.bi_sector);
if (err) { if (err) {
dev_err(&btt->nd_btt->dev, dev_err(&btt->nd_btt->dev,
"io error in %s sector %lld, len %d,\n", "io error in %s sector %lld, len %d,\n",
...@@ -1483,16 +1483,16 @@ static blk_qc_t btt_make_request(struct request_queue *q, struct bio *bio) ...@@ -1483,16 +1483,16 @@ static blk_qc_t btt_make_request(struct request_queue *q, struct bio *bio)
} }
static int btt_rw_page(struct block_device *bdev, sector_t sector, static int btt_rw_page(struct block_device *bdev, sector_t sector,
struct page *page, bool is_write) struct page *page, unsigned int op)
{ {
struct btt *btt = bdev->bd_disk->private_data; struct btt *btt = bdev->bd_disk->private_data;
int rc; int rc;
unsigned int len; unsigned int len;
len = hpage_nr_pages(page) * PAGE_SIZE; len = hpage_nr_pages(page) * PAGE_SIZE;
rc = btt_do_bvec(btt, NULL, page, len, 0, is_write, sector); rc = btt_do_bvec(btt, NULL, page, len, 0, op, sector);
if (rc == 0) if (rc == 0)
page_endio(page, is_write, 0); page_endio(page, op_is_write(op), 0);
return rc; return rc;
} }
......
...@@ -120,7 +120,7 @@ static blk_status_t read_pmem(struct page *page, unsigned int off, ...@@ -120,7 +120,7 @@ static blk_status_t read_pmem(struct page *page, unsigned int off,
} }
static blk_status_t pmem_do_bvec(struct pmem_device *pmem, struct page *page, static blk_status_t pmem_do_bvec(struct pmem_device *pmem, struct page *page,
unsigned int len, unsigned int off, bool is_write, unsigned int len, unsigned int off, unsigned int op,
sector_t sector) sector_t sector)
{ {
blk_status_t rc = BLK_STS_OK; blk_status_t rc = BLK_STS_OK;
...@@ -131,7 +131,7 @@ static blk_status_t pmem_do_bvec(struct pmem_device *pmem, struct page *page, ...@@ -131,7 +131,7 @@ static blk_status_t pmem_do_bvec(struct pmem_device *pmem, struct page *page,
if (unlikely(is_bad_pmem(&pmem->bb, sector, len))) if (unlikely(is_bad_pmem(&pmem->bb, sector, len)))
bad_pmem = true; bad_pmem = true;
if (!is_write) { if (!op_is_write(op)) {
if (unlikely(bad_pmem)) if (unlikely(bad_pmem))
rc = BLK_STS_IOERR; rc = BLK_STS_IOERR;
else { else {
...@@ -180,8 +180,7 @@ static blk_qc_t pmem_make_request(struct request_queue *q, struct bio *bio) ...@@ -180,8 +180,7 @@ static blk_qc_t pmem_make_request(struct request_queue *q, struct bio *bio)
do_acct = nd_iostat_start(bio, &start); do_acct = nd_iostat_start(bio, &start);
bio_for_each_segment(bvec, bio, iter) { bio_for_each_segment(bvec, bio, iter) {
rc = pmem_do_bvec(pmem, bvec.bv_page, bvec.bv_len, rc = pmem_do_bvec(pmem, bvec.bv_page, bvec.bv_len,
bvec.bv_offset, op_is_write(bio_op(bio)), bvec.bv_offset, bio_op(bio), iter.bi_sector);
iter.bi_sector);
if (rc) { if (rc) {
bio->bi_status = rc; bio->bi_status = rc;
break; break;
...@@ -198,13 +197,13 @@ static blk_qc_t pmem_make_request(struct request_queue *q, struct bio *bio) ...@@ -198,13 +197,13 @@ static blk_qc_t pmem_make_request(struct request_queue *q, struct bio *bio)
} }
static int pmem_rw_page(struct block_device *bdev, sector_t sector, static int pmem_rw_page(struct block_device *bdev, sector_t sector,
struct page *page, bool is_write) struct page *page, unsigned int op)
{ {
struct pmem_device *pmem = bdev->bd_queue->queuedata; struct pmem_device *pmem = bdev->bd_queue->queuedata;
blk_status_t rc; blk_status_t rc;
rc = pmem_do_bvec(pmem, page, hpage_nr_pages(page) * PAGE_SIZE, rc = pmem_do_bvec(pmem, page, hpage_nr_pages(page) * PAGE_SIZE,
0, is_write, sector); 0, op, sector);
/* /*
* The ->rw_page interface is subtle and tricky. The core * The ->rw_page interface is subtle and tricky. The core
...@@ -213,7 +212,7 @@ static int pmem_rw_page(struct block_device *bdev, sector_t sector, ...@@ -213,7 +212,7 @@ static int pmem_rw_page(struct block_device *bdev, sector_t sector,
* caused by double completion. * caused by double completion.
*/ */
if (rc == 0) if (rc == 0)
page_endio(page, is_write, 0); page_endio(page, op_is_write(op), 0);
return blk_status_to_errno(rc); return blk_status_to_errno(rc);
} }
......
...@@ -665,7 +665,8 @@ int bdev_read_page(struct block_device *bdev, sector_t sector, ...@@ -665,7 +665,8 @@ int bdev_read_page(struct block_device *bdev, sector_t sector,
result = blk_queue_enter(bdev->bd_queue, 0); result = blk_queue_enter(bdev->bd_queue, 0);
if (result) if (result)
return result; return result;
result = ops->rw_page(bdev, sector + get_start_sect(bdev), page, false); result = ops->rw_page(bdev, sector + get_start_sect(bdev), page,
REQ_OP_READ);
blk_queue_exit(bdev->bd_queue); blk_queue_exit(bdev->bd_queue);
return result; return result;
} }
...@@ -703,7 +704,8 @@ int bdev_write_page(struct block_device *bdev, sector_t sector, ...@@ -703,7 +704,8 @@ int bdev_write_page(struct block_device *bdev, sector_t sector,
return result; return result;
set_page_writeback(page); set_page_writeback(page);
result = ops->rw_page(bdev, sector + get_start_sect(bdev), page, true); result = ops->rw_page(bdev, sector + get_start_sect(bdev), page,
REQ_OP_WRITE);
if (result) { if (result) {
end_page_writeback(page); end_page_writeback(page);
} else { } else {
......
...@@ -51,8 +51,8 @@ static void mpage_end_io(struct bio *bio) ...@@ -51,8 +51,8 @@ static void mpage_end_io(struct bio *bio)
bio_for_each_segment_all(bv, bio, i) { bio_for_each_segment_all(bv, bio, i) {
struct page *page = bv->bv_page; struct page *page = bv->bv_page;
page_endio(page, op_is_write(bio_op(bio)), page_endio(page, bio_op(bio),
blk_status_to_errno(bio->bi_status)); blk_status_to_errno(bio->bi_status));
} }
bio_put(bio); bio_put(bio);
......
...@@ -1943,7 +1943,7 @@ static inline bool integrity_req_gap_front_merge(struct request *req, ...@@ -1943,7 +1943,7 @@ static inline bool integrity_req_gap_front_merge(struct request *req,
struct block_device_operations { struct block_device_operations {
int (*open) (struct block_device *, fmode_t); int (*open) (struct block_device *, fmode_t);
void (*release) (struct gendisk *, fmode_t); void (*release) (struct gendisk *, fmode_t);
int (*rw_page)(struct block_device *, sector_t, struct page *, bool); int (*rw_page)(struct block_device *, sector_t, struct page *, unsigned int);
int (*ioctl) (struct block_device *, fmode_t, unsigned, unsigned long); int (*ioctl) (struct block_device *, fmode_t, unsigned, unsigned long);
int (*compat_ioctl) (struct block_device *, fmode_t, unsigned, unsigned long); int (*compat_ioctl) (struct block_device *, fmode_t, unsigned, unsigned long);
unsigned int (*check_events) (struct gendisk *disk, unsigned int (*check_events) (struct gendisk *disk,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment