From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Subject: Re: [PATCH 14/17] aoe: convert aoeblk to blk-mq To: Ed Cashin , Ed Cashin Cc: linux-block@vger.kernel.org References: <20181011165909.32615-1-axboe@kernel.dk> <20181011165909.32615-15-axboe@kernel.dk> <2fb82c13-66c0-30bb-a408-10e01abc648f@kernel.dk> From: Jens Axboe Message-ID: <19b0d1ee-ad98-b97e-04ce-206c7dbea5a2@kernel.dk> Date: Sun, 14 Oct 2018 12:44:21 -0600 MIME-Version: 1.0 In-Reply-To: Content-Type: text/plain; charset=utf-8 List-ID: On 10/13/18 6:48 PM, Ed Cashin wrote: > I reviewed the changes. They looked good. Thanks Ed! -- Jens Axboe From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: MIME-Version: 1.0 References: <20181011165909.32615-1-axboe@kernel.dk> <20181011165909.32615-15-axboe@kernel.dk> <2fb82c13-66c0-30bb-a408-10e01abc648f@kernel.dk> In-Reply-To: From: Ed Cashin Date: Sat, 13 Oct 2018 20:48:55 -0400 Message-ID: Subject: Re: [PATCH 14/17] aoe: convert aoeblk to blk-mq To: Ed Cashin Cc: axboe@kernel.dk, linux-block@vger.kernel.org Content-Type: multipart/alternative; boundary="0000000000000e2e52057825b027" List-ID: --0000000000000e2e52057825b027 Content-Type: text/plain; charset="UTF-8" I reviewed the changes. They looked good. On Fri, Oct 12, 2018 at 12:26 PM Ed Cashin wrote: > On Fri, Oct 12, 2018 at 12:23 PM Jens Axboe wrote: > > > > On 10/12/18 10:17 AM, Ed Cashin wrote: > > > On Fri, Oct 12, 2018 at 10:20 AM Jens Axboe wrote: > > >> > > >> On 10/12/18 5:28 AM, Ed Cashin wrote: > > >>> OK. We always tried to avoid putting includes in the .h file, so > > >>> if you wouldn't mind moving the include to the C files, that would > > >>> be nice. I wouldn't insist, though. > > >> > > >> There's really no way around it, since I'm embedding the tag_set > > >> in the device. > > >> > > >> Is that OK with you? > > > > > > Yes, it's fine. Thank you. > > > > Can I add a reviewed-by? > > Acked-by is already fine, but I can give it more attention tomorrow, and > after > that a reviewed-by would be appropriate. > > -- > Ed > -- Ed Cashin --0000000000000e2e52057825b027 Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable
I reviewed the changes. They looked good.

On Fri, Oct 12, 2018 = at 12:26 PM Ed Cashin <ed.cashin@ac= m.org> wrote:
On Fri, Oct 12= , 2018 at 12:23 PM Jens Axboe <axboe@kernel.dk> wrote:
>
> On 10/12/18 10:17 AM, Ed Cashin wrote:
> > On Fri, Oct 12, 2018 at 10:20 AM Jens Axboe <axboe@kernel.dk> wrote:
> >>
> >> On 10/12/18 5:28 AM, Ed Cashin wrote:
> >>> OK.=C2=A0 We always tried to avoid putting includes in th= e .h file, so
> >>> if you wouldn't mind moving the include to the C file= s, that would
> >>> be nice.=C2=A0 I wouldn't insist, though.
> >>
> >> There's really no way around it, since I'm embedding = the tag_set
> >> in the device.
> >>
> >> Is that OK with you?
> >
> > Yes, it's fine.=C2=A0 Thank you.
>
> Can I add a reviewed-by?

Acked-by is already fine, but I can give it more attention tomorrow, and af= ter
that a reviewed-by would be appropriate.

