* [PATCH 4/7] nonblocking aio: return on congested block device [not found] <20170214024603.9563-1-rgoldwyn@suse.de> @ 2017-02-14 2:46 ` Goldwyn Rodrigues 2017-02-14 3:55 ` Ming Lei 0 siblings, 1 reply; 3+ messages in thread From: Goldwyn Rodrigues @ 2017-02-14 2:46 UTC (permalink / raw) To: linux-fsdevel; +Cc: jack, Goldwyn Rodrigues, linux-block From: Goldwyn Rodrigues <rgoldwyn@suse.com> A new flag BIO_NONBLOCKING is introduced to identify bio's orignating from iocb with IOCB_NONBLOCKING. struct request are requested using BLK_MQ_REQ_NOWAIT if BIO_NONBLOCKING is set. Signed-off-by: Goldwyn Rodrigues <rgoldwyn@suse.com> --- block/blk-core.c | 13 +++++++++++-- block/blk-mq.c | 18 ++++++++++++++++-- fs/direct-io.c | 11 +++++++++-- include/linux/blk_types.h | 1 + 4 files changed, 37 insertions(+), 6 deletions(-) diff --git a/block/blk-core.c b/block/blk-core.c index 14d7c07..9767573 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -1257,6 +1257,11 @@ static struct request *get_request(struct request_queue *q, int op, if (!IS_ERR(rq)) return rq; + if (bio_flagged(bio, BIO_NONBLOCKING)) { + blk_put_rl(rl); + return ERR_PTR(-EAGAIN); + } + if (!gfpflags_allow_blocking(gfp_mask) || unlikely(blk_queue_dying(q))) { blk_put_rl(rl); return rq; @@ -2035,7 +2040,7 @@ blk_qc_t generic_make_request(struct bio *bio) do { struct request_queue *q = bdev_get_queue(bio->bi_bdev); - if (likely(blk_queue_enter(q, false) == 0)) { + if (likely(blk_queue_enter(q, bio_flagged(bio, BIO_NONBLOCKING)) == 0)) { ret = q->make_request_fn(q, bio); blk_queue_exit(q); @@ -2044,7 +2049,11 @@ blk_qc_t generic_make_request(struct bio *bio) } else { struct bio *bio_next = bio_list_pop(current->bio_list); - bio_io_error(bio); + if (unlikely(bio_flagged(bio, BIO_NONBLOCKING))) { + bio->bi_error = -EAGAIN; + bio_endio(bio); + } else + bio_io_error(bio); bio = bio_next; } } while (bio); diff --git a/block/blk-mq.c b/block/blk-mq.c index 81caceb..7a7c674 100644 --- a/block/blk-mq.c +++ b/block/blk-mq.c @@ -1213,6 +1213,8 @@ static struct request *blk_mq_map_request(struct request_queue *q, trace_block_getrq(q, bio, op); blk_mq_set_alloc_data(&alloc_data, q, 0, ctx, hctx); + if (bio_flagged(bio, BIO_NONBLOCKING)) + alloc_data.flags |= BLK_MQ_REQ_NOWAIT; rq = __blk_mq_alloc_request(&alloc_data, op, op_flags); data->hctx = alloc_data.hctx; @@ -1286,8 +1288,14 @@ static blk_qc_t blk_mq_make_request(struct request_queue *q, struct bio *bio) return BLK_QC_T_NONE; rq = blk_mq_map_request(q, bio, &data); - if (unlikely(!rq)) + if (unlikely(!rq)) { + if (bio_flagged(bio, BIO_NONBLOCKING)) + bio->bi_error = -EAGAIN; + else + bio->bi_error = -EIO; + bio_endio(bio); return BLK_QC_T_NONE; + } cookie = blk_tag_to_qc_t(rq->tag, data.hctx->queue_num); @@ -1381,8 +1389,14 @@ static blk_qc_t blk_sq_make_request(struct request_queue *q, struct bio *bio) request_count = blk_plug_queued_count(q); rq = blk_mq_map_request(q, bio, &data); - if (unlikely(!rq)) + if (unlikely(!rq)) { + if (bio_flagged(bio, BIO_NONBLOCKING)) + bio->bi_error = -EAGAIN; + else + bio->bi_error = -EIO; + bio_endio(bio); return BLK_QC_T_NONE; + } cookie = blk_tag_to_qc_t(rq->tag, data.hctx->queue_num); diff --git a/fs/direct-io.c b/fs/direct-io.c index fb9aa16..9997fed 100644 --- a/fs/direct-io.c +++ b/fs/direct-io.c @@ -386,6 +386,9 @@ dio_bio_alloc(struct dio *dio, struct dio_submit *sdio, else bio->bi_end_io = dio_bio_end_io; + if (dio->iocb->ki_flags & IOCB_NONBLOCKING) + bio_set_flag(bio, BIO_NONBLOCKING); + sdio->bio = bio; sdio->logical_offset_in_bio = sdio->cur_page_fs_offset; } @@ -480,8 +483,12 @@ static int dio_bio_complete(struct dio *dio, struct bio *bio) unsigned i; int err; - if (bio->bi_error) - dio->io_error = -EIO; + if (bio->bi_error) { + if (bio_flagged(bio, BIO_NONBLOCKING)) + dio->io_error = bio->bi_error; + else + dio->io_error = -EIO; + } if (dio->is_async && dio->op == REQ_OP_READ && dio->should_dirty) { err = bio->bi_error; diff --git a/include/linux/blk_types.h b/include/linux/blk_types.h index cd395ec..94855cf 100644 --- a/include/linux/blk_types.h +++ b/include/linux/blk_types.h @@ -119,6 +119,7 @@ struct bio { #define BIO_QUIET 6 /* Make BIO Quiet */ #define BIO_CHAIN 7 /* chained bio, ->bi_remaining in effect */ #define BIO_REFFED 8 /* bio has elevated ->bi_cnt */ +#define BIO_NONBLOCKING 9 /* don't block over blk device congestion */ /* * Flags starting here get preserved by bio_reset() - this includes -- 2.10.2 ^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [PATCH 4/7] nonblocking aio: return on congested block device 2017-02-14 2:46 ` [PATCH 4/7] nonblocking aio: return on congested block device Goldwyn Rodrigues @ 2017-02-14 3:55 ` Ming Lei 2017-02-15 11:13 ` Goldwyn Rodrigues 0 siblings, 1 reply; 3+ messages in thread From: Ming Lei @ 2017-02-14 3:55 UTC (permalink / raw) To: Goldwyn Rodrigues Cc: Linux FS Devel, Jan Kara, Goldwyn Rodrigues, linux-block On Tue, Feb 14, 2017 at 10:46 AM, Goldwyn Rodrigues <rgoldwyn@suse.de> wrote: > From: Goldwyn Rodrigues <rgoldwyn@suse.com> > > A new flag BIO_NONBLOCKING is introduced to identify bio's > orignating from iocb with IOCB_NONBLOCKING. struct request > are requested using BLK_MQ_REQ_NOWAIT if BIO_NONBLOCKING is set. > > Signed-off-by: Goldwyn Rodrigues <rgoldwyn@suse.com> > --- > block/blk-core.c | 13 +++++++++++-- > block/blk-mq.c | 18 ++++++++++++++++-- > fs/direct-io.c | 11 +++++++++-- > include/linux/blk_types.h | 1 + > 4 files changed, 37 insertions(+), 6 deletions(-) > > diff --git a/block/blk-core.c b/block/blk-core.c > index 14d7c07..9767573 100644 > --- a/block/blk-core.c > +++ b/block/blk-core.c > @@ -1257,6 +1257,11 @@ static struct request *get_request(struct request_queue *q, int op, > if (!IS_ERR(rq)) > return rq; > > + if (bio_flagged(bio, BIO_NONBLOCKING)) { > + blk_put_rl(rl); > + return ERR_PTR(-EAGAIN); > + } > + > if (!gfpflags_allow_blocking(gfp_mask) || unlikely(blk_queue_dying(q))) { > blk_put_rl(rl); > return rq; > @@ -2035,7 +2040,7 @@ blk_qc_t generic_make_request(struct bio *bio) > do { > struct request_queue *q = bdev_get_queue(bio->bi_bdev); > > - if (likely(blk_queue_enter(q, false) == 0)) { > + if (likely(blk_queue_enter(q, bio_flagged(bio, BIO_NONBLOCKING)) == 0)) { > ret = q->make_request_fn(q, bio); > > blk_queue_exit(q); > @@ -2044,7 +2049,11 @@ blk_qc_t generic_make_request(struct bio *bio) > } else { > struct bio *bio_next = bio_list_pop(current->bio_list); > > - bio_io_error(bio); > + if (unlikely(bio_flagged(bio, BIO_NONBLOCKING))) { > + bio->bi_error = -EAGAIN; > + bio_endio(bio); > + } else > + bio_io_error(bio); > bio = bio_next; > } > } while (bio); > diff --git a/block/blk-mq.c b/block/blk-mq.c > index 81caceb..7a7c674 100644 > --- a/block/blk-mq.c > +++ b/block/blk-mq.c > @@ -1213,6 +1213,8 @@ static struct request *blk_mq_map_request(struct request_queue *q, > > trace_block_getrq(q, bio, op); > blk_mq_set_alloc_data(&alloc_data, q, 0, ctx, hctx); > + if (bio_flagged(bio, BIO_NONBLOCKING)) > + alloc_data.flags |= BLK_MQ_REQ_NOWAIT; > rq = __blk_mq_alloc_request(&alloc_data, op, op_flags); > > data->hctx = alloc_data.hctx; > @@ -1286,8 +1288,14 @@ static blk_qc_t blk_mq_make_request(struct request_queue *q, struct bio *bio) > return BLK_QC_T_NONE; > > rq = blk_mq_map_request(q, bio, &data); > - if (unlikely(!rq)) > + if (unlikely(!rq)) { > + if (bio_flagged(bio, BIO_NONBLOCKING)) > + bio->bi_error = -EAGAIN; > + else > + bio->bi_error = -EIO; > + bio_endio(bio); > return BLK_QC_T_NONE; > + } > > cookie = blk_tag_to_qc_t(rq->tag, data.hctx->queue_num); > > @@ -1381,8 +1389,14 @@ static blk_qc_t blk_sq_make_request(struct request_queue *q, struct bio *bio) > request_count = blk_plug_queued_count(q); > > rq = blk_mq_map_request(q, bio, &data); > - if (unlikely(!rq)) > + if (unlikely(!rq)) { > + if (bio_flagged(bio, BIO_NONBLOCKING)) > + bio->bi_error = -EAGAIN; > + else > + bio->bi_error = -EIO; > + bio_endio(bio); > return BLK_QC_T_NONE; > + } There are other places in which blocking may be triggered, such as allocating for bio clone, wbt_wait(), and sleep in .make_request(), like md, dm and bcache's. IMO it should be hard to deal with all, so what is the expection for flag of BIO_NONBLOCKING? > > cookie = blk_tag_to_qc_t(rq->tag, data.hctx->queue_num); > > diff --git a/fs/direct-io.c b/fs/direct-io.c > index fb9aa16..9997fed 100644 > --- a/fs/direct-io.c > +++ b/fs/direct-io.c > @@ -386,6 +386,9 @@ dio_bio_alloc(struct dio *dio, struct dio_submit *sdio, > else > bio->bi_end_io = dio_bio_end_io; > > + if (dio->iocb->ki_flags & IOCB_NONBLOCKING) > + bio_set_flag(bio, BIO_NONBLOCKING); > + > sdio->bio = bio; > sdio->logical_offset_in_bio = sdio->cur_page_fs_offset; > } > @@ -480,8 +483,12 @@ static int dio_bio_complete(struct dio *dio, struct bio *bio) > unsigned i; > int err; > > - if (bio->bi_error) > - dio->io_error = -EIO; > + if (bio->bi_error) { > + if (bio_flagged(bio, BIO_NONBLOCKING)) > + dio->io_error = bio->bi_error; > + else > + dio->io_error = -EIO; > + } > > if (dio->is_async && dio->op == REQ_OP_READ && dio->should_dirty) { > err = bio->bi_error; > diff --git a/include/linux/blk_types.h b/include/linux/blk_types.h > index cd395ec..94855cf 100644 > --- a/include/linux/blk_types.h > +++ b/include/linux/blk_types.h > @@ -119,6 +119,7 @@ struct bio { > #define BIO_QUIET 6 /* Make BIO Quiet */ > #define BIO_CHAIN 7 /* chained bio, ->bi_remaining in effect */ > #define BIO_REFFED 8 /* bio has elevated ->bi_cnt */ > +#define BIO_NONBLOCKING 9 /* don't block over blk device congestion */ > > /* > * Flags starting here get preserved by bio_reset() - this includes > -- > 2.10.2 > -- Ming Lei ^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH 4/7] nonblocking aio: return on congested block device 2017-02-14 3:55 ` Ming Lei @ 2017-02-15 11:13 ` Goldwyn Rodrigues 0 siblings, 0 replies; 3+ messages in thread From: Goldwyn Rodrigues @ 2017-02-15 11:13 UTC (permalink / raw) To: Ming Lei, Goldwyn Rodrigues; +Cc: Linux FS Devel, Jan Kara, linux-block On 02/13/2017 09:55 PM, Ming Lei wrote: > On Tue, Feb 14, 2017 at 10:46 AM, Goldwyn Rodrigues <rgoldwyn@suse.de> wrote: >> From: Goldwyn Rodrigues <rgoldwyn@suse.com> >> >> A new flag BIO_NONBLOCKING is introduced to identify bio's >> orignating from iocb with IOCB_NONBLOCKING. struct request >> are requested using BLK_MQ_REQ_NOWAIT if BIO_NONBLOCKING is set. >> >> Signed-off-by: Goldwyn Rodrigues <rgoldwyn@suse.com> >> --- >> block/blk-core.c | 13 +++++++++++-- >> block/blk-mq.c | 18 ++++++++++++++++-- >> fs/direct-io.c | 11 +++++++++-- >> include/linux/blk_types.h | 1 + >> 4 files changed, 37 insertions(+), 6 deletions(-) >> >> diff --git a/block/blk-core.c b/block/blk-core.c >> index 14d7c07..9767573 100644 >> --- a/block/blk-core.c >> +++ b/block/blk-core.c >> @@ -1257,6 +1257,11 @@ static struct request *get_request(struct request_queue *q, int op, >> if (!IS_ERR(rq)) >> return rq; >> >> + if (bio_flagged(bio, BIO_NONBLOCKING)) { >> + blk_put_rl(rl); >> + return ERR_PTR(-EAGAIN); >> + } >> + >> if (!gfpflags_allow_blocking(gfp_mask) || unlikely(blk_queue_dying(q))) { >> blk_put_rl(rl); >> return rq; >> @@ -2035,7 +2040,7 @@ blk_qc_t generic_make_request(struct bio *bio) >> do { >> struct request_queue *q = bdev_get_queue(bio->bi_bdev); >> >> - if (likely(blk_queue_enter(q, false) == 0)) { >> + if (likely(blk_queue_enter(q, bio_flagged(bio, BIO_NONBLOCKING)) == 0)) { >> ret = q->make_request_fn(q, bio); >> >> blk_queue_exit(q); >> @@ -2044,7 +2049,11 @@ blk_qc_t generic_make_request(struct bio *bio) >> } else { >> struct bio *bio_next = bio_list_pop(current->bio_list); >> >> - bio_io_error(bio); >> + if (unlikely(bio_flagged(bio, BIO_NONBLOCKING))) { >> + bio->bi_error = -EAGAIN; >> + bio_endio(bio); >> + } else >> + bio_io_error(bio); >> bio = bio_next; >> } >> } while (bio); >> diff --git a/block/blk-mq.c b/block/blk-mq.c >> index 81caceb..7a7c674 100644 >> --- a/block/blk-mq.c >> +++ b/block/blk-mq.c >> @@ -1213,6 +1213,8 @@ static struct request *blk_mq_map_request(struct request_queue *q, >> >> trace_block_getrq(q, bio, op); >> blk_mq_set_alloc_data(&alloc_data, q, 0, ctx, hctx); >> + if (bio_flagged(bio, BIO_NONBLOCKING)) >> + alloc_data.flags |= BLK_MQ_REQ_NOWAIT; >> rq = __blk_mq_alloc_request(&alloc_data, op, op_flags); >> >> data->hctx = alloc_data.hctx; >> @@ -1286,8 +1288,14 @@ static blk_qc_t blk_mq_make_request(struct request_queue *q, struct bio *bio) >> return BLK_QC_T_NONE; >> >> rq = blk_mq_map_request(q, bio, &data); >> - if (unlikely(!rq)) >> + if (unlikely(!rq)) { >> + if (bio_flagged(bio, BIO_NONBLOCKING)) >> + bio->bi_error = -EAGAIN; >> + else >> + bio->bi_error = -EIO; >> + bio_endio(bio); >> return BLK_QC_T_NONE; >> + } >> >> cookie = blk_tag_to_qc_t(rq->tag, data.hctx->queue_num); >> >> @@ -1381,8 +1389,14 @@ static blk_qc_t blk_sq_make_request(struct request_queue *q, struct bio *bio) >> request_count = blk_plug_queued_count(q); >> >> rq = blk_mq_map_request(q, bio, &data); >> - if (unlikely(!rq)) >> + if (unlikely(!rq)) { >> + if (bio_flagged(bio, BIO_NONBLOCKING)) >> + bio->bi_error = -EAGAIN; >> + else >> + bio->bi_error = -EIO; >> + bio_endio(bio); >> return BLK_QC_T_NONE; >> + } > > There are other places in which blocking may be triggered, such > as allocating for bio clone, wbt_wait(), and sleep in .make_request(), > like md, dm and bcache's. > > IMO it should be hard to deal with all, so what is the expection for > flag of BIO_NONBLOCKING? > This is a part of the effort of making direct AIO nonblocking. I should have posted all patches to all lists. BIO_NONBLOCKING is a bio generated from a non-blocking AIO. Ideally it should bail whenever it sees that it would block and sleep if the blockqueue is congested (only). While earlier we had thought of limiting it to get_request(), I expanded it to blk-mq (which now I think may not be as useful). >> >> cookie = blk_tag_to_qc_t(rq->tag, data.hctx->queue_num); >> >> diff --git a/fs/direct-io.c b/fs/direct-io.c >> index fb9aa16..9997fed 100644 >> --- a/fs/direct-io.c >> +++ b/fs/direct-io.c >> @@ -386,6 +386,9 @@ dio_bio_alloc(struct dio *dio, struct dio_submit *sdio, >> else >> bio->bi_end_io = dio_bio_end_io; >> >> + if (dio->iocb->ki_flags & IOCB_NONBLOCKING) >> + bio_set_flag(bio, BIO_NONBLOCKING); >> + >> sdio->bio = bio; >> sdio->logical_offset_in_bio = sdio->cur_page_fs_offset; >> } >> @@ -480,8 +483,12 @@ static int dio_bio_complete(struct dio *dio, struct bio *bio) >> unsigned i; >> int err; >> >> - if (bio->bi_error) >> - dio->io_error = -EIO; >> + if (bio->bi_error) { >> + if (bio_flagged(bio, BIO_NONBLOCKING)) >> + dio->io_error = bio->bi_error; >> + else >> + dio->io_error = -EIO; >> + } >> >> if (dio->is_async && dio->op == REQ_OP_READ && dio->should_dirty) { >> err = bio->bi_error; >> diff --git a/include/linux/blk_types.h b/include/linux/blk_types.h >> index cd395ec..94855cf 100644 >> --- a/include/linux/blk_types.h >> +++ b/include/linux/blk_types.h >> @@ -119,6 +119,7 @@ struct bio { >> #define BIO_QUIET 6 /* Make BIO Quiet */ >> #define BIO_CHAIN 7 /* chained bio, ->bi_remaining in effect */ >> #define BIO_REFFED 8 /* bio has elevated ->bi_cnt */ >> +#define BIO_NONBLOCKING 9 /* don't block over blk device congestion */ >> >> /* >> * Flags starting here get preserved by bio_reset() - this includes >> -- >> 2.10.2 >> > > > -- Goldwyn ^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2017-02-15 11:13 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <20170214024603.9563-1-rgoldwyn@suse.de>
2017-02-14 2:46 ` [PATCH 4/7] nonblocking aio: return on congested block device Goldwyn Rodrigues
2017-02-14 3:55 ` Ming Lei
2017-02-15 11:13 ` Goldwyn Rodrigues
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox