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

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

c11f0c0b5bb9 ("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: Tejun 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: Jens Axboe <axboe@kernel.dk>

authored by

Tejun Heo and committed by
Jens Axboe
3f289dcb ada94973

+34 -33
+7 -7
drivers/block/brd.c
··· 254 254 * Process a single bvec of a bio. 255 255 */ 256 256 static int brd_do_bvec(struct brd_device *brd, struct page *page, 257 - unsigned int len, unsigned int off, bool is_write, 257 + unsigned int len, unsigned int off, unsigned int op, 258 258 sector_t sector) 259 259 { 260 260 void *mem; 261 261 int err = 0; 262 262 263 - if (is_write) { 263 + if (op_is_write(op)) { 264 264 err = copy_to_brd_setup(brd, sector, len); 265 265 if (err) 266 266 goto out; 267 267 } 268 268 269 269 mem = kmap_atomic(page); 270 - if (!is_write) { 270 + if (!op_is_write(op)) { 271 271 copy_from_brd(mem + off, brd, sector, len); 272 272 flush_dcache_page(page); 273 273 } else { ··· 296 296 int err; 297 297 298 298 err = brd_do_bvec(brd, bvec.bv_page, len, bvec.bv_offset, 299 - op_is_write(bio_op(bio)), sector); 299 + bio_op(bio), sector); 300 300 if (err) 301 301 goto io_error; 302 302 sector += len >> SECTOR_SHIFT; ··· 310 310 } 311 311 312 312 static int brd_rw_page(struct block_device *bdev, sector_t sector, 313 - struct page *page, bool is_write) 313 + struct page *page, unsigned int op) 314 314 { 315 315 struct brd_device *brd = bdev->bd_disk->private_data; 316 316 int err; 317 317 318 318 if (PageTransHuge(page)) 319 319 return -ENOTSUPP; 320 - err = brd_do_bvec(brd, page, PAGE_SIZE, 0, is_write, sector); 321 - page_endio(page, is_write, err); 320 + err = brd_do_bvec(brd, page, PAGE_SIZE, 0, op, sector); 321 + page_endio(page, op_is_write(op), err); 322 322 return err; 323 323 } 324 324
+8 -8
drivers/block/zram/zram_drv.c
··· 1274 1274 * Returns 1 if IO request was successfully submitted. 1275 1275 */ 1276 1276 static int zram_bvec_rw(struct zram *zram, struct bio_vec *bvec, u32 index, 1277 - int offset, bool is_write, struct bio *bio) 1277 + int offset, unsigned int op, struct bio *bio) 1278 1278 { 1279 1279 unsigned long start_time = jiffies; 1280 - int rw_acct = is_write ? REQ_OP_WRITE : REQ_OP_READ; 1280 + int rw_acct = op_is_write(op) ? REQ_OP_WRITE : REQ_OP_READ; 1281 1281 struct request_queue *q = zram->disk->queue; 1282 1282 int ret; 1283 1283 1284 1284 generic_start_io_acct(q, rw_acct, bvec->bv_len >> SECTOR_SHIFT, 1285 1285 &zram->disk->part0); 1286 1286 1287 - if (!is_write) { 1287 + if (!op_is_write(op)) { 1288 1288 atomic64_inc(&zram->stats.num_reads); 1289 1289 ret = zram_bvec_read(zram, bvec, index, offset, bio); 1290 1290 flush_dcache_page(bvec->bv_page); ··· 1300 1300 zram_slot_unlock(zram, index); 1301 1301 1302 1302 if (unlikely(ret < 0)) { 1303 - if (!is_write) 1303 + if (!op_is_write(op)) 1304 1304 atomic64_inc(&zram->stats.failed_reads); 1305 1305 else 1306 1306 atomic64_inc(&zram->stats.failed_writes); ··· 1338 1338 bv.bv_len = min_t(unsigned int, PAGE_SIZE - offset, 1339 1339 unwritten); 1340 1340 if (zram_bvec_rw(zram, &bv, index, offset, 1341 - op_is_write(bio_op(bio)), bio) < 0) 1341 + bio_op(bio), bio) < 0) 1342 1342 goto out; 1343 1343 1344 1344 bv.bv_offset += bv.bv_len; ··· 1390 1390 } 1391 1391 1392 1392 static int zram_rw_page(struct block_device *bdev, sector_t sector, 1393 - struct page *page, bool is_write) 1393 + struct page *page, unsigned int op) 1394 1394 { 1395 1395 int offset, ret; 1396 1396 u32 index; ··· 1414 1414 bv.bv_len = PAGE_SIZE; 1415 1415 bv.bv_offset = 0; 1416 1416 1417 - ret = zram_bvec_rw(zram, &bv, index, offset, is_write, NULL); 1417 + ret = zram_bvec_rw(zram, &bv, index, offset, op, NULL); 1418 1418 out: 1419 1419 /* 1420 1420 * If I/O fails, just return error(ie, non-zero) without ··· 1429 1429 1430 1430 switch (ret) { 1431 1431 case 0: 1432 - page_endio(page, is_write, 0); 1432 + page_endio(page, op_is_write(op), 0); 1433 1433 break; 1434 1434 case 1: 1435 1435 ret = 0;
+6 -6
drivers/nvdimm/btt.c
··· 1423 1423 1424 1424 static int btt_do_bvec(struct btt *btt, struct bio_integrity_payload *bip, 1425 1425 struct page *page, unsigned int len, unsigned int off, 1426 - bool is_write, sector_t sector) 1426 + unsigned int op, sector_t sector) 1427 1427 { 1428 1428 int ret; 1429 1429 1430 - if (!is_write) { 1430 + if (!op_is_write(op)) { 1431 1431 ret = btt_read_pg(btt, bip, page, off, sector, len); 1432 1432 flush_dcache_page(page); 1433 1433 } else { ··· 1464 1464 } 1465 1465 1466 1466 err = btt_do_bvec(btt, bip, bvec.bv_page, len, bvec.bv_offset, 1467 - op_is_write(bio_op(bio)), iter.bi_sector); 1467 + bio_op(bio), iter.bi_sector); 1468 1468 if (err) { 1469 1469 dev_err(&btt->nd_btt->dev, 1470 1470 "io error in %s sector %lld, len %d,\n", ··· 1483 1483 } 1484 1484 1485 1485 static int btt_rw_page(struct block_device *bdev, sector_t sector, 1486 - struct page *page, bool is_write) 1486 + struct page *page, unsigned int op) 1487 1487 { 1488 1488 struct btt *btt = bdev->bd_disk->private_data; 1489 1489 int rc; 1490 1490 unsigned int len; 1491 1491 1492 1492 len = hpage_nr_pages(page) * PAGE_SIZE; 1493 - rc = btt_do_bvec(btt, NULL, page, len, 0, is_write, sector); 1493 + rc = btt_do_bvec(btt, NULL, page, len, 0, op, sector); 1494 1494 if (rc == 0) 1495 - page_endio(page, is_write, 0); 1495 + page_endio(page, op_is_write(op), 0); 1496 1496 1497 1497 return rc; 1498 1498 }
+6 -7
drivers/nvdimm/pmem.c
··· 120 120 } 121 121 122 122 static blk_status_t pmem_do_bvec(struct pmem_device *pmem, struct page *page, 123 - unsigned int len, unsigned int off, bool is_write, 123 + unsigned int len, unsigned int off, unsigned int op, 124 124 sector_t sector) 125 125 { 126 126 blk_status_t rc = BLK_STS_OK; ··· 131 131 if (unlikely(is_bad_pmem(&pmem->bb, sector, len))) 132 132 bad_pmem = true; 133 133 134 - if (!is_write) { 134 + if (!op_is_write(op)) { 135 135 if (unlikely(bad_pmem)) 136 136 rc = BLK_STS_IOERR; 137 137 else { ··· 180 180 do_acct = nd_iostat_start(bio, &start); 181 181 bio_for_each_segment(bvec, bio, iter) { 182 182 rc = pmem_do_bvec(pmem, bvec.bv_page, bvec.bv_len, 183 - bvec.bv_offset, op_is_write(bio_op(bio)), 184 - iter.bi_sector); 183 + bvec.bv_offset, bio_op(bio), iter.bi_sector); 185 184 if (rc) { 186 185 bio->bi_status = rc; 187 186 break; ··· 197 198 } 198 199 199 200 static int pmem_rw_page(struct block_device *bdev, sector_t sector, 200 - struct page *page, bool is_write) 201 + struct page *page, unsigned int op) 201 202 { 202 203 struct pmem_device *pmem = bdev->bd_queue->queuedata; 203 204 blk_status_t rc; 204 205 205 206 rc = pmem_do_bvec(pmem, page, hpage_nr_pages(page) * PAGE_SIZE, 206 - 0, is_write, sector); 207 + 0, op, sector); 207 208 208 209 /* 209 210 * The ->rw_page interface is subtle and tricky. The core ··· 212 213 * caused by double completion. 213 214 */ 214 215 if (rc == 0) 215 - page_endio(page, is_write, 0); 216 + page_endio(page, op_is_write(op), 0); 216 217 217 218 return blk_status_to_errno(rc); 218 219 }
+4 -2
fs/block_dev.c
··· 665 665 result = blk_queue_enter(bdev->bd_queue, 0); 666 666 if (result) 667 667 return result; 668 - result = ops->rw_page(bdev, sector + get_start_sect(bdev), page, false); 668 + result = ops->rw_page(bdev, sector + get_start_sect(bdev), page, 669 + REQ_OP_READ); 669 670 blk_queue_exit(bdev->bd_queue); 670 671 return result; 671 672 } ··· 704 703 return result; 705 704 706 705 set_page_writeback(page); 707 - result = ops->rw_page(bdev, sector + get_start_sect(bdev), page, true); 706 + result = ops->rw_page(bdev, sector + get_start_sect(bdev), page, 707 + REQ_OP_WRITE); 708 708 if (result) { 709 709 end_page_writeback(page); 710 710 } else {
+2 -2
fs/mpage.c
··· 51 51 52 52 bio_for_each_segment_all(bv, bio, i) { 53 53 struct page *page = bv->bv_page; 54 - page_endio(page, op_is_write(bio_op(bio)), 55 - blk_status_to_errno(bio->bi_status)); 54 + page_endio(page, bio_op(bio), 55 + blk_status_to_errno(bio->bi_status)); 56 56 } 57 57 58 58 bio_put(bio);
+1 -1
include/linux/blkdev.h
··· 1943 1943 struct block_device_operations { 1944 1944 int (*open) (struct block_device *, fmode_t); 1945 1945 void (*release) (struct gendisk *, fmode_t); 1946 - int (*rw_page)(struct block_device *, sector_t, struct page *, bool); 1946 + int (*rw_page)(struct block_device *, sector_t, struct page *, unsigned int); 1947 1947 int (*ioctl) (struct block_device *, fmode_t, unsigned, unsigned long); 1948 1948 int (*compat_ioctl) (struct block_device *, fmode_t, unsigned, unsigned long); 1949 1949 unsigned int (*check_events) (struct gendisk *disk,