Prepare for supporting IO polling for bio based driver. Add ->poll_bio callback so that bio driver can provide their own logic for polling bio. Signed-off-by: Ming Lei <ming.lei@xxxxxxxxxx> --- block/blk-core.c | 18 +++++++++++++----- block/genhd.c | 3 +++ include/linux/blkdev.h | 2 ++ 3 files changed, 18 insertions(+), 5 deletions(-) diff --git a/block/blk-core.c b/block/blk-core.c index 1e24c71c6738..a1552ec8d608 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -1113,11 +1113,13 @@ EXPORT_SYMBOL(submit_bio); */ int bio_poll(struct bio *bio, unsigned int flags) { - struct request_queue *q = bio->bi_bdev->bd_disk->queue; + struct gendisk *disk = bio->bi_bdev->bd_disk; + struct request_queue *q = disk->queue; blk_qc_t cookie = READ_ONCE(bio->bi_cookie); int ret; - if (cookie == BLK_QC_T_NONE || !blk_queue_poll(q)) + if ((queue_is_mq(q) && cookie == BLK_QC_T_NONE) || + !blk_queue_poll(q)) return 0; if (current->plug) @@ -1125,10 +1127,16 @@ int bio_poll(struct bio *bio, unsigned int flags) if (blk_queue_enter(q, BLK_MQ_REQ_NOWAIT)) return 0; - if (WARN_ON_ONCE(!queue_is_mq(q))) - ret = 0; /* not yet implemented, should not happen */ - else + if (!queue_is_mq(q)) { + if (disk->fops->poll_bio) { + ret = disk->fops->poll_bio(bio, flags); + } else { + WARN_ON_ONCE(1); + ret = 0; + } + } else { ret = blk_mq_poll(q, cookie, flags); + } blk_queue_exit(q); return ret; } diff --git a/block/genhd.c b/block/genhd.c index 5f5628216295..042dfa5b3f79 100644 --- a/block/genhd.c +++ b/block/genhd.c @@ -471,6 +471,9 @@ static void __device_add_disk(struct device *parent, struct gendisk *disk, { int ret; + /* ->poll_bio is only for bio based driver */ + WARN_ON_ONCE(queue_is_mq(disk->queue) && disk->fops->poll_bio); + /* * The disk queue should now be all set with enough information about * the device for the elevator code to pick an adequate default diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index fc0ba0b80776..6da6fb120148 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -1858,6 +1858,8 @@ static inline void blk_ksm_unregister(struct request_queue *q) { } struct block_device_operations { void (*submit_bio)(struct bio *bio); + /* ->poll_bio is for bio driver only */ + int (*poll_bio)(struct bio *bio, unsigned int flags); int (*open) (struct block_device *, fmode_t); void (*release) (struct gendisk *, fmode_t); int (*rw_page)(struct block_device *, sector_t, struct page *, unsigned int); -- 2.31.1