--
=C2=A0 Ed
--
=C2=A0 Ed Cashin <ecashin@noserose.ne= t>
--0000000000000e2e52057825b027-- From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: MIME-Version: 1.0 References: <20181011165909.32615-1-axboe@kernel.dk> <20181011165909.32615-15-axboe@kernel.dk> <2fb82c13-66c0-30bb-a408-10e01abc648f@kernel.dk> In-Reply-To: <2fb82c13-66c0-30bb-a408-10e01abc648f@kernel.dk> From: Ed Cashin Date: Fri, 12 Oct 2018 12:26:13 -0400 Message-ID: Subject: Re: [PATCH 14/17] aoe: convert aoeblk to blk-mq To: axboe@kernel.dk Cc: "Ed L. Cashin" , linux-block@vger.kernel.org Content-Type: text/plain; charset="UTF-8" List-ID: On Fri, Oct 12, 2018 at 12:23 PM Jens Axboe wrote: > > On 10/12/18 10:17 AM, Ed Cashin wrote: > > On Fri, Oct 12, 2018 at 10:20 AM Jens Axboe wrote: > >> > >> On 10/12/18 5:28 AM, Ed Cashin wrote: > >>> OK. We always tried to avoid putting includes in the .h file, so > >>> if you wouldn't mind moving the include to the C files, that would > >>> be nice. I wouldn't insist, though. > >> > >> There's really no way around it, since I'm embedding the tag_set > >> in the device. > >> > >> Is that OK with you? > > > > Yes, it's fine. Thank you. > > Can I add a reviewed-by? Acked-by is already fine, but I can give it more attention tomorrow, and after that a reviewed-by would be appropriate. -- Ed From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Subject: Re: [PATCH 14/17] aoe: convert aoeblk to blk-mq To: Ed Cashin Cc: linux-block@vger.kernel.org References: <20181011165909.32615-1-axboe@kernel.dk> <20181011165909.32615-15-axboe@kernel.dk> From: Jens Axboe Message-ID: <2fb82c13-66c0-30bb-a408-10e01abc648f@kernel.dk> Date: Fri, 12 Oct 2018 10:23:08 -0600 MIME-Version: 1.0 In-Reply-To: Content-Type: text/plain; charset=utf-8 List-ID: On 10/12/18 10:17 AM, Ed Cashin wrote: > On Fri, Oct 12, 2018 at 10:20 AM Jens Axboe wrote: >> >> On 10/12/18 5:28 AM, Ed Cashin wrote: >>> OK. We always tried to avoid putting includes in the .h file, so >>> if you wouldn't mind moving the include to the C files, that would >>> be nice. I wouldn't insist, though. >> >> There's really no way around it, since I'm embedding the tag_set >> in the device. >> >> Is that OK with you? > > Yes, it's fine. Thank you. Can I add a reviewed-by? -- Jens Axboe From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: MIME-Version: 1.0 References: <20181011165909.32615-1-axboe@kernel.dk> <20181011165909.32615-15-axboe@kernel.dk> In-Reply-To: From: Ed Cashin Date: Fri, 12 Oct 2018 12:17:08 -0400 Message-ID: Subject: Re: [PATCH 14/17] aoe: convert aoeblk to blk-mq To: axboe@kernel.dk Cc: linux-block@vger.kernel.org, "Ed L. Cashin" Content-Type: text/plain; charset="UTF-8" List-ID: On Fri, Oct 12, 2018 at 10:20 AM Jens Axboe wrote: > > On 10/12/18 5:28 AM, Ed Cashin wrote: > > OK. We always tried to avoid putting includes in the .h file, so > > if you wouldn't mind moving the include to the C files, that would > > be nice. I wouldn't insist, though. > > There's really no way around it, since I'm embedding the tag_set > in the device. > > Is that OK with you? Yes, it's fine. Thank you. From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Subject: Re: [PATCH 14/17] aoe: convert aoeblk to blk-mq To: Ed Cashin Cc: linux-block@vger.kernel.org, "Ed L. Cashin" References: <20181011165909.32615-1-axboe@kernel.dk> <20181011165909.32615-15-axboe@kernel.dk> From: Jens Axboe Message-ID: Date: Fri, 12 Oct 2018 08:20:00 -0600 MIME-Version: 1.0 In-Reply-To: Content-Type: text/plain; charset=utf-8 List-ID: On 10/12/18 5:28 AM, Ed Cashin wrote: > OK. We always tried to avoid putting includes in the .h file, so > if you wouldn't mind moving the include to the C files, that would > be nice. I wouldn't insist, though. There's really no way around it, since I'm embedding the tag_set in the device. Is that OK with you? -- Jens Axboe From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: MIME-Version: 1.0 References: <20181011165909.32615-1-axboe@kernel.dk> <20181011165909.32615-15-axboe@kernel.dk> In-Reply-To: <20181011165909.32615-15-axboe@kernel.dk> From: Ed Cashin Date: Fri, 12 Oct 2018 07:28:29 -0400 Message-ID: Subject: Re: [PATCH 14/17] aoe: convert aoeblk to blk-mq To: axboe@kernel.dk Cc: linux-block@vger.kernel.org, "Ed L. Cashin" Content-Type: text/plain; charset="UTF-8" List-ID: OK. We always tried to avoid putting includes in the .h file, so if you wouldn't mind moving the include to the C files, that would be nice. I wouldn't insist, though. On Thu, Oct 11, 2018 at 12:59 PM Jens Axboe wrote: > > Straight forward conversion - instead of rewriting the internal buffer > retrieval logic, just replace the previous elevator peeking with an > internal list of requests. > > Cc: "Ed L. Cashin" > Signed-off-by: Jens Axboe > --- > drivers/block/aoe/aoe.h | 4 ++++ > drivers/block/aoe/aoeblk.c | 49 ++++++++++++++++++++++++++++---------- > drivers/block/aoe/aoecmd.c | 17 +++++++++---- > drivers/block/aoe/aoedev.c | 14 ++++++----- > 4 files changed, 60 insertions(+), 24 deletions(-) > > diff --git a/drivers/block/aoe/aoe.h b/drivers/block/aoe/aoe.h > index c0ebda1283cc..9b9db29fe712 100644 > --- a/drivers/block/aoe/aoe.h > +++ b/drivers/block/aoe/aoe.h > @@ -1,4 +1,6 @@ > /* Copyright (c) 2013 Coraid, Inc. See COPYING for GPL terms. */ > +#include > + > #define VERSION "85" > #define AOE_MAJOR 152 > #define DEVICE_NAME "aoe" > @@ -164,6 +166,8 @@ struct aoedev { > struct gendisk *gd; > struct dentry *debugfs; > struct request_queue *blkq; > + struct list_head rq_list; > + struct blk_mq_tag_set tag_set; > struct hd_geometry geo; > sector_t ssize; > struct timer_list timer; > diff --git a/drivers/block/aoe/aoeblk.c b/drivers/block/aoe/aoeblk.c > index 429ebb84b592..ba4afa0ce1c7 100644 > --- a/drivers/block/aoe/aoeblk.c > +++ b/drivers/block/aoe/aoeblk.c > @@ -6,7 +6,7 @@ > > #include > #include > -#include > +#include > #include > #include > #include > @@ -274,23 +274,25 @@ aoeblk_release(struct gendisk *disk, fmode_t mode) > spin_unlock_irqrestore(&d->lock, flags); > } > > -static void > -aoeblk_request(struct request_queue *q) > +static blk_status_t aoeblk_queue_rq(struct blk_mq_hw_ctx *hctx, > + const struct blk_mq_queue_data *bd) > { > - struct aoedev *d; > - struct request *rq; > + struct aoedev *d = hctx->queue->queuedata; > + > + spin_lock_irq(&d->lock); > > - d = q->queuedata; > if ((d->flags & DEVFL_UP) == 0) { > pr_info_ratelimited("aoe: device %ld.%d is not up\n", > d->aoemajor, d->aoeminor); > - while ((rq = blk_peek_request(q))) { > - blk_start_request(rq); > - aoe_end_request(d, rq, 1); > - } > - return; > + spin_unlock_irq(&d->lock); > + blk_mq_start_request(bd->rq); > + return BLK_STS_IOERR; > } > + > + list_add_tail(&bd->rq->queuelist, &d->rq_list); > aoecmd_work(d); > + spin_unlock_irq(&d->lock); > + return BLK_STS_OK; > } > > static int > @@ -345,6 +347,10 @@ static const struct block_device_operations aoe_bdops = { > .owner = THIS_MODULE, > }; > > +static const struct blk_mq_ops aoeblk_mq_ops = { > + .queue_rq = aoeblk_queue_rq, > +}; > + > /* alloc_disk and add_disk can sleep */ > void > aoeblk_gdalloc(void *vp) > @@ -353,9 +359,11 @@ aoeblk_gdalloc(void *vp) > struct gendisk *gd; > mempool_t *mp; > struct request_queue *q; > + struct blk_mq_tag_set *set; > enum { KB = 1024, MB = KB * KB, READ_AHEAD = 2 * MB, }; > ulong flags; > int late = 0; > + int err; > > spin_lock_irqsave(&d->lock, flags); > if (d->flags & DEVFL_GDALLOC > @@ -382,10 +390,25 @@ aoeblk_gdalloc(void *vp) > d->aoemajor, d->aoeminor); > goto err_disk; > } > - q = blk_init_queue(aoeblk_request, &d->lock); > - if (q == NULL) { > + > + set = &d->tag_set; > + set->ops = &aoeblk_mq_ops; > + set->nr_hw_queues = 1; > + set->queue_depth = 128; > + set->numa_node = NUMA_NO_NODE; > + set->flags = BLK_MQ_F_SHOULD_MERGE; > + err = blk_mq_alloc_tag_set(set); > + if (err) { > + pr_err("aoe: cannot allocate tag set for %ld.%d\n", > + d->aoemajor, d->aoeminor); > + goto err_mempool; > + } > + > + q = blk_mq_init_queue(set); > + if (IS_ERR(q)) { > pr_err("aoe: cannot allocate block queue for %ld.%d\n", > d->aoemajor, d->aoeminor); > + blk_mq_free_tag_set(set); > goto err_mempool; > } > > diff --git a/drivers/block/aoe/aoecmd.c b/drivers/block/aoe/aoecmd.c > index 136dc507d020..fce0fc1fa7bf 100644 > --- a/drivers/block/aoe/aoecmd.c > +++ b/drivers/block/aoe/aoecmd.c > @@ -7,7 +7,7 @@ > #include > #include > #include > -#include > +#include > #include > #include > #include > @@ -857,10 +857,12 @@ nextbuf(struct aoedev *d) > return d->ip.buf; > rq = d->ip.rq; > if (rq == NULL) { > - rq = blk_peek_request(q); > + rq = list_first_entry_or_null(&d->rq_list, struct request, > + queuelist); > if (rq == NULL) > return NULL; > - blk_start_request(rq); > + list_del_init(&rq->queuelist); > + blk_mq_start_request(rq); > d->ip.rq = rq; > d->ip.nxbio = rq->bio; > rq->special = (void *) rqbiocnt(rq); > @@ -1045,6 +1047,7 @@ aoe_end_request(struct aoedev *d, struct request *rq, int fastfail) > struct bio *bio; > int bok; > struct request_queue *q; > + blk_status_t err = BLK_STS_OK; > > q = d->blkq; > if (rq == d->ip.rq) > @@ -1052,11 +1055,15 @@ aoe_end_request(struct aoedev *d, struct request *rq, int fastfail) > do { > bio = rq->bio; > bok = !fastfail && !bio->bi_status; > - } while (__blk_end_request(rq, bok ? BLK_STS_OK : BLK_STS_IOERR, bio->bi_iter.bi_size)); > + if (!bok) > + err = BLK_STS_IOERR; > + } while (blk_update_request(rq, bok ? BLK_STS_OK : BLK_STS_IOERR, bio->bi_iter.bi_size)); > + > + __blk_mq_end_request(rq, err); > > /* cf. http://lkml.org/lkml/2006/10/31/28 */ > if (!fastfail) > - __blk_run_queue(q); > + blk_mq_run_hw_queues(q, true); > } > > static void > diff --git a/drivers/block/aoe/aoedev.c b/drivers/block/aoe/aoedev.c > index 41060e9cedf2..96b420ddff3f 100644 > --- a/drivers/block/aoe/aoedev.c > +++ b/drivers/block/aoe/aoedev.c > @@ -5,7 +5,7 @@ > */ > > #include > -#include > +#include > #include > #include > #include > @@ -197,7 +197,6 @@ aoedev_downdev(struct aoedev *d) > { > struct aoetgt *t, **tt, **te; > struct list_head *head, *pos, *nx; > - struct request *rq; > int i; > > d->flags &= ~DEVFL_UP; > @@ -225,10 +224,11 @@ aoedev_downdev(struct aoedev *d) > > /* fast fail all pending I/O */ > if (d->blkq) { > - while ((rq = blk_peek_request(d->blkq))) { > - blk_start_request(rq); > - aoe_end_request(d, rq, 1); > - } > + /* UP is cleared, freeze+quiesce to insure all are errored */ > + blk_mq_freeze_queue(d->blkq); > + blk_mq_quiesce_queue(d->blkq); > + blk_mq_unquiesce_queue(d->blkq); > + blk_mq_unfreeze_queue(d->blkq); > } > > if (d->gd) > @@ -278,6 +278,7 @@ freedev(struct aoedev *d) > aoedisk_rm_sysfs(d); > del_gendisk(d->gd); > put_disk(d->gd); > + blk_mq_free_tag_set(&d->tag_set); > blk_cleanup_queue(d->blkq); > } > t = d->targets; > @@ -464,6 +465,7 @@ aoedev_by_aoeaddr(ulong maj, int min, int do_alloc) > d->ntargets = NTARGETS; > INIT_WORK(&d->work, aoecmd_sleepwork); > spin_lock_init(&d->lock); > + INIT_LIST_HEAD(&d->rq_list); > skb_queue_head_init(&d->skbpool); > timer_setup(&d->timer, dummy_timer, 0); > d->timer.expires = jiffies + HZ; > -- > 2.17.1 > -- Ed Cashin From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: From: Jens Axboe To: linux-block@vger.kernel.org Cc: Jens Axboe , "Ed L. Cashin" Subject: [PATCH 14/17] aoe: convert aoeblk to blk-mq Date: Thu, 11 Oct 2018 10:59:06 -0600 Message-Id: <20181011165909.32615-15-axboe@kernel.dk> In-Reply-To: <20181011165909.32615-1-axboe@kernel.dk> References: <20181011165909.32615-1-axboe@kernel.dk> List-ID: Straight forward conversion - instead of rewriting the internal buffer retrieval logic, just replace the previous elevator peeking with an internal list of requests. Cc: "Ed L. Cashin" Signed-off-by: Jens Axboe --- drivers/block/aoe/aoe.h | 4 ++++ drivers/block/aoe/aoeblk.c | 49 ++++++++++++++++++++++++++++---------- drivers/block/aoe/aoecmd.c | 17 +++++++++---- drivers/block/aoe/aoedev.c | 14 ++++++----- 4 files changed, 60 insertions(+), 24 deletions(-) diff --git a/drivers/block/aoe/aoe.h b/drivers/block/aoe/aoe.h index c0ebda1283cc..9b9db29fe712 100644 --- a/drivers/block/aoe/aoe.h +++ b/drivers/block/aoe/aoe.h @@ -1,4 +1,6 @@ /* Copyright (c) 2013 Coraid, Inc. See COPYING for GPL terms. */ +#include + #define VERSION "85" #define AOE_MAJOR 152 #define DEVICE_NAME "aoe" @@ -164,6 +166,8 @@ struct aoedev { struct gendisk *gd; struct dentry *debugfs; struct request_queue *blkq; + struct list_head rq_list; + struct blk_mq_tag_set tag_set; struct hd_geometry geo; sector_t ssize; struct timer_list timer; diff --git a/drivers/block/aoe/aoeblk.c b/drivers/block/aoe/aoeblk.c index 429ebb84b592..ba4afa0ce1c7 100644 --- a/drivers/block/aoe/aoeblk.c +++ b/drivers/block/aoe/aoeblk.c @@ -6,7 +6,7 @@ #include #include -#include +#include #include #include #include @@ -274,23 +274,25 @@ aoeblk_release(struct gendisk *disk, fmode_t mode) spin_unlock_irqrestore(&d->lock, flags); } -static void -aoeblk_request(struct request_queue *q) +static blk_status_t aoeblk_queue_rq(struct blk_mq_hw_ctx *hctx, + const struct blk_mq_queue_data *bd) { - struct aoedev *d; - struct request *rq; + struct aoedev *d = hctx->queue->queuedata; + + spin_lock_irq(&d->lock); - d = q->queuedata; if ((d->flags & DEVFL_UP) == 0) { pr_info_ratelimited("aoe: device %ld.%d is not up\n", d->aoemajor, d->aoeminor); - while ((rq = blk_peek_request(q))) { - blk_start_request(rq); - aoe_end_request(d, rq, 1); - } - return; + spin_unlock_irq(&d->lock); + blk_mq_start_request(bd->rq); + return BLK_STS_IOERR; } + + list_add_tail(&bd->rq->queuelist, &d->rq_list); aoecmd_work(d); + spin_unlock_irq(&d->lock); + return BLK_STS_OK; } static int @@ -345,6 +347,10 @@ static const struct block_device_operations aoe_bdops = { .owner = THIS_MODULE, }; +static const struct blk_mq_ops aoeblk_mq_ops = { + .queue_rq = aoeblk_queue_rq, +}; + /* alloc_disk and add_disk can sleep */ void aoeblk_gdalloc(void *vp) @@ -353,9 +359,11 @@ aoeblk_gdalloc(void *vp) struct gendisk *gd; mempool_t *mp; struct request_queue *q; + struct blk_mq_tag_set *set; enum { KB = 1024, MB = KB * KB, READ_AHEAD = 2 * MB, }; ulong flags; int late = 0; + int err; spin_lock_irqsave(&d->lock, flags); if (d->flags & DEVFL_GDALLOC @@ -382,10 +390,25 @@ aoeblk_gdalloc(void *vp) d->aoemajor, d->aoeminor); goto err_disk; } - q = blk_init_queue(aoeblk_request, &d->lock); - if (q == NULL) { + + set = &d->tag_set; + set->ops = &aoeblk_mq_ops; + set->nr_hw_queues = 1; + set->queue_depth = 128; + set->numa_node = NUMA_NO_NODE; + set->flags = BLK_MQ_F_SHOULD_MERGE; + err = blk_mq_alloc_tag_set(set); + if (err) { + pr_err("aoe: cannot allocate tag set for %ld.%d\n", + d->aoemajor, d->aoeminor); + goto err_mempool; + } + + q = blk_mq_init_queue(set); + if (IS_ERR(q)) { pr_err("aoe: cannot allocate block queue for %ld.%d\n", d->aoemajor, d->aoeminor); + blk_mq_free_tag_set(set); goto err_mempool; } diff --git a/drivers/block/aoe/aoecmd.c b/drivers/block/aoe/aoecmd.c index 136dc507d020..fce0fc1fa7bf 100644 --- a/drivers/block/aoe/aoecmd.c +++ b/drivers/block/aoe/aoecmd.c @@ -7,7 +7,7 @@ #include #include #include -#include +#include #include #include #include @@ -857,10 +857,12 @@ nextbuf(struct aoedev *d) return d->ip.buf; rq = d->ip.rq; if (rq == NULL) { - rq = blk_peek_request(q); + rq = list_first_entry_or_null(&d->rq_list, struct request, + queuelist); if (rq == NULL) return NULL; - blk_start_request(rq); + list_del_init(&rq->queuelist); + blk_mq_start_request(rq); d->ip.rq = rq; d->ip.nxbio = rq->bio; rq->special = (void *) rqbiocnt(rq); @@ -1045,6 +1047,7 @@ aoe_end_request(struct aoedev *d, struct request *rq, int fastfail) struct bio *bio; int bok; struct request_queue *q; + blk_status_t err = BLK_STS_OK; q = d->blkq; if (rq == d->ip.rq) @@ -1052,11 +1055,15 @@ aoe_end_request(struct aoedev *d, struct request *rq, int fastfail) do { bio = rq->bio; bok = !fastfail && !bio->bi_status; - } while (__blk_end_request(rq, bok ? BLK_STS_OK : BLK_STS_IOERR, bio->bi_iter.bi_size)); + if (!bok) + err = BLK_STS_IOERR; + } while (blk_update_request(rq, bok ? BLK_STS_OK : BLK_STS_IOERR, bio->bi_iter.bi_size)); + + __blk_mq_end_request(rq, err); /* cf. http://lkml.org/lkml/2006/10/31/28 */ if (!fastfail) - __blk_run_queue(q); + blk_mq_run_hw_queues(q, true); } static void diff --git a/drivers/block/aoe/aoedev.c b/drivers/block/aoe/aoedev.c index 41060e9cedf2..96b420ddff3f 100644 --- a/drivers/block/aoe/aoedev.c +++ b/drivers/block/aoe/aoedev.c @@ -5,7 +5,7 @@ */ #include -#include +#include #include #include #include @@ -197,7 +197,6 @@ aoedev_downdev(struct aoedev *d) { struct aoetgt *t, **tt, **te; struct list_head *head, *pos, *nx; - struct request *rq; int i; d->flags &= ~DEVFL_UP; @@ -225,10 +224,11 @@ aoedev_downdev(struct aoedev *d) /* fast fail all pending I/O */ if (d->blkq) { - while ((rq = blk_peek_request(d->blkq))) { - blk_start_request(rq); - aoe_end_request(d, rq, 1); - } + /* UP is cleared, freeze+quiesce to insure all are errored */ + blk_mq_freeze_queue(d->blkq); + blk_mq_quiesce_queue(d->blkq); + blk_mq_unquiesce_queue(d->blkq); + blk_mq_unfreeze_queue(d->blkq); } if (d->gd) @@ -278,6 +278,7 @@ freedev(struct aoedev *d) aoedisk_rm_sysfs(d); del_gendisk(d->gd); put_disk(d->gd); + blk_mq_free_tag_set(&d->tag_set); blk_cleanup_queue(d->blkq); } t = d->targets; @@ -464,6 +465,7 @@ aoedev_by_aoeaddr(ulong maj, int min, int do_alloc) d->ntargets = NTARGETS; INIT_WORK(&d->work, aoecmd_sleepwork); spin_lock_init(&d->lock); + INIT_LIST_HEAD(&d->rq_list); skb_queue_head_init(&d->skbpool); timer_setup(&d->timer, dummy_timer, 0); d->timer.expires = jiffies + HZ; -- 2.17.1 From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: From: Jens Axboe To: linux-block@vger.kernel.org Cc: Jens Axboe Subject: [PATCH 11/17] z2ram: convert to blk-mq Date: Thu, 11 Oct 2018 10:59:03 -0600 Message-Id: <20181011165909.32615-12-axboe@kernel.dk> In-Reply-To: <20181011165909.32615-1-axboe@kernel.dk> References: <20181011165909.32615-1-axboe@kernel.dk> List-ID: Straight forward conversion to blk-mq, nothing special about this driver. Signed-off-by: Jens Axboe --- drivers/block/z2ram.c | 96 ++++++++++++++++++++++++++----------------- 1 file changed, 58 insertions(+), 38 deletions(-) diff --git a/drivers/block/z2ram.c b/drivers/block/z2ram.c index d0c5bc4e0703..82a022a5297e 100644 --- a/drivers/block/z2ram.c +++ b/drivers/block/z2ram.c @@ -31,7 +31,7 @@ #include #include #include -#include +#include #include #include #include @@ -66,43 +66,44 @@ static DEFINE_SPINLOCK(z2ram_lock); static struct gendisk *z2ram_gendisk; -static void do_z2_request(struct request_queue *q) +static blk_status_t z2_queue_rq(struct blk_mq_hw_ctx *hctx, + const struct blk_mq_queue_data *bd) { - struct request *req; - - req = blk_fetch_request(q); - while (req) { - unsigned long start = blk_rq_pos(req) << 9; - unsigned long len = blk_rq_cur_bytes(req); - blk_status_t err = BLK_STS_OK; - - if (start + len > z2ram_size) { - pr_err(DEVICE_NAME ": bad access: block=%llu, " - "count=%u\n", - (unsigned long long)blk_rq_pos(req), - blk_rq_cur_sectors(req)); - err = BLK_STS_IOERR; - goto done; - } - while (len) { - unsigned long addr = start & Z2RAM_CHUNKMASK; - unsigned long size = Z2RAM_CHUNKSIZE - addr; - void *buffer = bio_data(req->bio); - - if (len < size) - size = len; - addr += z2ram_map[ start >> Z2RAM_CHUNKSHIFT ]; - if (rq_data_dir(req) == READ) - memcpy(buffer, (char *)addr, size); - else - memcpy((char *)addr, buffer, size); - start += size; - len -= size; - } - done: - if (!__blk_end_request_cur(req, err)) - req = blk_fetch_request(q); + struct request *req = bd->rq; + unsigned long start = blk_rq_pos(req) << 9; + unsigned long len = blk_rq_cur_bytes(req); + + blk_mq_start_request(req); + + if (start + len > z2ram_size) { + pr_err(DEVICE_NAME ": bad access: block=%llu, " + "count=%u\n", + (unsigned long long)blk_rq_pos(req), + blk_rq_cur_sectors(req)); + return BLK_STS_IOERR; } + + spin_lock_irq(&z2ram_lock); + + while (len) { + unsigned long addr = start & Z2RAM_CHUNKMASK; + unsigned long size = Z2RAM_CHUNKSIZE - addr; + void *buffer = bio_data(req->bio); + + if (len < size) + size = len; + addr += z2ram_map[ start >> Z2RAM_CHUNKSHIFT ]; + if (rq_data_dir(req) == READ) + memcpy(buffer, (char *)addr, size); + else + memcpy((char *)addr, buffer, size); + start += size; + len -= size; + } + + spin_unlock_irq(&z2ram_lock); + blk_mq_end_request(req, BLK_STS_OK); + return BLK_STS_OK; } static void @@ -337,6 +338,11 @@ static struct kobject *z2_find(dev_t dev, int *part, void *data) } static struct request_queue *z2_queue; +static struct blk_mq_tag_set tag_set; + +static const struct blk_mq_ops z2_mq_ops = { + .queue_rq = z2_queue_rq, +}; static int __init z2_init(void) @@ -355,10 +361,23 @@ z2_init(void) if (!z2ram_gendisk) goto out_disk; - z2_queue = blk_init_queue(do_z2_request, &z2ram_lock); - if (!z2_queue) + tag_set.ops = &z2_mq_ops; + tag_set.nr_hw_queues = 1; + tag_set.queue_depth = 16; /* no hard limit */ + tag_set.numa_node = NUMA_NO_NODE; + tag_set.flags = BLK_MQ_F_SHOULD_MERGE; + ret = blk_mq_alloc_tag_set(&tag_set); + if (ret) goto out_queue; + z2_queue = blk_mq_init_queue(&tag_set); + if (IS_ERR(z2_queue)) { + ret = PTR_ERR(z2_queue); + z2_queue = NULL; + blk_mq_free_tag_set(&tag_set); + goto out_queue; + } + z2ram_gendisk->major = Z2RAM_MAJOR; z2ram_gendisk->first_minor = 0; z2ram_gendisk->fops = &z2_fops; @@ -386,6 +405,7 @@ static void __exit z2_exit(void) unregister_blkdev(Z2RAM_MAJOR, DEVICE_NAME); del_gendisk(z2ram_gendisk); put_disk(z2ram_gendisk); + blk_mq_free_tag_set(&tag_set); blk_cleanup_queue(z2_queue); if ( current_device != -1 ) -- 2.17.1 From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: From: Jens Axboe To: linux-block@vger.kernel.org Cc: Jens Axboe Subject: [PATCH 02/17] sx8: convert to blk-mq Date: Thu, 11 Oct 2018 10:58:54 -0600 Message-Id: <20181011165909.32615-3-axboe@kernel.dk> In-Reply-To: <20181011165909.32615-1-axboe@kernel.dk> References: <20181011165909.32615-1-axboe@kernel.dk> List-ID: Convert from the old request_fn style driver to blk-mq. Signed-off-by: Jens Axboe --- drivers/block/sx8.c | 133 +++++++++++++++++++++++++++++--------------- 1 file changed, 88 insertions(+), 45 deletions(-) diff --git a/drivers/block/sx8.c b/drivers/block/sx8.c index 4d90e5eba2f5..5402dfdf331b 100644 --- a/drivers/block/sx8.c +++ b/drivers/block/sx8.c @@ -16,7 +16,7 @@ #include #include #include -#include +#include #include #include #include @@ -244,6 +244,7 @@ struct carm_port { unsigned int port_no; struct gendisk *disk; struct carm_host *host; + struct blk_mq_tag_set tag_set; /* attached device characteristics */ u64 capacity; @@ -279,6 +280,7 @@ struct carm_host { unsigned int state; u32 fw_ver; + struct blk_mq_tag_set tag_set; struct request_queue *oob_q; unsigned int n_oob; @@ -750,7 +752,7 @@ static inline void carm_end_request_queued(struct carm_host *host, struct request *req = crq->rq; int rc; - __blk_end_request_all(req, error); + blk_mq_end_request(req, error); rc = carm_put_request(host, crq); assert(rc == 0); @@ -760,7 +762,7 @@ static inline void carm_push_q (struct carm_host *host, struct request_queue *q) { unsigned int idx = host->wait_q_prod % CARM_MAX_WAIT_Q; - blk_stop_queue(q); + blk_mq_stop_hw_queues(q); VPRINTK("STOPPED QUEUE %p\n", q); host->wait_q[idx] = q; @@ -785,7 +787,7 @@ static inline void carm_round_robin(struct carm_host *host) { struct request_queue *q = carm_pop_q(host); if (q) { - blk_start_queue(q); + blk_mq_start_hw_queues(q); VPRINTK("STARTED QUEUE %p\n", q); } } @@ -802,62 +804,62 @@ static inline void carm_end_rq(struct carm_host *host, struct carm_request *crq, } } -static void carm_oob_rq_fn(struct request_queue *q) +static blk_status_t carm_oob_queue_rq(struct blk_mq_hw_ctx *hctx, + const struct blk_mq_queue_data *bd) { + struct request_queue *q = hctx->queue; struct carm_host *host = q->queuedata; struct carm_request *crq; - struct request *rq; int rc; - while (1) { - DPRINTK("get req\n"); - rq = blk_fetch_request(q); - if (!rq) - break; + blk_mq_start_request(bd->rq); + + spin_lock_irq(&host->lock); - crq = rq->special; - assert(crq != NULL); - assert(crq->rq == rq); + crq = bd->rq->special; + assert(crq != NULL); + assert(crq->rq == bd->rq); - crq->n_elem = 0; + crq->n_elem = 0; - DPRINTK("send req\n"); - rc = carm_send_msg(host, crq); - if (rc) { - blk_requeue_request(q, rq); - carm_push_q(host, q); - return; /* call us again later, eventually */ - } + DPRINTK("send req\n"); + rc = carm_send_msg(host, crq); + if (rc) { + carm_push_q(host, q); + spin_unlock_irq(&host->lock); + return BLK_STS_DEV_RESOURCE; } + + spin_unlock_irq(&host->lock); + return BLK_STS_OK; } -static void carm_rq_fn(struct request_queue *q) +static blk_status_t carm_queue_rq(struct blk_mq_hw_ctx *hctx, + const struct blk_mq_queue_data *bd) { + struct request_queue *q = hctx->queue; struct carm_port *port = q->queuedata; struct carm_host *host = port->host; struct carm_msg_rw *msg; struct carm_request *crq; - struct request *rq; + struct request *rq = bd->rq; struct scatterlist *sg; int writing = 0, pci_dir, i, n_elem, rc; u32 tmp; unsigned int msg_size; -queue_one_request: - VPRINTK("get req\n"); - rq = blk_peek_request(q); - if (!rq) - return; + blk_mq_start_request(rq); + + spin_lock_irq(&host->lock); crq = carm_get_request(host); if (!crq) { carm_push_q(host, q); - return; /* call us again later, eventually */ + spin_unlock_irq(&host->lock); + return BLK_STS_DEV_RESOURCE; } crq->rq = rq; - blk_start_request(rq); - if (rq_data_dir(rq) == WRITE) { writing = 1; pci_dir = PCI_DMA_TODEVICE; @@ -869,15 +871,19 @@ static void carm_rq_fn(struct request_queue *q) sg = &crq->sg[0]; n_elem = blk_rq_map_sg(q, rq, sg); if (n_elem <= 0) { + /* request with no s/g entries? */ carm_end_rq(host, crq, BLK_STS_IOERR); - return; /* request with no s/g entries? */ + spin_unlock_irq(&host->lock); + return BLK_STS_IOERR; } /* map scatterlist to PCI bus addresses */ n_elem = pci_map_sg(host->pdev, sg, n_elem, pci_dir); if (n_elem <= 0) { + /* request with no s/g entries? */ carm_end_rq(host, crq, BLK_STS_IOERR); - return; /* request with no s/g entries? */ + spin_unlock_irq(&host->lock); + return BLK_STS_IOERR; } crq->n_elem = n_elem; crq->port = port; @@ -927,12 +933,13 @@ static void carm_rq_fn(struct request_queue *q) rc = carm_send_msg(host, crq); if (rc) { carm_put_request(host, crq); - blk_requeue_request(q, rq); carm_push_q(host, q); - return; /* call us again later, eventually */ + spin_unlock_irq(&host->lock); + return BLK_STS_DEV_RESOURCE; } - goto queue_one_request; + spin_unlock_irq(&host->lock); + return BLK_STS_OK; } static void carm_handle_array_info(struct carm_host *host, @@ -1485,6 +1492,14 @@ static int carm_init_host(struct carm_host *host) return 0; } +static const struct blk_mq_ops carm_oob_mq_ops = { + .queue_rq = carm_oob_queue_rq, +}; + +static const struct blk_mq_ops carm_mq_ops = { + .queue_rq = carm_queue_rq, +}; + static int carm_init_disks(struct carm_host *host) { unsigned int i; @@ -1494,6 +1509,7 @@ static int carm_init_disks(struct carm_host *host) struct gendisk *disk; struct request_queue *q; struct carm_port *port; + struct blk_mq_tag_set *set; port = &host->port[i]; port->host = host; @@ -1513,9 +1529,19 @@ static int carm_init_disks(struct carm_host *host) disk->fops = &carm_bd_ops; disk->private_data = port; - q = blk_init_queue(carm_rq_fn, &host->lock); - if (!q) { - rc = -ENOMEM; + set = &port->tag_set; + set->ops = &carm_mq_ops; + set->nr_hw_queues = 1; + set->queue_depth = max_queue; + set->numa_node = NUMA_NO_NODE; + set->flags = BLK_MQ_F_SHOULD_MERGE; + rc = blk_mq_alloc_tag_set(set); + if (rc) + break; + + q = blk_mq_init_queue(set); + if (IS_ERR(q)) { + rc = PTR_ERR(q); break; } disk->queue = q; @@ -1533,14 +1559,18 @@ static void carm_free_disks(struct carm_host *host) unsigned int i; for (i = 0; i < CARM_MAX_PORTS; i++) { - struct gendisk *disk = host->port[i].disk; + struct carm_port *port = &host->port[i]; + struct gendisk *disk = port->disk; + if (disk) { struct request_queue *q = disk->queue; if (disk->flags & GENHD_FL_UP) del_gendisk(disk); - if (q) + if (q) { + blk_mq_free_tag_set(&port->tag_set); blk_cleanup_queue(q); + } put_disk(disk); } } @@ -1568,6 +1598,7 @@ static int carm_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) unsigned int pci_dac; int rc; struct request_queue *q; + struct blk_mq_tag_set *set; unsigned int i; printk_once(KERN_DEBUG DRV_NAME " version " DRV_VERSION "\n"); @@ -1636,11 +1667,21 @@ static int carm_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) goto err_out_iounmap; } - q = blk_init_queue(carm_oob_rq_fn, &host->lock); - if (!q) { + set = &host->tag_set; + set->ops = &carm_oob_mq_ops; + set->nr_hw_queues = 1; + set->queue_depth = 1; + set->numa_node = NUMA_NO_NODE; + set->flags = BLK_MQ_F_NO_SCHED; + rc = blk_mq_alloc_tag_set(set); + if (rc) + goto err_out_pci_free; + + q = blk_mq_init_queue(set); + if (IS_ERR(q)) { printk(KERN_ERR DRV_NAME "(%s): OOB queue alloc failure\n", pci_name(pdev)); - rc = -ENOMEM; + rc = PTR_ERR(q); goto err_out_pci_free; } host->oob_q = q; @@ -1704,6 +1745,7 @@ static int carm_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) clear_bit(0, &carm_major_alloc); else if (host->major == 161) clear_bit(1, &carm_major_alloc); + blk_mq_free_tag_set(&host->tag_set); blk_cleanup_queue(host->oob_q); err_out_pci_free: pci_free_consistent(pdev, CARM_SHM_SIZE, host->shm, host->shm_dma); @@ -1735,6 +1777,7 @@ static void carm_remove_one (struct pci_dev *pdev) clear_bit(0, &carm_major_alloc); else if (host->major == 161) clear_bit(1, &carm_major_alloc); + blk_mq_free_tag_set(&host->tag_set); blk_cleanup_queue(host->oob_q); pci_free_consistent(pdev, CARM_SHM_SIZE, host->shm, host->shm_dma); iounmap(host->mmio); -- 2.17.1 From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Subject: Re: [PATCH 03/17] ps3disk: convert to blk-mq To: Geoff Levand , linux-block@vger.kernel.org Cc: Benjamin Herrenschmidt , Geert Uytterhoeven References: <20181011165909.32615-1-axboe@kernel.dk> <20181011165909.32615-4-axboe@kernel.dk> <17539e5f-742b-796e-8e36-31327120f883@infradead.org> <7f27a68f-9cbe-c4c2-5c35-70763a5b1484@infradead.org> <3403ae47-1aaa-9d01-817c-cd52a7daa272@infradead.org> <6d7ccd4c-0d41-e2d3-6ecd-b9efbd7358b5@infradead.org> From: Jens Axboe Message-ID: <870de740-005f-ff82-ef33-7c8aac1a2c86@kernel.dk> Date: Mon, 15 Oct 2018 13:30:48 -0600 MIME-Version: 1.0 In-Reply-To: <6d7ccd4c-0d41-e2d3-6ecd-b9efbd7358b5@infradead.org> Content-Type: text/plain; charset=utf-8 List-ID: On 10/15/18 1:24 PM, Geoff Levand wrote: > Hi Jens, > > On 10/15/2018 11:38 AM, Jens Axboe wrote: >> Weird, it looks like we're waiting for something to complete, and then >> we have a few others waiting for queue new IO. >> >> Can you try and move the blk_mq_end_request() inside the priv->lock >> section and see if that helps? > > With the change below to your V2 I can't get it to have an > error. I did mkfs.ext4, some big file downloads, and ran > 'fsck.ext3 -c' for a while. OK good, that's better than having to make the bigger change I just sent out. > Thanks for working late on it. Thanks for testing! I'll add your tested-by. -- Jens Axboe From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Subject: Re: [PATCH 03/17] ps3disk: convert to blk-mq To: Jens Axboe , linux-block@vger.kernel.org Cc: Benjamin Herrenschmidt , Geert Uytterhoeven References: <20181011165909.32615-1-axboe@kernel.dk> <20181011165909.32615-4-axboe@kernel.dk> <17539e5f-742b-796e-8e36-31327120f883@infradead.org> <7f27a68f-9cbe-c4c2-5c35-70763a5b1484@infradead.org> <3403ae47-1aaa-9d01-817c-cd52a7daa272@infradead.org> From: Geoff Levand Message-ID: <6d7ccd4c-0d41-e2d3-6ecd-b9efbd7358b5@infradead.org> Date: Mon, 15 Oct 2018 12:24:28 -0700 MIME-Version: 1.0 In-Reply-To: Content-Type: text/plain; charset=utf-8 List-ID: Hi Jens, On 10/15/2018 11:38 AM, Jens Axboe wrote: > Weird, it looks like we're waiting for something to complete, and then > we have a few others waiting for queue new IO. > > Can you try and move the blk_mq_end_request() inside the priv->lock > section and see if that helps? With the change below to your V2 I can't get it to have an error. I did mkfs.ext4, some big file downloads, and ran 'fsck.ext3 -c' for a while. Thanks for working late on it. -Geoff --- a/drivers/block/ps3disk.c +++ b/drivers/block/ps3disk.c @@ -274,10 +274,9 @@ static irqreturn_t ps3disk_interrupt(int irq, void *data) ps3disk_scatter_gather(dev, req, 0); } - blk_mq_end_request(req, error); - spin_lock(&priv->lock); priv->req = NULL; + blk_mq_end_request(req, error); spin_unlock(&priv->lock); blk_mq_run_hw_queues(priv->queue, true); @@ -458,7 +457,7 @@ static int ps3disk_probe(struct ps3_system_bus_device *_dev) set = &priv->tag_set; set->ops = &ps3disk_mq_ops; set->nr_hw_queues = 1; - set->queue_depth = 2; + set->queue_depth = 1; set->numa_node = NUMA_NO_NODE; set->flags = BLK_MQ_F_SHOULD_MERGE; error = blk_mq_alloc_tag_set(set); From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Subject: Re: [PATCH 03/17] ps3disk: convert to blk-mq From: Jens Axboe To: Geoff Levand , linux-block@vger.kernel.org Cc: Benjamin Herrenschmidt , Geert Uytterhoeven References: <20181011165909.32615-1-axboe@kernel.dk> <20181011165909.32615-4-axboe@kernel.dk> <17539e5f-742b-796e-8e36-31327120f883@infradead.org> <7f27a68f-9cbe-c4c2-5c35-70763a5b1484@infradead.org> <3403ae47-1aaa-9d01-817c-cd52a7daa272@infradead.org> Message-ID: <6c9f8842-6043-60c2-ed68-39cae1fc2cc8@kernel.dk> Date: Mon, 15 Oct 2018 13:09:11 -0600 MIME-Version: 1.0 In-Reply-To: Content-Type: text/plain; charset=utf-8 List-ID: On 10/15/18 12:38 PM, Jens Axboe wrote: > On 10/15/18 12:23 PM, Geoff Levand wrote: >> Hi Jens, >> >> On 10/15/2018 09:27 AM, Jens Axboe wrote:> Can you try and change the queue depth to 1 instead of 2? It's set in> the tag_set, as ->queue_depth. >> >> With this change: >> >> - set->queue_depth = 2; >> + set->queue_depth = 1; >> >> Something is still wrong. It can sometimes boot, sometimes udevd hangs >> up on /sbin/blkid. If it boots I can sometimes mount a ps3disk >> partition, but then cat or echo to a file will hang. Other times the >> mount command will hang. I saw this error appear in the system log: > > Weird, it looks like we're waiting for something to complete, and then > we have a few others waiting for queue new IO. > > Can you try and move the blk_mq_end_request() inside the priv->lock > section and see if that helps? If that still fails, replace with this version. It's closer to the original logic. Thanks for testing!! diff --git a/block/blk-mq.c b/block/blk-mq.c index c2ecd64a2403..dcf10e39995a 100644 --- a/block/blk-mq.c +++ b/block/blk-mq.c @@ -2507,6 +2507,39 @@ struct request_queue *blk_mq_init_queue(struct blk_mq_tag_set *set) } EXPORT_SYMBOL(blk_mq_init_queue); +/* + * Helper for setting up a queue with mq ops, given queue depth, and + * the passed in mq ops flags. + */ +struct request_queue *blk_mq_init_sq_queue(struct blk_mq_tag_set *set, + const struct blk_mq_ops *ops, + unsigned int queue_depth, + unsigned int set_flags) +{ + struct request_queue *q; + int ret; + + memset(set, 0, sizeof(*set)); + set->ops = ops; + set->nr_hw_queues = 1; + set->queue_depth = queue_depth; + set->numa_node = NUMA_NO_NODE; + set->flags = set_flags; + + ret = blk_mq_alloc_tag_set(set); + if (ret) + return ERR_PTR(ret); + + q = blk_mq_init_queue(set); + if (IS_ERR(q)) { + blk_mq_free_tag_set(set); + return q; + } + + return q; +} +EXPORT_SYMBOL(blk_mq_init_sq_queue); + static int blk_mq_hw_ctx_size(struct blk_mq_tag_set *tag_set) { int hw_ctx_size = sizeof(struct blk_mq_hw_ctx); diff --git a/include/linux/blk-mq.h b/include/linux/blk-mq.h index 1da59c16f637..2286dc12c6bc 100644 --- a/include/linux/blk-mq.h +++ b/include/linux/blk-mq.h @@ -203,6 +203,10 @@ enum { struct request_queue *blk_mq_init_queue(struct blk_mq_tag_set *); struct request_queue *blk_mq_init_allocated_queue(struct blk_mq_tag_set *set, struct request_queue *q); +struct request_queue *blk_mq_init_sq_queue(struct blk_mq_tag_set *set, + const struct blk_mq_ops *ops, + unsigned int queue_depth, + unsigned int set_flags); int blk_mq_register_dev(struct device *, struct request_queue *); void blk_mq_unregister_dev(struct device *, struct request_queue *); diff --git a/drivers/block/ps3disk.c b/drivers/block/ps3disk.c index 29a4419e8ba3..affc25a431e2 100644 --- a/drivers/block/ps3disk.c +++ b/drivers/block/ps3disk.c @@ -19,7 +19,7 @@ */ #include -#include +#include #include #include @@ -42,6 +42,8 @@ struct ps3disk_private { spinlock_t lock; /* Request queue spinlock */ struct request_queue *queue; + struct blk_mq_tag_set tag_set; + struct list_head rq_list; struct gendisk *gendisk; unsigned int blocking_factor; struct request *req; @@ -118,8 +120,8 @@ static void ps3disk_scatter_gather(struct ps3_storage_device *dev, } } -static int ps3disk_submit_request_sg(struct ps3_storage_device *dev, - struct request *req) +static blk_status_t ps3disk_submit_request_sg(struct ps3_storage_device *dev, + struct request *req) { struct ps3disk_private *priv = ps3_system_bus_get_drvdata(&dev->sbd); int write = rq_data_dir(req), res; @@ -158,16 +160,15 @@ static int ps3disk_submit_request_sg(struct ps3_storage_device *dev, if (res) { dev_err(&dev->sbd.core, "%s:%u: %s failed %d\n", __func__, __LINE__, op, res); - __blk_end_request_all(req, BLK_STS_IOERR); - return 0; + return BLK_STS_IOERR; } priv->req = req; - return 1; + return BLK_STS_OK; } -static int ps3disk_submit_flush_request(struct ps3_storage_device *dev, - struct request *req) +static blk_status_t ps3disk_submit_flush_request(struct ps3_storage_device *dev, + struct request *req) { struct ps3disk_private *priv = ps3_system_bus_get_drvdata(&dev->sbd); u64 res; @@ -180,50 +181,63 @@ static int ps3disk_submit_flush_request(struct ps3_storage_device *dev, if (res) { dev_err(&dev->sbd.core, "%s:%u: sync cache failed 0x%llx\n", __func__, __LINE__, res); - __blk_end_request_all(req, BLK_STS_IOERR); - return 0; + return BLK_STS_IOERR; } priv->req = req; - return 1; + return BLK_STS_OK; } -static void ps3disk_do_request(struct ps3_storage_device *dev, - struct request_queue *q) +static blk_status_t __ps3disk_do_request(struct ps3_storage_device *dev, + struct request *req) { + dev_dbg(&dev->sbd.core, "%s:%u\n", __func__, __LINE__); + + switch (req_op(req)) { + case REQ_OP_FLUSH: + return ps3disk_submit_flush_request(dev, req); + case REQ_OP_READ: + case REQ_OP_WRITE: + return ps3disk_submit_request_sg(dev, req); + default: + blk_dump_rq_flags(req, DEVICE_NAME " bad request"); + return BLK_STS_IOERR; + } +} + +static void ps3disk_do_request(struct ps3_storage_device *dev) +{ + struct ps3disk_private *priv = ps3_system_bus_get_drvdata(&dev->sbd); struct request *req; + blk_status_t ret; - dev_dbg(&dev->sbd.core, "%s:%u\n", __func__, __LINE__); + while (!list_empty(&priv->rq_list)) { + req = list_first_entry(&priv->rq_list, struct request, queuelist); + list_del_init(&req->queuelist); + blk_mq_start_request(req); - while ((req = blk_fetch_request(q))) { - switch (req_op(req)) { - case REQ_OP_FLUSH: - if (ps3disk_submit_flush_request(dev, req)) - return; - break; - case REQ_OP_READ: - case REQ_OP_WRITE: - if (ps3disk_submit_request_sg(dev, req)) - return; - break; - default: - blk_dump_rq_flags(req, DEVICE_NAME " bad request"); - __blk_end_request_all(req, BLK_STS_IOERR); + ret = __ps3disk_do_request(dev, req); + if (ret == BLK_STS_IOERR) { + blk_mq_end_request(req, BLK_STS_IOERR); + continue; } + break; } } -static void ps3disk_request(struct request_queue *q) +static blk_status_t ps3disk_queue_rq(struct blk_mq_hw_ctx *hctx, + const struct blk_mq_queue_data *bd) { - struct ps3_storage_device *dev = q->queuedata; + struct ps3_storage_device *dev = hctx->queue->queuedata; struct ps3disk_private *priv = ps3_system_bus_get_drvdata(&dev->sbd); - if (priv->req) { - dev_dbg(&dev->sbd.core, "%s:%u busy\n", __func__, __LINE__); - return; - } + spin_lock_irq(&priv->lock); + list_add_tail(&bd->rq->queuelist, &priv->rq_list); + if (!priv->req) + ps3disk_do_request(dev); + spin_unlock_irq(&priv->lock); - ps3disk_do_request(dev, q); + return BLK_STS_OK; } static irqreturn_t ps3disk_interrupt(int irq, void *data) @@ -280,9 +294,9 @@ static irqreturn_t ps3disk_interrupt(int irq, void *data) } spin_lock(&priv->lock); - __blk_end_request_all(req, error); + blk_mq_end_request(req, error); priv->req = NULL; - ps3disk_do_request(dev, priv->queue); + ps3disk_do_request(dev); spin_unlock(&priv->lock); return IRQ_HANDLED; @@ -404,6 +418,10 @@ static unsigned long ps3disk_mask; static DEFINE_MUTEX(ps3disk_mask_mutex); +static const struct blk_mq_ops ps3disk_mq_ops = { + .queue_rq = ps3disk_queue_rq, +}; + static int ps3disk_probe(struct ps3_system_bus_device *_dev) { struct ps3_storage_device *dev = to_ps3_storage_device(&_dev->core); @@ -440,6 +458,7 @@ static int ps3disk_probe(struct ps3_system_bus_device *_dev) ps3_system_bus_set_drvdata(_dev, priv); spin_lock_init(&priv->lock); + INIT_LIST_HEAD(&priv->rq_list); dev->bounce_size = BOUNCE_SIZE; dev->bounce_buf = kmalloc(BOUNCE_SIZE, GFP_DMA); @@ -454,11 +473,12 @@ static int ps3disk_probe(struct ps3_system_bus_device *_dev) ps3disk_identify(dev); - queue = blk_init_queue(ps3disk_request, &priv->lock); - if (!queue) { - dev_err(&dev->sbd.core, "%s:%u: blk_init_queue failed\n", + queue = blk_mq_init_sq_queue(&priv->tag_set, &ps3disk_mq_ops, 16, + BLK_MQ_F_SHOULD_MERGE); + if (IS_ERR(queue)) { + dev_err(&dev->sbd.core, "%s:%u: blk_mq_init_queue failed\n", __func__, __LINE__); - error = -ENOMEM; + error = PTR_ERR(queue); goto fail_teardown; } @@ -505,6 +525,7 @@ static int ps3disk_probe(struct ps3_system_bus_device *_dev) fail_cleanup_queue: blk_cleanup_queue(queue); + blk_mq_free_tag_set(&priv->tag_set); fail_teardown: ps3stor_teardown(dev); fail_free_bounce: @@ -530,6 +551,7 @@ static int ps3disk_remove(struct ps3_system_bus_device *_dev) mutex_unlock(&ps3disk_mask_mutex); del_gendisk(priv->gendisk); blk_cleanup_queue(priv->queue); + blk_mq_free_tag_set(&priv->tag_set); put_disk(priv->gendisk); dev_notice(&dev->sbd.core, "Synchronizing disk cache\n"); ps3disk_sync_cache(dev); -- Jens Axboe From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Subject: Re: [PATCH 03/17] ps3disk: convert to blk-mq To: Geoff Levand , linux-block@vger.kernel.org Cc: Benjamin Herrenschmidt , Geert Uytterhoeven References: <20181011165909.32615-1-axboe@kernel.dk> <20181011165909.32615-4-axboe@kernel.dk> <17539e5f-742b-796e-8e36-31327120f883@infradead.org> <7f27a68f-9cbe-c4c2-5c35-70763a5b1484@infradead.org> <3403ae47-1aaa-9d01-817c-cd52a7daa272@infradead.org> From: Jens Axboe Message-ID: Date: Mon, 15 Oct 2018 12:38:21 -0600 MIME-Version: 1.0 In-Reply-To: <3403ae47-1aaa-9d01-817c-cd52a7daa272@infradead.org> Content-Type: text/plain; charset=utf-8 List-ID: On 10/15/18 12:23 PM, Geoff Levand wrote: > Hi Jens, > > On 10/15/2018 09:27 AM, Jens Axboe wrote:> Can you try and change the queue depth to 1 instead of 2? It's set in> the tag_set, as ->queue_depth. > > With this change: > > - set->queue_depth = 2; > + set->queue_depth = 1; > > Something is still wrong. It can sometimes boot, sometimes udevd hangs > up on /sbin/blkid. If it boots I can sometimes mount a ps3disk > partition, but then cat or echo to a file will hang. Other times the > mount command will hang. I saw this error appear in the system log: Weird, it looks like we're waiting for something to complete, and then we have a few others waiting for queue new IO. Can you try and move the blk_mq_end_request() inside the priv->lock section and see if that helps? -- Jens Axboe From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Subject: Re: [PATCH 03/17] ps3disk: convert to blk-mq To: Jens Axboe , linux-block@vger.kernel.org Cc: Benjamin Herrenschmidt , Geert Uytterhoeven References: <20181011165909.32615-1-axboe@kernel.dk> <20181011165909.32615-4-axboe@kernel.dk> <17539e5f-742b-796e-8e36-31327120f883@infradead.org> <7f27a68f-9cbe-c4c2-5c35-70763a5b1484@infradead.org> From: Geoff Levand Message-ID: <3403ae47-1aaa-9d01-817c-cd52a7daa272@infradead.org> Date: Mon, 15 Oct 2018 11:23:18 -0700 MIME-Version: 1.0 In-Reply-To: Content-Type: text/plain; charset=utf-8 List-ID: Hi Jens, On 10/15/2018 09:27 AM, Jens Axboe wrote:> Can you try and change the queue depth to 1 instead of 2? It's set in> the tag_set, as ->queue_depth. With this change: - set->queue_depth = 2; + set->queue_depth = 1; Something is still wrong. It can sometimes boot, sometimes udevd hangs up on /sbin/blkid. If it boots I can sometimes mount a ps3disk partition, but then cat or echo to a file will hang. Other times the mount command will hang. I saw this error appear in the system log: Oct 15 10:51:47 ps3 kernel: jbd2/ps3da2-8 D 0 2463 2 0x00000800 Oct 15 10:51:47 ps3 kernel: Call Trace: Oct 15 10:51:47 ps3 kernel: [c00000000d3c36b0] [c00000000d3c3750] 0xc00000000d3c3750 (unreliable) Oct 15 10:51:47 ps3 kernel: [c00000000d3c3880] [c0000000000152d0] .__switch_to+0x290/0x300 Oct 15 10:51:47 ps3 kernel: [c00000000d3c3930] [c000000000571d3c] .__schedule+0x904/0x958 Oct 15 10:51:47 ps3 kernel: [c00000000d3c3a10] [c000000000571e0c] .schedule+0x7c/0x90 Oct 15 10:51:47 ps3 kernel: [c00000000d3c3a90] [c0000000002553c4] .jbd2_journal_commit_transaction+0xb84/0x1f68 Oct 15 10:51:47 ps3 kernel: [c00000000d3c3ca0] [c00000000025ad94] .kjournald2+0xc8/0x230 Oct 15 10:51:47 ps3 kernel: [c00000000d3c3d70] [c0000000000713c4] .kthread+0x14c/0x154 Oct 15 10:51:47 ps3 kernel: [c00000000d3c3e30] [c00000000000a83c] .ret_from_kernel_thread+0x58/0x7c Oct 15 10:51:47 ps3 kernel: ext4lazyinit D 0 2465 2 0x00000800 Oct 15 10:51:47 ps3 kernel: Call Trace: Oct 15 10:51:47 ps3 kernel: [c00000000a12f130] [c00000000a12f1b0] 0xc00000000a12f1b0 (unreliable) Oct 15 10:51:47 ps3 kernel: [c00000000a12f300] [c0000000000152d0] .__switch_to+0x290/0x300 Oct 15 10:51:47 ps3 kernel: [c00000000a12f3b0] [c000000000571d3c] .__schedule+0x904/0x958 Oct 15 10:51:47 ps3 kernel: [c00000000a12f490] [c000000000571e0c] .schedule+0x7c/0x90 Oct 15 10:51:47 ps3 kernel: [c00000000a12f510] [c00000000007e1b0] .io_schedule+0x1c/0x34 Oct 15 10:51:47 ps3 kernel: [c00000000a12f590] [c0000000002fbc60] .blk_mq_get_tag+0x180/0x2a0 Oct 15 10:51:47 ps3 kernel: [c00000000a12f660] [c0000000002f59c0] .blk_mq_get_request+0x230/0x4c4 Oct 15 10:51:47 ps3 kernel: [c00000000a12f700] [c0000000002f88b8] .blk_mq_make_request+0x1c0/0x6ec Oct 15 10:51:47 ps3 kernel: [c00000000a12f7f0] [c0000000002e9b10] .generic_make_request+0x3a0/0x450 Oct 15 10:51:47 ps3 kernel: [c00000000a12f8b0] [c0000000002e9c08] .submit_bio+0x48/0x148 Oct 15 10:51:47 ps3 kernel: [c00000000a12f970] [c0000000002f49e0] .next_bio+0x50/0x60 Oct 15 10:51:47 ps3 kernel: [c00000000a12f9f0] [c0000000002f5074] .__blkdev_issue_zero_pages+0xa4/0x168 Oct 15 10:51:47 ps3 kernel: [c00000000a12fac0] [c0000000002f5360] .blkdev_issue_zeroout+0x168/0x16c Oct 15 10:51:47 ps3 kernel: [c00000000a12fbb0] [c00000000020edb8] .ext4_init_inode_table+0x230/0x34c Oct 15 10:51:47 ps3 kernel: [c00000000a12fc90] [c000000000242c30] .ext4_lazyinit_thread+0x21c/0x2f8 Oct 15 10:51:47 ps3 kernel: [c00000000a12fd70] [c0000000000713c4] .kthread+0x14c/0x154 Oct 15 10:51:47 ps3 kernel: [c00000000a12fe30] [c00000000000a83c] .ret_from_kernel_thread+0x58/0x7c Oct 15 10:51:47 ps3 kernel: kworker/u4:11 D 0 2478 2 0x00000800 Oct 15 10:51:47 ps3 kernel: Workqueue: writeback .wb_workfn (flush-254:0) Oct 15 10:51:47 ps3 kernel: Call Trace: Oct 15 10:51:47 ps3 kernel: [c00000000d5928f0] [c00000000d592990] 0xc00000000d592990 (unreliable) Oct 15 10:51:47 ps3 kernel: [c00000000d592ac0] [c0000000000152d0] .__switch_to+0x290/0x300 Oct 15 10:51:47 ps3 kernel: [c00000000d592b70] [c000000000571d3c] .__schedule+0x904/0x958 Oct 15 10:51:47 ps3 kernel: [c00000000d592c50] [c000000000571e0c] .schedule+0x7c/0x90 Oct 15 10:51:47 ps3 kernel: [c00000000d592cd0] [c00000000007e1b0] .io_schedule+0x1c/0x34 Oct 15 10:51:47 ps3 kernel: [c00000000d592d50] [c0000000002fbc60] .blk_mq_get_tag+0x180/0x2a0 Oct 15 10:51:47 ps3 kernel: [c00000000d592e20] [c0000000002f59c0] .blk_mq_get_request+0x230/0x4c4 Oct 15 10:51:47 ps3 kernel: [c00000000d592ec0] [c0000000002f88b8] .blk_mq_make_request+0x1c0/0x6ec Oct 15 10:51:47 ps3 kernel: [c00000000d592fb0] [c0000000002e9b10] .generic_make_request+0x3a0/0x450 Oct 15 10:51:47 ps3 kernel: [c00000000d593070] [c0000000002e9c08] .submit_bio+0x48/0x148 Oct 15 10:51:47 ps3 kernel: [c00000000d593130] [c0000000001aa2f8] .submit_bh_wbc.isra.9+0x198/0x1a8 Oct 15 10:51:47 ps3 kernel: [c00000000d5931d0] [c0000000001aa594] .__block_write_full_page+0x28c/0x430 Oct 15 10:51:47 ps3 kernel: [c00000000d5932c0] [c0000000001adc1c] .blkdev_writepage+0x1c/0x30 Oct 15 10:51:47 ps3 kernel: [c00000000d593330] [c000000000118fbc] .__writepage+0x34/0x80 Oct 15 10:51:47 ps3 kernel: [c00000000d5933b0] [c000000000118920] .write_cache_pages+0x39c/0x47c Oct 15 10:51:47 ps3 kernel: [c00000000d593550] [c000000000118a54] .generic_writepages+0x54/0x70 Oct 15 10:51:47 ps3 kernel: [c00000000d593600] [c0000000001adbbc] .blkdev_writepages+0x10/0x24 Oct 15 10:51:47 ps3 kernel: [c00000000d593670] [c00000000011ab80] .do_writepages+0x54/0xa0 Oct 15 10:51:47 ps3 kernel: [c00000000d5936f0] [c00000000019d84c] .__writeback_single_inode+0x104/0x698 Oct 15 10:51:47 ps3 kernel: [c00000000d5937b0] [c00000000019e0b8] .writeback_sb_inodes+0x2d8/0x480 Oct 15 10:51:47 ps3 kernel: [c00000000d5938e0] [c00000000019e2d4] .__writeback_inodes_wb+0x74/0xb0 Oct 15 10:51:47 ps3 kernel: [c00000000d593990] [c00000000019e7b8] .wb_writeback+0x3f8/0x464 Oct 15 10:51:47 ps3 kernel: [c00000000d593ab0] [c00000000019f388] .wb_workfn+0x43c/0x5ac Oct 15 10:51:47 ps3 kernel: [c00000000d593be0] [c00000000006aae0] .process_one_work+0x30c/0x588 Oct 15 10:51:47 ps3 kernel: [c00000000d593cb0] [c00000000006b2b4] .worker_thread+0x294/0x33c Oct 15 10:51:47 ps3 kernel: [c00000000d593d70] [c0000000000713c4] .kthread+0x14c/0x154 Oct 15 10:51:47 ps3 kernel: [c00000000d593e30] [c00000000000a83c] .ret_from_kernel_thread+0x58/0x7c Oct 15 10:51:47 ps3 kernel: cat D 0 2481 1 0x00000012 Oct 15 10:51:47 ps3 kernel: Call Trace: Oct 15 10:51:47 ps3 kernel: [c00000000b6a3130] [c00000000b6a31d0] 0xc00000000b6a31d0 (unreliable) Oct 15 10:51:47 ps3 kernel: [c00000000b6a3300] [c0000000000152d0] .__switch_to+0x290/0x300 Oct 15 10:51:47 ps3 kernel: [c00000000b6a33b0] [c000000000571d3c] .__schedule+0x904/0x958 Oct 15 10:51:47 ps3 kernel: [c00000000b6a3490] [c000000000571e0c] .schedule+0x7c/0x90 Oct 15 10:51:47 ps3 kernel: [c00000000b6a3510] [c000000000250dac] .wait_transaction_locked+0xd8/0xf4 Oct 15 10:51:47 ps3 kernel: [c00000000b6a35d0] [c000000000250e3c] .add_transaction_credits+0x2c/0x370 Oct 15 10:51:47 ps3 kernel: [c00000000b6a36a0] [c0000000002519a0] .start_this_handle+0x2f0/0x3bc Oct 15 10:51:47 ps3 kernel: [c00000000b6a37d0] [c000000000251b5c] .jbd2__journal_start+0xf0/0x27c Oct 15 10:51:47 ps3 kernel: [c00000000b6a3890] [c0000000001fd828] .__ext4_journal_start_sb+0x1b4/0x1ec Oct 15 10:51:47 ps3 kernel: [c00000000b6a3950] [c000000000209b90] .ext4_file_open+0xc8/0x1c8 Oct 15 10:51:47 ps3 kernel: [c00000000b6a3a50] [c000000000167b18] .do_dentry_open+0x2a0/0x380 Oct 15 10:51:47 ps3 kernel: [c00000000b6a3af0] [c00000000017c7b0] .path_openat+0x4a4/0x904 Oct 15 10:51:47 ps3 kernel: [c00000000b6a3bf0] [c00000000017cc50] .do_filp_open+0x40/0x88 Oct 15 10:51:47 ps3 kernel: [c00000000b6a3d60] [c000000000169074] .do_sys_open+0x13c/0x228 Oct 15 10:51:47 ps3 kernel: [c00000000b6a3e30] [c00000000000a4a4] system_call+0x5c/0x70 Oct 15 10:51:47 ps3 kernel: Oct 15 10:51:47 ps3 kernel: Showing all locks held in the system: Oct 15 10:51:47 ps3 kernel: 1 lock held by khungtaskd/148: Oct 15 10:51:47 ps3 kernel: #0: 000000003bcb2a3a (rcu_read_lock){....}, at: .debug_show_all_locks+0x38/0x1ac Oct 15 10:51:47 ps3 kernel: 2 locks held by ps3fb/301: Oct 15 10:51:47 ps3 kernel: 1 lock held by in:imklog/1779: Oct 15 10:51:47 ps3 kernel: #0: 00000000713da15f (&f->f_pos_lock){+.+.}, at: .__fdget_pos+0x48/0x58 Oct 15 10:51:47 ps3 kernel: 2 locks held by getty/2404: Oct 15 10:51:47 ps3 kernel: #0: 00000000ced8d07b (&tty->ldisc_sem){++++}, at: .tty_ldisc_ref_wait+0x2c/0x54 Oct 15 10:51:47 ps3 kernel: #1: 00000000fd462e7d (&ldata->atomic_read_lock){+.+.}, at: .n_tty_read+0x1bc/0x724 Oct 15 10:51:47 ps3 kernel: 2 locks held by getty/2405: Oct 15 10:51:47 ps3 kernel: #0: 000000009e9dff48 (&tty->ldisc_sem){++++}, at: .tty_ldisc_ref_wait+0x2c/0x54 Oct 15 10:51:47 ps3 kernel: #1: 0000000098475abc (&ldata->atomic_read_lock){+.+.}, at: .n_tty_read+0x1bc/0x724 Oct 15 10:51:47 ps3 kernel: 2 locks held by getty/2406: Oct 15 10:51:47 ps3 kernel: #0: 00000000f060a6f0 (&tty->ldisc_sem){++++}, at: .tty_ldisc_ref_wait+0x2c/0x54 Oct 15 10:51:47 ps3 kernel: #1: 00000000efce01c3 (&ldata->atomic_read_lock){+.+.}, at: .n_tty_read+0x1bc/0x724 Oct 15 10:51:47 ps3 kernel: 2 locks held by getty/2407: Oct 15 10:51:47 ps3 kernel: #0: 00000000935f3792 (&tty->ldisc_sem){++++}, at: .tty_ldisc_ref_wait+0x2c/0x54 Oct 15 10:51:47 ps3 kernel: #1: 00000000efa3bee7 (&ldata->atomic_read_lock){+.+.}, at: .n_tty_read+0x1bc/0x724 Oct 15 10:51:47 ps3 kernel: 2 locks held by getty/2408: Oct 15 10:51:47 ps3 kernel: #0: 00000000111a56ee (&tty->ldisc_sem){++++}, at: .tty_ldisc_ref_wait+0x2c/0x54 Oct 15 10:51:47 ps3 kernel: #1: 00000000f219e2ab (&ldata->atomic_read_lock){+.+.}, at: .n_tty_read+0x1bc/0x724 Oct 15 10:51:47 ps3 kernel: 2 locks held by getty/2409: Oct 15 10:51:47 ps3 kernel: #0: 0000000045df3048 (&tty->ldisc_sem){++++}, at: .tty_ldisc_ref_wait+0x2c/0x54 Oct 15 10:51:47 ps3 kernel: #1: 00000000deede503 (&ldata->atomic_read_lock){+.+.}, at: .n_tty_read+0x1bc/0x724 Oct 15 10:51:47 ps3 kernel: 4 locks held by ext4lazyinit/2465: Oct 15 10:51:47 ps3 kernel: #0: 000000001603d342 (&type->s_umount_key#26){.+.+}, at: .ext4_lazyinit_thread+0x12c/0x2f8 Oct 15 10:51:47 ps3 kernel: #1: 00000000c857701f (sb_writers#10){.+.+}, at: .ext4_lazyinit_thread+0x14c/0x2f8 Oct 15 10:51:47 ps3 kernel: #2: 000000004c766729 (jbd2_handle){++++}, at: .start_this_handle+0x2f8/0x3bc Oct 15 10:51:47 ps3 kernel: #3: 000000001c56823b (&meta_group_info[i]->alloc_sem){+.+.}, at: .ext4_init_inode_table+0xcc/0x34c Oct 15 10:51:47 ps3 kernel: 3 locks held by kworker/u4:11/2478: Oct 15 10:51:47 ps3 kernel: #0: 0000000030f3b24b ((wq_completion)"writeback"){+.+.}, at: .process_one_work+0x1bc/0x588 Oct 15 10:51:47 ps3 kernel: #1: 00000000a1fc5fc0 ((work_completion)(&(&wb->dwork)->work)){+.+.}, at: .process_one_work+0x1bc/0x588 Oct 15 10:51:47 ps3 kernel: #2: 000000007f2fe323 (&type->s_umount_key#27){.+.+}, at: .trylock_super+0x24/0x70 Oct 15 10:51:47 ps3 kernel: 1 lock held by cat/2481: Oct 15 10:51:47 ps3 kernel: #0: 00000000aa6085f9 (sb_internal){.+.+}, at: .ext4_file_open+0x54/0x1c8 Oct 15 10:51:47 ps3 kernel: 2 locks held by bash/2490: Oct 15 10:51:47 ps3 kernel: #0: 0000000077655c1f (&tty->ldisc_sem){++++}, at: .tty_ldisc_ref_wait+0x2c/0x54 Oct 15 10:51:47 ps3 kernel: #1: 000000006f4f8843 (&ldata->atomic_read_lock){+.+.}, at: .n_tty_read+0x1bc/0x724 Oct 15 10:51:47 ps3 kernel: 2 locks held by touch/2518: Oct 15 10:51:47 ps3 kernel: #0: 00000000c857701f (sb_writers#10){.+.+}, at: .mnt_want_write+0x28/0x58 Oct 15 10:51:47 ps3 kernel: #1: 00000000957b6825 (&type->i_mutex_dir_key#4){++++}, at: .path_openat+0x308/0x904 Oct 15 10:51:47 ps3 kernel: Oct 15 10:51:47 ps3 kernel: ============================================= From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Subject: Re: [PATCH 03/17] ps3disk: convert to blk-mq From: Jens Axboe To: Geoff Levand , linux-block@vger.kernel.org Cc: Benjamin Herrenschmidt , Geert Uytterhoeven References: <20181011165909.32615-1-axboe@kernel.dk> <20181011165909.32615-4-axboe@kernel.dk> <17539e5f-742b-796e-8e36-31327120f883@infradead.org> <7f27a68f-9cbe-c4c2-5c35-70763a5b1484@infradead.org> Message-ID: <898e01a5-0000-d5db-d1b6-f58cd4366ce3@kernel.dk> Date: Mon, 15 Oct 2018 10:47:39 -0600 MIME-Version: 1.0 In-Reply-To: Content-Type: text/plain; charset=utf-8 List-ID: On 10/15/18 10:27 AM, Jens Axboe wrote: > On 10/15/18 10:22 AM, Geoff Levand wrote: >> Hi Jens, >> >> On 10/12/2018 05:58 PM, Jens Axboe wrote: >>> On 10/12/18 4:47 PM, Geoff Levand wrote: >>>> On 10/11/2018 09:58 AM, Jens Axboe wrote: >>>>> Convert from the old request_fn style driver to blk-mq. >>>> >>>> I tested this on PS3 applied to v4.19-rc7, and on boot it either >>>> gets a deadlock message or becomes unstable with various other >>>> block related error messages. >>>> >>>> For what its worth, I put an image of the deadlock message here: >>>> >>>> https://storage.googleapis.com/public-tmp-files/blk-deadlock.jpg >>> >>> Thanks for testing! Can you try this incremental? It's mostly just >>> a cleanup on top, but the last hunk should be the thing that >>> hopefully makes this tick again. If you prefer just using a new >>> patch, this one is updated: >>> >>> http://git.kernel.dk/cgit/linux-block/commit/?h=mq-conversions&id=5c86f76f45e7c8d5a47a1f20b3e7b93fc945168a >> >> I tested your V2 applied to v4.19-rc8 and it works a little >> better, in that the system will now boot up, but the ps3disk >> still gets hung up. >> >> I added a '#define DEBUG' to ps3disk.c and saved the dmesg >> output with and without the patch here: >> >> https://storage.googleapis.com/public-tmp-files/dmesg-ok.txt >> https://storage.googleapis.com/public-tmp-files/dmesg-ng.txt >> >> Looking at dmesg-ng.txt, it seems things are going OK, but then >> go wrong with a 'tag mismatch': >> >> [ 6.068298] ps3disk sb_03: ps3disk_do_request:193 >> [ 6.068318] ps3disk sb_03: ps3disk_submit_request_sg:140: read req has 2 bvecs for 16 sectors >> [ 6.068339] ps3disk sb_03: ps3disk_submit_request_sg:146: read 16 sectors starting at 256 >> [ 6.074231] ps3disk sb_03: ps3disk_interrupt:239: tag mismatch, got 0, expected 1 >> [ 6.084125] ps3disk sb_03: ps3disk_interrupt:271: read completed >> [ 6.084147] ps3disk sb_03: ps3disk_scatter_gather:107: bio 0: 16 sectors from 256 >> [ 6.084174] ps3disk sb_03: ps3disk_scatter_gather:107: bio 1: 16 sectors from 256 >> [ 6.084405] ps3disk sb_03: ps3disk_interrupt:252 non-block layer request completed >> ... >> [ 242.657694] INFO: task blkid:563 blocked for more than 120 seconds. >> >> Geert is the original author of the PS3 disk support. Geert, >> can you see anything wrong in the patch? > > Can you try and change the queue depth to 1 instead of 2? It's set in > the tag_set, as ->queue_depth. I took a closer look at it, and I think that's it. The driver doesn't support any queueing, so we must limit the depth to 1. Either artificially like it did before, or just by setting the depth to 1. The latter is cleaner imho. If you make the above mentioned edit, changing the 2 to a 1, it should work. -- Jens Axboe From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Subject: Re: [PATCH 03/17] ps3disk: convert to blk-mq To: Geoff Levand , linux-block@vger.kernel.org Cc: Benjamin Herrenschmidt , Geert Uytterhoeven References: <20181011165909.32615-1-axboe@kernel.dk> <20181011165909.32615-4-axboe@kernel.dk> <17539e5f-742b-796e-8e36-31327120f883@infradead.org> <7f27a68f-9cbe-c4c2-5c35-70763a5b1484@infradead.org> From: Jens Axboe Message-ID: Date: Mon, 15 Oct 2018 10:27:12 -0600 MIME-Version: 1.0 In-Reply-To: <7f27a68f-9cbe-c4c2-5c35-70763a5b1484@infradead.org> Content-Type: text/plain; charset=utf-8 List-ID: On 10/15/18 10:22 AM, Geoff Levand wrote: > Hi Jens, > > On 10/12/2018 05:58 PM, Jens Axboe wrote: >> On 10/12/18 4:47 PM, Geoff Levand wrote: >>> On 10/11/2018 09:58 AM, Jens Axboe wrote: >>>> Convert from the old request_fn style driver to blk-mq. >>> >>> I tested this on PS3 applied to v4.19-rc7, and on boot it either >>> gets a deadlock message or becomes unstable with various other >>> block related error messages. >>> >>> For what its worth, I put an image of the deadlock message here: >>> >>> https://storage.googleapis.com/public-tmp-files/blk-deadlock.jpg >> >> Thanks for testing! Can you try this incremental? It's mostly just >> a cleanup on top, but the last hunk should be the thing that >> hopefully makes this tick again. If you prefer just using a new >> patch, this one is updated: >> >> http://git.kernel.dk/cgit/linux-block/commit/?h=mq-conversions&id=5c86f76f45e7c8d5a47a1f20b3e7b93fc945168a > > I tested your V2 applied to v4.19-rc8 and it works a little > better, in that the system will now boot up, but the ps3disk > still gets hung up. > > I added a '#define DEBUG' to ps3disk.c and saved the dmesg > output with and without the patch here: > > https://storage.googleapis.com/public-tmp-files/dmesg-ok.txt > https://storage.googleapis.com/public-tmp-files/dmesg-ng.txt > > Looking at dmesg-ng.txt, it seems things are going OK, but then > go wrong with a 'tag mismatch': > > [ 6.068298] ps3disk sb_03: ps3disk_do_request:193 > [ 6.068318] ps3disk sb_03: ps3disk_submit_request_sg:140: read req has 2 bvecs for 16 sectors > [ 6.068339] ps3disk sb_03: ps3disk_submit_request_sg:146: read 16 sectors starting at 256 > [ 6.074231] ps3disk sb_03: ps3disk_interrupt:239: tag mismatch, got 0, expected 1 > [ 6.084125] ps3disk sb_03: ps3disk_interrupt:271: read completed > [ 6.084147] ps3disk sb_03: ps3disk_scatter_gather:107: bio 0: 16 sectors from 256 > [ 6.084174] ps3disk sb_03: ps3disk_scatter_gather:107: bio 1: 16 sectors from 256 > [ 6.084405] ps3disk sb_03: ps3disk_interrupt:252 non-block layer request completed > ... > [ 242.657694] INFO: task blkid:563 blocked for more than 120 seconds. > > Geert is the original author of the PS3 disk support. Geert, > can you see anything wrong in the patch? Can you try and change the queue depth to 1 instead of 2? It's set in the tag_set, as ->queue_depth. -- Jens Axboe From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from bombadil.infradead.org ([198.137.202.133]:50614 "EHLO bombadil.infradead.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726528AbeJPAIc (ORCPT ); Mon, 15 Oct 2018 20:08:32 -0400 Subject: Re: [PATCH 03/17] ps3disk: convert to blk-mq To: Jens Axboe , linux-block@vger.kernel.org Cc: Benjamin Herrenschmidt , Geert Uytterhoeven References: <20181011165909.32615-1-axboe@kernel.dk> <20181011165909.32615-4-axboe@kernel.dk> <17539e5f-742b-796e-8e36-31327120f883@infradead.org> From: Geoff Levand Message-ID: <7f27a68f-9cbe-c4c2-5c35-70763a5b1484@infradead.org> Date: Mon, 15 Oct 2018 09:22:29 -0700 MIME-Version: 1.0 In-Reply-To: Content-Type: text/plain; charset=utf-8 Sender: linux-block-owner@vger.kernel.org List-Id: linux-block@vger.kernel.org Hi Jens, On 10/12/2018 05:58 PM, Jens Axboe wrote: > On 10/12/18 4:47 PM, Geoff Levand wrote: >> On 10/11/2018 09:58 AM, Jens Axboe wrote: >>> Convert from the old request_fn style driver to blk-mq. >> >> I tested this on PS3 applied to v4.19-rc7, and on boot it either >> gets a deadlock message or becomes unstable with various other >> block related error messages. >> >> For what its worth, I put an image of the deadlock message here: >> >> https://storage.googleapis.com/public-tmp-files/blk-deadlock.jpg > > Thanks for testing! Can you try this incremental? It's mostly just > a cleanup on top, but the last hunk should be the thing that > hopefully makes this tick again. If you prefer just using a new > patch, this one is updated: > > http://git.kernel.dk/cgit/linux-block/commit/?h=mq-conversions&id=5c86f76f45e7c8d5a47a1f20b3e7b93fc945168a I tested your V2 applied to v4.19-rc8 and it works a little better, in that the system will now boot up, but the ps3disk still gets hung up. I added a '#define DEBUG' to ps3disk.c and saved the dmesg output with and without the patch here: https://storage.googleapis.com/public-tmp-files/dmesg-ok.txt https://storage.googleapis.com/public-tmp-files/dmesg-ng.txt Looking at dmesg-ng.txt, it seems things are going OK, but then go wrong with a 'tag mismatch': [ 6.068298] ps3disk sb_03: ps3disk_do_request:193 [ 6.068318] ps3disk sb_03: ps3disk_submit_request_sg:140: read req has 2 bvecs for 16 sectors [ 6.068339] ps3disk sb_03: ps3disk_submit_request_sg:146: read 16 sectors starting at 256 [ 6.074231] ps3disk sb_03: ps3disk_interrupt:239: tag mismatch, got 0, expected 1 [ 6.084125] ps3disk sb_03: ps3disk_interrupt:271: read completed [ 6.084147] ps3disk sb_03: ps3disk_scatter_gather:107: bio 0: 16 sectors from 256 [ 6.084174] ps3disk sb_03: ps3disk_scatter_gather:107: bio 1: 16 sectors from 256 [ 6.084405] ps3disk sb_03: ps3disk_interrupt:252 non-block layer request completed ... [ 242.657694] INFO: task blkid:563 blocked for more than 120 seconds. Geert is the original author of the PS3 disk support. Geert, can you see anything wrong in the patch? -Geoff From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Subject: Re: [PATCH 03/17] ps3disk: convert to blk-mq To: Geoff Levand , linux-block@vger.kernel.org Cc: Benjamin Herrenschmidt References: <20181011165909.32615-1-axboe@kernel.dk> <20181011165909.32615-4-axboe@kernel.dk> <17539e5f-742b-796e-8e36-31327120f883@infradead.org> From: Jens Axboe Message-ID: Date: Fri, 12 Oct 2018 18:58:50 -0600 MIME-Version: 1.0 In-Reply-To: <17539e5f-742b-796e-8e36-31327120f883@infradead.org> Content-Type: text/plain; charset=utf-8 List-ID: On 10/12/18 4:47 PM, Geoff Levand wrote: > Hi Jens, > > On 10/11/2018 09:58 AM, Jens Axboe wrote: >> Convert from the old request_fn style driver to blk-mq. > > I tested this on PS3 applied to v4.19-rc7, and on boot it either > gets a deadlock message or becomes unstable with various other > block related error messages. > > For what its worth, I put an image of the deadlock message here: > > https://storage.googleapis.com/public-tmp-files/blk-deadlock.jpg Thanks for testing! Can you try this incremental? It's mostly just a cleanup on top, but the last hunk should be the thing that hopefully makes this tick again. If you prefer just using a new patch, this one is updated: http://git.kernel.dk/cgit/linux-block/commit/?h=mq-conversions&id=5c86f76f45e7c8d5a47a1f20b3e7b93fc945168a diff --git a/drivers/block/ps3disk.c b/drivers/block/ps3disk.c index 5f777b694f3c..338ea9dc3393 100644 --- a/drivers/block/ps3disk.c +++ b/drivers/block/ps3disk.c @@ -119,8 +119,8 @@ static void ps3disk_scatter_gather(struct ps3_storage_device *dev, } } -static void ps3disk_submit_request_sg(struct ps3_storage_device *dev, - struct request *req) +static blk_status_t ps3disk_submit_request_sg(struct ps3_storage_device *dev, + struct request *req) { struct ps3disk_private *priv = ps3_system_bus_get_drvdata(&dev->sbd); int write = rq_data_dir(req), res; @@ -159,15 +159,15 @@ static void ps3disk_submit_request_sg(struct ps3_storage_device *dev, if (res) { dev_err(&dev->sbd.core, "%s:%u: %s failed %d\n", __func__, __LINE__, op, res); - blk_mq_end_request(req, BLK_STS_IOERR); - return; + return BLK_STS_IOERR; } priv->req = req; + return BLK_STS_OK; } -static void ps3disk_submit_flush_request(struct ps3_storage_device *dev, - struct request *req) +static blk_status_t ps3disk_submit_flush_request(struct ps3_storage_device *dev, + struct request *req) { struct ps3disk_private *priv = ps3_system_bus_get_drvdata(&dev->sbd); u64 res; @@ -180,29 +180,27 @@ static void ps3disk_submit_flush_request(struct ps3_storage_device *dev, if (res) { dev_err(&dev->sbd.core, "%s:%u: sync cache failed 0x%llx\n", __func__, __LINE__, res); - blk_mq_end_request(req, BLK_STS_IOERR); - return; + return BLK_STS_IOERR; } priv->req = req; + return BLK_STS_OK; } -static void ps3disk_do_request(struct ps3_storage_device *dev, - struct request *req) +static blk_status_t ps3disk_do_request(struct ps3_storage_device *dev, + struct request *req) { dev_dbg(&dev->sbd.core, "%s:%u\n", __func__, __LINE__); switch (req_op(req)) { case REQ_OP_FLUSH: - ps3disk_submit_flush_request(dev, req); - break; + return ps3disk_submit_flush_request(dev, req); case REQ_OP_READ: case REQ_OP_WRITE: - ps3disk_submit_request_sg(dev, req); - break; + return ps3disk_submit_request_sg(dev, req); default: blk_dump_rq_flags(req, DEVICE_NAME " bad request"); - blk_mq_end_request(req, BLK_STS_IOERR); + return BLK_STS_IOERR; } } @@ -212,14 +210,15 @@ static blk_status_t ps3disk_queue_rq(struct blk_mq_hw_ctx *hctx, struct request_queue *q = hctx->queue; struct ps3_storage_device *dev = q->queuedata; struct ps3disk_private *priv = ps3_system_bus_get_drvdata(&dev->sbd); + blk_status_t ret; blk_mq_start_request(bd->rq); spin_lock_irq(&priv->lock); - ps3disk_do_request(dev, bd->rq); + ret = ps3disk_do_request(dev, bd->rq); spin_unlock_irq(&priv->lock); - return BLK_STS_OK; + return ret; } static irqreturn_t ps3disk_interrupt(int irq, void *data) @@ -281,7 +280,7 @@ static irqreturn_t ps3disk_interrupt(int irq, void *data) priv->req = NULL; spin_unlock(&priv->lock); - blk_mq_start_hw_queues(priv->queue); + blk_mq_run_hw_queues(priv->queue, true); return IRQ_HANDLED; } -- Jens Axboe From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from bombadil.infradead.org ([198.137.202.133]:60876 "EHLO bombadil.infradead.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725894AbeJMGWQ (ORCPT ); Sat, 13 Oct 2018 02:22:16 -0400 Subject: Re: [PATCH 03/17] ps3disk: convert to blk-mq To: Jens Axboe , linux-block@vger.kernel.org Cc: Benjamin Herrenschmidt References: <20181011165909.32615-1-axboe@kernel.dk> <20181011165909.32615-4-axboe@kernel.dk> From: Geoff Levand Message-ID: <17539e5f-742b-796e-8e36-31327120f883@infradead.org> Date: Fri, 12 Oct 2018 15:47:37 -0700 MIME-Version: 1.0 In-Reply-To: <20181011165909.32615-4-axboe@kernel.dk> Content-Type: text/plain; charset=utf-8 Sender: linux-block-owner@vger.kernel.org List-Id: linux-block@vger.kernel.org Hi Jens, On 10/11/2018 09:58 AM, Jens Axboe wrote: > Convert from the old request_fn style driver to blk-mq. I tested this on PS3 applied to v4.19-rc7, and on boot it either gets a deadlock message or becomes unstable with various other block related error messages. For what its worth, I put an image of the deadlock message here: https://storage.googleapis.com/public-tmp-files/blk-deadlock.jpg -Geoff From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: From: Jens Axboe To: linux-block@vger.kernel.org Cc: Jens Axboe , Geoff Levand , Benjamin Herrenschmidt Subject: [PATCH 03/17] ps3disk: convert to blk-mq Date: Thu, 11 Oct 2018 10:58:55 -0600 Message-Id: <20181011165909.32615-4-axboe@kernel.dk> In-Reply-To: <20181011165909.32615-1-axboe@kernel.dk> References: <20181011165909.32615-1-axboe@kernel.dk> List-ID: Convert from the old request_fn style driver to blk-mq. Cc: Geoff Levand Cc: Benjamin Herrenschmidt Signed-off-by: Jens Axboe --- drivers/block/ps3disk.c | 95 +++++++++++++++++++++++------------------ 1 file changed, 54 insertions(+), 41 deletions(-) diff --git a/drivers/block/ps3disk.c b/drivers/block/ps3disk.c index afe1508d82c6..e8b41e95a679 100644 --- a/drivers/block/ps3disk.c +++ b/drivers/block/ps3disk.c @@ -19,7 +19,7 @@ */ #include -#include +#include #include #include @@ -42,6 +42,7 @@ struct ps3disk_private { spinlock_t lock; /* Request queue spinlock */ struct request_queue *queue; + struct blk_mq_tag_set tag_set; struct gendisk *gendisk; unsigned int blocking_factor; struct request *req; @@ -118,8 +119,8 @@ static void ps3disk_scatter_gather(struct ps3_storage_device *dev, } } -static int ps3disk_submit_request_sg(struct ps3_storage_device *dev, - struct request *req) +static void ps3disk_submit_request_sg(struct ps3_storage_device *dev, + struct request *req) { struct ps3disk_private *priv = ps3_system_bus_get_drvdata(&dev->sbd); int write = rq_data_dir(req), res; @@ -158,16 +159,15 @@ static int ps3disk_submit_request_sg(struct ps3_storage_device *dev, if (res) { dev_err(&dev->sbd.core, "%s:%u: %s failed %d\n", __func__, __LINE__, op, res); - __blk_end_request_all(req, BLK_STS_IOERR); - return 0; + blk_mq_end_request(req, BLK_STS_IOERR); + return; } priv->req = req; - return 1; } -static int ps3disk_submit_flush_request(struct ps3_storage_device *dev, - struct request *req) +static void ps3disk_submit_flush_request(struct ps3_storage_device *dev, + struct request *req) { struct ps3disk_private *priv = ps3_system_bus_get_drvdata(&dev->sbd); u64 res; @@ -180,50 +180,46 @@ static int ps3disk_submit_flush_request(struct ps3_storage_device *dev, if (res) { dev_err(&dev->sbd.core, "%s:%u: sync cache failed 0x%llx\n", __func__, __LINE__, res); - __blk_end_request_all(req, BLK_STS_IOERR); - return 0; + blk_mq_end_request(req, BLK_STS_IOERR); + return; } priv->req = req; - return 1; } static void ps3disk_do_request(struct ps3_storage_device *dev, - struct request_queue *q) + struct request *req) { - struct request *req; - dev_dbg(&dev->sbd.core, "%s:%u\n", __func__, __LINE__); - while ((req = blk_fetch_request(q))) { - switch (req_op(req)) { - case REQ_OP_FLUSH: - if (ps3disk_submit_flush_request(dev, req)) - return; - break; - case REQ_OP_READ: - case REQ_OP_WRITE: - if (ps3disk_submit_request_sg(dev, req)) - return; - break; - default: - blk_dump_rq_flags(req, DEVICE_NAME " bad request"); - __blk_end_request_all(req, BLK_STS_IOERR); - } + switch (req_op(req)) { + case REQ_OP_FLUSH: + ps3disk_submit_flush_request(dev, req); + break; + case REQ_OP_READ: + case REQ_OP_WRITE: + ps3disk_submit_request_sg(dev, req); + break; + default: + blk_dump_rq_flags(req, DEVICE_NAME " bad request"); + blk_mq_end_request(req, BLK_STS_IOERR); } } -static void ps3disk_request(struct request_queue *q) +static blk_status_t ps3disk_queue_rq(struct blk_mq_hw_ctx *hctx, + const struct blk_mq_queue_data *bd) { + struct request_queue *q = hctx->queue; struct ps3_storage_device *dev = q->queuedata; struct ps3disk_private *priv = ps3_system_bus_get_drvdata(&dev->sbd); - if (priv->req) { - dev_dbg(&dev->sbd.core, "%s:%u busy\n", __func__, __LINE__); - return; - } + blk_mq_start_request(bd->rq); + + spin_lock_irq(&priv->lock); + ps3disk_do_request(dev, bd->rq); + spin_unlock_irq(&priv->lock); - ps3disk_do_request(dev, q); + return BLK_STS_OK; } static irqreturn_t ps3disk_interrupt(int irq, void *data) @@ -279,12 +275,13 @@ static irqreturn_t ps3disk_interrupt(int irq, void *data) ps3disk_scatter_gather(dev, req, 0); } + blk_mq_end_request(req, error); + spin_lock(&priv->lock); - __blk_end_request_all(req, error); priv->req = NULL; - ps3disk_do_request(dev, priv->queue); spin_unlock(&priv->lock); + blk_mq_start_hw_queues(priv->queue); return IRQ_HANDLED; } @@ -404,6 +401,10 @@ static unsigned long ps3disk_mask; static DEFINE_MUTEX(ps3disk_mask_mutex); +static const struct blk_mq_ops ps3disk_mq_ops = { + .queue_rq = ps3disk_queue_rq, +}; + static int ps3disk_probe(struct ps3_system_bus_device *_dev) { struct ps3_storage_device *dev = to_ps3_storage_device(&_dev->core); @@ -411,6 +412,7 @@ static int ps3disk_probe(struct ps3_system_bus_device *_dev) int error; unsigned int devidx; struct request_queue *queue; + struct blk_mq_tag_set *set; struct gendisk *gendisk; if (dev->blk_size < 512) { @@ -454,11 +456,21 @@ static int ps3disk_probe(struct ps3_system_bus_device *_dev) ps3disk_identify(dev); - queue = blk_init_queue(ps3disk_request, &priv->lock); - if (!queue) { - dev_err(&dev->sbd.core, "%s:%u: blk_init_queue failed\n", + set = &priv->tag_set; + set->ops = &ps3disk_mq_ops; + set->nr_hw_queues = 1; + set->queue_depth = 2; + set->numa_node = NUMA_NO_NODE; + set->flags = BLK_MQ_F_SHOULD_MERGE; + error = blk_mq_alloc_tag_set(set); + if (error) + goto fail_teardown; + + queue = blk_mq_init_queue(set); + if (IS_ERR(queue)) { + dev_err(&dev->sbd.core, "%s:%u: blk_mq_init_queue failed\n", __func__, __LINE__); - error = -ENOMEM; + error = PTR_ERR(queue); goto fail_teardown; } @@ -504,6 +516,7 @@ static int ps3disk_probe(struct ps3_system_bus_device *_dev) return 0; fail_cleanup_queue: + blk_mq_free_tag_set(&priv->tag_set); blk_cleanup_queue(queue); fail_teardown: ps3stor_teardown(dev); -- 2.17.1 From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Subject: Re: [PATCH 07/17] uml: convert ubd to blk-mq To: Ming Lei Cc: linux-block@vger.kernel.org, Jeff Dike References: <20181011165909.32615-1-axboe@kernel.dk> <20181011165909.32615-8-axboe@kernel.dk> <20181015102717.GB31722@ming.t460p> From: Jens Axboe Message-ID: Date: Mon, 15 Oct 2018 08:16:32 -0600 MIME-Version: 1.0 In-Reply-To: <20181015102717.GB31722@ming.t460p> Content-Type: text/plain; charset=utf-8 List-ID: On 10/15/18 4:27 AM, Ming Lei wrote: > On Thu, Oct 11, 2018 at 10:58:59AM -0600, Jens Axboe wrote: >> @@ -947,9 +970,12 @@ static int ubd_add(int n, char **error_out) >> >> err = 0; >> out: >> + blk_mq_free_tag_set(&ubd_dev->tag_set); >> +out1: >> return err; >> >> out_cleanup: >> + blk_mq_free_tag_set(&ubd_dev->tag_set); >> blk_cleanup_queue(ubd_dev->queue); > > blk_mq_free_tag_set() should have been put after blk_cleanup_queue(). Doesn't matter for this error path, but I do agree in general that should be the case. I'll fix those up. -- Jens Axboe From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Date: Mon, 15 Oct 2018 18:27:18 +0800 From: Ming Lei To: Jens Axboe Cc: linux-block@vger.kernel.org, Jeff Dike Subject: Re: [PATCH 07/17] uml: convert ubd to blk-mq Message-ID: <20181015102717.GB31722@ming.t460p> References: <20181011165909.32615-1-axboe@kernel.dk> <20181011165909.32615-8-axboe@kernel.dk> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii In-Reply-To: <20181011165909.32615-8-axboe@kernel.dk> List-ID: On Thu, Oct 11, 2018 at 10:58:59AM -0600, Jens Axboe wrote: > Just a straight forward conversion. The retry handling could > potentially be done by blk-mq as well, but that's for another > day. > > Cc: Jeff Dike > Signed-off-by: Jens Axboe > --- > arch/um/drivers/ubd_kern.c | 154 ++++++++++++++++++++++--------------- > 1 file changed, 94 insertions(+), 60 deletions(-) > > diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c > index 83c470364dfb..a302962a441d 100644 > --- a/arch/um/drivers/ubd_kern.c > +++ b/arch/um/drivers/ubd_kern.c > @@ -22,7 +22,7 @@ > > #include > #include > -#include > +#include > #include > #include > #include > @@ -156,6 +156,7 @@ struct ubd { > struct cow cow; > struct platform_device pdev; > struct request_queue *queue; > + struct blk_mq_tag_set tag_set; > spinlock_t lock; > struct scatterlist sg[MAX_SG]; > struct request *request; > @@ -436,7 +437,9 @@ __uml_help(udb_setup, > " in the boot output.\n\n" > ); > > -static void do_ubd_request(struct request_queue * q); > +static void ubd_handle_request(struct ubd *dev); > +static blk_status_t ubd_queue_rq(struct blk_mq_hw_ctx *hctx, > + const struct blk_mq_queue_data *bd); > > /* Only changed by ubd_init, which is an initcall. */ > static int thread_fd = -1; > @@ -520,12 +523,12 @@ static void ubd_handler(void) > return; > } > for (count = 0; count < n/sizeof(struct io_thread_req *); count++) { > - blk_end_request( > - (*irq_req_buffer)[count]->req, > - BLK_STS_OK, > - (*irq_req_buffer)[count]->length > - ); > - kfree((*irq_req_buffer)[count]); > + struct io_thread_req *io_req = (*irq_req_buffer)[count]; > + > + if (!blk_update_request(io_req->req, BLK_STS_OK, io_req->length)) > + __blk_mq_end_request(io_req->req, BLK_STS_OK); > + > + kfree(io_req); > } > } > reactivate_fd(thread_fd, UBD_IRQ); > @@ -534,7 +537,7 @@ static void ubd_handler(void) > ubd = container_of(list, struct ubd, restart); > list_del_init(&ubd->restart); > spin_lock_irqsave(&ubd->lock, flags); > - do_ubd_request(ubd->queue); > + ubd_handle_request(ubd); > spin_unlock_irqrestore(&ubd->lock, flags); > } > } > @@ -856,6 +859,7 @@ static void ubd_device_release(struct device *dev) > { > struct ubd *ubd_dev = dev_get_drvdata(dev); > > + blk_mq_free_tag_set(&ubd_dev->tag_set); > blk_cleanup_queue(ubd_dev->queue); > *ubd_dev = ((struct ubd) DEFAULT_UBD); > } > @@ -897,20 +901,25 @@ static int ubd_disk_register(int major, u64 size, int unit, > return 0; > } > > +static const struct blk_mq_ops ubd_mq_ops = { > + .queue_rq = ubd_queue_rq, > +}; > + > #define ROUND_BLOCK(n) ((n + ((1 << 9) - 1)) & (-1 << 9)) > > static int ubd_add(int n, char **error_out) > { > struct ubd *ubd_dev = &ubd_devs[n]; > + struct blk_mq_tag_set *set; > int err = 0; > > if(ubd_dev->file == NULL) > - goto out; > + goto out1; > > err = ubd_file_size(ubd_dev, &ubd_dev->size); > if(err < 0){ > *error_out = "Couldn't determine size of device's file"; > - goto out; > + goto out1; > } > > ubd_dev->size = ROUND_BLOCK(ubd_dev->size); > @@ -918,12 +927,26 @@ static int ubd_add(int n, char **error_out) > INIT_LIST_HEAD(&ubd_dev->restart); > sg_init_table(ubd_dev->sg, MAX_SG); > > - err = -ENOMEM; > - ubd_dev->queue = blk_init_queue(do_ubd_request, &ubd_dev->lock); > - if (ubd_dev->queue == NULL) { > + set = &ubd_dev->tag_set; > + set->ops = &ubd_mq_ops; > + set->nr_hw_queues = 1; > + set->queue_depth = 2; > + set->numa_node = NUMA_NO_NODE; > + set->flags = BLK_MQ_F_SHOULD_MERGE; > + err = blk_mq_alloc_tag_set(set); > + if (err) { > + *error_out = "Failed to initialize device tag set"; > + goto out1; > + } > + > + ubd_dev->queue = blk_mq_init_queue(set); > + if (IS_ERR(ubd_dev->queue)) { > + err = PTR_ERR(ubd_dev->queue); > + ubd_dev->queue = NULL; > *error_out = "Failed to initialize device queue"; > goto out; > } > + > ubd_dev->queue->queuedata = ubd_dev; > blk_queue_write_cache(ubd_dev->queue, true, false); > > @@ -947,9 +970,12 @@ static int ubd_add(int n, char **error_out) > > err = 0; > out: > + blk_mq_free_tag_set(&ubd_dev->tag_set); > +out1: > return err; > > out_cleanup: > + blk_mq_free_tag_set(&ubd_dev->tag_set); > blk_cleanup_queue(ubd_dev->queue); blk_mq_free_tag_set() should have been put after blk_cleanup_queue(). -- Ming From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: From: Jens Axboe To: linux-block@vger.kernel.org Cc: Jens Axboe , Jeff Dike Subject: [PATCH 07/17] uml: convert ubd to blk-mq Date: Thu, 11 Oct 2018 10:58:59 -0600 Message-Id: <20181011165909.32615-8-axboe@kernel.dk> In-Reply-To: <20181011165909.32615-1-axboe@kernel.dk> References: <20181011165909.32615-1-axboe@kernel.dk> List-ID: Just a straight forward conversion. The retry handling could potentially be done by blk-mq as well, but that's for another day. Cc: Jeff Dike Signed-off-by: Jens Axboe --- arch/um/drivers/ubd_kern.c | 154 ++++++++++++++++++++++--------------- 1 file changed, 94 insertions(+), 60 deletions(-) diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c index 83c470364dfb..a302962a441d 100644 --- a/arch/um/drivers/ubd_kern.c +++ b/arch/um/drivers/ubd_kern.c @@ -22,7 +22,7 @@ #include #include -#include +#include #include #include #include @@ -156,6 +156,7 @@ struct ubd { struct cow cow; struct platform_device pdev; struct request_queue *queue; + struct blk_mq_tag_set tag_set; spinlock_t lock; struct scatterlist sg[MAX_SG]; struct request *request; @@ -436,7 +437,9 @@ __uml_help(udb_setup, " in the boot output.\n\n" ); -static void do_ubd_request(struct request_queue * q); +static void ubd_handle_request(struct ubd *dev); +static blk_status_t ubd_queue_rq(struct blk_mq_hw_ctx *hctx, + const struct blk_mq_queue_data *bd); /* Only changed by ubd_init, which is an initcall. */ static int thread_fd = -1; @@ -520,12 +523,12 @@ static void ubd_handler(void) return; } for (count = 0; count < n/sizeof(struct io_thread_req *); count++) { - blk_end_request( - (*irq_req_buffer)[count]->req, - BLK_STS_OK, - (*irq_req_buffer)[count]->length - ); - kfree((*irq_req_buffer)[count]); + struct io_thread_req *io_req = (*irq_req_buffer)[count]; + + if (!blk_update_request(io_req->req, BLK_STS_OK, io_req->length)) + __blk_mq_end_request(io_req->req, BLK_STS_OK); + + kfree(io_req); } } reactivate_fd(thread_fd, UBD_IRQ); @@ -534,7 +537,7 @@ static void ubd_handler(void) ubd = container_of(list, struct ubd, restart); list_del_init(&ubd->restart); spin_lock_irqsave(&ubd->lock, flags); - do_ubd_request(ubd->queue); + ubd_handle_request(ubd); spin_unlock_irqrestore(&ubd->lock, flags); } } @@ -856,6 +859,7 @@ static void ubd_device_release(struct device *dev) { struct ubd *ubd_dev = dev_get_drvdata(dev); + blk_mq_free_tag_set(&ubd_dev->tag_set); blk_cleanup_queue(ubd_dev->queue); *ubd_dev = ((struct ubd) DEFAULT_UBD); } @@ -897,20 +901,25 @@ static int ubd_disk_register(int major, u64 size, int unit, return 0; } +static const struct blk_mq_ops ubd_mq_ops = { + .queue_rq = ubd_queue_rq, +}; + #define ROUND_BLOCK(n) ((n + ((1 << 9) - 1)) & (-1 << 9)) static int ubd_add(int n, char **error_out) { struct ubd *ubd_dev = &ubd_devs[n]; + struct blk_mq_tag_set *set; int err = 0; if(ubd_dev->file == NULL) - goto out; + goto out1; err = ubd_file_size(ubd_dev, &ubd_dev->size); if(err < 0){ *error_out = "Couldn't determine size of device's file"; - goto out; + goto out1; } ubd_dev->size = ROUND_BLOCK(ubd_dev->size); @@ -918,12 +927,26 @@ static int ubd_add(int n, char **error_out) INIT_LIST_HEAD(&ubd_dev->restart); sg_init_table(ubd_dev->sg, MAX_SG); - err = -ENOMEM; - ubd_dev->queue = blk_init_queue(do_ubd_request, &ubd_dev->lock); - if (ubd_dev->queue == NULL) { + set = &ubd_dev->tag_set; + set->ops = &ubd_mq_ops; + set->nr_hw_queues = 1; + set->queue_depth = 2; + set->numa_node = NUMA_NO_NODE; + set->flags = BLK_MQ_F_SHOULD_MERGE; + err = blk_mq_alloc_tag_set(set); + if (err) { + *error_out = "Failed to initialize device tag set"; + goto out1; + } + + ubd_dev->queue = blk_mq_init_queue(set); + if (IS_ERR(ubd_dev->queue)) { + err = PTR_ERR(ubd_dev->queue); + ubd_dev->queue = NULL; *error_out = "Failed to initialize device queue"; goto out; } + ubd_dev->queue->queuedata = ubd_dev; blk_queue_write_cache(ubd_dev->queue, true, false); @@ -947,9 +970,12 @@ static int ubd_add(int n, char **error_out) err = 0; out: + blk_mq_free_tag_set(&ubd_dev->tag_set); +out1: return err; out_cleanup: + blk_mq_free_tag_set(&ubd_dev->tag_set); blk_cleanup_queue(ubd_dev->queue); goto out; } @@ -1338,10 +1364,11 @@ static bool submit_request(struct io_thread_req *io_req, struct ubd *dev) int n = os_write_file(thread_fd, &io_req, sizeof(io_req)); if (n != sizeof(io_req)) { - if (n != -EAGAIN) + if (n != -EAGAIN) { printk("write to io thread failed, " "errno = %d\n", -n); - else if (list_empty(&dev->restart)) + blk_mq_end_request(io_req->req, BLK_STS_IOERR); + } else if (list_empty(&dev->restart)) list_add(&dev->restart, &restart); kfree(io_req); @@ -1351,62 +1378,69 @@ static bool submit_request(struct io_thread_req *io_req, struct ubd *dev) } /* Called with dev->lock held */ -static void do_ubd_request(struct request_queue *q) +static void ubd_handle_request(struct ubd *dev) { + struct request *req = dev->request; struct io_thread_req *io_req; - struct request *req; - - while(1){ - struct ubd *dev = q->queuedata; - if(dev->request == NULL){ - struct request *req = blk_fetch_request(q); - if(req == NULL) - return; - dev->request = req; - dev->rq_pos = blk_rq_pos(req); - dev->start_sg = 0; - dev->end_sg = blk_rq_map_sg(q, req, dev->sg); + if (req_op(req) == REQ_OP_FLUSH) { + io_req = kmalloc(sizeof(struct io_thread_req), GFP_ATOMIC); + if (io_req == NULL) { + if (list_empty(&dev->restart)) + list_add(&dev->restart, &restart); + return; } + prepare_flush_request(req, io_req); + if (submit_request(io_req, dev) == false) + return; + } - req = dev->request; + while (dev->start_sg < dev->end_sg){ + struct scatterlist *sg = &dev->sg[dev->start_sg]; - if (req_op(req) == REQ_OP_FLUSH) { - io_req = kmalloc(sizeof(struct io_thread_req), - GFP_ATOMIC); - if (io_req == NULL) { - if (list_empty(&dev->restart)) - list_add(&dev->restart, &restart); - return; - } - prepare_flush_request(req, io_req); - if (submit_request(io_req, dev) == false) - return; + io_req = kmalloc(sizeof(struct io_thread_req), GFP_ATOMIC); + if (io_req == NULL){ + if (list_empty(&dev->restart)) + list_add(&dev->restart, &restart); + return; } + prepare_request(req, io_req, + (unsigned long long)dev->rq_pos << 9, + sg->offset, sg->length, sg_page(sg)); - while(dev->start_sg < dev->end_sg){ - struct scatterlist *sg = &dev->sg[dev->start_sg]; + if (submit_request(io_req, dev) == false) + return; - io_req = kmalloc(sizeof(struct io_thread_req), - GFP_ATOMIC); - if(io_req == NULL){ - if(list_empty(&dev->restart)) - list_add(&dev->restart, &restart); - return; - } - prepare_request(req, io_req, - (unsigned long long)dev->rq_pos << 9, - sg->offset, sg->length, sg_page(sg)); + dev->rq_pos += sg->length >> 9; + dev->start_sg++; + } - if (submit_request(io_req, dev) == false) - return; + dev->end_sg = 0; + dev->request = NULL; +} - dev->rq_pos += sg->length >> 9; - dev->start_sg++; - } - dev->end_sg = 0; - dev->request = NULL; +static blk_status_t ubd_queue_rq(struct blk_mq_hw_ctx *hctx, + const struct blk_mq_queue_data *bd) +{ + struct ubd *dev = hctx->queue->queuedata; + struct request *req; + + spin_lock_irq(&dev->lock); + if (dev->request != NULL) { + spin_unlock_irq(&dev->lock); + return BLK_STS_DEV_RESOURCE; } + + req = bd->rq; + blk_mq_start_request(req); + dev->request = req; + dev->rq_pos = blk_rq_pos(req); + dev->start_sg = 0; + dev->end_sg = blk_rq_map_sg(req->q, req, dev->sg); + + ubd_handle_request(dev); + spin_unlock_irq(&dev->lock); + return BLK_STS_OK; } static int ubd_getgeo(struct block_device *bdev, struct hd_geometry *geo) -- 2.17.1 From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: From: Jens Axboe To: linux-block@vger.kernel.org Cc: Jens Axboe Subject: [PATCH 05/17] paride: convert pd to blk-mq Date: Thu, 11 Oct 2018 10:58:57 -0600 Message-Id: <20181011165909.32615-6-axboe@kernel.dk> In-Reply-To: <20181011165909.32615-1-axboe@kernel.dk> References: <20181011165909.32615-1-axboe@kernel.dk> List-ID: Signed-off-by: Jens Axboe --- drivers/block/paride/pd.c | 109 ++++++++++++++++++++++---------------- 1 file changed, 62 insertions(+), 47 deletions(-) diff --git a/drivers/block/paride/pd.c b/drivers/block/paride/pd.c index 7cf947586fe4..87636d6ce191 100644 --- a/drivers/block/paride/pd.c +++ b/drivers/block/paride/pd.c @@ -151,7 +151,7 @@ enum {D_PRT, D_PRO, D_UNI, D_MOD, D_GEO, D_SBY, D_DLY, D_SLV}; #include #include #include /* for the eject ioctl */ -#include +#include #include #include #include @@ -236,6 +236,7 @@ struct pd_unit { int alt_geom; char name[PD_NAMELEN]; /* pda, pdb, etc ... */ struct gendisk *gd; + struct blk_mq_tag_set tag_set; }; static struct pd_unit pd[PD_UNITS]; @@ -355,25 +356,6 @@ enum action {Fail = 0, Ok = 1, Hold, Wait}; static struct request *pd_req; /* current request */ static enum action (*phase)(void); -static void run_fsm(void); - -static void ps_tq_int(struct work_struct *work); - -static DECLARE_DELAYED_WORK(fsm_tq, ps_tq_int); - -static void schedule_fsm(void) -{ - if (!nice) - schedule_delayed_work(&fsm_tq, 0); - else - schedule_delayed_work(&fsm_tq, nice-1); -} - -static void ps_tq_int(struct work_struct *work) -{ - run_fsm(); -} - static enum action do_pd_io_start(void); static enum action pd_special(void); static enum action do_pd_read_start(void); @@ -387,7 +369,7 @@ static int pd_claimed; static struct pd_unit *pd_current; /* current request's drive */ static PIA *pi_current; /* current request's PIA */ -static int set_next_request(void) +static int run_next_queue(void) { struct gendisk *disk; struct request_queue *q; @@ -398,11 +380,8 @@ static int set_next_request(void) q = disk ? disk->queue : NULL; if (++pd_queue == PD_UNITS) pd_queue = 0; - if (q) { - pd_req = blk_fetch_request(q); - if (pd_req) - break; - } + if (q) + blk_mq_run_hw_queues(q, true); } while (pd_queue != old_pos); return pd_req != NULL; @@ -438,17 +417,20 @@ static void run_fsm(void) pd_claimed = 0; phase = NULL; spin_lock_irqsave(&pd_lock, saved_flags); - if (!__blk_end_request_cur(pd_req, - res == Ok ? 0 : BLK_STS_IOERR)) { - if (!set_next_request()) - stop = 1; + if (!blk_update_request(pd_req, + res == Ok ? 0 : BLK_STS_IOERR, + blk_rq_cur_bytes(pd_req))) { + __blk_mq_end_request(pd_req, + res == Ok ? 0 : BLK_STS_IOERR); + run_next_queue(); + stop = 1; } spin_unlock_irqrestore(&pd_lock, saved_flags); if (stop) return; /* fall through */ case Hold: - schedule_fsm(); + blk_mq_run_hw_queues(pd_req->q, true); return; case Wait: pi_disconnect(pi_current); @@ -505,11 +487,17 @@ static int pd_next_buf(void) if (pd_count) return 0; spin_lock_irqsave(&pd_lock, saved_flags); - __blk_end_request_cur(pd_req, 0); - pd_count = blk_rq_cur_sectors(pd_req); - pd_buf = bio_data(pd_req->bio); + if (!blk_update_request(pd_req, 0, blk_rq_cur_bytes(pd_req))) { + __blk_mq_end_request(pd_req, 0); + pd_req = NULL; + pd_count = 0; + pd_buf = NULL; + } else { + pd_count = blk_rq_cur_sectors(pd_req); + pd_buf = bio_data(pd_req->bio); + } spin_unlock_irqrestore(&pd_lock, saved_flags); - return 0; + return !pd_count; } static unsigned long pd_timeout; @@ -726,15 +714,22 @@ static enum action pd_identify(struct pd_unit *disk) /* end of io request engine */ -static void do_pd_request(struct request_queue * q) +static blk_status_t pd_queue_rq(struct blk_mq_hw_ctx *hctx, + const struct blk_mq_queue_data *bd) { - if (pd_req) - return; - pd_req = blk_fetch_request(q); - if (!pd_req) - return; + spin_lock_irq(&pd_lock); - schedule_fsm(); + /* this should not be possible */ + if (pd_req) { + spin_unlock_irq(&pd_lock); + return BLK_STS_DEV_RESOURCE; + } + + pd_req = bd->rq; + spin_unlock_irq(&pd_lock); + blk_mq_start_request(bd->rq); + run_fsm(); + return BLK_STS_OK; } static int pd_special_command(struct pd_unit *disk, @@ -847,23 +842,42 @@ static const struct block_device_operations pd_fops = { /* probing */ +static const struct blk_mq_ops pd_mq_ops = { + .queue_rq = pd_queue_rq, +}; + static void pd_probe_drive(struct pd_unit *disk) { - struct gendisk *p = alloc_disk(1 << PD_BITS); + struct blk_mq_tag_set *set; + struct gendisk *p; + + p = alloc_disk(1 << PD_BITS); if (!p) return; + strcpy(p->disk_name, disk->name); p->fops = &pd_fops; p->major = major; p->first_minor = (disk - pd) << PD_BITS; disk->gd = p; p->private_data = disk; - p->queue = blk_init_queue(do_pd_request, &pd_lock); - if (!p->queue) { - disk->gd = NULL; - put_disk(p); + + set = &disk->tag_set; + set->ops = &pd_mq_ops; + set->nr_hw_queues = 1; + set->queue_depth = 1; + set->numa_node = NUMA_NO_NODE; + set->flags = BLK_MQ_F_SHOULD_MERGE | BLK_MQ_F_BLOCKING; + if (blk_mq_alloc_tag_set(set)) + return; + + p->queue = blk_mq_init_queue(set); + if (IS_ERR(p->queue)) { + blk_mq_free_tag_set(set); + p->queue = NULL; return; } + blk_queue_max_hw_sectors(p->queue, cluster); blk_queue_bounce_limit(p->queue, BLK_BOUNCE_HIGH); @@ -971,6 +985,7 @@ static void __exit pd_exit(void) if (p) { disk->gd = NULL; del_gendisk(p); + blk_mq_free_tag_set(&disk->tag_set); blk_cleanup_queue(p->queue); put_disk(p); pi_release(disk->pi); -- 2.17.1 From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Subject: Re: [PATCH 12/17] blk-mq-sched: export way for drivers to insert request To: Christoph Hellwig Cc: linux-block@vger.kernel.org References: <20181011165909.32615-1-axboe@kernel.dk> <20181011165909.32615-13-axboe@kernel.dk> <20181014184935.GA1944@infradead.org> From: Jens Axboe Message-ID: <8fcbef11-84a4-80a8-2fc0-e11b5db55721@kernel.dk> Date: Sun, 14 Oct 2018 12:56:17 -0600 MIME-Version: 1.0 In-Reply-To: <20181014184935.GA1944@infradead.org> Content-Type: text/plain; charset=utf-8 List-ID: On 10/14/18 12:49 PM, Christoph Hellwig wrote: > On Thu, Oct 11, 2018 at 10:59:04AM -0600, Jens Axboe wrote: >> We'll need this for the IDE conversion, which queues sense requests. > > Why can't the ide code use blk_execute_rq_nowait? Yeah it can, I made that change and dropped this patch. -- Jens Axboe From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Date: Sun, 14 Oct 2018 11:49:35 -0700 From: Christoph Hellwig To: Jens Axboe Cc: linux-block@vger.kernel.org Subject: Re: [PATCH 12/17] blk-mq-sched: export way for drivers to insert request Message-ID: <20181014184935.GA1944@infradead.org> References: <20181011165909.32615-1-axboe@kernel.dk> <20181011165909.32615-13-axboe@kernel.dk> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii In-Reply-To: <20181011165909.32615-13-axboe@kernel.dk> List-ID: On Thu, Oct 11, 2018 at 10:59:04AM -0600, Jens Axboe wrote: > We'll need this for the IDE conversion, which queues sense requests. Why can't the ide code use blk_execute_rq_nowait? From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: From: Jens Axboe To: linux-block@vger.kernel.org Cc: Jens Axboe Subject: [PATCH 12/17] blk-mq-sched: export way for drivers to insert request Date: Thu, 11 Oct 2018 10:59:04 -0600 Message-Id: <20181011165909.32615-13-axboe@kernel.dk> In-Reply-To: <20181011165909.32615-1-axboe@kernel.dk> References: <20181011165909.32615-1-axboe@kernel.dk> List-ID: We'll need this for the IDE conversion, which queues sense requests. Signed-off-by: Jens Axboe --- block/blk-mq-sched.c | 1 + block/blk-mq-sched.h | 2 -- include/linux/blk-mq.h | 2 ++ 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/block/blk-mq-sched.c b/block/blk-mq-sched.c index 29bfe8017a2d..f307af1a42bc 100644 --- a/block/blk-mq-sched.c +++ b/block/blk-mq-sched.c @@ -395,6 +395,7 @@ void blk_mq_sched_insert_request(struct request *rq, bool at_head, if (run_queue) blk_mq_run_hw_queue(hctx, async); } +EXPORT_SYMBOL_GPL(blk_mq_sched_insert_request); void blk_mq_sched_insert_requests(struct request_queue *q, struct blk_mq_ctx *ctx, diff --git a/block/blk-mq-sched.h b/block/blk-mq-sched.h index 4e028ee42430..6b3e8255f3af 100644 --- a/block/blk-mq-sched.h +++ b/block/blk-mq-sched.h @@ -17,8 +17,6 @@ bool __blk_mq_sched_bio_merge(struct request_queue *q, struct bio *bio); bool blk_mq_sched_try_insert_merge(struct request_queue *q, struct request *rq); void blk_mq_sched_restart(struct blk_mq_hw_ctx *hctx); -void blk_mq_sched_insert_request(struct request *rq, bool at_head, - bool run_queue, bool async); void blk_mq_sched_insert_requests(struct request_queue *q, struct blk_mq_ctx *ctx, struct list_head *list, bool run_queue_async); diff --git a/include/linux/blk-mq.h b/include/linux/blk-mq.h index 1da59c16f637..1d4f8588701d 100644 --- a/include/linux/blk-mq.h +++ b/include/linux/blk-mq.h @@ -260,6 +260,8 @@ void blk_mq_add_to_requeue_list(struct request *rq, bool at_head, bool kick_requeue_list); void blk_mq_kick_requeue_list(struct request_queue *q); void blk_mq_delay_kick_requeue_list(struct request_queue *q, unsigned long msecs); +void blk_mq_sched_insert_request(struct request *rq, bool at_head, + bool run_queue, bool async); void blk_mq_complete_request(struct request *rq); bool blk_mq_bio_list_merge(struct request_queue *q, struct list_head *list, struct bio *bio); -- 2.17.1 From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: From: Jens Axboe To: linux-block@vger.kernel.org Cc: Jens Axboe Subject: [PATCH 10/17] gdrom: convert to blk-mq Date: Thu, 11 Oct 2018 10:59:02 -0600 Message-Id: <20181011165909.32615-11-axboe@kernel.dk> In-Reply-To: <20181011165909.32615-1-axboe@kernel.dk> References: <20181011165909.32615-1-axboe@kernel.dk> List-ID: Ditch the deffered list, lock, and workqueue handling. Just mark the set as being blocking, so we are invoked from a workqueue already. Signed-off-by: Jens Axboe --- drivers/cdrom/gdrom.c | 182 ++++++++++++++++++++---------------------- 1 file changed, 87 insertions(+), 95 deletions(-) diff --git a/drivers/cdrom/gdrom.c b/drivers/cdrom/gdrom.c index ae3a7537cf0f..41b57d9c4424 100644 --- a/drivers/cdrom/gdrom.c +++ b/drivers/cdrom/gdrom.c @@ -31,12 +31,11 @@ #include #include #include -#include +#include #include #include #include #include -#include #include #include #include @@ -102,11 +101,6 @@ static int gdrom_major; static DECLARE_WAIT_QUEUE_HEAD(command_queue); static DECLARE_WAIT_QUEUE_HEAD(request_queue); -static DEFINE_SPINLOCK(gdrom_lock); -static void gdrom_readdisk_dma(struct work_struct *work); -static DECLARE_WORK(work, gdrom_readdisk_dma); -static LIST_HEAD(gdrom_deferred); - struct gdromtoc { unsigned int entry[99]; unsigned int first, last; @@ -122,6 +116,7 @@ static struct gdrom_unit { char disk_type; struct gdromtoc *toc; struct request_queue *gdrom_rq; + struct blk_mq_tag_set tag_set; } gd; struct gdrom_id { @@ -584,103 +579,83 @@ static int gdrom_set_interrupt_handlers(void) * 9 -> sectors >> 8 * 10 -> sectors */ -static void gdrom_readdisk_dma(struct work_struct *work) +static blk_status_t gdrom_readdisk_dma(struct request *req) { int block, block_cnt; blk_status_t err; struct packet_command *read_command; - struct list_head *elem, *next; - struct request *req; unsigned long timeout; - if (list_empty(&gdrom_deferred)) - return; read_command = kzalloc(sizeof(struct packet_command), GFP_KERNEL); if (!read_command) - return; /* get more memory later? */ + return BLK_STS_RESOURCE; + read_command->cmd[0] = 0x30; read_command->cmd[1] = 0x20; - spin_lock(&gdrom_lock); - list_for_each_safe(elem, next, &gdrom_deferred) { - req = list_entry(elem, struct request, queuelist); - spin_unlock(&gdrom_lock); - block = blk_rq_pos(req)/GD_TO_BLK + GD_SESSION_OFFSET; - block_cnt = blk_rq_sectors(req)/GD_TO_BLK; - __raw_writel(virt_to_phys(bio_data(req->bio)), GDROM_DMA_STARTADDR_REG); - __raw_writel(block_cnt * GDROM_HARD_SECTOR, GDROM_DMA_LENGTH_REG); - __raw_writel(1, GDROM_DMA_DIRECTION_REG); - __raw_writel(1, GDROM_DMA_ENABLE_REG); - read_command->cmd[2] = (block >> 16) & 0xFF; - read_command->cmd[3] = (block >> 8) & 0xFF; - read_command->cmd[4] = block & 0xFF; - read_command->cmd[8] = (block_cnt >> 16) & 0xFF; - read_command->cmd[9] = (block_cnt >> 8) & 0xFF; - read_command->cmd[10] = block_cnt & 0xFF; - /* set for DMA */ - __raw_writeb(1, GDROM_ERROR_REG); - /* other registers */ - __raw_writeb(0, GDROM_SECNUM_REG); - __raw_writeb(0, GDROM_BCL_REG); - __raw_writeb(0, GDROM_BCH_REG); - __raw_writeb(0, GDROM_DSEL_REG); - __raw_writeb(0, GDROM_INTSEC_REG); - /* Wait for registers to reset after any previous activity */ - timeout = jiffies + HZ / 2; - while (gdrom_is_busy() && time_before(jiffies, timeout)) - cpu_relax(); - __raw_writeb(GDROM_COM_PACKET, GDROM_STATUSCOMMAND_REG); - timeout = jiffies + HZ / 2; - /* Wait for packet command to finish */ - while (gdrom_is_busy() && time_before(jiffies, timeout)) - cpu_relax(); - gd.pending = 1; - gd.transfer = 1; - outsw(GDROM_DATA_REG, &read_command->cmd, 6); - timeout = jiffies + HZ / 2; - /* Wait for any pending DMA to finish */ - while (__raw_readb(GDROM_DMA_STATUS_REG) && - time_before(jiffies, timeout)) - cpu_relax(); - /* start transfer */ - __raw_writeb(1, GDROM_DMA_STATUS_REG); - wait_event_interruptible_timeout(request_queue, - gd.transfer == 0, GDROM_DEFAULT_TIMEOUT); - err = gd.transfer ? BLK_STS_IOERR : BLK_STS_OK; - gd.transfer = 0; - gd.pending = 0; - /* now seek to take the request spinlock - * before handling ending the request */ - spin_lock(&gdrom_lock); - list_del_init(&req->queuelist); - __blk_end_request_all(req, err); - } - spin_unlock(&gdrom_lock); + block = blk_rq_pos(req)/GD_TO_BLK + GD_SESSION_OFFSET; + block_cnt = blk_rq_sectors(req)/GD_TO_BLK; + __raw_writel(virt_to_phys(bio_data(req->bio)), GDROM_DMA_STARTADDR_REG); + __raw_writel(block_cnt * GDROM_HARD_SECTOR, GDROM_DMA_LENGTH_REG); + __raw_writel(1, GDROM_DMA_DIRECTION_REG); + __raw_writel(1, GDROM_DMA_ENABLE_REG); + read_command->cmd[2] = (block >> 16) & 0xFF; + read_command->cmd[3] = (block >> 8) & 0xFF; + read_command->cmd[4] = block & 0xFF; + read_command->cmd[8] = (block_cnt >> 16) & 0xFF; + read_command->cmd[9] = (block_cnt >> 8) & 0xFF; + read_command->cmd[10] = block_cnt & 0xFF; + /* set for DMA */ + __raw_writeb(1, GDROM_ERROR_REG); + /* other registers */ + __raw_writeb(0, GDROM_SECNUM_REG); + __raw_writeb(0, GDROM_BCL_REG); + __raw_writeb(0, GDROM_BCH_REG); + __raw_writeb(0, GDROM_DSEL_REG); + __raw_writeb(0, GDROM_INTSEC_REG); + /* Wait for registers to reset after any previous activity */ + timeout = jiffies + HZ / 2; + while (gdrom_is_busy() && time_before(jiffies, timeout)) + cpu_relax(); + __raw_writeb(GDROM_COM_PACKET, GDROM_STATUSCOMMAND_REG); + timeout = jiffies + HZ / 2; + /* Wait for packet command to finish */ + while (gdrom_is_busy() && time_before(jiffies, timeout)) + cpu_relax(); + gd.pending = 1; + gd.transfer = 1; + outsw(GDROM_DATA_REG, &read_command->cmd, 6); + timeout = jiffies + HZ / 2; + /* Wait for any pending DMA to finish */ + while (__raw_readb(GDROM_DMA_STATUS_REG) && + time_before(jiffies, timeout)) + cpu_relax(); + /* start transfer */ + __raw_writeb(1, GDROM_DMA_STATUS_REG); + wait_event_interruptible_timeout(request_queue, + gd.transfer == 0, GDROM_DEFAULT_TIMEOUT); + err = gd.transfer ? BLK_STS_IOERR : BLK_STS_OK; + gd.transfer = 0; + gd.pending = 0; + + blk_mq_end_request(req, err); kfree(read_command); + return BLK_STS_OK; } -static void gdrom_request(struct request_queue *rq) -{ - struct request *req; - - while ((req = blk_fetch_request(rq)) != NULL) { - switch (req_op(req)) { - case REQ_OP_READ: - /* - * Add to list of deferred work and then schedule - * workqueue. - */ - list_add_tail(&req->queuelist, &gdrom_deferred); - schedule_work(&work); - break; - case REQ_OP_WRITE: - pr_notice("Read only device - write request ignored\n"); - __blk_end_request_all(req, BLK_STS_IOERR); - break; - default: - printk(KERN_DEBUG "gdrom: Non-fs request ignored\n"); - __blk_end_request_all(req, BLK_STS_IOERR); - break; - } +static blk_status_t gdrom_queue_rq(struct blk_mq_hw_ctx *hctx, + const struct blk_mq_queue_data *bd) +{ + blk_mq_start_request(bd->rq); + + switch (req_op(bd->rq)) { + case REQ_OP_READ: + return gdrom_readdisk_dma(bd->rq); + case REQ_OP_WRITE: + pr_notice("Read only device - write request ignored\n"); + return BLK_STS_IOERR; + default: + printk(KERN_DEBUG "gdrom: Non-fs request ignored\n"); + return BLK_STS_IOERR; } } @@ -768,6 +743,10 @@ static int probe_gdrom_setupqueue(void) return gdrom_init_dma_mode(); } +static const struct blk_mq_ops gdrom_mq_ops = { + .queue_rq = gdrom_queue_rq, +}; + /* * register this as a block device and as compliant with the * universal CD Rom driver interface @@ -811,11 +790,23 @@ static int probe_gdrom(struct platform_device *devptr) err = gdrom_set_interrupt_handlers(); if (err) goto probe_fail_cmdirq_register; - gd.gdrom_rq = blk_init_queue(gdrom_request, &gdrom_lock); - if (!gd.gdrom_rq) { - err = -ENOMEM; + + gd.tag_set.ops = &gdrom_mq_ops; + gd.tag_set.nr_hw_queues = 1; + gd.tag_set.queue_depth = 1; + gd.tag_set.numa_node = NUMA_NO_NODE; + gd.tag_set.flags = BLK_MQ_F_SHOULD_MERGE | BLK_MQ_F_BLOCKING; + err = blk_mq_alloc_tag_set(&td.tag_set); + if (err) + goto probe_fail_requestq; + + gd.gdrom_rq = blk_mq_init_queue(set); + if (IS_ERR(gd.gdrom_rq)) { + rc = PTR_ERR(gd.gdrom_rq); + gd.gdrom_rq = NULL; goto probe_fail_requestq; } + blk_queue_bounce_limit(gd.gdrom_rq, BLK_BOUNCE_HIGH); err = probe_gdrom_setupqueue(); @@ -831,6 +822,7 @@ static int probe_gdrom(struct platform_device *devptr) return 0; probe_fail_toc: + blk_mq_free_tag_set(&gd.tag_set); blk_cleanup_queue(gd.gdrom_rq); probe_fail_requestq: free_irq(HW_EVENT_GDROM_DMA, &gd); @@ -849,7 +841,7 @@ static int probe_gdrom(struct platform_device *devptr) static int remove_gdrom(struct platform_device *devptr) { - flush_work(&work); + blk_mq_free_tag_set(&gd.tag_set); blk_cleanup_queue(gd.gdrom_rq); free_irq(HW_EVENT_GDROM_CMD, &gd); free_irq(HW_EVENT_GDROM_DMA, &gd); -- 2.17.1 From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Subject: Re: [PATCH 01/17] sunvdc: convert to blk-mq From: Jens Axboe To: Ming Lei Cc: linux-block@vger.kernel.org, David Miller References: <20181011165909.32615-1-axboe@kernel.dk> <20181011165909.32615-2-axboe@kernel.dk> <20181015103728.GC31722@ming.t460p> Message-ID: <2e9b9df4-944f-aa59-2c68-9cb7b1250cd7@kernel.dk> Date: Mon, 15 Oct 2018 08:50:51 -0600 MIME-Version: 1.0 In-Reply-To: Content-Type: text/plain; charset=utf-8 List-ID: On 10/15/18 8:19 AM, Jens Axboe wrote: > On 10/15/18 4:38 AM, Ming Lei wrote: >>> @@ -320,7 +320,7 @@ static void vdc_end_one(struct vdc_port *port, struct vio_dring_state *dr, >>> >>> rqe->req = NULL; >>> >>> - __blk_end_request(req, (desc->status ? BLK_STS_IOERR : 0), desc->size); >>> + blk_mq_end_request(req, desc->status ? BLK_STS_IOERR : 0); >> >> blk_mq_end_request() may trigger BUG in case of partial completion, >> however looks it is fine for __blk_end_request(). > > True, I'll change this to the blk_update_request() + > __blk_mq_end_request() combo instead. I take that back, it's correct as is. This isn't a partial completion, it's completing the request. The BUG() inside blk_mq_end_request() would indicate a bug in the internal code, we don't expect a not-done return when we ask to complete the whole thing. -- Jens Axboe From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Subject: Re: [PATCH 01/17] sunvdc: convert to blk-mq To: Ming Lei Cc: linux-block@vger.kernel.org, David Miller References: <20181011165909.32615-1-axboe@kernel.dk> <20181011165909.32615-2-axboe@kernel.dk> <20181015103728.GC31722@ming.t460p> From: Jens Axboe Message-ID: Date: Mon, 15 Oct 2018 08:19:02 -0600 MIME-Version: 1.0 In-Reply-To: <20181015103728.GC31722@ming.t460p> Content-Type: text/plain; charset=utf-8 List-ID: On 10/15/18 4:38 AM, Ming Lei wrote: >> @@ -320,7 +320,7 @@ static void vdc_end_one(struct vdc_port *port, struct vio_dring_state *dr, >> >> rqe->req = NULL; >> >> - __blk_end_request(req, (desc->status ? BLK_STS_IOERR : 0), desc->size); >> + blk_mq_end_request(req, desc->status ? BLK_STS_IOERR : 0); > > blk_mq_end_request() may trigger BUG in case of partial completion, > however looks it is fine for __blk_end_request(). True, I'll change this to the blk_update_request() + __blk_mq_end_request() combo instead. > Most of conversions have the above pattern, maybe it is easier to > introduce the following block API: > > struct reuqest_queue *blk_mq_alloc_and_init_sq(set, ops, queue_depth) Yeah I did consider that, I'll make that addition. -- Jens Axboe From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Date: Mon, 15 Oct 2018 18:38:12 +0800 From: Ming Lei To: Jens Axboe Cc: linux-block@vger.kernel.org, David Miller Subject: Re: [PATCH 01/17] sunvdc: convert to blk-mq Message-ID: <20181015103728.GC31722@ming.t460p> References: <20181011165909.32615-1-axboe@kernel.dk> <20181011165909.32615-2-axboe@kernel.dk> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii In-Reply-To: <20181011165909.32615-2-axboe@kernel.dk> List-ID: On Thu, Oct 11, 2018 at 10:58:53AM -0600, Jens Axboe wrote: > Convert from the old request_fn style driver to blk-mq. > > Cc: David Miller > Signed-off-by: Jens Axboe > --- > drivers/block/sunvdc.c | 161 ++++++++++++++++++++++++++++------------- > 1 file changed, 110 insertions(+), 51 deletions(-) > > diff --git a/drivers/block/sunvdc.c b/drivers/block/sunvdc.c > index f68e9baffad7..bf51a2307ce1 100644 > --- a/drivers/block/sunvdc.c > +++ b/drivers/block/sunvdc.c > @@ -6,7 +6,7 @@ > #include > #include > #include > -#include > +#include > #include > #include > #include > @@ -66,9 +66,10 @@ struct vdc_port { > > u64 max_xfer_size; > u32 vdisk_block_size; > + u32 drain; > > u64 ldc_timeout; > - struct timer_list ldc_reset_timer; > + struct delayed_work ldc_reset_timer_work; > struct work_struct ldc_reset_work; > > /* The server fills these in for us in the disk attribute > @@ -80,12 +81,14 @@ struct vdc_port { > u8 vdisk_mtype; > u32 vdisk_phys_blksz; > > + struct blk_mq_tag_set tag_set; > + > char disk_name[32]; > }; > > static void vdc_ldc_reset(struct vdc_port *port); > static void vdc_ldc_reset_work(struct work_struct *work); > -static void vdc_ldc_reset_timer(struct timer_list *t); > +static void vdc_ldc_reset_timer_work(struct work_struct *work); > > static inline struct vdc_port *to_vdc_port(struct vio_driver_state *vio) > { > @@ -175,11 +178,8 @@ static void vdc_blk_queue_start(struct vdc_port *port) > * handshake completes, so check for initial handshake before we've > * allocated a disk. > */ > - if (port->disk && blk_queue_stopped(port->disk->queue) && > - vdc_tx_dring_avail(dr) * 100 / VDC_TX_RING_SIZE >= 50) { > - blk_start_queue(port->disk->queue); > - } > - > + if (port->disk && vdc_tx_dring_avail(dr) * 100 / VDC_TX_RING_SIZE >= 50) > + blk_mq_start_hw_queues(port->disk->queue); > } > > static void vdc_finish(struct vio_driver_state *vio, int err, int waiting_for) > @@ -197,7 +197,7 @@ static void vdc_handshake_complete(struct vio_driver_state *vio) > { > struct vdc_port *port = to_vdc_port(vio); > > - del_timer(&port->ldc_reset_timer); > + cancel_delayed_work(&port->ldc_reset_timer_work); > vdc_finish(vio, 0, WAITING_FOR_LINK_UP); > vdc_blk_queue_start(port); > } > @@ -320,7 +320,7 @@ static void vdc_end_one(struct vdc_port *port, struct vio_dring_state *dr, > > rqe->req = NULL; > > - __blk_end_request(req, (desc->status ? BLK_STS_IOERR : 0), desc->size); > + blk_mq_end_request(req, desc->status ? BLK_STS_IOERR : 0); blk_mq_end_request() may trigger BUG in case of partial completion, however looks it is fine for __blk_end_request(). > > vdc_blk_queue_start(port); > } > @@ -525,29 +525,40 @@ static int __send_request(struct request *req) > return err; > } > > -static void do_vdc_request(struct request_queue *rq) > +static blk_status_t vdc_queue_rq(struct blk_mq_hw_ctx *hctx, > + const struct blk_mq_queue_data *bd) > { > - struct request *req; > + struct vdc_port *port = hctx->queue->queuedata; > + struct vio_dring_state *dr; > + unsigned long flags; > > - while ((req = blk_peek_request(rq)) != NULL) { > - struct vdc_port *port; > - struct vio_dring_state *dr; > + dr = &port->vio.drings[VIO_DRIVER_TX_RING]; > > - port = req->rq_disk->private_data; > - dr = &port->vio.drings[VIO_DRIVER_TX_RING]; > - if (unlikely(vdc_tx_dring_avail(dr) < 1)) > - goto wait; > + blk_mq_start_request(bd->rq); > > - blk_start_request(req); > + spin_lock_irqsave(&port->vio.lock, flags); > > - if (__send_request(req) < 0) { > - blk_requeue_request(rq, req); > -wait: > - /* Avoid pointless unplugs. */ > - blk_stop_queue(rq); > - break; > - } > + /* > + * Doing drain, just end the request in error > + */ > + if (unlikely(port->drain)) { > + spin_unlock_irqrestore(&port->vio.lock, flags); > + return BLK_STS_IOERR; > } > + > + if (unlikely(vdc_tx_dring_avail(dr) < 1)) { > + spin_unlock_irqrestore(&port->vio.lock, flags); > + blk_mq_stop_hw_queue(hctx); > + return BLK_STS_DEV_RESOURCE; > + } > + > + if (__send_request(bd->rq) < 0) { > + spin_unlock_irqrestore(&port->vio.lock, flags); > + return BLK_STS_IOERR; > + } > + > + spin_unlock_irqrestore(&port->vio.lock, flags); > + return BLK_STS_OK; > } > > static int generic_request(struct vdc_port *port, u8 op, void *buf, int len) > @@ -759,6 +770,44 @@ static void vdc_port_down(struct vdc_port *port) > vio_ldc_free(&port->vio); > } > > +static const struct blk_mq_ops vdc_mq_ops = { > + .queue_rq = vdc_queue_rq, > +}; > + > +static void cleanup_queue(struct request_queue *q) > +{ > + struct vdc_port *port = q->queuedata; > + > + blk_mq_free_tag_set(&port->tag_set); > + blk_cleanup_queue(q); blk_mq_free_tag_set() need to be put after blk_cleanup_queue(). > +} > + > +static struct request_queue *init_queue(struct vdc_port *port) > +{ > + struct blk_mq_tag_set *set = &port->tag_set; > + struct request_queue *q; > + int ret; > + > + set->ops = &vdc_mq_ops; > + set->nr_hw_queues = 1; > + set->queue_depth = VDC_TX_RING_SIZE; > + set->numa_node = NUMA_NO_NODE; > + set->flags = BLK_MQ_F_SHOULD_MERGE; > + > + ret = blk_mq_alloc_tag_set(set); > + if (ret) > + return ERR_PTR(ret); > + > + q = blk_mq_init_queue(set); > + if (IS_ERR(q)) { > + blk_mq_free_tag_set(set); > + return q; > + } Most of conversions have the above pattern, maybe it is easier to introduce the following block API: struct reuqest_queue *blk_mq_alloc_and_init_sq(set, ops, queue_depth) -- Ming From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: From: Jens Axboe To: linux-block@vger.kernel.org Cc: Jens Axboe , David Miller Subject: [PATCH 01/17] sunvdc: convert to blk-mq Date: Thu, 11 Oct 2018 10:58:53 -0600 Message-Id: <20181011165909.32615-2-axboe@kernel.dk> In-Reply-To: <20181011165909.32615-1-axboe@kernel.dk> References: <20181011165909.32615-1-axboe@kernel.dk> List-ID: Convert from the old request_fn style driver to blk-mq. Cc: David Miller Signed-off-by: Jens Axboe --- drivers/block/sunvdc.c | 161 ++++++++++++++++++++++++++++------------- 1 file changed, 110 insertions(+), 51 deletions(-) diff --git a/drivers/block/sunvdc.c b/drivers/block/sunvdc.c index f68e9baffad7..bf51a2307ce1 100644 --- a/drivers/block/sunvdc.c +++ b/drivers/block/sunvdc.c @@ -6,7 +6,7 @@ #include #include #include -#include +#include #include #include #include @@ -66,9 +66,10 @@ struct vdc_port { u64 max_xfer_size; u32 vdisk_block_size; + u32 drain; u64 ldc_timeout; - struct timer_list ldc_reset_timer; + struct delayed_work ldc_reset_timer_work; struct work_struct ldc_reset_work; /* The server fills these in for us in the disk attribute @@ -80,12 +81,14 @@ struct vdc_port { u8 vdisk_mtype; u32 vdisk_phys_blksz; + struct blk_mq_tag_set tag_set; + char disk_name[32]; }; static void vdc_ldc_reset(struct vdc_port *port); static void vdc_ldc_reset_work(struct work_struct *work); -static void vdc_ldc_reset_timer(struct timer_list *t); +static void vdc_ldc_reset_timer_work(struct work_struct *work); static inline struct vdc_port *to_vdc_port(struct vio_driver_state *vio) { @@ -175,11 +178,8 @@ static void vdc_blk_queue_start(struct vdc_port *port) * handshake completes, so check for initial handshake before we've * allocated a disk. */ - if (port->disk && blk_queue_stopped(port->disk->queue) && - vdc_tx_dring_avail(dr) * 100 / VDC_TX_RING_SIZE >= 50) { - blk_start_queue(port->disk->queue); - } - + if (port->disk && vdc_tx_dring_avail(dr) * 100 / VDC_TX_RING_SIZE >= 50) + blk_mq_start_hw_queues(port->disk->queue); } static void vdc_finish(struct vio_driver_state *vio, int err, int waiting_for) @@ -197,7 +197,7 @@ static void vdc_handshake_complete(struct vio_driver_state *vio) { struct vdc_port *port = to_vdc_port(vio); - del_timer(&port->ldc_reset_timer); + cancel_delayed_work(&port->ldc_reset_timer_work); vdc_finish(vio, 0, WAITING_FOR_LINK_UP); vdc_blk_queue_start(port); } @@ -320,7 +320,7 @@ static void vdc_end_one(struct vdc_port *port, struct vio_dring_state *dr, rqe->req = NULL; - __blk_end_request(req, (desc->status ? BLK_STS_IOERR : 0), desc->size); + blk_mq_end_request(req, desc->status ? BLK_STS_IOERR : 0); vdc_blk_queue_start(port); } @@ -525,29 +525,40 @@ static int __send_request(struct request *req) return err; } -static void do_vdc_request(struct request_queue *rq) +static blk_status_t vdc_queue_rq(struct blk_mq_hw_ctx *hctx, + const struct blk_mq_queue_data *bd) { - struct request *req; + struct vdc_port *port = hctx->queue->queuedata; + struct vio_dring_state *dr; + unsigned long flags; - while ((req = blk_peek_request(rq)) != NULL) { - struct vdc_port *port; - struct vio_dring_state *dr; + dr = &port->vio.drings[VIO_DRIVER_TX_RING]; - port = req->rq_disk->private_data; - dr = &port->vio.drings[VIO_DRIVER_TX_RING]; - if (unlikely(vdc_tx_dring_avail(dr) < 1)) - goto wait; + blk_mq_start_request(bd->rq); - blk_start_request(req); + spin_lock_irqsave(&port->vio.lock, flags); - if (__send_request(req) < 0) { - blk_requeue_request(rq, req); -wait: - /* Avoid pointless unplugs. */ - blk_stop_queue(rq); - break; - } + /* + * Doing drain, just end the request in error + */ + if (unlikely(port->drain)) { + spin_unlock_irqrestore(&port->vio.lock, flags); + return BLK_STS_IOERR; } + + if (unlikely(vdc_tx_dring_avail(dr) < 1)) { + spin_unlock_irqrestore(&port->vio.lock, flags); + blk_mq_stop_hw_queue(hctx); + return BLK_STS_DEV_RESOURCE; + } + + if (__send_request(bd->rq) < 0) { + spin_unlock_irqrestore(&port->vio.lock, flags); + return BLK_STS_IOERR; + } + + spin_unlock_irqrestore(&port->vio.lock, flags); + return BLK_STS_OK; } static int generic_request(struct vdc_port *port, u8 op, void *buf, int len) @@ -759,6 +770,44 @@ static void vdc_port_down(struct vdc_port *port) vio_ldc_free(&port->vio); } +static const struct blk_mq_ops vdc_mq_ops = { + .queue_rq = vdc_queue_rq, +}; + +static void cleanup_queue(struct request_queue *q) +{ + struct vdc_port *port = q->queuedata; + + blk_mq_free_tag_set(&port->tag_set); + blk_cleanup_queue(q); +} + +static struct request_queue *init_queue(struct vdc_port *port) +{ + struct blk_mq_tag_set *set = &port->tag_set; + struct request_queue *q; + int ret; + + set->ops = &vdc_mq_ops; + set->nr_hw_queues = 1; + set->queue_depth = VDC_TX_RING_SIZE; + set->numa_node = NUMA_NO_NODE; + set->flags = BLK_MQ_F_SHOULD_MERGE; + + ret = blk_mq_alloc_tag_set(set); + if (ret) + return ERR_PTR(ret); + + q = blk_mq_init_queue(set); + if (IS_ERR(q)) { + blk_mq_free_tag_set(set); + return q; + } + + q->queuedata = port; + return q; +} + static int probe_disk(struct vdc_port *port) { struct request_queue *q; @@ -796,17 +845,17 @@ static int probe_disk(struct vdc_port *port) (u64)geom.num_sec); } - q = blk_init_queue(do_vdc_request, &port->vio.lock); - if (!q) { + q = init_queue(port); + if (IS_ERR(q)) { printk(KERN_ERR PFX "%s: Could not allocate queue.\n", port->vio.name); - return -ENOMEM; + return PTR_ERR(q); } g = alloc_disk(1 << PARTITION_SHIFT); if (!g) { printk(KERN_ERR PFX "%s: Could not allocate gendisk.\n", port->vio.name); - blk_cleanup_queue(q); + cleanup_queue(q); return -ENOMEM; } @@ -981,7 +1030,7 @@ static int vdc_port_probe(struct vio_dev *vdev, const struct vio_device_id *id) */ ldc_timeout = mdesc_get_property(hp, vdev->mp, "vdc-timeout", NULL); port->ldc_timeout = ldc_timeout ? *ldc_timeout : 0; - timer_setup(&port->ldc_reset_timer, vdc_ldc_reset_timer, 0); + INIT_DELAYED_WORK(&port->ldc_reset_timer_work, vdc_ldc_reset_timer_work); INIT_WORK(&port->ldc_reset_work, vdc_ldc_reset_work); err = vio_driver_init(&port->vio, vdev, VDEV_DISK, @@ -1034,18 +1083,14 @@ static int vdc_port_remove(struct vio_dev *vdev) struct vdc_port *port = dev_get_drvdata(&vdev->dev); if (port) { - unsigned long flags; - - spin_lock_irqsave(&port->vio.lock, flags); - blk_stop_queue(port->disk->queue); - spin_unlock_irqrestore(&port->vio.lock, flags); + blk_mq_stop_hw_queues(port->disk->queue); flush_work(&port->ldc_reset_work); - del_timer_sync(&port->ldc_reset_timer); + cancel_delayed_work_sync(&port->ldc_reset_timer_work); del_timer_sync(&port->vio.timer); del_gendisk(port->disk); - blk_cleanup_queue(port->disk->queue); + cleanup_queue(port->disk->queue); put_disk(port->disk); port->disk = NULL; @@ -1080,32 +1125,46 @@ static void vdc_requeue_inflight(struct vdc_port *port) } rqe->req = NULL; - blk_requeue_request(port->disk->queue, req); + blk_mq_requeue_request(req, false); } } static void vdc_queue_drain(struct vdc_port *port) { - struct request *req; + struct request_queue *q = port->disk->queue; - while ((req = blk_fetch_request(port->disk->queue)) != NULL) - __blk_end_request_all(req, BLK_STS_IOERR); + /* + * Mark the queue as draining, then freeze/quiesce to ensure + * that all existing requests are seen in ->queue_rq() and killed + */ + port->drain = 1; + spin_unlock_irq(&port->vio.lock); + + blk_mq_freeze_queue(q); + blk_mq_quiesce_queue(q); + + spin_lock_irq(&port->vio.lock); + port->drain = 0; + blk_mq_unquiesce_queue(q); + blk_mq_unfreeze_queue(q); } -static void vdc_ldc_reset_timer(struct timer_list *t) +static void vdc_ldc_reset_timer_work(struct work_struct *work) { - struct vdc_port *port = from_timer(port, t, ldc_reset_timer); - struct vio_driver_state *vio = &port->vio; - unsigned long flags; + struct vdc_port *port; + struct vio_driver_state *vio; - spin_lock_irqsave(&vio->lock, flags); + port = container_of(work, struct vdc_port, ldc_reset_timer_work.work); + vio = &port->vio; + + spin_lock_irq(&vio->lock); if (!(port->vio.hs_state & VIO_HS_COMPLETE)) { pr_warn(PFX "%s ldc down %llu seconds, draining queue\n", port->disk_name, port->ldc_timeout); vdc_queue_drain(port); vdc_blk_queue_start(port); } - spin_unlock_irqrestore(&vio->lock, flags); + spin_unlock_irq(&vio->lock); } static void vdc_ldc_reset_work(struct work_struct *work) @@ -1129,7 +1188,7 @@ static void vdc_ldc_reset(struct vdc_port *port) assert_spin_locked(&port->vio.lock); pr_warn(PFX "%s ldc link reset\n", port->disk_name); - blk_stop_queue(port->disk->queue); + blk_mq_stop_hw_queues(port->disk->queue); vdc_requeue_inflight(port); vdc_port_down(port); @@ -1146,7 +1205,7 @@ static void vdc_ldc_reset(struct vdc_port *port) } if (port->ldc_timeout) - mod_timer(&port->ldc_reset_timer, + mod_delayed_work(system_wq, &port->ldc_reset_timer_work, round_jiffies(jiffies + HZ * port->ldc_timeout)); mod_timer(&port->vio.timer, round_jiffies(jiffies + HZ)); return; -- 2.17.1 From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: From: Jens Axboe To: linux-block@vger.kernel.org Cc: Jens Axboe , David Miller Subject: [PATCH 13/17] ide: convert to blk-mq Date: Thu, 11 Oct 2018 10:59:05 -0600 Message-Id: <20181011165909.32615-14-axboe@kernel.dk> In-Reply-To: <20181011165909.32615-1-axboe@kernel.dk> References: <20181011165909.32615-1-axboe@kernel.dk> List-ID: ide-disk and ide-cd tested as working just fine, ide-tape and ide-floppy haven't. But the latter don't require changes, so they should work without issue. Cc: David Miller Signed-off-by: Jens Axboe --- drivers/ide/ide-atapi.c | 25 ++++-- drivers/ide/ide-cd.c | 175 +++++++++++++++++++++------------------- drivers/ide/ide-disk.c | 8 +- drivers/ide/ide-io.c | 84 ++++++++++--------- drivers/ide/ide-park.c | 2 +- drivers/ide/ide-pm.c | 26 ++---- drivers/ide/ide-probe.c | 43 +++++----- include/linux/ide.h | 8 +- 8 files changed, 194 insertions(+), 177 deletions(-) diff --git a/drivers/ide/ide-atapi.c b/drivers/ide/ide-atapi.c index 8b2b72b93885..d65c3b2ab2b3 100644 --- a/drivers/ide/ide-atapi.c +++ b/drivers/ide/ide-atapi.c @@ -172,8 +172,8 @@ EXPORT_SYMBOL_GPL(ide_create_request_sense_cmd); void ide_prep_sense(ide_drive_t *drive, struct request *rq) { struct request_sense *sense = &drive->sense_data; - struct request *sense_rq = drive->sense_rq; - struct scsi_request *req = scsi_req(sense_rq); + struct request *sense_rq; + struct scsi_request *req; unsigned int cmd_len, sense_len; int err; @@ -196,9 +196,16 @@ void ide_prep_sense(ide_drive_t *drive, struct request *rq) if (ata_sense_request(rq) || drive->sense_rq_armed) return; + sense_rq = drive->sense_rq; + if (!sense_rq) { + sense_rq = blk_mq_alloc_request(drive->queue, REQ_OP_DRV_IN, + BLK_MQ_REQ_RESERVED | BLK_MQ_REQ_NOWAIT); + drive->sense_rq = sense_rq; + } + req = scsi_req(sense_rq); + memset(sense, 0, sizeof(*sense)); - blk_rq_init(rq->q, sense_rq); scsi_req_init(req); err = blk_rq_map_kern(drive->queue, sense_rq, sense, sense_len, @@ -207,6 +214,8 @@ void ide_prep_sense(ide_drive_t *drive, struct request *rq) if (printk_ratelimit()) printk(KERN_WARNING PFX "%s: failed to map sense " "buffer\n", drive->name); + blk_mq_free_request(sense_rq); + drive->sense_rq = NULL; return; } @@ -226,6 +235,8 @@ EXPORT_SYMBOL_GPL(ide_prep_sense); int ide_queue_sense_rq(ide_drive_t *drive, void *special) { + struct request *sense_rq = drive->sense_rq; + /* deferred failure from ide_prep_sense() */ if (!drive->sense_rq_armed) { printk(KERN_WARNING PFX "%s: error queuing a sense request\n", @@ -233,12 +244,12 @@ int ide_queue_sense_rq(ide_drive_t *drive, void *special) return -ENOMEM; } - drive->sense_rq->special = special; + sense_rq->special = special; drive->sense_rq_armed = false; drive->hwif->rq = NULL; - elv_add_request(drive->queue, drive->sense_rq, ELEVATOR_INSERT_FRONT); + blk_mq_sched_insert_request(sense_rq, true, true, true); return 0; } EXPORT_SYMBOL_GPL(ide_queue_sense_rq); @@ -270,10 +281,8 @@ void ide_retry_pc(ide_drive_t *drive) */ drive->hwif->rq = NULL; ide_requeue_and_plug(drive, failed_rq); - if (ide_queue_sense_rq(drive, pc)) { - blk_start_request(failed_rq); + if (ide_queue_sense_rq(drive, pc)) ide_complete_rq(drive, BLK_STS_IOERR, blk_rq_bytes(failed_rq)); - } } EXPORT_SYMBOL_GPL(ide_retry_pc); diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c index 44a7a255ef74..188bcfb07aac 100644 --- a/drivers/ide/ide-cd.c +++ b/drivers/ide/ide-cd.c @@ -258,11 +258,22 @@ static int ide_cd_breathe(ide_drive_t *drive, struct request *rq) /* * take a breather */ - blk_delay_queue(drive->queue, 1); + blk_mq_requeue_request(rq, false); + blk_mq_delay_kick_requeue_list(drive->queue, 1); return 1; } } +static void ide_cd_free_sense(ide_drive_t *drive) +{ + if (!drive->sense_rq) + return; + + blk_mq_free_request(drive->sense_rq); + drive->sense_rq = NULL; + drive->sense_rq_armed = false; +} + /** * Returns: * 0: if the request should be continued. @@ -516,6 +527,82 @@ static bool ide_cd_error_cmd(ide_drive_t *drive, struct ide_cmd *cmd) return false; } +/* standard prep_rq_fn that builds 10 byte cmds */ +static int ide_cdrom_prep_fs(struct request_queue *q, struct request *rq) +{ + int hard_sect = queue_logical_block_size(q); + long block = (long)blk_rq_pos(rq) / (hard_sect >> 9); + unsigned long blocks = blk_rq_sectors(rq) / (hard_sect >> 9); + struct scsi_request *req = scsi_req(rq); + + if (rq_data_dir(rq) == READ) + req->cmd[0] = GPCMD_READ_10; + else + req->cmd[0] = GPCMD_WRITE_10; + + /* + * fill in lba + */ + req->cmd[2] = (block >> 24) & 0xff; + req->cmd[3] = (block >> 16) & 0xff; + req->cmd[4] = (block >> 8) & 0xff; + req->cmd[5] = block & 0xff; + + /* + * and transfer length + */ + req->cmd[7] = (blocks >> 8) & 0xff; + req->cmd[8] = blocks & 0xff; + req->cmd_len = 10; + return BLKPREP_OK; +} + +/* + * Most of the SCSI commands are supported directly by ATAPI devices. + * This transform handles the few exceptions. + */ +static int ide_cdrom_prep_pc(struct request *rq) +{ + u8 *c = scsi_req(rq)->cmd; + + /* transform 6-byte read/write commands to the 10-byte version */ + if (c[0] == READ_6 || c[0] == WRITE_6) { + c[8] = c[4]; + c[5] = c[3]; + c[4] = c[2]; + c[3] = c[1] & 0x1f; + c[2] = 0; + c[1] &= 0xe0; + c[0] += (READ_10 - READ_6); + scsi_req(rq)->cmd_len = 10; + return BLKPREP_OK; + } + + /* + * it's silly to pretend we understand 6-byte sense commands, just + * reject with ILLEGAL_REQUEST and the caller should take the + * appropriate action + */ + if (c[0] == MODE_SENSE || c[0] == MODE_SELECT) { + scsi_req(rq)->result = ILLEGAL_REQUEST; + return BLKPREP_KILL; + } + + return BLKPREP_OK; +} + +static int ide_cdrom_prep_fn(ide_drive_t *drive, struct request *rq) +{ + if (!blk_rq_is_passthrough(rq)) { + scsi_req_init(scsi_req(rq)); + + return ide_cdrom_prep_fs(drive->queue, rq); + } else if (blk_rq_is_scsi(rq)) + return ide_cdrom_prep_pc(rq); + + return 0; +} + static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive) { ide_hwif_t *hwif = drive->hwif; @@ -675,7 +762,7 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive) out_end: if (blk_rq_is_scsi(rq) && rc == 0) { scsi_req(rq)->resid_len = 0; - blk_end_request_all(rq, BLK_STS_OK); + blk_mq_end_request(rq, BLK_STS_OK); hwif->rq = NULL; } else { if (sense && uptodate) @@ -705,6 +792,8 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive) if (sense && rc == 2) ide_error(drive, "request sense failure", stat); } + + ide_cd_free_sense(drive); return ide_stopped; } @@ -729,7 +818,7 @@ static ide_startstop_t cdrom_start_rw(ide_drive_t *drive, struct request *rq) * We may be retrying this request after an error. Fix up any * weirdness which might be present in the request packet. */ - q->prep_rq_fn(q, rq); + ide_cdrom_prep_fn(drive, rq); } /* fs requests *must* be hardware frame aligned */ @@ -1323,82 +1412,6 @@ static int ide_cdrom_probe_capabilities(ide_drive_t *drive) return nslots; } -/* standard prep_rq_fn that builds 10 byte cmds */ -static int ide_cdrom_prep_fs(struct request_queue *q, struct request *rq) -{ - int hard_sect = queue_logical_block_size(q); - long block = (long)blk_rq_pos(rq) / (hard_sect >> 9); - unsigned long blocks = blk_rq_sectors(rq) / (hard_sect >> 9); - struct scsi_request *req = scsi_req(rq); - - q->initialize_rq_fn(rq); - - if (rq_data_dir(rq) == READ) - req->cmd[0] = GPCMD_READ_10; - else - req->cmd[0] = GPCMD_WRITE_10; - - /* - * fill in lba - */ - req->cmd[2] = (block >> 24) & 0xff; - req->cmd[3] = (block >> 16) & 0xff; - req->cmd[4] = (block >> 8) & 0xff; - req->cmd[5] = block & 0xff; - - /* - * and transfer length - */ - req->cmd[7] = (blocks >> 8) & 0xff; - req->cmd[8] = blocks & 0xff; - req->cmd_len = 10; - return BLKPREP_OK; -} - -/* - * Most of the SCSI commands are supported directly by ATAPI devices. - * This transform handles the few exceptions. - */ -static int ide_cdrom_prep_pc(struct request *rq) -{ - u8 *c = scsi_req(rq)->cmd; - - /* transform 6-byte read/write commands to the 10-byte version */ - if (c[0] == READ_6 || c[0] == WRITE_6) { - c[8] = c[4]; - c[5] = c[3]; - c[4] = c[2]; - c[3] = c[1] & 0x1f; - c[2] = 0; - c[1] &= 0xe0; - c[0] += (READ_10 - READ_6); - scsi_req(rq)->cmd_len = 10; - return BLKPREP_OK; - } - - /* - * it's silly to pretend we understand 6-byte sense commands, just - * reject with ILLEGAL_REQUEST and the caller should take the - * appropriate action - */ - if (c[0] == MODE_SENSE || c[0] == MODE_SELECT) { - scsi_req(rq)->result = ILLEGAL_REQUEST; - return BLKPREP_KILL; - } - - return BLKPREP_OK; -} - -static int ide_cdrom_prep_fn(struct request_queue *q, struct request *rq) -{ - if (!blk_rq_is_passthrough(rq)) - return ide_cdrom_prep_fs(q, rq); - else if (blk_rq_is_scsi(rq)) - return ide_cdrom_prep_pc(rq); - - return 0; -} - struct cd_list_entry { const char *id_model; const char *id_firmware; @@ -1508,7 +1521,7 @@ static int ide_cdrom_setup(ide_drive_t *drive) ide_debug_log(IDE_DBG_PROBE, "enter"); - blk_queue_prep_rq(q, ide_cdrom_prep_fn); + drive->prep_rq = ide_cdrom_prep_fn; blk_queue_dma_alignment(q, 31); blk_queue_update_dma_pad(q, 15); @@ -1569,7 +1582,7 @@ static void ide_cd_release(struct device *dev) if (devinfo->handle == drive) unregister_cdrom(devinfo); drive->driver_data = NULL; - blk_queue_prep_rq(drive->queue, NULL); + drive->prep_rq = NULL; g->private_data = NULL; put_disk(g); kfree(info); diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c index e3b4e659082d..b14a1446586d 100644 --- a/drivers/ide/ide-disk.c +++ b/drivers/ide/ide-disk.c @@ -187,6 +187,9 @@ static ide_startstop_t ide_do_rw_disk(ide_drive_t *drive, struct request *rq, BUG_ON(drive->dev_flags & IDE_DFLAG_BLOCKED); BUG_ON(blk_rq_is_passthrough(rq)); + if (drive->queue->prep_rq_fn && drive->queue->prep_rq_fn(drive->queue, rq)) + return ide_stopped; + ledtrig_disk_activity(rq_data_dir(rq) == WRITE); pr_debug("%s: %sing: block=%llu, sectors=%u\n", @@ -427,9 +430,8 @@ static void ide_disk_unlock_native_capacity(ide_drive_t *drive) drive->dev_flags |= IDE_DFLAG_NOHPA; /* disable HPA on resume */ } -static int idedisk_prep_fn(struct request_queue *q, struct request *rq) +static int idedisk_prep_fn(ide_drive_t *drive, struct request *rq) { - ide_drive_t *drive = q->queuedata; struct ide_cmd *cmd; if (req_op(rq) != REQ_OP_FLUSH) @@ -548,7 +550,7 @@ static void update_flush(ide_drive_t *drive) if (barrier) { wc = true; - blk_queue_prep_rq(drive->queue, idedisk_prep_fn); + drive->prep_rq = idedisk_prep_fn; } } diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c index 0d93e0cfbeaf..b583eeac7864 100644 --- a/drivers/ide/ide-io.c +++ b/drivers/ide/ide-io.c @@ -67,7 +67,15 @@ int ide_end_rq(ide_drive_t *drive, struct request *rq, blk_status_t error, ide_dma_on(drive); } - return blk_end_request(rq, error, nr_bytes); + if (!blk_update_request(rq, error, nr_bytes)) { + if (rq == drive->sense_rq) + drive->sense_rq = NULL; + + __blk_mq_end_request(rq, error); + return 0; + } + + return 1; } EXPORT_SYMBOL_GPL(ide_end_rq); @@ -307,8 +315,6 @@ static ide_startstop_t start_request (ide_drive_t *drive, struct request *rq) { ide_startstop_t startstop; - BUG_ON(!(rq->rq_flags & RQF_STARTED)); - #ifdef DEBUG printk("%s: start_request: current=0x%08lx\n", drive->hwif->name, (unsigned long) rq); @@ -320,6 +326,9 @@ static ide_startstop_t start_request (ide_drive_t *drive, struct request *rq) goto kill_rq; } + if (drive->prep_rq && drive->prep_rq(drive, rq)) + return ide_stopped; + if (ata_pm_request(rq)) ide_check_pm_state(drive, rq); @@ -430,44 +439,38 @@ static inline void ide_unlock_host(struct ide_host *host) } } -static void __ide_requeue_and_plug(struct request_queue *q, struct request *rq) -{ - if (rq) - blk_requeue_request(q, rq); - if (rq || blk_peek_request(q)) { - /* Use 3ms as that was the old plug delay */ - blk_delay_queue(q, 3); - } -} - void ide_requeue_and_plug(ide_drive_t *drive, struct request *rq) { struct request_queue *q = drive->queue; - unsigned long flags; - spin_lock_irqsave(q->queue_lock, flags); - __ide_requeue_and_plug(q, rq); - spin_unlock_irqrestore(q->queue_lock, flags); + /* Use 3ms as that was the old plug delay */ + if (rq) { + blk_mq_requeue_request(rq, false); + blk_mq_delay_kick_requeue_list(q, 3); + } else + blk_mq_delay_run_hw_queue(q->queue_hw_ctx[0], 3); } /* * Issue a new request to a device. */ -void do_ide_request(struct request_queue *q) +blk_status_t ide_queue_rq(struct blk_mq_hw_ctx *hctx, + const struct blk_mq_queue_data *bd) { - ide_drive_t *drive = q->queuedata; + ide_drive_t *drive = hctx->queue->queuedata; ide_hwif_t *hwif = drive->hwif; struct ide_host *host = hwif->host; struct request *rq = NULL; ide_startstop_t startstop; - spin_unlock_irq(q->queue_lock); - /* HLD do_request() callback might sleep, make sure it's okay */ might_sleep(); if (ide_lock_host(host, hwif)) - goto plug_device_2; + return BLK_STS_DEV_RESOURCE; + + rq = bd->rq; + blk_mq_start_request(rq); spin_lock_irq(&hwif->lock); @@ -503,21 +506,16 @@ void do_ide_request(struct request_queue *q) hwif->cur_dev = drive; drive->dev_flags &= ~(IDE_DFLAG_SLEEPING | IDE_DFLAG_PARKED); - spin_unlock_irq(&hwif->lock); - spin_lock_irq(q->queue_lock); /* * we know that the queue isn't empty, but this can happen * if the q->prep_rq_fn() decides to kill a request */ - if (!rq) - rq = blk_fetch_request(drive->queue); - - spin_unlock_irq(q->queue_lock); - spin_lock_irq(&hwif->lock); - if (!rq) { - ide_unlock_port(hwif); - goto out; + rq = bd->rq; + if (!rq) { + ide_unlock_port(hwif); + goto out; + } } /* @@ -553,21 +551,19 @@ void do_ide_request(struct request_queue *q) hwif->rq = NULL; goto repeat; } - } else - goto plug_device; + } else { +plug_device: + spin_unlock_irq(&hwif->lock); + ide_unlock_host(host); + ide_requeue_and_plug(drive, rq); + return BLK_STS_OK; + } + out: spin_unlock_irq(&hwif->lock); if (rq == NULL) ide_unlock_host(host); - spin_lock_irq(q->queue_lock); - return; - -plug_device: - spin_unlock_irq(&hwif->lock); - ide_unlock_host(host); -plug_device_2: - spin_lock_irq(q->queue_lock); - __ide_requeue_and_plug(q, rq); + return BLK_STS_OK; } static int drive_is_ready(ide_drive_t *drive) @@ -617,6 +613,8 @@ void ide_timer_expiry (struct timer_list *t) int plug_device = 0; struct request *uninitialized_var(rq_in_flight); + return; + spin_lock_irqsave(&hwif->lock, flags); handler = hwif->handler; diff --git a/drivers/ide/ide-park.c b/drivers/ide/ide-park.c index 622f0edb3945..45f989792633 100644 --- a/drivers/ide/ide-park.c +++ b/drivers/ide/ide-park.c @@ -54,7 +54,7 @@ static void issue_park_cmd(ide_drive_t *drive, unsigned long timeout) scsi_req(rq)->cmd[0] = REQ_UNPARK_HEADS; scsi_req(rq)->cmd_len = 1; ide_req(rq)->type = ATA_PRIV_MISC; - elv_add_request(q, rq, ELEVATOR_INSERT_FRONT); + blk_mq_sched_insert_request(rq, true, true, true); out: return; diff --git a/drivers/ide/ide-pm.c b/drivers/ide/ide-pm.c index 59217aa1d1fb..cca47adda527 100644 --- a/drivers/ide/ide-pm.c +++ b/drivers/ide/ide-pm.c @@ -40,32 +40,20 @@ int generic_ide_suspend(struct device *dev, pm_message_t mesg) return ret; } -static void ide_end_sync_rq(struct request *rq, blk_status_t error) -{ - complete(rq->end_io_data); -} - static int ide_pm_execute_rq(struct request *rq) { struct request_queue *q = rq->q; - DECLARE_COMPLETION_ONSTACK(wait); - - rq->end_io_data = &wait; - rq->end_io = ide_end_sync_rq; spin_lock_irq(q->queue_lock); if (unlikely(blk_queue_dying(q))) { rq->rq_flags |= RQF_QUIET; scsi_req(rq)->result = -ENXIO; - __blk_end_request_all(rq, BLK_STS_OK); spin_unlock_irq(q->queue_lock); + blk_mq_end_request(rq, BLK_STS_OK); return -ENXIO; } - __elv_add_request(q, rq, ELEVATOR_INSERT_FRONT); - __blk_run_queue_uncond(q); spin_unlock_irq(q->queue_lock); - - wait_for_completion_io(&wait); + blk_execute_rq(q, NULL, rq, true); return scsi_req(rq)->result ? -EIO : 0; } @@ -226,15 +214,14 @@ void ide_complete_pm_rq(ide_drive_t *drive, struct request *rq) #endif spin_lock_irqsave(q->queue_lock, flags); if (ide_req(rq)->type == ATA_PRIV_PM_SUSPEND) - blk_stop_queue(q); + blk_mq_stop_hw_queues(q); else drive->dev_flags &= ~IDE_DFLAG_BLOCKED; spin_unlock_irqrestore(q->queue_lock, flags); drive->hwif->rq = NULL; - if (blk_end_request(rq, BLK_STS_OK, 0)) - BUG(); + blk_mq_end_request(rq, BLK_STS_OK); } void ide_check_pm_state(ide_drive_t *drive, struct request *rq) @@ -260,7 +247,6 @@ void ide_check_pm_state(ide_drive_t *drive, struct request *rq) ide_hwif_t *hwif = drive->hwif; const struct ide_tp_ops *tp_ops = hwif->tp_ops; struct request_queue *q = drive->queue; - unsigned long flags; int rc; #ifdef DEBUG_PM printk("%s: Wakeup request inited, waiting for !BSY...\n", drive->name); @@ -274,8 +260,6 @@ void ide_check_pm_state(ide_drive_t *drive, struct request *rq) if (rc) printk(KERN_WARNING "%s: drive not ready on wakeup\n", drive->name); - spin_lock_irqsave(q->queue_lock, flags); - blk_start_queue(q); - spin_unlock_irqrestore(q->queue_lock, flags); + blk_mq_start_hw_queues(q); } } diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c index 3b75a7b7a284..31ed4ab90fff 100644 --- a/drivers/ide/ide-probe.c +++ b/drivers/ide/ide-probe.c @@ -750,6 +750,11 @@ static void ide_initialize_rq(struct request *rq) req->sreq.sense = req->sense; } +static const struct blk_mq_ops ide_mq_ops = { + .queue_rq = ide_queue_rq, + .initialize_rq_fn = ide_initialize_rq, +}; + /* * init request queue */ @@ -759,6 +764,7 @@ static int ide_init_queue(ide_drive_t *drive) ide_hwif_t *hwif = drive->hwif; int max_sectors = 256; int max_sg_entries = PRD_ENTRIES; + struct blk_mq_tag_set *set; /* * Our default set up assumes the normal IDE case, @@ -767,19 +773,26 @@ static int ide_init_queue(ide_drive_t *drive) * limits and LBA48 we could raise it but as yet * do not. */ - q = blk_alloc_queue_node(GFP_KERNEL, hwif_to_node(hwif), NULL); - if (!q) + + set = &drive->tag_set; + set->ops = &ide_mq_ops; + set->nr_hw_queues = 1; + set->queue_depth = 32; + set->reserved_tags = 1; + set->cmd_size = sizeof(struct ide_request); + set->numa_node = hwif_to_node(hwif); + set->flags = BLK_MQ_F_SHOULD_MERGE | BLK_MQ_F_BLOCKING; + if (blk_mq_alloc_tag_set(set)) return 1; - q->request_fn = do_ide_request; - q->initialize_rq_fn = ide_initialize_rq; - q->cmd_size = sizeof(struct ide_request); - blk_queue_flag_set(QUEUE_FLAG_SCSI_PASSTHROUGH, q); - if (blk_init_allocated_queue(q) < 0) { - blk_cleanup_queue(q); + q = blk_mq_init_queue(set); + if (IS_ERR(q)) { + blk_mq_free_tag_set(set); return 1; } + blk_queue_flag_set(QUEUE_FLAG_SCSI_PASSTHROUGH, q); + q->queuedata = drive; blk_queue_segment_boundary(q, 0xffff); @@ -965,6 +978,10 @@ static void drive_release_dev (struct device *dev) ide_proc_unregister_device(drive); + if (drive->sense_rq) + blk_mq_free_request(drive->sense_rq); + + blk_mq_free_tag_set(&drive->tag_set); blk_cleanup_queue(drive->queue); drive->queue = NULL; @@ -1145,12 +1162,10 @@ static void ide_port_init_devices_data(ide_hwif_t *hwif) ide_port_for_each_dev(i, drive, hwif) { u8 j = (hwif->index * MAX_DRIVES) + i; u16 *saved_id = drive->id; - struct request *saved_sense_rq = drive->sense_rq; memset(drive, 0, sizeof(*drive)); memset(saved_id, 0, SECTOR_SIZE); drive->id = saved_id; - drive->sense_rq = saved_sense_rq; drive->media = ide_disk; drive->select = (i << 4) | ATA_DEVICE_OBS; @@ -1255,7 +1270,6 @@ static void ide_port_free_devices(ide_hwif_t *hwif) int i; ide_port_for_each_dev(i, drive, hwif) { - kfree(drive->sense_rq); kfree(drive->id); kfree(drive); } @@ -1283,17 +1297,10 @@ static int ide_port_alloc_devices(ide_hwif_t *hwif, int node) if (drive->id == NULL) goto out_free_drive; - drive->sense_rq = kmalloc(sizeof(struct request) + - sizeof(struct ide_request), GFP_KERNEL); - if (!drive->sense_rq) - goto out_free_id; - hwif->devices[i] = drive; } return 0; -out_free_id: - kfree(drive->id); out_free_drive: kfree(drive); out_nomem: diff --git a/include/linux/ide.h b/include/linux/ide.h index c74b0321922a..3e55c362ab7e 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h @@ -10,7 +10,7 @@ #include #include #include -#include +#include #include #include #include @@ -529,6 +529,10 @@ struct ide_drive_s { struct request_queue *queue; /* request queue */ + int (*prep_rq)(struct ide_drive_s *, struct request *); + + struct blk_mq_tag_set tag_set; + struct request *rq; /* current request */ void *driver_data; /* extra driver data */ u16 *id; /* identification info */ @@ -1208,7 +1212,7 @@ extern void ide_stall_queue(ide_drive_t *drive, unsigned long timeout); extern void ide_timer_expiry(struct timer_list *t); extern irqreturn_t ide_intr(int irq, void *dev_id); -extern void do_ide_request(struct request_queue *); +extern blk_status_t ide_queue_rq(struct blk_mq_hw_ctx *, const struct blk_mq_queue_data *); extern void ide_requeue_and_plug(ide_drive_t *drive, struct request *rq); void ide_init_disk(struct gendisk *, ide_drive_t *); -- 2.17.1 From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Return-Path: michal.simek@xilinx.com Subject: Re: [PATCH 15/17] xsysace: convert to blk-mq To: Jens Axboe , CC: Michal Simek References: <20181011165909.32615-1-axboe@kernel.dk> <20181011165909.32615-16-axboe@kernel.dk> From: Michal Simek Message-ID: <0f7caa33-46d4-c727-7bbf-59d27cd7d373@xilinx.com> Date: Fri, 12 Oct 2018 07:46:16 +0200 MIME-Version: 1.0 In-Reply-To: <20181011165909.32615-16-axboe@kernel.dk> Content-Type: text/plain; charset="utf-8" List-ID: On 11.10.2018 18:59, Jens Axboe wrote: > Straight forward conversion, using an internal list to enable the > driver to pull requests at will. > > Cc: Michal Simek > Signed-off-by: Jens Axboe > --- > drivers/block/xsysace.c | 91 ++++++++++++++++++++++++++++++----------- > 1 file changed, 66 insertions(+), 25 deletions(-) > > diff --git a/drivers/block/xsysace.c b/drivers/block/xsysace.c > index c24589414c75..ddaa362ffe82 100644 > --- a/drivers/block/xsysace.c > +++ b/drivers/block/xsysace.c > @@ -88,7 +88,7 @@ > #include > #include > #include > -#include > +#include > #include > #include > #include > @@ -209,6 +209,8 @@ struct ace_device { > struct device *dev; > struct request_queue *queue; > struct gendisk *gd; > + struct blk_mq_tag_set tag_set; > + struct list_head rq_list; > > /* Inserted CF card parameters */ > u16 cf_id[ATA_ID_WORDS]; > @@ -462,18 +464,26 @@ static inline void ace_fsm_yieldirq(struct ace_device *ace) > ace->fsm_continue_flag = 0; > } > > +static bool ace_has_next_request(struct request_queue *q) > +{ > + struct ace_device *ace = q->queuedata; > + > + return !list_empty(&ace->rq_list); > +} > + > /* Get the next read/write request; ending requests that we don't handle */ > static struct request *ace_get_next_request(struct request_queue *q) > { > - struct request *req; > + struct ace_device *ace = q->queuedata; > + struct request *rq; > > - while ((req = blk_peek_request(q)) != NULL) { > - if (!blk_rq_is_passthrough(req)) > - break; > - blk_start_request(req); > - __blk_end_request_all(req, BLK_STS_IOERR); > + rq = list_first_entry_or_null(&ace->rq_list, struct request, queuelist); > + if (rq) { > + list_del_init(&rq->queuelist); > + blk_mq_start_request(rq); > } > - return req; > + > + return NULL; > } > > static void ace_fsm_dostate(struct ace_device *ace) > @@ -499,11 +509,11 @@ static void ace_fsm_dostate(struct ace_device *ace) > > /* Drop all in-flight and pending requests */ > if (ace->req) { > - __blk_end_request_all(ace->req, BLK_STS_IOERR); > + blk_mq_end_request(ace->req, BLK_STS_IOERR); > ace->req = NULL; > } > - while ((req = blk_fetch_request(ace->queue)) != NULL) > - __blk_end_request_all(req, BLK_STS_IOERR); > + while ((req = ace_get_next_request(ace->queue)) != NULL) > + blk_mq_end_request(req, BLK_STS_IOERR); > > /* Drop back to IDLE state and notify waiters */ > ace->fsm_state = ACE_FSM_STATE_IDLE; > @@ -517,7 +527,7 @@ static void ace_fsm_dostate(struct ace_device *ace) > switch (ace->fsm_state) { > case ACE_FSM_STATE_IDLE: > /* See if there is anything to do */ > - if (ace->id_req_count || ace_get_next_request(ace->queue)) { > + if (ace->id_req_count || ace_has_next_request(ace->queue)) { > ace->fsm_iter_num++; > ace->fsm_state = ACE_FSM_STATE_REQ_LOCK; > mod_timer(&ace->stall_timer, jiffies + HZ); > @@ -651,7 +661,6 @@ static void ace_fsm_dostate(struct ace_device *ace) > ace->fsm_state = ACE_FSM_STATE_IDLE; > break; > } > - blk_start_request(req); > > /* Okay, it's a data request, set it up for transfer */ > dev_dbg(ace->dev, > @@ -728,7 +737,8 @@ static void ace_fsm_dostate(struct ace_device *ace) > } > > /* bio finished; is there another one? */ > - if (__blk_end_request_cur(ace->req, BLK_STS_OK)) { > + if (blk_update_request(ace->req, BLK_STS_OK, > + blk_rq_cur_bytes(ace->req))) { > /* dev_dbg(ace->dev, "next block; h=%u c=%u\n", > * blk_rq_sectors(ace->req), > * blk_rq_cur_sectors(ace->req)); > @@ -854,17 +864,23 @@ static irqreturn_t ace_interrupt(int irq, void *dev_id) > /* --------------------------------------------------------------------- > * Block ops > */ > -static void ace_request(struct request_queue * q) > +static blk_status_t ace_queue_rq(struct blk_mq_hw_ctx *hctx, > + const struct blk_mq_queue_data *bd) > { > - struct request *req; > - struct ace_device *ace; > + struct ace_device *ace = hctx->queue->queuedata; > + struct request *req = bd->rq; > > - req = ace_get_next_request(q); > - > - if (req) { > - ace = req->rq_disk->private_data; > - tasklet_schedule(&ace->fsm_tasklet); > + if (blk_rq_is_passthrough(req)) { > + blk_mq_start_request(req); > + return BLK_STS_IOERR; > } > + > + spin_lock_irq(&ace->lock); > + list_add_tail(&req->queuelist, &ace->rq_list); > + spin_unlock_irq(&ace->lock); > + > + tasklet_schedule(&ace->fsm_tasklet); > + return BLK_STS_OK; > } > > static unsigned int ace_check_events(struct gendisk *gd, unsigned int clearing) > @@ -957,11 +973,16 @@ static const struct block_device_operations ace_fops = { > .getgeo = ace_getgeo, > }; > > +static const struct blk_mq_ops ace_mq_ops = { > + .queue_rq = ace_queue_rq, > +}; > + > /* -------------------------------------------------------------------- > * SystemACE device setup/teardown code > */ > static int ace_setup(struct ace_device *ace) > { > + struct blk_mq_tag_set *set; > u16 version; > u16 val; > int rc; > @@ -972,6 +993,7 @@ static int ace_setup(struct ace_device *ace) > > spin_lock_init(&ace->lock); > init_completion(&ace->id_completion); > + INIT_LIST_HEAD(&ace->rq_list); > > /* > * Map the device > @@ -989,9 +1011,25 @@ static int ace_setup(struct ace_device *ace) > /* > * Initialize the request queue > */ > - ace->queue = blk_init_queue(ace_request, &ace->lock); > - if (ace->queue == NULL) > + set = &ace->tag_set; > + set->ops = &ace_mq_ops; > + set->nr_hw_queues = 1; > + set->queue_depth = 2; > + set->numa_node = NUMA_NO_NODE; > + set->flags = BLK_MQ_F_SHOULD_MERGE; > + rc = blk_mq_alloc_tag_set(set); > + if (rc) > goto err_blk_initq; > + > + ace->queue = blk_mq_init_queue(set); > + if (IS_ERR(ace->queue)) { > + rc = PTR_ERR(ace->queue); > + ace->queue = NULL; > + blk_mq_free_tag_set(&ace->tag_set); > + goto err_blk_initq; > + } > + ace->queue->queuedata = ace; > + > blk_queue_logical_block_size(ace->queue, 512); > blk_queue_bounce_limit(ace->queue, BLK_BOUNCE_HIGH); > > @@ -1065,6 +1103,7 @@ static int ace_setup(struct ace_device *ace) > err_read: > put_disk(ace->gd); > err_alloc_disk: > + blk_mq_free_tag_set(&ace->tag_set); > blk_cleanup_queue(ace->queue); > err_blk_initq: > iounmap(ace->baseaddr); > @@ -1081,8 +1120,10 @@ static void ace_teardown(struct ace_device *ace) > put_disk(ace->gd); > } > > - if (ace->queue) > + if (ace->queue) { > + blk_mq_free_tag_set(&ace->tag_set); > blk_cleanup_queue(ace->queue); > + } > > tasklet_kill(&ace->fsm_tasklet); > > None is testing this driver anymore that's why feel free to do this change and if there is any issue this patch can be reverted back. That's why Acked-by: Michal Simek Thanks, Michal From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: From: Jens Axboe To: linux-block@vger.kernel.org Cc: Jens Axboe , Michal Simek Subject: [PATCH 15/17] xsysace: convert to blk-mq Date: Thu, 11 Oct 2018 10:59:07 -0600 Message-Id: <20181011165909.32615-16-axboe@kernel.dk> In-Reply-To: <20181011165909.32615-1-axboe@kernel.dk> References: <20181011165909.32615-1-axboe@kernel.dk> List-ID: Straight forward conversion, using an internal list to enable the driver to pull requests at will. Cc: Michal Simek Signed-off-by: Jens Axboe --- drivers/block/xsysace.c | 91 ++++++++++++++++++++++++++++++----------- 1 file changed, 66 insertions(+), 25 deletions(-) diff --git a/drivers/block/xsysace.c b/drivers/block/xsysace.c index c24589414c75..ddaa362ffe82 100644 --- a/drivers/block/xsysace.c +++ b/drivers/block/xsysace.c @@ -88,7 +88,7 @@ #include #include #include -#include +#include #include #include #include @@ -209,6 +209,8 @@ struct ace_device { struct device *dev; struct request_queue *queue; struct gendisk *gd; + struct blk_mq_tag_set tag_set; + struct list_head rq_list; /* Inserted CF card parameters */ u16 cf_id[ATA_ID_WORDS]; @@ -462,18 +464,26 @@ static inline void ace_fsm_yieldirq(struct ace_device *ace) ace->fsm_continue_flag = 0; } +static bool ace_has_next_request(struct request_queue *q) +{ + struct ace_device *ace = q->queuedata; + + return !list_empty(&ace->rq_list); +} + /* Get the next read/write request; ending requests that we don't handle */ static struct request *ace_get_next_request(struct request_queue *q) { - struct request *req; + struct ace_device *ace = q->queuedata; + struct request *rq; - while ((req = blk_peek_request(q)) != NULL) { - if (!blk_rq_is_passthrough(req)) - break; - blk_start_request(req); - __blk_end_request_all(req, BLK_STS_IOERR); + rq = list_first_entry_or_null(&ace->rq_list, struct request, queuelist); + if (rq) { + list_del_init(&rq->queuelist); + blk_mq_start_request(rq); } - return req; + + return NULL; } static void ace_fsm_dostate(struct ace_device *ace) @@ -499,11 +509,11 @@ static void ace_fsm_dostate(struct ace_device *ace) /* Drop all in-flight and pending requests */ if (ace->req) { - __blk_end_request_all(ace->req, BLK_STS_IOERR); + blk_mq_end_request(ace->req, BLK_STS_IOERR); ace->req = NULL; } - while ((req = blk_fetch_request(ace->queue)) != NULL) - __blk_end_request_all(req, BLK_STS_IOERR); + while ((req = ace_get_next_request(ace->queue)) != NULL) + blk_mq_end_request(req, BLK_STS_IOERR); /* Drop back to IDLE state and notify waiters */ ace->fsm_state = ACE_FSM_STATE_IDLE; @@ -517,7 +527,7 @@ static void ace_fsm_dostate(struct ace_device *ace) switch (ace->fsm_state) { case ACE_FSM_STATE_IDLE: /* See if there is anything to do */ - if (ace->id_req_count || ace_get_next_request(ace->queue)) { + if (ace->id_req_count || ace_has_next_request(ace->queue)) { ace->fsm_iter_num++; ace->fsm_state = ACE_FSM_STATE_REQ_LOCK; mod_timer(&ace->stall_timer, jiffies + HZ); @@ -651,7 +661,6 @@ static void ace_fsm_dostate(struct ace_device *ace) ace->fsm_state = ACE_FSM_STATE_IDLE; break; } - blk_start_request(req); /* Okay, it's a data request, set it up for transfer */ dev_dbg(ace->dev, @@ -728,7 +737,8 @@ static void ace_fsm_dostate(struct ace_device *ace) } /* bio finished; is there another one? */ - if (__blk_end_request_cur(ace->req, BLK_STS_OK)) { + if (blk_update_request(ace->req, BLK_STS_OK, + blk_rq_cur_bytes(ace->req))) { /* dev_dbg(ace->dev, "next block; h=%u c=%u\n", * blk_rq_sectors(ace->req), * blk_rq_cur_sectors(ace->req)); @@ -854,17 +864,23 @@ static irqreturn_t ace_interrupt(int irq, void *dev_id) /* --------------------------------------------------------------------- * Block ops */ -static void ace_request(struct request_queue * q) +static blk_status_t ace_queue_rq(struct blk_mq_hw_ctx *hctx, + const struct blk_mq_queue_data *bd) { - struct request *req; - struct ace_device *ace; + struct ace_device *ace = hctx->queue->queuedata; + struct request *req = bd->rq; - req = ace_get_next_request(q); - - if (req) { - ace = req->rq_disk->private_data; - tasklet_schedule(&ace->fsm_tasklet); + if (blk_rq_is_passthrough(req)) { + blk_mq_start_request(req); + return BLK_STS_IOERR; } + + spin_lock_irq(&ace->lock); + list_add_tail(&req->queuelist, &ace->rq_list); + spin_unlock_irq(&ace->lock); + + tasklet_schedule(&ace->fsm_tasklet); + return BLK_STS_OK; } static unsigned int ace_check_events(struct gendisk *gd, unsigned int clearing) @@ -957,11 +973,16 @@ static const struct block_device_operations ace_fops = { .getgeo = ace_getgeo, }; +static const struct blk_mq_ops ace_mq_ops = { + .queue_rq = ace_queue_rq, +}; + /* -------------------------------------------------------------------- * SystemACE device setup/teardown code */ static int ace_setup(struct ace_device *ace) { + struct blk_mq_tag_set *set; u16 version; u16 val; int rc; @@ -972,6 +993,7 @@ static int ace_setup(struct ace_device *ace) spin_lock_init(&ace->lock); init_completion(&ace->id_completion); + INIT_LIST_HEAD(&ace->rq_list); /* * Map the device @@ -989,9 +1011,25 @@ static int ace_setup(struct ace_device *ace) /* * Initialize the request queue */ - ace->queue = blk_init_queue(ace_request, &ace->lock); - if (ace->queue == NULL) + set = &ace->tag_set; + set->ops = &ace_mq_ops; + set->nr_hw_queues = 1; + set->queue_depth = 2; + set->numa_node = NUMA_NO_NODE; + set->flags = BLK_MQ_F_SHOULD_MERGE; + rc = blk_mq_alloc_tag_set(set); + if (rc) goto err_blk_initq; + + ace->queue = blk_mq_init_queue(set); + if (IS_ERR(ace->queue)) { + rc = PTR_ERR(ace->queue); + ace->queue = NULL; + blk_mq_free_tag_set(&ace->tag_set); + goto err_blk_initq; + } + ace->queue->queuedata = ace; + blk_queue_logical_block_size(ace->queue, 512); blk_queue_bounce_limit(ace->queue, BLK_BOUNCE_HIGH); @@ -1065,6 +1103,7 @@ static int ace_setup(struct ace_device *ace) err_read: put_disk(ace->gd); err_alloc_disk: + blk_mq_free_tag_set(&ace->tag_set); blk_cleanup_queue(ace->queue); err_blk_initq: iounmap(ace->baseaddr); @@ -1081,8 +1120,10 @@ static void ace_teardown(struct ace_device *ace) put_disk(ace->gd); } - if (ace->queue) + if (ace->queue) { + blk_mq_free_tag_set(&ace->tag_set); blk_cleanup_queue(ace->queue); + } tasklet_kill(&ace->fsm_tasklet); -- 2.17.1 From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: From: Jens Axboe To: linux-block@vger.kernel.org Cc: Jens Axboe Subject: [PATCH 04/17] paride: convert pcd to blk-mq Date: Thu, 11 Oct 2018 10:58:56 -0600 Message-Id: <20181011165909.32615-5-axboe@kernel.dk> In-Reply-To: <20181011165909.32615-1-axboe@kernel.dk> References: <20181011165909.32615-1-axboe@kernel.dk> List-ID: Signed-off-by: Jens Axboe --- drivers/block/paride/pcd.c | 98 +++++++++++++++++++++++++------------- 1 file changed, 66 insertions(+), 32 deletions(-) diff --git a/drivers/block/paride/pcd.c b/drivers/block/paride/pcd.c index a026211afb51..f2b82e3510d8 100644 --- a/drivers/block/paride/pcd.c +++ b/drivers/block/paride/pcd.c @@ -137,7 +137,7 @@ enum {D_PRT, D_PRO, D_UNI, D_MOD, D_SLV, D_DLY}; #include #include #include -#include +#include #include #include @@ -186,7 +186,8 @@ static int pcd_packet(struct cdrom_device_info *cdi, static int pcd_detect(void); static void pcd_probe_capabilities(void); static void do_pcd_read_drq(void); -static void do_pcd_request(struct request_queue * q); +static blk_status_t pcd_queue_rq(struct blk_mq_hw_ctx *hctx, + const struct blk_mq_queue_data *bd); static void do_pcd_read(void); struct pcd_unit { @@ -199,6 +200,8 @@ struct pcd_unit { char *name; /* pcd0, pcd1, etc */ struct cdrom_device_info info; /* uniform cdrom interface */ struct gendisk *disk; + struct blk_mq_tag_set tag_set; + struct list_head rq_list; }; static struct pcd_unit pcd[PCD_UNITS]; @@ -292,6 +295,10 @@ static const struct cdrom_device_ops pcd_dops = { CDC_CD_RW, }; +static const struct blk_mq_ops pcd_mq_ops = { + .queue_rq = pcd_queue_rq, +}; + static void pcd_init_units(void) { struct pcd_unit *cd; @@ -300,13 +307,29 @@ static void pcd_init_units(void) pcd_drive_count = 0; for (unit = 0, cd = pcd; unit < PCD_UNITS; unit++, cd++) { struct gendisk *disk = alloc_disk(1); + struct blk_mq_tag_set *set; + if (!disk) continue; - disk->queue = blk_init_queue(do_pcd_request, &pcd_lock); - if (!disk->queue) { - put_disk(disk); + + set = &cd->tag_set; + set->ops = &pcd_mq_ops; + set->nr_hw_queues = 1; + set->queue_depth = 1; + set->numa_node = NUMA_NO_NODE; + set->flags = BLK_MQ_F_SHOULD_MERGE; + if (blk_mq_alloc_tag_set(set)) + continue; + + disk->queue = blk_mq_init_queue(set); + if (IS_ERR(disk->queue)) { + blk_mq_free_tag_set(set); + disk->queue = NULL; continue; } + + INIT_LIST_HEAD(&cd->rq_list); + disk->queue->queuedata = cd; blk_queue_bounce_limit(disk->queue, BLK_BOUNCE_HIGH); cd->disk = disk; cd->pi = &cd->pia; @@ -748,18 +771,18 @@ static int pcd_queue; static int set_next_request(void) { struct pcd_unit *cd; - struct request_queue *q; int old_pos = pcd_queue; do { cd = &pcd[pcd_queue]; - q = cd->present ? cd->disk->queue : NULL; if (++pcd_queue == PCD_UNITS) pcd_queue = 0; - if (q) { - pcd_req = blk_fetch_request(q); - if (pcd_req) - break; + if (cd->present && !list_empty(&cd->rq_list)) { + pcd_req = list_first_entry(&cd->rq_list, struct request, + queuelist); + list_del_init(&pcd_req->queuelist); + blk_mq_start_request(pcd_req); + break; } } while (pcd_queue != old_pos); @@ -768,33 +791,41 @@ static int set_next_request(void) static void pcd_request(void) { + struct pcd_unit *cd; + if (pcd_busy) return; - while (1) { - if (!pcd_req && !set_next_request()) - return; - if (rq_data_dir(pcd_req) == READ) { - struct pcd_unit *cd = pcd_req->rq_disk->private_data; - if (cd != pcd_current) - pcd_bufblk = -1; - pcd_current = cd; - pcd_sector = blk_rq_pos(pcd_req); - pcd_count = blk_rq_cur_sectors(pcd_req); - pcd_buf = bio_data(pcd_req->bio); - pcd_busy = 1; - ps_set_intr(do_pcd_read, NULL, 0, nice); - return; - } else { - __blk_end_request_all(pcd_req, BLK_STS_IOERR); - pcd_req = NULL; - } - } + if (!pcd_req && !set_next_request()) + return; + + cd = pcd_req->rq_disk->private_data; + if (cd != pcd_current) + pcd_bufblk = -1; + pcd_current = cd; + pcd_sector = blk_rq_pos(pcd_req); + pcd_count = blk_rq_cur_sectors(pcd_req); + pcd_buf = bio_data(pcd_req->bio); + pcd_busy = 1; + ps_set_intr(do_pcd_read, NULL, 0, nice); } -static void do_pcd_request(struct request_queue *q) +static blk_status_t pcd_queue_rq(struct blk_mq_hw_ctx *hctx, + const struct blk_mq_queue_data *bd) { + struct pcd_unit *cd = hctx->queue->queuedata; + + if (rq_data_dir(bd->rq) != READ) { + blk_mq_start_request(bd->rq); + return BLK_STS_IOERR; + } + + spin_lock_irq(&pcd_lock); + list_add_tail(&bd->rq->queuelist, &cd->rq_list); pcd_request(); + spin_unlock_irq(&pcd_lock); + + return BLK_STS_OK; } static inline void next_request(blk_status_t err) @@ -802,8 +833,10 @@ static inline void next_request(blk_status_t err) unsigned long saved_flags; spin_lock_irqsave(&pcd_lock, saved_flags); - if (!__blk_end_request_cur(pcd_req, err)) + if (!blk_update_request(pcd_req, err, blk_rq_cur_bytes(pcd_req))) { + __blk_mq_end_request(pcd_req, err); pcd_req = NULL; + } pcd_busy = 0; pcd_request(); spin_unlock_irqrestore(&pcd_lock, saved_flags); @@ -1010,6 +1043,7 @@ static void __exit pcd_exit(void) pi_release(cd->pi); unregister_cdrom(&cd->info); } + blk_mq_free_tag_set(&cd->tag_set); blk_cleanup_queue(cd->disk->queue); put_disk(cd->disk); } -- 2.17.1 From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from localhost.localdomain ([216.160.245.98]) by smtp.gmail.com with ESMTPSA id z128-v6sm8366088itc.21.2018.10.11.09.59.11 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 11 Oct 2018 09:59:12 -0700 (PDT) From: Jens Axboe To: linux-block@vger.kernel.org Subject: [PATCHSET 0/17] Convert drivers to blk-mq Date: Thu, 11 Oct 2018 10:58:52 -0600 Message-Id: <20181011165909.32615-1-axboe@kernel.dk> List-ID: The long term plan has always been to deprecate and remove the legacy request_fn based IO path. This also means killing all that code, and going back to maintaining a single IO stack again. To accomplish this, we need to convert the remaining drivers to blk-mq. This converts everything but the floppy drivers, which should be coming shortly as well. -- Jens Axboe From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: MIME-Version: 1.0 References: <20181011165909.32615-1-axboe@kernel.dk> <20181011165909.32615-9-axboe@kernel.dk> In-Reply-To: <20181011165909.32615-9-axboe@kernel.dk> From: Maxim Levitsky Date: Sun, 14 Oct 2018 09:30:58 +0300 Message-ID: Subject: Re: [PATCH 08/17] ms_block: convert to blk-mq To: Jens Axboe Cc: linux-block@vger.kernel.org Content-Type: text/plain; charset="UTF-8" List-ID: Hi! I haven't yet had a chance to test this patch but I will do during this week. Thanks! Best regards, Maxim Levitsky On Thu, Oct 11, 2018 at 7:59 PM Jens Axboe wrote: > > Straight forward conversion, room for optimization in how everything > is punted to a work queue. Also looks plenty racy all over the map, > with the state changes. I fixed a bunch of them up while doing the > conversion, but there are surely more. > > Cc: Maxim Levitsky > Signed-off-by: Jens Axboe > --- > drivers/memstick/core/ms_block.c | 121 ++++++++++++++++++------------- > drivers/memstick/core/ms_block.h | 1 + > 2 files changed, 73 insertions(+), 49 deletions(-) > > diff --git a/drivers/memstick/core/ms_block.c b/drivers/memstick/core/ms_block.c > index 716fc8ed31d3..b829f55ff577 100644 > --- a/drivers/memstick/core/ms_block.c > +++ b/drivers/memstick/core/ms_block.c > @@ -15,7 +15,7 @@ > #define pr_fmt(fmt) DRIVER_NAME ": " fmt > > #include > -#include > +#include > #include > #include > #include > @@ -1873,69 +1873,65 @@ static void msb_io_work(struct work_struct *work) > struct msb_data *msb = container_of(work, struct msb_data, io_work); > int page, error, len; > sector_t lba; > - unsigned long flags; > struct scatterlist *sg = msb->prealloc_sg; > + struct request *req; > > dbg_verbose("IO: work started"); > > while (1) { > - spin_lock_irqsave(&msb->q_lock, flags); > + spin_lock_irq(&msb->q_lock); > > if (msb->need_flush_cache) { > msb->need_flush_cache = false; > - spin_unlock_irqrestore(&msb->q_lock, flags); > + spin_unlock_irq(&msb->q_lock); > msb_cache_flush(msb); > continue; > } > > - if (!msb->req) { > - msb->req = blk_fetch_request(msb->queue); > - if (!msb->req) { > - dbg_verbose("IO: no more requests exiting"); > - spin_unlock_irqrestore(&msb->q_lock, flags); > - return; > - } > + req = msb->req; > + if (!req) { > + dbg_verbose("IO: no more requests exiting"); > + spin_unlock_irq(&msb->q_lock); > + return; > } > > - spin_unlock_irqrestore(&msb->q_lock, flags); > - > - /* If card was removed meanwhile */ > - if (!msb->req) > - return; > + spin_unlock_irq(&msb->q_lock); > > /* process the request */ > dbg_verbose("IO: processing new request"); > - blk_rq_map_sg(msb->queue, msb->req, sg); > + blk_rq_map_sg(msb->queue, req, sg); > > - lba = blk_rq_pos(msb->req); > + lba = blk_rq_pos(req); > > sector_div(lba, msb->page_size / 512); > page = sector_div(lba, msb->pages_in_block); > > if (rq_data_dir(msb->req) == READ) > error = msb_do_read_request(msb, lba, page, sg, > - blk_rq_bytes(msb->req), &len); > + blk_rq_bytes(req), &len); > else > error = msb_do_write_request(msb, lba, page, sg, > - blk_rq_bytes(msb->req), &len); > + blk_rq_bytes(req), &len); > > - spin_lock_irqsave(&msb->q_lock, flags); > - > - if (len) > - if (!__blk_end_request(msb->req, BLK_STS_OK, len)) > - msb->req = NULL; > + if (len && !blk_update_request(req, BLK_STS_OK, len)) { > + __blk_mq_end_request(req, BLK_STS_OK); > + spin_lock_irq(&msb->q_lock); > + msb->req = NULL; > + spin_unlock_irq(&msb->q_lock); > + } > > if (error && msb->req) { > blk_status_t ret = errno_to_blk_status(error); > + > dbg_verbose("IO: ending one sector of the request with error"); > - if (!__blk_end_request(msb->req, ret, msb->page_size)) > - msb->req = NULL; > + blk_mq_end_request(req, ret); > + spin_lock_irq(&msb->q_lock); > + msb->req = NULL; > + spin_unlock_irq(&msb->q_lock); > } > > if (msb->req) > dbg_verbose("IO: request still pending"); > - > - spin_unlock_irqrestore(&msb->q_lock, flags); > } > } > > @@ -2002,29 +1998,40 @@ static int msb_bd_getgeo(struct block_device *bdev, > return 0; > } > > -static void msb_submit_req(struct request_queue *q) > +static blk_status_t msb_queue_rq(struct blk_mq_hw_ctx *hctx, > + const struct blk_mq_queue_data *bd) > { > - struct memstick_dev *card = q->queuedata; > + struct memstick_dev *card = hctx->queue->queuedata; > struct msb_data *msb = memstick_get_drvdata(card); > - struct request *req = NULL; > + struct request *req = bd->rq; > > dbg_verbose("Submit request"); > > + spin_lock_irq(&msb->q_lock); > + > if (msb->card_dead) { > dbg("Refusing requests on removed card"); > > WARN_ON(!msb->io_queue_stopped); > > - while ((req = blk_fetch_request(q)) != NULL) > - __blk_end_request_all(req, BLK_STS_IOERR); > - return; > + spin_unlock_irq(&msb->q_lock); > + blk_mq_start_request(req); > + return BLK_STS_IOERR; > } > > - if (msb->req) > - return; > + if (msb->req) { > + spin_unlock_irq(&msb->q_lock); > + return BLK_STS_DEV_RESOURCE; > + } > + > + blk_mq_start_request(req); > + msb->req = req; > > if (!msb->io_queue_stopped) > queue_work(msb->io_queue, &msb->io_work); > + > + spin_unlock_irq(&msb->q_lock); > + return BLK_STS_OK; > } > > static int msb_check_card(struct memstick_dev *card) > @@ -2040,21 +2047,20 @@ static void msb_stop(struct memstick_dev *card) > > dbg("Stopping all msblock IO"); > > + blk_mq_stop_hw_queues(msb->queue); > spin_lock_irqsave(&msb->q_lock, flags); > - blk_stop_queue(msb->queue); > msb->io_queue_stopped = true; > spin_unlock_irqrestore(&msb->q_lock, flags); > > del_timer_sync(&msb->cache_flush_timer); > flush_workqueue(msb->io_queue); > > + spin_lock_irqsave(&msb->q_lock, flags); > if (msb->req) { > - spin_lock_irqsave(&msb->q_lock, flags); > - blk_requeue_request(msb->queue, msb->req); > + blk_mq_requeue_request(msb->req, false); > msb->req = NULL; > - spin_unlock_irqrestore(&msb->q_lock, flags); > } > - > + spin_unlock_irqrestore(&msb->q_lock, flags); > } > > static void msb_start(struct memstick_dev *card) > @@ -2077,9 +2083,7 @@ static void msb_start(struct memstick_dev *card) > msb->need_flush_cache = true; > msb->io_queue_stopped = false; > > - spin_lock_irqsave(&msb->q_lock, flags); > - blk_start_queue(msb->queue); > - spin_unlock_irqrestore(&msb->q_lock, flags); > + blk_mq_start_hw_queues(msb->queue); > > queue_work(msb->io_queue, &msb->io_work); > > @@ -2092,10 +2096,15 @@ static const struct block_device_operations msb_bdops = { > .owner = THIS_MODULE > }; > > +static const struct blk_mq_ops msb_mq_ops = { > + .queue_rq = msb_queue_rq, > +}; > + > /* Registers the block device */ > static int msb_init_disk(struct memstick_dev *card) > { > struct msb_data *msb = memstick_get_drvdata(card); > + struct blk_mq_tag_set *set = NULL; > int rc; > unsigned long capacity; > > @@ -2112,10 +2121,21 @@ static int msb_init_disk(struct memstick_dev *card) > goto out_release_id; > } > > - msb->queue = blk_init_queue(msb_submit_req, &msb->q_lock); > - if (!msb->queue) { > - rc = -ENOMEM; > + set = &msb->tag_set; > + set->ops = &msb_mq_ops; > + set->nr_hw_queues = 1; > + set->queue_depth = 2; > + set->numa_node = NUMA_NO_NODE; > + set->flags = BLK_MQ_F_SHOULD_MERGE; > + rc = blk_mq_alloc_tag_set(set); > + if (rc) > goto out_put_disk; > + > + msb->queue = blk_mq_init_queue(set); > + if (IS_ERR(msb->queue)) { > + rc = PTR_ERR(msb->queue); > + msb->queue = NULL; > + goto out_put_tag; > } > > msb->queue->queuedata = card; > @@ -2150,6 +2170,8 @@ static int msb_init_disk(struct memstick_dev *card) > dbg("Disk added"); > return 0; > > +out_put_tag: > + blk_mq_free_tag_set(&msb->tag_set); > out_put_disk: > put_disk(msb->disk); > out_release_id: > @@ -2202,11 +2224,12 @@ static void msb_remove(struct memstick_dev *card) > /* Take care of unhandled + new requests from now on */ > spin_lock_irqsave(&msb->q_lock, flags); > msb->card_dead = true; > - blk_start_queue(msb->queue); > spin_unlock_irqrestore(&msb->q_lock, flags); > + blk_mq_start_hw_queues(msb->queue); > > /* Remove the disk */ > del_gendisk(msb->disk); > + blk_mq_free_tag_set(msb->queue->tag_set); > blk_cleanup_queue(msb->queue); > msb->queue = NULL; > > diff --git a/drivers/memstick/core/ms_block.h b/drivers/memstick/core/ms_block.h > index 53962c3b21df..9ba84e0ced63 100644 > --- a/drivers/memstick/core/ms_block.h > +++ b/drivers/memstick/core/ms_block.h > @@ -152,6 +152,7 @@ struct msb_data { > struct gendisk *disk; > struct request_queue *queue; > spinlock_t q_lock; > + struct blk_mq_tag_set tag_set; > struct hd_geometry geometry; > struct attribute_group attr_group; > struct request *req; > -- > 2.17.1 > From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: From: Jens Axboe To: linux-block@vger.kernel.org Cc: Jens Axboe , Maxim Levitsky Subject: [PATCH 08/17] ms_block: convert to blk-mq Date: Thu, 11 Oct 2018 10:59:00 -0600 Message-Id: <20181011165909.32615-9-axboe@kernel.dk> In-Reply-To: <20181011165909.32615-1-axboe@kernel.dk> References: <20181011165909.32615-1-axboe@kernel.dk> List-ID: Straight forward conversion, room for optimization in how everything is punted to a work queue. Also looks plenty racy all over the map, with the state changes. I fixed a bunch of them up while doing the conversion, but there are surely more. Cc: Maxim Levitsky Signed-off-by: Jens Axboe --- drivers/memstick/core/ms_block.c | 121 ++++++++++++++++++------------- drivers/memstick/core/ms_block.h | 1 + 2 files changed, 73 insertions(+), 49 deletions(-) diff --git a/drivers/memstick/core/ms_block.c b/drivers/memstick/core/ms_block.c index 716fc8ed31d3..b829f55ff577 100644 --- a/drivers/memstick/core/ms_block.c +++ b/drivers/memstick/core/ms_block.c @@ -15,7 +15,7 @@ #define pr_fmt(fmt) DRIVER_NAME ": " fmt #include -#include +#include #include #include #include @@ -1873,69 +1873,65 @@ static void msb_io_work(struct work_struct *work) struct msb_data *msb = container_of(work, struct msb_data, io_work); int page, error, len; sector_t lba; - unsigned long flags; struct scatterlist *sg = msb->prealloc_sg; + struct request *req; dbg_verbose("IO: work started"); while (1) { - spin_lock_irqsave(&msb->q_lock, flags); + spin_lock_irq(&msb->q_lock); if (msb->need_flush_cache) { msb->need_flush_cache = false; - spin_unlock_irqrestore(&msb->q_lock, flags); + spin_unlock_irq(&msb->q_lock); msb_cache_flush(msb); continue; } - if (!msb->req) { - msb->req = blk_fetch_request(msb->queue); - if (!msb->req) { - dbg_verbose("IO: no more requests exiting"); - spin_unlock_irqrestore(&msb->q_lock, flags); - return; - } + req = msb->req; + if (!req) { + dbg_verbose("IO: no more requests exiting"); + spin_unlock_irq(&msb->q_lock); + return; } - spin_unlock_irqrestore(&msb->q_lock, flags); - - /* If card was removed meanwhile */ - if (!msb->req) - return; + spin_unlock_irq(&msb->q_lock); /* process the request */ dbg_verbose("IO: processing new request"); - blk_rq_map_sg(msb->queue, msb->req, sg); + blk_rq_map_sg(msb->queue, req, sg); - lba = blk_rq_pos(msb->req); + lba = blk_rq_pos(req); sector_div(lba, msb->page_size / 512); page = sector_div(lba, msb->pages_in_block); if (rq_data_dir(msb->req) == READ) error = msb_do_read_request(msb, lba, page, sg, - blk_rq_bytes(msb->req), &len); + blk_rq_bytes(req), &len); else error = msb_do_write_request(msb, lba, page, sg, - blk_rq_bytes(msb->req), &len); + blk_rq_bytes(req), &len); - spin_lock_irqsave(&msb->q_lock, flags); - - if (len) - if (!__blk_end_request(msb->req, BLK_STS_OK, len)) - msb->req = NULL; + if (len && !blk_update_request(req, BLK_STS_OK, len)) { + __blk_mq_end_request(req, BLK_STS_OK); + spin_lock_irq(&msb->q_lock); + msb->req = NULL; + spin_unlock_irq(&msb->q_lock); + } if (error && msb->req) { blk_status_t ret = errno_to_blk_status(error); + dbg_verbose("IO: ending one sector of the request with error"); - if (!__blk_end_request(msb->req, ret, msb->page_size)) - msb->req = NULL; + blk_mq_end_request(req, ret); + spin_lock_irq(&msb->q_lock); + msb->req = NULL; + spin_unlock_irq(&msb->q_lock); } if (msb->req) dbg_verbose("IO: request still pending"); - - spin_unlock_irqrestore(&msb->q_lock, flags); } } @@ -2002,29 +1998,40 @@ static int msb_bd_getgeo(struct block_device *bdev, return 0; } -static void msb_submit_req(struct request_queue *q) +static blk_status_t msb_queue_rq(struct blk_mq_hw_ctx *hctx, + const struct blk_mq_queue_data *bd) { - struct memstick_dev *card = q->queuedata; + struct memstick_dev *card = hctx->queue->queuedata; struct msb_data *msb = memstick_get_drvdata(card); - struct request *req = NULL; + struct request *req = bd->rq; dbg_verbose("Submit request"); + spin_lock_irq(&msb->q_lock); + if (msb->card_dead) { dbg("Refusing requests on removed card"); WARN_ON(!msb->io_queue_stopped); - while ((req = blk_fetch_request(q)) != NULL) - __blk_end_request_all(req, BLK_STS_IOERR); - return; + spin_unlock_irq(&msb->q_lock); + blk_mq_start_request(req); + return BLK_STS_IOERR; } - if (msb->req) - return; + if (msb->req) { + spin_unlock_irq(&msb->q_lock); + return BLK_STS_DEV_RESOURCE; + } + + blk_mq_start_request(req); + msb->req = req; if (!msb->io_queue_stopped) queue_work(msb->io_queue, &msb->io_work); + + spin_unlock_irq(&msb->q_lock); + return BLK_STS_OK; } static int msb_check_card(struct memstick_dev *card) @@ -2040,21 +2047,20 @@ static void msb_stop(struct memstick_dev *card) dbg("Stopping all msblock IO"); + blk_mq_stop_hw_queues(msb->queue); spin_lock_irqsave(&msb->q_lock, flags); - blk_stop_queue(msb->queue); msb->io_queue_stopped = true; spin_unlock_irqrestore(&msb->q_lock, flags); del_timer_sync(&msb->cache_flush_timer); flush_workqueue(msb->io_queue); + spin_lock_irqsave(&msb->q_lock, flags); if (msb->req) { - spin_lock_irqsave(&msb->q_lock, flags); - blk_requeue_request(msb->queue, msb->req); + blk_mq_requeue_request(msb->req, false); msb->req = NULL; - spin_unlock_irqrestore(&msb->q_lock, flags); } - + spin_unlock_irqrestore(&msb->q_lock, flags); } static void msb_start(struct memstick_dev *card) @@ -2077,9 +2083,7 @@ static void msb_start(struct memstick_dev *card) msb->need_flush_cache = true; msb->io_queue_stopped = false; - spin_lock_irqsave(&msb->q_lock, flags); - blk_start_queue(msb->queue); - spin_unlock_irqrestore(&msb->q_lock, flags); + blk_mq_start_hw_queues(msb->queue); queue_work(msb->io_queue, &msb->io_work); @@ -2092,10 +2096,15 @@ static const struct block_device_operations msb_bdops = { .owner = THIS_MODULE }; +static const struct blk_mq_ops msb_mq_ops = { + .queue_rq = msb_queue_rq, +}; + /* Registers the block device */ static int msb_init_disk(struct memstick_dev *card) { struct msb_data *msb = memstick_get_drvdata(card); + struct blk_mq_tag_set *set = NULL; int rc; unsigned long capacity; @@ -2112,10 +2121,21 @@ static int msb_init_disk(struct memstick_dev *card) goto out_release_id; } - msb->queue = blk_init_queue(msb_submit_req, &msb->q_lock); - if (!msb->queue) { - rc = -ENOMEM; + set = &msb->tag_set; + set->ops = &msb_mq_ops; + set->nr_hw_queues = 1; + set->queue_depth = 2; + set->numa_node = NUMA_NO_NODE; + set->flags = BLK_MQ_F_SHOULD_MERGE; + rc = blk_mq_alloc_tag_set(set); + if (rc) goto out_put_disk; + + msb->queue = blk_mq_init_queue(set); + if (IS_ERR(msb->queue)) { + rc = PTR_ERR(msb->queue); + msb->queue = NULL; + goto out_put_tag; } msb->queue->queuedata = card; @@ -2150,6 +2170,8 @@ static int msb_init_disk(struct memstick_dev *card) dbg("Disk added"); return 0; +out_put_tag: + blk_mq_free_tag_set(&msb->tag_set); out_put_disk: put_disk(msb->disk); out_release_id: @@ -2202,11 +2224,12 @@ static void msb_remove(struct memstick_dev *card) /* Take care of unhandled + new requests from now on */ spin_lock_irqsave(&msb->q_lock, flags); msb->card_dead = true; - blk_start_queue(msb->queue); spin_unlock_irqrestore(&msb->q_lock, flags); + blk_mq_start_hw_queues(msb->queue); /* Remove the disk */ del_gendisk(msb->disk); + blk_mq_free_tag_set(msb->queue->tag_set); blk_cleanup_queue(msb->queue); msb->queue = NULL; diff --git a/drivers/memstick/core/ms_block.h b/drivers/memstick/core/ms_block.h index 53962c3b21df..9ba84e0ced63 100644 --- a/drivers/memstick/core/ms_block.h +++ b/drivers/memstick/core/ms_block.h @@ -152,6 +152,7 @@ struct msb_data { struct gendisk *disk; struct request_queue *queue; spinlock_t q_lock; + struct blk_mq_tag_set tag_set; struct hd_geometry geometry; struct attribute_group attr_group; struct request *req; -- 2.17.1 From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: From: Jens Axboe To: linux-block@vger.kernel.org Cc: Jens Axboe Subject: [PATCH 06/17] paride: convert pf to blk-mq Date: Thu, 11 Oct 2018 10:58:58 -0600 Message-Id: <20181011165909.32615-7-axboe@kernel.dk> In-Reply-To: <20181011165909.32615-1-axboe@kernel.dk> References: <20181011165909.32615-1-axboe@kernel.dk> List-ID: Signed-off-by: Jens Axboe --- drivers/block/paride/pf.c | 68 +++++++++++++++++++++++++++++++-------- 1 file changed, 54 insertions(+), 14 deletions(-) diff --git a/drivers/block/paride/pf.c b/drivers/block/paride/pf.c index eef7a91f667d..58866cf495f8 100644 --- a/drivers/block/paride/pf.c +++ b/drivers/block/paride/pf.c @@ -152,7 +152,7 @@ enum {D_PRT, D_PRO, D_UNI, D_MOD, D_SLV, D_LUN, D_DLY}; #include #include #include -#include +#include #include #include #include @@ -206,7 +206,8 @@ module_param_array(drive3, int, NULL, 0); #define ATAPI_WRITE_10 0x2a static int pf_open(struct block_device *bdev, fmode_t mode); -static void do_pf_request(struct request_queue * q); +static blk_status_t pf_queue_rq(struct blk_mq_hw_ctx *hctx, + const struct blk_mq_queue_data *bd); static int pf_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, unsigned long arg); static int pf_getgeo(struct block_device *bdev, struct hd_geometry *geo); @@ -238,6 +239,8 @@ struct pf_unit { int present; /* device present ? */ char name[PF_NAMELEN]; /* pf0, pf1, ... */ struct gendisk *disk; + struct blk_mq_tag_set tag_set; + struct list_head rq_list; }; static struct pf_unit units[PF_UNITS]; @@ -277,6 +280,10 @@ static const struct block_device_operations pf_fops = { .check_events = pf_check_events, }; +static const struct blk_mq_ops pf_mq_ops = { + .queue_rq = pf_queue_rq, +}; + static void __init pf_init_units(void) { struct pf_unit *pf; @@ -284,14 +291,34 @@ static void __init pf_init_units(void) pf_drive_count = 0; for (unit = 0, pf = units; unit < PF_UNITS; unit++, pf++) { - struct gendisk *disk = alloc_disk(1); + struct blk_mq_tag_set *set; + struct gendisk *disk; + + disk = alloc_disk(1); if (!disk) continue; - disk->queue = blk_init_queue(do_pf_request, &pf_spin_lock); - if (!disk->queue) { + + set = &pf->tag_set; + set->ops = &pf_mq_ops; + set->nr_hw_queues = 1; + set->queue_depth = 1; + set->numa_node = NUMA_NO_NODE; + set->flags = BLK_MQ_F_SHOULD_MERGE; + if (blk_mq_alloc_tag_set(set)) { put_disk(disk); - return; + continue; } + + disk->queue = blk_mq_init_queue(set); + if (IS_ERR(disk->queue)) { + blk_mq_free_tag_set(set); + put_disk(disk); + disk->queue = NULL; + continue; + } + + INIT_LIST_HEAD(&pf->rq_list); + disk->queue->queuedata = pf; blk_queue_max_segments(disk->queue, cluster); blk_queue_bounce_limit(disk->queue, BLK_BOUNCE_HIGH); pf->disk = disk; @@ -784,18 +811,18 @@ static int pf_queue; static int set_next_request(void) { struct pf_unit *pf; - struct request_queue *q; int old_pos = pf_queue; do { pf = &units[pf_queue]; - q = pf->present ? pf->disk->queue : NULL; if (++pf_queue == PF_UNITS) pf_queue = 0; - if (q) { - pf_req = blk_fetch_request(q); - if (pf_req) - break; + if (pf->present && !list_empty(&pf->rq_list)) { + pf_req = list_first_entry(&pf->rq_list, struct request, + queuelist); + list_del_init(&pf_req->queuelist); + blk_mq_start_request(pf_req); + break; } } while (pf_queue != old_pos); @@ -804,8 +831,12 @@ static int set_next_request(void) static void pf_end_request(blk_status_t err) { - if (pf_req && !__blk_end_request_cur(pf_req, err)) + if (!pf_req) + return; + if (!blk_update_request(pf_req, err, blk_rq_cur_bytes(pf_req))) { + __blk_mq_end_request(pf_req, err); pf_req = NULL; + } } static void pf_request(void) @@ -842,9 +873,17 @@ static void pf_request(void) } } -static void do_pf_request(struct request_queue *q) +static blk_status_t pf_queue_rq(struct blk_mq_hw_ctx *hctx, + const struct blk_mq_queue_data *bd) { + struct pf_unit *pf = hctx->queue->queuedata; + + spin_lock_irq(&pf_spin_lock); + list_add_tail(&bd->rq->queuelist, &pf->rq_list); pf_request(); + spin_unlock_irq(&pf_spin_lock); + + return BLK_STS_OK; } static int pf_next_buf(void) @@ -1023,6 +1062,7 @@ static void __exit pf_exit(void) if (!pf->present) continue; del_gendisk(pf->disk); + blk_mq_free_tag_set(&pf->tag_set); blk_cleanup_queue(pf->disk->queue); put_disk(pf->disk); pi_release(pf->pi); -- 2.17.1 From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Subject: Re: [PATCH 17/17] null_blk: remove legacy IO path To: =?UTF-8?Q?S=c3=a9bastien_Boisvert?= , linux-block@vger.kernel.org References: <20181011165909.32615-1-axboe@kernel.dk> <20181011165909.32615-18-axboe@kernel.dk> <2b272814-d4b9-a761-0d6c-22bb85d86c58@gydle.com> From: Jens Axboe Message-ID: <2fc11623-c246-25ea-4de2-4b88f51e3f9a@kernel.dk> Date: Fri, 12 Oct 2018 11:50:54 -0600 MIME-Version: 1.0 In-Reply-To: Content-Type: text/plain; charset=utf-8 List-ID: On 10/12/18 11:37 AM, Sébastien Boisvert wrote: > On 2018-10-12 01:30 PM, Jens Axboe wrote: >> On 10/12/18 11:24 AM, Sébastien Boisvert wrote: >>>> + if (g_queue_mode == NULL_Q_RQ) { >>>> + pr_err("null_blk: legacy IO path no longer available\n"); >>>> + return -EINVAL; >>>> + } >>> >>> Is this the only location where the value NULL_Q_RQ has be checked ? >> >> I've since fixed a few more, all should be well now. The updated version >> is here: >> >> http://git.kernel.dk/cgit/linux-block/commit/?h=mq-conversions&id=d6fd3bd94a7333a8cd0bf7ef18f719ef7e052dc4 >> >>> Since the enum that contains NULL_Q_RQ is in >>> drivers/block/null_blk_main.c, and not in a linux header file, would >>> it be thinkable to remove NULL_Q_RQ from the enum too, and not adding >>> this legacy check ? >>> >>> Would that break user space (the number one rule) ? >> >> It wouldn't break user space. In any case, if someone is currently using >> queue_mode=1, it'd fail to load after this patch. >> > > Just curious, where can this be passed (mount option, boot option, > /sys, /proc, driver code, or whatnot) ? It's a module parameter, so through modprobe or (if builtin), using a command line option. >> I'm checking that at the bottom, we could remove NULL_Q_RQ if we just >> made that check == 1 instead. But cleaner to keep it, imho. >> > > I agree, if queue_mode=1 can be passed. It'll have to fail it. If the user asks for this specific mode, and that mode no longer exists, then it has to fail. It's not like this is root device or anything like that, it's just for testing. It'd be worse NOT to fail the modprobe, since then the user/scripts/tests will think they are testing one thing, but in fact testing something else. -- Jens Axboe From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Subject: Re: [PATCH 17/17] null_blk: remove legacy IO path To: Jens Axboe , linux-block@vger.kernel.org References: <20181011165909.32615-1-axboe@kernel.dk> <20181011165909.32615-18-axboe@kernel.dk> <2b272814-d4b9-a761-0d6c-22bb85d86c58@gydle.com> From: =?UTF-8?Q?S=c3=a9bastien_Boisvert?= Message-ID: Date: Fri, 12 Oct 2018 13:37:16 -0400 MIME-Version: 1.0 In-Reply-To: Content-Type: text/plain; charset=utf-8 List-ID: On 2018-10-12 01:30 PM, Jens Axboe wrote: > On 10/12/18 11:24 AM, Sébastien Boisvert wrote: >>> + if (g_queue_mode == NULL_Q_RQ) { >>> + pr_err("null_blk: legacy IO path no longer available\n"); >>> + return -EINVAL; >>> + } >> >> Is this the only location where the value NULL_Q_RQ has be checked ? > > I've since fixed a few more, all should be well now. The updated version > is here: > > http://git.kernel.dk/cgit/linux-block/commit/?h=mq-conversions&id=d6fd3bd94a7333a8cd0bf7ef18f719ef7e052dc4 > >> Since the enum that contains NULL_Q_RQ is in >> drivers/block/null_blk_main.c, and not in a linux header file, would >> it be thinkable to remove NULL_Q_RQ from the enum too, and not adding >> this legacy check ? >> >> Would that break user space (the number one rule) ? > > It wouldn't break user space. In any case, if someone is currently using > queue_mode=1, it'd fail to load after this patch. > Just curious, where can this be passed (mount option, boot option, /sys, /proc, driver code, or whatnot) ? > I'm checking that at the bottom, we could remove NULL_Q_RQ if we just > made that check == 1 instead. But cleaner to keep it, imho. > I agree, if queue_mode=1 can be passed. Reviewed-by: Sébastien Boisvert From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Subject: Re: [PATCH 17/17] null_blk: remove legacy IO path To: =?UTF-8?Q?S=c3=a9bastien_Boisvert?= , linux-block@vger.kernel.org References: <20181011165909.32615-1-axboe@kernel.dk> <20181011165909.32615-18-axboe@kernel.dk> <2b272814-d4b9-a761-0d6c-22bb85d86c58@gydle.com> From: Jens Axboe Message-ID: Date: Fri, 12 Oct 2018 11:30:06 -0600 MIME-Version: 1.0 In-Reply-To: <2b272814-d4b9-a761-0d6c-22bb85d86c58@gydle.com> Content-Type: text/plain; charset=utf-8 List-ID: On 10/12/18 11:24 AM, Sébastien Boisvert wrote: >> + if (g_queue_mode == NULL_Q_RQ) { >> + pr_err("null_blk: legacy IO path no longer available\n"); >> + return -EINVAL; >> + } > > Is this the only location where the value NULL_Q_RQ has be checked ? I've since fixed a few more, all should be well now. The updated version is here: http://git.kernel.dk/cgit/linux-block/commit/?h=mq-conversions&id=d6fd3bd94a7333a8cd0bf7ef18f719ef7e052dc4 > Since the enum that contains NULL_Q_RQ is in > drivers/block/null_blk_main.c, and not in a linux header file, would > it be thinkable to remove NULL_Q_RQ from the enum too, and not adding > this legacy check ? > > Would that break user space (the number one rule) ? It wouldn't break user space. In any case, if someone is currently using queue_mode=1, it'd fail to load after this patch. I'm checking that at the bottom, we could remove NULL_Q_RQ if we just made that check == 1 instead. But cleaner to keep it, imho. -- Jens Axboe From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: To: Jens Axboe , linux-block@vger.kernel.org References: <20181011165909.32615-1-axboe@kernel.dk> <20181011165909.32615-18-axboe@kernel.dk> From: =?UTF-8?Q?S=c3=a9bastien_Boisvert?= Subject: Re: [PATCH 17/17] null_blk: remove legacy IO path Message-ID: <2b272814-d4b9-a761-0d6c-22bb85d86c58@gydle.com> Date: Fri, 12 Oct 2018 13:24:07 -0400 MIME-Version: 1.0 In-Reply-To: <20181011165909.32615-18-axboe@kernel.dk> Content-Type: text/plain; charset=utf-8 List-ID: Hello Jens, On 2018-10-11 12:59 PM, Jens Axboe wrote: > We're planning on removing this code completely, kill the old > path. > > Signed-off-by: Jens Axboe > --- > drivers/block/null_blk_main.c | 96 +++-------------------------------- > 1 file changed, 6 insertions(+), 90 deletions(-) > > diff --git a/drivers/block/null_blk_main.c b/drivers/block/null_blk_main.c > index 093b614d6524..8142cc8ff952 100644 > --- a/drivers/block/null_blk_main.c > +++ b/drivers/block/null_blk_main.c > @@ -616,10 +616,6 @@ static void end_cmd(struct nullb_cmd *cmd) > case NULL_Q_MQ: > blk_mq_end_request(cmd->rq, cmd->error); > return; > - case NULL_Q_RQ: > - INIT_LIST_HEAD(&cmd->rq->queuelist); > - blk_end_request_all(cmd->rq, cmd->error); > - break; > case NULL_Q_BIO: > cmd->bio->bi_status = cmd->error; > bio_endio(cmd->bio); > @@ -627,15 +623,6 @@ static void end_cmd(struct nullb_cmd *cmd) > } > > free_cmd(cmd); > - > - /* Restart queue if needed, as we are freeing a tag */ > - if (queue_mode == NULL_Q_RQ && blk_queue_stopped(q)) { > - unsigned long flags; > - > - spin_lock_irqsave(q->queue_lock, flags); > - blk_start_queue_async(q); > - spin_unlock_irqrestore(q->queue_lock, flags); > - } > } > > static enum hrtimer_restart null_cmd_timer_expired(struct hrtimer *timer) > @@ -1197,17 +1184,8 @@ static blk_status_t null_handle_cmd(struct nullb_cmd *cmd) > /* race with timer */ > if (atomic_long_read(&nullb->cur_bytes) > 0) > null_restart_queue_async(nullb); > - if (dev->queue_mode == NULL_Q_RQ) { > - struct request_queue *q = nullb->q; > - > - spin_lock_irq(q->queue_lock); > - rq->rq_flags |= RQF_DONTPREP; > - blk_requeue_request(q, rq); > - spin_unlock_irq(q->queue_lock); > - return BLK_STS_OK; > - } else > - /* requeue request */ > - return BLK_STS_DEV_RESOURCE; > + /* requeue request */ > + return BLK_STS_DEV_RESOURCE; > } > } > > @@ -1278,9 +1256,6 @@ static blk_status_t null_handle_cmd(struct nullb_cmd *cmd) > case NULL_Q_MQ: > blk_mq_complete_request(cmd->rq); > break; > - case NULL_Q_RQ: > - blk_complete_request(cmd->rq); > - break; > case NULL_Q_BIO: > /* > * XXX: no proper submitting cpu information available. > @@ -1349,30 +1324,6 @@ static blk_qc_t null_queue_bio(struct request_queue *q, struct bio *bio) > return BLK_QC_T_NONE; > } > > -static enum blk_eh_timer_return null_rq_timed_out_fn(struct request *rq) > -{ > - pr_info("null: rq %p timed out\n", rq); > - __blk_complete_request(rq); > - return BLK_EH_DONE; > -} > - > -static int null_rq_prep_fn(struct request_queue *q, struct request *req) > -{ > - struct nullb *nullb = q->queuedata; > - struct nullb_queue *nq = nullb_to_queue(nullb); > - struct nullb_cmd *cmd; > - > - cmd = alloc_cmd(nq, 0); > - if (cmd) { > - cmd->rq = req; > - req->special = cmd; > - return BLKPREP_OK; > - } > - blk_stop_queue(q); > - > - return BLKPREP_DEFER; > -} > - > static bool should_timeout_request(struct request *rq) > { > #ifdef CONFIG_BLK_DEV_NULL_BLK_FAULT_INJECTION > @@ -1391,27 +1342,6 @@ static bool should_requeue_request(struct request *rq) > return false; > } > > -static void null_request_fn(struct request_queue *q) > -{ > - struct request *rq; > - > - while ((rq = blk_fetch_request(q)) != NULL) { > - struct nullb_cmd *cmd = rq->special; > - > - /* just ignore the request */ > - if (should_timeout_request(rq)) > - continue; > - if (should_requeue_request(rq)) { > - blk_requeue_request(q, rq); > - continue; > - } > - > - spin_unlock_irq(q->queue_lock); > - null_handle_cmd(cmd); > - spin_lock_irq(q->queue_lock); > - } > -} > - > static enum blk_eh_timer_return null_timeout_rq(struct request *rq, bool res) > { > pr_info("null: rq %p timed out\n", rq); > @@ -1766,24 +1696,6 @@ static int null_add_dev(struct nullb_device *dev) > rv = init_driver_queues(nullb); > if (rv) > goto out_cleanup_blk_queue; > - } else { > - nullb->q = blk_init_queue_node(null_request_fn, &nullb->lock, > - dev->home_node); > - if (!nullb->q) { > - rv = -ENOMEM; > - goto out_cleanup_queues; > - } > - > - if (!null_setup_fault()) > - goto out_cleanup_blk_queue; > - > - blk_queue_prep_rq(nullb->q, null_rq_prep_fn); > - blk_queue_softirq_done(nullb->q, null_softirq_done_fn); > - blk_queue_rq_timed_out(nullb->q, null_rq_timed_out_fn); > - nullb->q->rq_timeout = 5 * HZ; > - rv = init_driver_queues(nullb); > - if (rv) > - goto out_cleanup_blk_queue; > } > > if (dev->mbps) { > @@ -1865,6 +1777,10 @@ static int __init null_init(void) > return -EINVAL; > } > > + if (g_queue_mode == NULL_Q_RQ) { > + pr_err("null_blk: legacy IO path no longer available\n"); > + return -EINVAL; > + } Is this the only location where the value NULL_Q_RQ has be checked ? Since the enum that contains NULL_Q_RQ is in drivers/block/null_blk_main.c, and not in a linux header file, would it be thinkable to remove NULL_Q_RQ from the enum too, and not adding this legacy check ? Would that break user space (the number one rule) ? See in 0778a9f2dd924c3af41971ba40eec44793aea531 from remotes/axboe-linux-block/master : drivers/block/null_blk_main.c-79-enum { drivers/block/null_blk_main.c-80- NULL_Q_BIO = 0, drivers/block/null_blk_main.c:81: NULL_Q_RQ = 1, drivers/block/null_blk_main.c-82- NULL_Q_MQ = 2, drivers/block/null_blk_main.c-83-}; > if (g_queue_mode == NULL_Q_MQ && g_use_per_node_hctx) { > if (g_submit_queues != nr_online_nodes) { > pr_warn("null_blk: submit_queues param is set to %u.\n", > From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Subject: Re: [PATCH 17/17] null_blk: remove legacy IO path To: Johannes Thumshirn , Dongli Zhang Cc: linux-block@vger.kernel.org References: <20181011165909.32615-1-axboe@kernel.dk> <20181011165909.32615-18-axboe@kernel.dk> <477afa55-24b3-b0ac-0f69-0ebe74beb11c@suse.de> From: Jens Axboe Message-ID: <0f67146e-6db3-56d7-5500-7a3d31b2ed91@kernel.dk> Date: Fri, 12 Oct 2018 08:18:24 -0600 MIME-Version: 1.0 In-Reply-To: <477afa55-24b3-b0ac-0f69-0ebe74beb11c@suse.de> Content-Type: text/plain; charset=windows-1252 List-ID: On 10/12/18 2:51 AM, Johannes Thumshirn wrote: > On 12/10/18 08:56, Dongli Zhang wrote: >> Hi Jens, >> >> Will the legacy path be fully deprecated? >> >> In addition to performance measurement, null_blk is a very good tutorial for >> beginners to understand how to implement a legacy path based block driver from >> scratch. Unless legacy path is not used any longer, why not keep it in the code >> as a tutorial? > > But when there is no tutorial on how to write drivers for the legacy > path no one will write drivers for the legacy path and will be upset > when we remove it. Plus the legacy path is going away right now, that's the whole point of this series of patches. Once this is done, I'm killing all that code. The whole point of legacy is that it's, well, legacy. Nobody should be writing that style of driver anymore. null_blk has a clean blk-mq implementation, that's what people can look at if they want to learn how to write a new blk-mq driver. -- Jens Axboe From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Subject: Re: [PATCH 17/17] null_blk: remove legacy IO path To: Dongli Zhang , Jens Axboe Cc: linux-block@vger.kernel.org References: <20181011165909.32615-1-axboe@kernel.dk> <20181011165909.32615-18-axboe@kernel.dk> From: Johannes Thumshirn Message-ID: <477afa55-24b3-b0ac-0f69-0ebe74beb11c@suse.de> Date: Fri, 12 Oct 2018 10:51:32 +0200 MIME-Version: 1.0 In-Reply-To: Content-Type: text/plain; charset=windows-1252 List-ID: On 12/10/18 08:56, Dongli Zhang wrote: > Hi Jens, > > Will the legacy path be fully deprecated? > > In addition to performance measurement, null_blk is a very good tutorial for > beginners to understand how to implement a legacy path based block driver from > scratch. Unless legacy path is not used any longer, why not keep it in the code > as a tutorial? But when there is no tutorial on how to write drivers for the legacy path no one will write drivers for the legacy path and will be upset when we remove it. Johannes -- Johannes Thumshirn SUSE Labs jthumshirn@suse.de +49 911 74053 689 SUSE LINUX GmbH, Maxfeldstr. 5, 90409 N�rnberg GF: Felix Imend�rffer, Jane Smithard, Graham Norton HRB 21284 (AG N�rnberg) Key fingerprint = EC38 9CAB C2C4 F25D 8600 D0D0 0393 969D 2D76 0850 From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Subject: Re: [PATCH 17/17] null_blk: remove legacy IO path To: Jens Axboe References: <20181011165909.32615-1-axboe@kernel.dk> <20181011165909.32615-18-axboe@kernel.dk> Cc: linux-block@vger.kernel.org From: Dongli Zhang Message-ID: Date: Fri, 12 Oct 2018 14:56:42 +0800 MIME-Version: 1.0 In-Reply-To: <20181011165909.32615-18-axboe@kernel.dk> Content-Type: text/plain; charset=windows-1252 List-ID: Hi Jens, Will the legacy path be fully deprecated? In addition to performance measurement, null_blk is a very good tutorial for beginners to understand how to implement a legacy path based block driver from scratch. Unless legacy path is not used any longer, why not keep it in the code as a tutorial? Dongli Zhang On 10/12/2018 12:59 AM, Jens Axboe wrote: > We're planning on removing this code completely, kill the old > path. > > Signed-off-by: Jens Axboe > --- > drivers/block/null_blk_main.c | 96 +++-------------------------------- > 1 file changed, 6 insertions(+), 90 deletions(-) > > diff --git a/drivers/block/null_blk_main.c b/drivers/block/null_blk_main.c > index 093b614d6524..8142cc8ff952 100644 > --- a/drivers/block/null_blk_main.c > +++ b/drivers/block/null_blk_main.c > @@ -616,10 +616,6 @@ static void end_cmd(struct nullb_cmd *cmd) > case NULL_Q_MQ: > blk_mq_end_request(cmd->rq, cmd->error); > return; > - case NULL_Q_RQ: > - INIT_LIST_HEAD(&cmd->rq->queuelist); > - blk_end_request_all(cmd->rq, cmd->error); > - break; > case NULL_Q_BIO: > cmd->bio->bi_status = cmd->error; > bio_endio(cmd->bio); > @@ -627,15 +623,6 @@ static void end_cmd(struct nullb_cmd *cmd) > } > > free_cmd(cmd); > - > - /* Restart queue if needed, as we are freeing a tag */ > - if (queue_mode == NULL_Q_RQ && blk_queue_stopped(q)) { > - unsigned long flags; > - > - spin_lock_irqsave(q->queue_lock, flags); > - blk_start_queue_async(q); > - spin_unlock_irqrestore(q->queue_lock, flags); > - } > } > > static enum hrtimer_restart null_cmd_timer_expired(struct hrtimer *timer) > @@ -1197,17 +1184,8 @@ static blk_status_t null_handle_cmd(struct nullb_cmd *cmd) > /* race with timer */ > if (atomic_long_read(&nullb->cur_bytes) > 0) > null_restart_queue_async(nullb); > - if (dev->queue_mode == NULL_Q_RQ) { > - struct request_queue *q = nullb->q; > - > - spin_lock_irq(q->queue_lock); > - rq->rq_flags |= RQF_DONTPREP; > - blk_requeue_request(q, rq); > - spin_unlock_irq(q->queue_lock); > - return BLK_STS_OK; > - } else > - /* requeue request */ > - return BLK_STS_DEV_RESOURCE; > + /* requeue request */ > + return BLK_STS_DEV_RESOURCE; > } > } > > @@ -1278,9 +1256,6 @@ static blk_status_t null_handle_cmd(struct nullb_cmd *cmd) > case NULL_Q_MQ: > blk_mq_complete_request(cmd->rq); > break; > - case NULL_Q_RQ: > - blk_complete_request(cmd->rq); > - break; > case NULL_Q_BIO: > /* > * XXX: no proper submitting cpu information available. > @@ -1349,30 +1324,6 @@ static blk_qc_t null_queue_bio(struct request_queue *q, struct bio *bio) > return BLK_QC_T_NONE; > } > > -static enum blk_eh_timer_return null_rq_timed_out_fn(struct request *rq) > -{ > - pr_info("null: rq %p timed out\n", rq); > - __blk_complete_request(rq); > - return BLK_EH_DONE; > -} > - > -static int null_rq_prep_fn(struct request_queue *q, struct request *req) > -{ > - struct nullb *nullb = q->queuedata; > - struct nullb_queue *nq = nullb_to_queue(nullb); > - struct nullb_cmd *cmd; > - > - cmd = alloc_cmd(nq, 0); > - if (cmd) { > - cmd->rq = req; > - req->special = cmd; > - return BLKPREP_OK; > - } > - blk_stop_queue(q); > - > - return BLKPREP_DEFER; > -} > - > static bool should_timeout_request(struct request *rq) > { > #ifdef CONFIG_BLK_DEV_NULL_BLK_FAULT_INJECTION > @@ -1391,27 +1342,6 @@ static bool should_requeue_request(struct request *rq) > return false; > } > > -static void null_request_fn(struct request_queue *q) > -{ > - struct request *rq; > - > - while ((rq = blk_fetch_request(q)) != NULL) { > - struct nullb_cmd *cmd = rq->special; > - > - /* just ignore the request */ > - if (should_timeout_request(rq)) > - continue; > - if (should_requeue_request(rq)) { > - blk_requeue_request(q, rq); > - continue; > - } > - > - spin_unlock_irq(q->queue_lock); > - null_handle_cmd(cmd); > - spin_lock_irq(q->queue_lock); > - } > -} > - > static enum blk_eh_timer_return null_timeout_rq(struct request *rq, bool res) > { > pr_info("null: rq %p timed out\n", rq); > @@ -1766,24 +1696,6 @@ static int null_add_dev(struct nullb_device *dev) > rv = init_driver_queues(nullb); > if (rv) > goto out_cleanup_blk_queue; > - } else { > - nullb->q = blk_init_queue_node(null_request_fn, &nullb->lock, > - dev->home_node); > - if (!nullb->q) { > - rv = -ENOMEM; > - goto out_cleanup_queues; > - } > - > - if (!null_setup_fault()) > - goto out_cleanup_blk_queue; > - > - blk_queue_prep_rq(nullb->q, null_rq_prep_fn); > - blk_queue_softirq_done(nullb->q, null_softirq_done_fn); > - blk_queue_rq_timed_out(nullb->q, null_rq_timed_out_fn); > - nullb->q->rq_timeout = 5 * HZ; > - rv = init_driver_queues(nullb); > - if (rv) > - goto out_cleanup_blk_queue; > } > > if (dev->mbps) { > @@ -1865,6 +1777,10 @@ static int __init null_init(void) > return -EINVAL; > } > > + if (g_queue_mode == NULL_Q_RQ) { > + pr_err("null_blk: legacy IO path no longer available\n"); > + return -EINVAL; > + } > if (g_queue_mode == NULL_Q_MQ && g_use_per_node_hctx) { > if (g_submit_queues != nr_online_nodes) { > pr_warn("null_blk: submit_queues param is set to %u.\n", > From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: From: Jens Axboe To: linux-block@vger.kernel.org Cc: Jens Axboe Subject: [PATCH 17/17] null_blk: remove legacy IO path Date: Thu, 11 Oct 2018 10:59:09 -0600 Message-Id: <20181011165909.32615-18-axboe@kernel.dk> In-Reply-To: <20181011165909.32615-1-axboe@kernel.dk> References: <20181011165909.32615-1-axboe@kernel.dk> List-ID: We're planning on removing this code completely, kill the old path. Signed-off-by: Jens Axboe --- drivers/block/null_blk_main.c | 96 +++-------------------------------- 1 file changed, 6 insertions(+), 90 deletions(-) diff --git a/drivers/block/null_blk_main.c b/drivers/block/null_blk_main.c index 093b614d6524..8142cc8ff952 100644 --- a/drivers/block/null_blk_main.c +++ b/drivers/block/null_blk_main.c @@ -616,10 +616,6 @@ static void end_cmd(struct nullb_cmd *cmd) case NULL_Q_MQ: blk_mq_end_request(cmd->rq, cmd->error); return; - case NULL_Q_RQ: - INIT_LIST_HEAD(&cmd->rq->queuelist); - blk_end_request_all(cmd->rq, cmd->error); - break; case NULL_Q_BIO: cmd->bio->bi_status = cmd->error; bio_endio(cmd->bio); @@ -627,15 +623,6 @@ static void end_cmd(struct nullb_cmd *cmd) } free_cmd(cmd); - - /* Restart queue if needed, as we are freeing a tag */ - if (queue_mode == NULL_Q_RQ && blk_queue_stopped(q)) { - unsigned long flags; - - spin_lock_irqsave(q->queue_lock, flags); - blk_start_queue_async(q); - spin_unlock_irqrestore(q->queue_lock, flags); - } } static enum hrtimer_restart null_cmd_timer_expired(struct hrtimer *timer) @@ -1197,17 +1184,8 @@ static blk_status_t null_handle_cmd(struct nullb_cmd *cmd) /* race with timer */ if (atomic_long_read(&nullb->cur_bytes) > 0) null_restart_queue_async(nullb); - if (dev->queue_mode == NULL_Q_RQ) { - struct request_queue *q = nullb->q; - - spin_lock_irq(q->queue_lock); - rq->rq_flags |= RQF_DONTPREP; - blk_requeue_request(q, rq); - spin_unlock_irq(q->queue_lock); - return BLK_STS_OK; - } else - /* requeue request */ - return BLK_STS_DEV_RESOURCE; + /* requeue request */ + return BLK_STS_DEV_RESOURCE; } } @@ -1278,9 +1256,6 @@ static blk_status_t null_handle_cmd(struct nullb_cmd *cmd) case NULL_Q_MQ: blk_mq_complete_request(cmd->rq); break; - case NULL_Q_RQ: - blk_complete_request(cmd->rq); - break; case NULL_Q_BIO: /* * XXX: no proper submitting cpu information available. @@ -1349,30 +1324,6 @@ static blk_qc_t null_queue_bio(struct request_queue *q, struct bio *bio) return BLK_QC_T_NONE; } -static enum blk_eh_timer_return null_rq_timed_out_fn(struct request *rq) -{ - pr_info("null: rq %p timed out\n", rq); - __blk_complete_request(rq); - return BLK_EH_DONE; -} - -static int null_rq_prep_fn(struct request_queue *q, struct request *req) -{ - struct nullb *nullb = q->queuedata; - struct nullb_queue *nq = nullb_to_queue(nullb); - struct nullb_cmd *cmd; - - cmd = alloc_cmd(nq, 0); - if (cmd) { - cmd->rq = req; - req->special = cmd; - return BLKPREP_OK; - } - blk_stop_queue(q); - - return BLKPREP_DEFER; -} - static bool should_timeout_request(struct request *rq) { #ifdef CONFIG_BLK_DEV_NULL_BLK_FAULT_INJECTION @@ -1391,27 +1342,6 @@ static bool should_requeue_request(struct request *rq) return false; } -static void null_request_fn(struct request_queue *q) -{ - struct request *rq; - - while ((rq = blk_fetch_request(q)) != NULL) { - struct nullb_cmd *cmd = rq->special; - - /* just ignore the request */ - if (should_timeout_request(rq)) - continue; - if (should_requeue_request(rq)) { - blk_requeue_request(q, rq); - continue; - } - - spin_unlock_irq(q->queue_lock); - null_handle_cmd(cmd); - spin_lock_irq(q->queue_lock); - } -} - static enum blk_eh_timer_return null_timeout_rq(struct request *rq, bool res) { pr_info("null: rq %p timed out\n", rq); @@ -1766,24 +1696,6 @@ static int null_add_dev(struct nullb_device *dev) rv = init_driver_queues(nullb); if (rv) goto out_cleanup_blk_queue; - } else { - nullb->q = blk_init_queue_node(null_request_fn, &nullb->lock, - dev->home_node); - if (!nullb->q) { - rv = -ENOMEM; - goto out_cleanup_queues; - } - - if (!null_setup_fault()) - goto out_cleanup_blk_queue; - - blk_queue_prep_rq(nullb->q, null_rq_prep_fn); - blk_queue_softirq_done(nullb->q, null_softirq_done_fn); - blk_queue_rq_timed_out(nullb->q, null_rq_timed_out_fn); - nullb->q->rq_timeout = 5 * HZ; - rv = init_driver_queues(nullb); - if (rv) - goto out_cleanup_blk_queue; } if (dev->mbps) { @@ -1865,6 +1777,10 @@ static int __init null_init(void) return -EINVAL; } + if (g_queue_mode == NULL_Q_RQ) { + pr_err("null_blk: legacy IO path no longer available\n"); + return -EINVAL; + } if (g_queue_mode == NULL_Q_MQ && g_use_per_node_hctx) { if (g_submit_queues != nr_online_nodes) { pr_warn("null_blk: submit_queues param is set to %u.\n", -- 2.17.1 From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: From: Jens Axboe To: linux-block@vger.kernel.org Cc: Jens Axboe Subject: [PATCH 09/17] mspro_block: convert to blk-mq Date: Thu, 11 Oct 2018 10:59:01 -0600 Message-Id: <20181011165909.32615-10-axboe@kernel.dk> In-Reply-To: <20181011165909.32615-1-axboe@kernel.dk> References: <20181011165909.32615-1-axboe@kernel.dk> List-ID: Straight forward conversion, there's room for improvement. Signed-off-by: Jens Axboe --- drivers/memstick/core/mspro_block.c | 133 ++++++++++++++++------------ 1 file changed, 78 insertions(+), 55 deletions(-) diff --git a/drivers/memstick/core/mspro_block.c b/drivers/memstick/core/mspro_block.c index 5ee932631fae..d55b398d16c4 100644 --- a/drivers/memstick/core/mspro_block.c +++ b/drivers/memstick/core/mspro_block.c @@ -12,7 +12,7 @@ * */ -#include +#include #include #include #include @@ -142,6 +142,7 @@ struct mspro_block_data { struct gendisk *disk; struct request_queue *queue; struct request *block_req; + struct blk_mq_tag_set tag_set; spinlock_t q_lock; unsigned short page_size; @@ -152,7 +153,6 @@ struct mspro_block_data { unsigned char system; unsigned char read_only:1, eject:1, - has_request:1, data_dir:1, active:1; unsigned char transfer_cmd; @@ -694,13 +694,12 @@ static void h_mspro_block_setup_cmd(struct memstick_dev *card, u64 offset, /*** Data transfer ***/ -static int mspro_block_issue_req(struct memstick_dev *card, int chunk) +static int mspro_block_issue_req(struct memstick_dev *card, bool chunk) { struct mspro_block_data *msb = memstick_get_drvdata(card); u64 t_off; unsigned int count; -try_again: while (chunk) { msb->current_page = 0; msb->current_seg = 0; @@ -709,9 +708,17 @@ static int mspro_block_issue_req(struct memstick_dev *card, int chunk) msb->req_sg); if (!msb->seg_count) { - chunk = __blk_end_request_cur(msb->block_req, - BLK_STS_RESOURCE); - continue; + unsigned int bytes = blk_rq_cur_bytes(msb->block_req); + + chunk = blk_update_request(msb->block_req, + BLK_STS_RESOURCE, + bytes); + if (chunk) + continue; + __blk_mq_end_request(msb->block_req, + BLK_STS_RESOURCE); + msb->block_req = NULL; + break; } t_off = blk_rq_pos(msb->block_req); @@ -729,30 +736,22 @@ static int mspro_block_issue_req(struct memstick_dev *card, int chunk) return 0; } - dev_dbg(&card->dev, "blk_fetch\n"); - msb->block_req = blk_fetch_request(msb->queue); - if (!msb->block_req) { - dev_dbg(&card->dev, "issue end\n"); - return -EAGAIN; - } - - dev_dbg(&card->dev, "trying again\n"); - chunk = 1; - goto try_again; + return 1; } static int mspro_block_complete_req(struct memstick_dev *card, int error) { struct mspro_block_data *msb = memstick_get_drvdata(card); - int chunk, cnt; + int cnt; + bool chunk; unsigned int t_len = 0; unsigned long flags; spin_lock_irqsave(&msb->q_lock, flags); - dev_dbg(&card->dev, "complete %d, %d\n", msb->has_request ? 1 : 0, + dev_dbg(&card->dev, "complete %d, %d\n", msb->block_req ? 1 : 0, error); - if (msb->has_request) { + if (msb->block_req) { /* Nothing to do - not really an error */ if (error == -EAGAIN) error = 0; @@ -777,15 +776,17 @@ static int mspro_block_complete_req(struct memstick_dev *card, int error) if (error && !t_len) t_len = blk_rq_cur_bytes(msb->block_req); - chunk = __blk_end_request(msb->block_req, + chunk = blk_update_request(msb->block_req, errno_to_blk_status(error), t_len); - - error = mspro_block_issue_req(card, chunk); - - if (!error) - goto out; - else - msb->has_request = 0; + if (chunk) { + error = mspro_block_issue_req(card, chunk); + if (!error) + goto out; + } else { + __blk_mq_end_request(msb->block_req, + errno_to_blk_status(error)); + msb->block_req = NULL; + } } else { if (!error) error = -EAGAIN; @@ -806,8 +807,8 @@ static void mspro_block_stop(struct memstick_dev *card) while (1) { spin_lock_irqsave(&msb->q_lock, flags); - if (!msb->has_request) { - blk_stop_queue(msb->queue); + if (!msb->block_req) { + blk_mq_stop_hw_queues(msb->queue); rc = 1; } spin_unlock_irqrestore(&msb->q_lock, flags); @@ -822,32 +823,37 @@ static void mspro_block_stop(struct memstick_dev *card) static void mspro_block_start(struct memstick_dev *card) { struct mspro_block_data *msb = memstick_get_drvdata(card); - unsigned long flags; - spin_lock_irqsave(&msb->q_lock, flags); - blk_start_queue(msb->queue); - spin_unlock_irqrestore(&msb->q_lock, flags); + blk_mq_start_hw_queues(msb->queue); } -static void mspro_block_submit_req(struct request_queue *q) +static blk_status_t mspro_queue_rq(struct blk_mq_hw_ctx *hctx, + const struct blk_mq_queue_data *bd) { - struct memstick_dev *card = q->queuedata; + struct memstick_dev *card = hctx->queue->queuedata; struct mspro_block_data *msb = memstick_get_drvdata(card); - struct request *req = NULL; - if (msb->has_request) - return; + spin_lock_irq(&msb->q_lock); - if (msb->eject) { - while ((req = blk_fetch_request(q)) != NULL) - __blk_end_request_all(req, BLK_STS_IOERR); + if (msb->block_req) { + spin_unlock_irq(&msb->q_lock); + return BLK_STS_DEV_RESOURCE; + } - return; + if (msb->eject) { + spin_unlock_irq(&msb->q_lock); + blk_mq_start_request(bd->rq); + return BLK_STS_IOERR; } - msb->has_request = 1; - if (mspro_block_issue_req(card, 0)) - msb->has_request = 0; + msb->block_req = bd->rq; + blk_mq_start_request(bd->rq); + + if (mspro_block_issue_req(card, true)) + msb->block_req = NULL; + + spin_unlock_irq(&msb->q_lock); + return BLK_STS_OK; } /*** Initialization ***/ @@ -1167,12 +1173,17 @@ static int mspro_block_init_card(struct memstick_dev *card) } +static const struct blk_mq_ops mspro_mq_ops = { + .queue_rq = mspro_queue_rq, +}; + static int mspro_block_init_disk(struct memstick_dev *card) { struct mspro_block_data *msb = memstick_get_drvdata(card); struct mspro_devinfo *dev_info = NULL; struct mspro_sys_info *sys_info = NULL; struct mspro_sys_attr *s_attr = NULL; + struct blk_mq_tag_set *set; int rc, disk_id; unsigned long capacity; @@ -1206,10 +1217,21 @@ static int mspro_block_init_disk(struct memstick_dev *card) goto out_release_id; } - msb->queue = blk_init_queue(mspro_block_submit_req, &msb->q_lock); - if (!msb->queue) { - rc = -ENOMEM; + set = &msb->tag_set; + set->ops = &mspro_mq_ops; + set->nr_hw_queues = 1; + set->queue_depth = 2; + set->numa_node = NUMA_NO_NODE; + set->flags = BLK_MQ_F_SHOULD_MERGE; + rc = blk_mq_alloc_tag_set(set); + if (rc) goto out_put_disk; + + msb->queue = blk_mq_init_queue(set); + if (IS_ERR(msb->queue)) { + rc = PTR_ERR(msb->queue); + msb->queue = NULL; + goto out_put_tag; } msb->queue->queuedata = card; @@ -1240,6 +1262,8 @@ static int mspro_block_init_disk(struct memstick_dev *card) msb->active = 1; return 0; +out_put_tag: + blk_mq_free_tag_set(&msb->tag_set); out_put_disk: put_disk(msb->disk); out_release_id: @@ -1318,12 +1342,13 @@ static void mspro_block_remove(struct memstick_dev *card) spin_lock_irqsave(&msb->q_lock, flags); msb->eject = 1; - blk_start_queue(msb->queue); spin_unlock_irqrestore(&msb->q_lock, flags); + blk_mq_start_hw_queues(msb->queue); del_gendisk(msb->disk); dev_dbg(&card->dev, "mspro block remove\n"); + blk_mq_free_tag_set(msb->queue->tag_set); blk_cleanup_queue(msb->queue); msb->queue = NULL; @@ -1344,8 +1369,9 @@ static int mspro_block_suspend(struct memstick_dev *card, pm_message_t state) struct mspro_block_data *msb = memstick_get_drvdata(card); unsigned long flags; + blk_mq_stop_hw_queues(msb->queue); + spin_lock_irqsave(&msb->q_lock, flags); - blk_stop_queue(msb->queue); msb->active = 0; spin_unlock_irqrestore(&msb->q_lock, flags); @@ -1355,7 +1381,6 @@ static int mspro_block_suspend(struct memstick_dev *card, pm_message_t state) static int mspro_block_resume(struct memstick_dev *card) { struct mspro_block_data *msb = memstick_get_drvdata(card); - unsigned long flags; int rc = 0; #ifdef CONFIG_MEMSTICK_UNSAFE_RESUME @@ -1401,9 +1426,7 @@ static int mspro_block_resume(struct memstick_dev *card) #endif /* CONFIG_MEMSTICK_UNSAFE_RESUME */ - spin_lock_irqsave(&msb->q_lock, flags); - blk_start_queue(msb->queue); - spin_unlock_irqrestore(&msb->q_lock, flags); + blk_mq_start_hw_queues(msb->queue); return rc; } -- 2.17.1 From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: From: Richard Weinberger To: Jens Axboe Cc: linux-block@vger.kernel.org, linux-mtd@lists.infradead.org, David Woodhouse Subject: Re: [PATCH 16/17] mtd_blkdevs: convert to blk-mq Date: Thu, 11 Oct 2018 23:31:31 +0200 Message-ID: <3224309.SPdaaRQAfj@blindfold> In-Reply-To: <6ac34916-e35d-d8d7-77d5-da83260714fc@kernel.dk> References: <20181011165909.32615-1-axboe@kernel.dk> <19488748.6iqVKhkDGp@blindfold> <6ac34916-e35d-d8d7-77d5-da83260714fc@kernel.dk> MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" List-ID: Am Donnerstag, 11. Oktober 2018, 23:21:56 CEST schrieb Jens Axboe: > >> if (!blk_update_request(req, res, blk_rq_cur_bytes(req))) { > >> - req = NULL; > >> __blk_mq_end_request(req, res); > >> + req = NULL; > > > > Hehe. :-) > > With this fix applied it works and passes my trivial test. > > Great, thanks for testing! Can I add your tested-by to it? Sure. Thanks, //richard From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Subject: Re: [PATCH 16/17] mtd_blkdevs: convert to blk-mq To: Richard Weinberger , linux-block@vger.kernel.org Cc: linux-mtd@lists.infradead.org, David Woodhouse References: <20181011165909.32615-1-axboe@kernel.dk> <263ca89f-94e4-1238-e396-8fb0a0111f97@kernel.dk> <19488748.6iqVKhkDGp@blindfold> From: Jens Axboe Message-ID: <6ac34916-e35d-d8d7-77d5-da83260714fc@kernel.dk> Date: Thu, 11 Oct 2018 15:21:56 -0600 MIME-Version: 1.0 In-Reply-To: <19488748.6iqVKhkDGp@blindfold> Content-Type: text/plain; charset=utf-8 List-ID: On 10/11/18 3:18 PM, Richard Weinberger wrote: > Jens, > > Am Donnerstag, 11. Oktober 2018, 23:14:07 CEST schrieb Jens Axboe: >> On 10/11/18 3:03 PM, Richard Weinberger wrote: >>> Jens, >>> >>> On Thu, Oct 11, 2018 at 7:00 PM Jens Axboe wrote: >>>> >>>> Straight forward conversion, using an internal list to enable the >>>> driver to pull requests at will. >>>> >>>> Dynamically allocate the tag set to avoid having to pull in the >>>> block headers for blktrans.h, since various mtd drivers use >>>> block conflicting names for defines and functions. >>> >>> This explodes on my test system. :-/ >> >> I think I see it, that was pretty stupid... Can you try with this one >> on top as well? >> >> diff --git a/drivers/mtd/mtd_blkdevs.c b/drivers/mtd/mtd_blkdevs.c >> index c26d692781af..e8f8fddce063 100644 >> --- a/drivers/mtd/mtd_blkdevs.c >> +++ b/drivers/mtd/mtd_blkdevs.c >> @@ -187,8 +187,8 @@ static void mtd_blktrans_work(struct mtd_blktrans_dev *dev) >> mutex_unlock(&dev->lock); >> >> if (!blk_update_request(req, res, blk_rq_cur_bytes(req))) { >> - req = NULL; >> __blk_mq_end_request(req, res); >> + req = NULL; > > Hehe. :-) > With this fix applied it works and passes my trivial test. Great, thanks for testing! Can I add your tested-by to it? -- Jens Axboe From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: From: Richard Weinberger To: Jens Axboe , linux-block@vger.kernel.org Cc: linux-mtd@lists.infradead.org, David Woodhouse Subject: Re: [PATCH 16/17] mtd_blkdevs: convert to blk-mq Date: Thu, 11 Oct 2018 23:18:55 +0200 Message-ID: <19488748.6iqVKhkDGp@blindfold> In-Reply-To: <263ca89f-94e4-1238-e396-8fb0a0111f97@kernel.dk> References: <20181011165909.32615-1-axboe@kernel.dk> <263ca89f-94e4-1238-e396-8fb0a0111f97@kernel.dk> MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" List-ID: Jens, Am Donnerstag, 11. Oktober 2018, 23:14:07 CEST schrieb Jens Axboe: > On 10/11/18 3:03 PM, Richard Weinberger wrote: > > Jens, > > > > On Thu, Oct 11, 2018 at 7:00 PM Jens Axboe wrote: > >> > >> Straight forward conversion, using an internal list to enable the > >> driver to pull requests at will. > >> > >> Dynamically allocate the tag set to avoid having to pull in the > >> block headers for blktrans.h, since various mtd drivers use > >> block conflicting names for defines and functions. > > > > This explodes on my test system. :-/ > > I think I see it, that was pretty stupid... Can you try with this one > on top as well? > > diff --git a/drivers/mtd/mtd_blkdevs.c b/drivers/mtd/mtd_blkdevs.c > index c26d692781af..e8f8fddce063 100644 > --- a/drivers/mtd/mtd_blkdevs.c > +++ b/drivers/mtd/mtd_blkdevs.c > @@ -187,8 +187,8 @@ static void mtd_blktrans_work(struct mtd_blktrans_dev *dev) > mutex_unlock(&dev->lock); > > if (!blk_update_request(req, res, blk_rq_cur_bytes(req))) { > - req = NULL; > __blk_mq_end_request(req, res); > + req = NULL; Hehe. :-) With this fix applied it works and passes my trivial test. Thanks, //richard From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Subject: Re: [PATCH 16/17] mtd_blkdevs: convert to blk-mq To: Richard Weinberger Cc: linux-block@vger.kernel.org, "linux-mtd @ lists . infradead . org" , David Woodhouse References: <20181011165909.32615-1-axboe@kernel.dk> <20181011165909.32615-17-axboe@kernel.dk> From: Jens Axboe Message-ID: <263ca89f-94e4-1238-e396-8fb0a0111f97@kernel.dk> Date: Thu, 11 Oct 2018 15:14:07 -0600 MIME-Version: 1.0 In-Reply-To: Content-Type: text/plain; charset=utf-8 List-ID: On 10/11/18 3:03 PM, Richard Weinberger wrote: > Jens, > > On Thu, Oct 11, 2018 at 7:00 PM Jens Axboe wrote: >> >> Straight forward conversion, using an internal list to enable the >> driver to pull requests at will. >> >> Dynamically allocate the tag set to avoid having to pull in the >> block headers for blktrans.h, since various mtd drivers use >> block conflicting names for defines and functions. > > This explodes on my test system. :-/ I think I see it, that was pretty stupid... Can you try with this one on top as well? diff --git a/drivers/mtd/mtd_blkdevs.c b/drivers/mtd/mtd_blkdevs.c index c26d692781af..e8f8fddce063 100644 --- a/drivers/mtd/mtd_blkdevs.c +++ b/drivers/mtd/mtd_blkdevs.c @@ -187,8 +187,8 @@ static void mtd_blktrans_work(struct mtd_blktrans_dev *dev) mutex_unlock(&dev->lock); if (!blk_update_request(req, res, blk_rq_cur_bytes(req))) { - req = NULL; __blk_mq_end_request(req, res); + req = NULL; } background_done = 0; -- Jens Axboe From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: MIME-Version: 1.0 References: <20181011165909.32615-1-axboe@kernel.dk> <20181011165909.32615-17-axboe@kernel.dk> In-Reply-To: <20181011165909.32615-17-axboe@kernel.dk> From: Richard Weinberger Date: Thu, 11 Oct 2018 23:03:55 +0200 Message-ID: Subject: Re: [PATCH 16/17] mtd_blkdevs: convert to blk-mq To: Jens Axboe Cc: linux-block@vger.kernel.org, "linux-mtd @ lists . infradead . org" , David Woodhouse Content-Type: text/plain; charset="UTF-8" List-ID: Jens, On Thu, Oct 11, 2018 at 7:00 PM Jens Axboe wrote: > > Straight forward conversion, using an internal list to enable the > driver to pull requests at will. > > Dynamically allocate the tag set to avoid having to pull in the > block headers for blktrans.h, since various mtd drivers use > block conflicting names for defines and functions. This explodes on my test system. :-/ [ 2.236594] BUG: unable to handle kernel NULL pointer dereference at 000000000000001a [ 2.237621] PGD 0 P4D 0 [ 2.237968] Oops: 0000 [#1] SMP PTI [ 2.238425] CPU: 3 PID: 1110 Comm: kworker/3:1H Not tainted 4.19.0-rc7+ #143 [ 2.239331] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.0.0-prebuilt.qemu-project.org 04/01/2014 [ 2.240893] Workqueue: kblockd blk_mq_run_work_fn [ 2.241533] RIP: 0010:__blk_mq_end_request+0xe/0xb0 [ 2.242212] Code: 44 21 c2 48 0f a3 10 73 02 f3 c3 f0 48 0f ab 10 c3 90 66 2e 0f 1f 84 00 00 00 00 00 41 54 55 89 f5 53 48 89 fb e8 f2 80 d6 ff 43 1a 02 49 89 c4 75 4f 4c 89 e6 48 89 df e8 4e 69 ff ff 48 83 [ 2.244798] RSP: 0018:ffffac65c2c43d20 EFLAGS: 00010216 [ 2.245469] RAX: 000000007caad848 RBX: 0000000000000000 RCX: 0000000000000017 [ 2.246382] RDX: 0000031c57000000 RSI: 001778d956000000 RDI: ffffffffa4cc70c0 [ 2.247296] RBP: 0000000000000000 R08: 00000000d2a4b8d8 R09: ffffffffa355ead3 [ 2.248208] R10: fffff1a2c5e46740 R11: ffffffffff76acba R12: 0000000000000000 [ 2.249123] R13: ffffa117793ff720 R14: ffffffffa46c7120 R15: 000000000007ff88 [ 2.259551] FS: 0000000000000000(0000) GS:ffffa1177ab80000(0000) knlGS:0000000000000000 [ 2.259552] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 2.259553] CR2: 000000000000001a CR3: 0000000177d44000 CR4: 00000000000006e0 [ 2.259560] Call Trace: [ 2.259630] mtd_queue_rq+0x1fa/0x400 [ 2.259661] blk_mq_dispatch_rq_list+0x8b/0x510 [ 2.259672] ? elv_rqhash_add+0x1/0x60 [ 2.259680] ? deadline_remove_request+0x44/0xa0 [ 2.259684] blk_mq_do_dispatch_sched+0x5a/0xf0 [ 2.259690] blk_mq_sched_dispatch_requests+0xf0/0x160 [ 2.259697] __blk_mq_run_hw_queue+0x49/0xc0 [ 2.259705] process_one_work+0x1e9/0x3d0 [ 2.259726] worker_thread+0x28/0x3d0 [ 2.259728] ? process_one_work+0x3d0/0x3d0 [ 2.259732] kthread+0x10e/0x130 [ 2.259740] ? kthread_create_worker_on_cpu+0x70/0x70 [ 2.259750] ret_from_fork+0x35/0x40 [ 2.259763] Modules linked in: [ 2.259767] CR2: 000000000000001a [ 2.259772] ---[ end trace b08076f7e1ed1f91 ]--- [ 2.259774] RIP: 0010:__blk_mq_end_request+0xe/0xb0 [ 2.259776] Code: 44 21 c2 48 0f a3 10 73 02 f3 c3 f0 48 0f ab 10 c3 90 66 2e 0f 1f 84 00 00 00 00 00 41 54 55 89 f5 53 48 89 fb e8 f2 80 d6 ff 43 1a 02 49 89 c4 75 4f 4c 89 e6 48 89 df e8 4e 69 ff ff 48 83 [ 2.259777] RSP: 0018:ffffac65c2c43d20 EFLAGS: 00010216 [ 2.259778] RAX: 000000007caad848 RBX: 0000000000000000 RCX: 0000000000000017 [ 2.259779] RDX: 0000031c57000000 RSI: 001778d956000000 RDI: ffffffffa4cc70c0 [ 2.259780] RBP: 0000000000000000 R08: 00000000d2a4b8d8 R09: ffffffffa355ead3 [ 2.259780] R10: fffff1a2c5e46740 R11: ffffffffff76acba R12: 0000000000000000 [ 2.259781] R13: ffffa117793ff720 R14: ffffffffa46c7120 R15: 000000000007ff88 [ 2.259782] FS: 0000000000000000(0000) GS:ffffa1177ab80000(0000) knlGS:0000000000000000 [ 2.259783] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 2.259784] CR2: 000000000000001a CR3: 0000000177d44000 CR4: 00000000000006e0 [ 2.259786] Kernel panic - not syncing: Fatal exception [ 2.261997] Kernel Offset: 0x22200000 from 0xffffffff81000000 (relocation range: 0xffffffff80000000-0xffffffffbfffffff) -- Thanks, //richard From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: From: Jens Axboe To: linux-block@vger.kernel.org Cc: Jens Axboe , David Woodhouse , linux-mtd@lists.infradead.org Subject: [PATCH 16/17] mtd_blkdevs: convert to blk-mq Date: Thu, 11 Oct 2018 10:59:08 -0600 Message-Id: <20181011165909.32615-17-axboe@kernel.dk> In-Reply-To: <20181011165909.32615-1-axboe@kernel.dk> References: <20181011165909.32615-1-axboe@kernel.dk> List-ID: Straight forward conversion, using an internal list to enable the driver to pull requests at will. Dynamically allocate the tag set to avoid having to pull in the block headers for blktrans.h, since various mtd drivers use block conflicting names for defines and functions. Cc: David Woodhouse Cc: linux-mtd@lists.infradead.org Signed-off-by: Jens Axboe --- drivers/mtd/mtd_blkdevs.c | 109 +++++++++++++++++++++++------------ include/linux/mtd/blktrans.h | 5 +- 2 files changed, 74 insertions(+), 40 deletions(-) diff --git a/drivers/mtd/mtd_blkdevs.c b/drivers/mtd/mtd_blkdevs.c index 29c0bfd74e8a..6a94cffbca20 100644 --- a/drivers/mtd/mtd_blkdevs.c +++ b/drivers/mtd/mtd_blkdevs.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -44,6 +45,8 @@ static void blktrans_dev_release(struct kref *kref) container_of(kref, struct mtd_blktrans_dev, ref); dev->disk->private_data = NULL; + blk_mq_free_tag_set(dev->tag_set); + kfree(dev->tag_set); blk_cleanup_queue(dev->rq); put_disk(dev->disk); list_del(&dev->list); @@ -134,28 +137,37 @@ int mtd_blktrans_cease_background(struct mtd_blktrans_dev *dev) } EXPORT_SYMBOL_GPL(mtd_blktrans_cease_background); -static void mtd_blktrans_work(struct work_struct *work) +static struct request *mtd_next_request(struct mtd_blktrans_dev *dev) +{ + struct request *rq; + + rq = list_first_entry_or_null(&dev->rq_list, struct request, queuelist); + if (rq) { + list_del_init(&rq->queuelist); + blk_mq_start_request(rq); + return rq; + } + + return NULL; +} + +static void mtd_blktrans_work(struct mtd_blktrans_dev *dev) { - struct mtd_blktrans_dev *dev = - container_of(work, struct mtd_blktrans_dev, work); struct mtd_blktrans_ops *tr = dev->tr; - struct request_queue *rq = dev->rq; struct request *req = NULL; int background_done = 0; - spin_lock_irq(rq->queue_lock); - while (1) { blk_status_t res; dev->bg_stop = false; - if (!req && !(req = blk_fetch_request(rq))) { + if (!req && !(req = mtd_next_request(dev))) { if (tr->background && !background_done) { - spin_unlock_irq(rq->queue_lock); + spin_unlock_irq(&dev->queue_lock); mutex_lock(&dev->lock); tr->background(dev); mutex_unlock(&dev->lock); - spin_lock_irq(rq->queue_lock); + spin_lock_irq(&dev->queue_lock); /* * Do background processing just once per idle * period. @@ -166,35 +178,39 @@ static void mtd_blktrans_work(struct work_struct *work) break; } - spin_unlock_irq(rq->queue_lock); + spin_unlock_irq(&dev->queue_lock); mutex_lock(&dev->lock); res = do_blktrans_request(dev->tr, dev, req); mutex_unlock(&dev->lock); - spin_lock_irq(rq->queue_lock); - - if (!__blk_end_request_cur(req, res)) + if (!blk_update_request(req, res, blk_rq_cur_bytes(req))) { req = NULL; + __blk_mq_end_request(req, res); + } background_done = 0; + spin_lock_irq(&dev->queue_lock); } - - spin_unlock_irq(rq->queue_lock); } -static void mtd_blktrans_request(struct request_queue *rq) +static blk_status_t mtd_queue_rq(struct blk_mq_hw_ctx *hctx, + const struct blk_mq_queue_data *bd) { struct mtd_blktrans_dev *dev; - struct request *req = NULL; - dev = rq->queuedata; + dev = hctx->queue->queuedata; + if (!dev) { + blk_mq_start_request(bd->rq); + return BLK_STS_IOERR; + } + + spin_lock_irq(&dev->queue_lock); + list_add_tail(&bd->rq->queuelist, &dev->rq_list); + mtd_blktrans_work(dev); + spin_unlock_irq(&dev->queue_lock); - if (!dev) - while ((req = blk_fetch_request(rq)) != NULL) - __blk_end_request_all(req, BLK_STS_IOERR); - else - queue_work(dev->wq, &dev->work); + return BLK_STS_OK; } static int blktrans_open(struct block_device *bdev, fmode_t mode) @@ -329,9 +345,14 @@ static const struct block_device_operations mtd_block_ops = { .getgeo = blktrans_getgeo, }; +static const struct blk_mq_ops mtd_mq_ops = { + .queue_rq = mtd_queue_rq, +}; + int add_mtd_blktrans_dev(struct mtd_blktrans_dev *new) { struct mtd_blktrans_ops *tr = new->tr; + struct blk_mq_tag_set *set; struct mtd_blktrans_dev *d; int last_devnum = -1; struct gendisk *gd; @@ -416,11 +437,28 @@ int add_mtd_blktrans_dev(struct mtd_blktrans_dev *new) /* Create the request queue */ spin_lock_init(&new->queue_lock); - new->rq = blk_init_queue(mtd_blktrans_request, &new->queue_lock); + INIT_LIST_HEAD(&new->rq_list); - if (!new->rq) + new->tag_set = kzalloc(sizeof(*new->tag_set), GFP_KERNEL); + if (!new->tag_set) goto error3; + set = new->tag_set; + set->ops = &mtd_mq_ops; + set->nr_hw_queues = 1; + set->queue_depth = 2; + set->numa_node = NUMA_NO_NODE; + set->flags = BLK_MQ_F_SHOULD_MERGE | BLK_MQ_F_BLOCKING; + ret = blk_mq_alloc_tag_set(set); + if (ret) + goto error4; + + new->rq = blk_mq_init_queue(set); + if (!new->rq) { + blk_mq_free_tag_set(new->tag_set); + goto error5; + } + if (tr->flush) blk_queue_write_cache(new->rq, true, false); @@ -437,13 +475,6 @@ int add_mtd_blktrans_dev(struct mtd_blktrans_dev *new) gd->queue = new->rq; - /* Create processing workqueue */ - new->wq = alloc_workqueue("%s%d", 0, 0, - tr->name, new->mtd->index); - if (!new->wq) - goto error4; - INIT_WORK(&new->work, mtd_blktrans_work); - if (new->readonly) set_disk_ro(gd, 1); @@ -455,8 +486,10 @@ int add_mtd_blktrans_dev(struct mtd_blktrans_dev *new) WARN_ON(ret); } return 0; +error5: + blk_mq_free_tag_set(new->tag_set); error4: - blk_cleanup_queue(new->rq); + kfree(new->tag_set); error3: put_disk(new->disk); error2: @@ -481,15 +514,17 @@ int del_mtd_blktrans_dev(struct mtd_blktrans_dev *old) /* Stop new requests to arrive */ del_gendisk(old->disk); - /* Stop workqueue. This will perform any pending request. */ - destroy_workqueue(old->wq); - /* Kill current requests */ spin_lock_irqsave(&old->queue_lock, flags); old->rq->queuedata = NULL; - blk_start_queue(old->rq); spin_unlock_irqrestore(&old->queue_lock, flags); + /* freeze+quiesce queue to ensure all requests are flushed */ + blk_mq_freeze_queue(old->rq); + blk_mq_quiesce_queue(old->rq); + blk_mq_unquiesce_queue(old->rq); + blk_mq_unfreeze_queue(old->rq); + /* If the device is currently open, tell trans driver to close it, then put mtd device, and don't touch it again */ mutex_lock(&old->lock); diff --git a/include/linux/mtd/blktrans.h b/include/linux/mtd/blktrans.h index e93837f647de..1d3ade69d39a 100644 --- a/include/linux/mtd/blktrans.h +++ b/include/linux/mtd/blktrans.h @@ -23,7 +23,6 @@ #include #include #include -#include struct hd_geometry; struct mtd_info; @@ -44,9 +43,9 @@ struct mtd_blktrans_dev { struct kref ref; struct gendisk *disk; struct attribute_group *disk_attributes; - struct workqueue_struct *wq; - struct work_struct work; struct request_queue *rq; + struct list_head rq_list; + struct blk_mq_tag_set *tag_set; spinlock_t queue_lock; void *priv; fmode_t file_mode; -- 2.17.1