Message ID | 20210617103549.930311-3-ming.lei@redhat.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | block/dm: support bio polling | expand |
> + 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; How does polling for a bio without a cookie make sense even when polling bio based? But if we come up for a good rationale for this I'd really split the conditions to make them more readable: if (!test_bit(QUEUE_FLAG_POLL, &q->queue_flags)) return 0; if (queue_is_mq(q) && cookie == BLK_QC_T_NONE) return 0; > + 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); I'd go for someting like: if (queue_is_mq(q)) ret = blk_mq_poll(q, cookie, flags); else if (disk->fops->poll_bio) ret = disk->fops->poll_bio(bio, flags); else WARN_ON_ONCE(1); with ret initialized to 0 at declaration time. > struct block_device_operations { > void (*submit_bio)(struct bio *bio); > + /* ->poll_bio is for bio driver only */ I'd drop the comment, this is already nicely documented in add_disk together with the actual check. We also don't note this for submit_bio here.
On Mon, Jun 21, 2021 at 09:25:02AM +0200, Christoph Hellwig wrote: > > + 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; > > How does polling for a bio without a cookie make sense even when > polling bio based? It isn't necessary to use bio->bi_cookie, that is why I doesn't use it, which actually provides one free 32bit in bio for bio based driver. > > But if we come up for a good rationale for this I'd really > split the conditions to make them more readable: > > if (!test_bit(QUEUE_FLAG_POLL, &q->queue_flags)) > return 0; > if (queue_is_mq(q) && cookie == BLK_QC_T_NONE) > return 0; OK. > > > + 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); > > I'd go for someting like: > > if (queue_is_mq(q)) > ret = blk_mq_poll(q, cookie, flags); > else if (disk->fops->poll_bio) > ret = disk->fops->poll_bio(bio, flags); > else > WARN_ON_ONCE(1); > > with ret initialized to 0 at declaration time. Fine. > > > struct block_device_operations { > > void (*submit_bio)(struct bio *bio); > > + /* ->poll_bio is for bio driver only */ > > I'd drop the comment, this is already nicely documented in add_disk > together with the actual check. We also don't note this for submit_bio > here. OK. thanks, Ming
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);
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@redhat.com> --- block/blk-core.c | 18 +++++++++++++----- block/genhd.c | 3 +++ include/linux/blkdev.h | 2 ++ 3 files changed, 18 insertions(+), 5 deletions(-)