Message ID | 20210602065345.355274-10-hch@lst.de |
---|---|
State | New |
Headers | show |
Series | None | expand |
Hi, On 02.06.2021 08:53, Christoph Hellwig wrote: > Use the blk_mq_alloc_disk API to simplify the gendisk and request_queue > allocation. > > Signed-off-by: Christoph Hellwig <hch@lst.de> This patch landed in linux-next as commit 6966bb921def ("mtd_blkdevs: use blk_mq_alloc_disk"). It causes the following regression on my QEMU arm64 setup: Using buffer write method Concatenating MTD devices: (0): "0.flash" (1): "0.flash" into device "0.flash" Unable to handle kernel NULL pointer dereference at virtual address 0000000000000068 Mem abort info: ESR = 0x96000004 EC = 0x25: DABT (current EL), IL = 32 bits SET = 0, FnV = 0 EA = 0, S1PTW = 0 Data abort info: ISV = 0, ISS = 0x00000004 CM = 0, WnR = 0 [0000000000000068] user address but active_mm is swapper Internal error: Oops: 96000004 [#1] PREEMPT SMP Modules linked in: CPU: 0 PID: 1 Comm: swapper/0 Not tainted 5.13.0-rc3+ #10492 Hardware name: linux,dummy-virt (DT) pstate: 00000005 (nzcv daif -PAN -UAO -TCO BTYPE=--) pc : blk_finish_plug+0x5c/0x268 lr : blk_queue_write_cache+0x28/0x70 ... Call trace: blk_finish_plug+0x5c/0x268 add_mtd_blktrans_dev+0x270/0x420 mtdblock_add_mtd+0x68/0x98 blktrans_notify_add+0x44/0x70 add_mtd_device+0x41c/0x490 mtd_device_parse_register+0xf4/0x1c8 physmap_flash_probe+0x44c/0x780 platform_probe+0x90/0xd8 really_probe+0x108/0x3c0 driver_probe_device+0x60/0xc0 device_driver_attach+0x6c/0x78 __driver_attach+0xc0/0x100 bus_for_each_dev+0x68/0xc8 driver_attach+0x20/0x28 bus_add_driver+0x168/0x1f8 driver_register+0x60/0x110 __platform_driver_register+0x24/0x30 physmap_init+0x18/0x20 do_one_initcall+0x84/0x450 kernel_init_freeable+0x2dc/0x334 kernel_init+0x10/0x110 ret_from_fork+0x10/0x18 Code: 88027c01 35ffffa2 17fff079 f9800031 (c85f7c22) ---[ end trace b774518e0766cc92 ]--- Kernel panic - not syncing: Attempted to kill init! exitcode=0x0000000b SMP: stopping secondary CPUs Kernel Offset: 0x594d1fa00000 from 0xffff800010000000 PHYS_OFFSET: 0xffffea7300000000 CPU features: 0x11000671,00000846 Memory Limit: none ---[ end Kernel panic - not syncing: Attempted to kill init! exitcode=0x0000000b ]--- > --- > drivers/mtd/mtd_blkdevs.c | 48 ++++++++++++++++++--------------------- > 1 file changed, 22 insertions(+), 26 deletions(-) > > diff --git a/drivers/mtd/mtd_blkdevs.c b/drivers/mtd/mtd_blkdevs.c > index fb8e12d590a1..5dc4c966ea73 100644 > --- a/drivers/mtd/mtd_blkdevs.c > +++ b/drivers/mtd/mtd_blkdevs.c > @@ -30,11 +30,9 @@ static void blktrans_dev_release(struct kref *kref) > struct mtd_blktrans_dev *dev = > container_of(kref, struct mtd_blktrans_dev, ref); > > - dev->disk->private_data = NULL; > - blk_cleanup_queue(dev->rq); > + blk_cleanup_disk(dev->disk); > blk_mq_free_tag_set(dev->tag_set); > kfree(dev->tag_set); > - put_disk(dev->disk); > list_del(&dev->list); > kfree(dev); > } > @@ -354,7 +352,7 @@ int add_mtd_blktrans_dev(struct mtd_blktrans_dev *new) > if (new->devnum > (MINORMASK >> tr->part_bits) || > (tr->part_bits && new->devnum >= 27 * 26)) { > mutex_unlock(&blktrans_ref_mutex); > - goto error1; > + return ret; > } > > list_add_tail(&new->list, &tr->devs); > @@ -366,17 +364,28 @@ int add_mtd_blktrans_dev(struct mtd_blktrans_dev *new) > if (!tr->writesect) > new->readonly = 1; > > - /* Create gendisk */ > ret = -ENOMEM; > - gd = alloc_disk(1 << tr->part_bits); > + new->tag_set = kzalloc(sizeof(*new->tag_set), GFP_KERNEL); > + if (!new->tag_set) > + goto out_list_del; > > - if (!gd) > - goto error2; > + ret = blk_mq_alloc_sq_tag_set(new->tag_set, &mtd_mq_ops, 2, > + BLK_MQ_F_SHOULD_MERGE | BLK_MQ_F_BLOCKING); > + if (ret) > + goto out_kfree_tag_set; > + > + /* Create gendisk */ > + gd = blk_mq_alloc_disk(new->tag_set, new); > + if (IS_ERR(gd)) { > + ret = PTR_ERR(gd); > + goto out_free_tag_set; > + } > > new->disk = gd; > gd->private_data = new; > gd->major = tr->major; > gd->first_minor = (new->devnum) << tr->part_bits; > + gd->minors = 1 << tr->part_bits; > gd->fops = &mtd_block_ops; > > if (tr->part_bits) > @@ -398,22 +407,9 @@ int add_mtd_blktrans_dev(struct mtd_blktrans_dev *new) > spin_lock_init(&new->queue_lock); > INIT_LIST_HEAD(&new->rq_list); > > - new->tag_set = kzalloc(sizeof(*new->tag_set), GFP_KERNEL); > - if (!new->tag_set) > - goto error3; > - > - new->rq = blk_mq_init_sq_queue(new->tag_set, &mtd_mq_ops, 2, > - BLK_MQ_F_SHOULD_MERGE | BLK_MQ_F_BLOCKING); > - if (IS_ERR(new->rq)) { > - ret = PTR_ERR(new->rq); > - new->rq = NULL; > - goto error4; > - } > - > if (tr->flush) > blk_queue_write_cache(new->rq, true, false); > > - new->rq->queuedata = new; > blk_queue_logical_block_size(new->rq, tr->blksize); > > blk_queue_flag_set(QUEUE_FLAG_NONROT, new->rq); > @@ -437,13 +433,13 @@ int add_mtd_blktrans_dev(struct mtd_blktrans_dev *new) > WARN_ON(ret); > } > return 0; > -error4: > + > +out_free_tag_set: > + blk_mq_free_tag_set(new->tag_set); > +out_kfree_tag_set: > kfree(new->tag_set); > -error3: > - put_disk(new->disk); > -error2: > +out_list_del: > list_del(&new->list); > -error1: > return ret; > } > Best regards -- Marek Szyprowski, PhD Samsung R&D Institute Poland
On Tue, Jun 15, 2021 at 05:47:44PM +0200, Marek Szyprowski wrote: > Hi, > > On 02.06.2021 08:53, Christoph Hellwig wrote: > > Use the blk_mq_alloc_disk API to simplify the gendisk and request_queue > > allocation. > > > > Signed-off-by: Christoph Hellwig <hch@lst.de> > > This patch landed in linux-next as commit 6966bb921def ("mtd_blkdevs: > use blk_mq_alloc_disk"). It causes the following regression on my QEMU > arm64 setup: Please try the patch below: diff --git a/drivers/mtd/mtd_blkdevs.c b/drivers/mtd/mtd_blkdevs.c index 5dc4c966ea73..6ce4bc57f919 100644 --- a/drivers/mtd/mtd_blkdevs.c +++ b/drivers/mtd/mtd_blkdevs.c @@ -382,6 +382,7 @@ int add_mtd_blktrans_dev(struct mtd_blktrans_dev *new) } new->disk = gd; + new->rq = new->disk->queue; gd->private_data = new; gd->major = tr->major; gd->first_minor = (new->devnum) << tr->part_bits;
Hi Christoph, On 15.06.2021 17:58, Christoph Hellwig wrote: > On Tue, Jun 15, 2021 at 05:47:44PM +0200, Marek Szyprowski wrote: >> On 02.06.2021 08:53, Christoph Hellwig wrote: >>> Use the blk_mq_alloc_disk API to simplify the gendisk and request_queue >>> allocation. >>> >>> Signed-off-by: Christoph Hellwig <hch@lst.de> >> This patch landed in linux-next as commit 6966bb921def ("mtd_blkdevs: >> use blk_mq_alloc_disk"). It causes the following regression on my QEMU >> arm64 setup: > Please try the patch below: > > diff --git a/drivers/mtd/mtd_blkdevs.c b/drivers/mtd/mtd_blkdevs.c > index 5dc4c966ea73..6ce4bc57f919 100644 > --- a/drivers/mtd/mtd_blkdevs.c > +++ b/drivers/mtd/mtd_blkdevs.c > @@ -382,6 +382,7 @@ int add_mtd_blktrans_dev(struct mtd_blktrans_dev *new) > } > > new->disk = gd; > + new->rq = new->disk->queue; > gd->private_data = new; > gd->major = tr->major; > gd->first_minor = (new->devnum) << tr->part_bits; Right, this fixes the issue, thanks. Feel free to add: Reported-by: Marek Szyprowski <m.szyprowski@samsung.com> Tested-by: Marek Szyprowski <m.szyprowski@samsung.com> Best regards -- Marek Szyprowski, PhD Samsung R&D Institute Poland
diff --git a/drivers/mtd/mtd_blkdevs.c b/drivers/mtd/mtd_blkdevs.c index fb8e12d590a1..5dc4c966ea73 100644 --- a/drivers/mtd/mtd_blkdevs.c +++ b/drivers/mtd/mtd_blkdevs.c @@ -30,11 +30,9 @@ static void blktrans_dev_release(struct kref *kref) struct mtd_blktrans_dev *dev = container_of(kref, struct mtd_blktrans_dev, ref); - dev->disk->private_data = NULL; - blk_cleanup_queue(dev->rq); + blk_cleanup_disk(dev->disk); blk_mq_free_tag_set(dev->tag_set); kfree(dev->tag_set); - put_disk(dev->disk); list_del(&dev->list); kfree(dev); } @@ -354,7 +352,7 @@ int add_mtd_blktrans_dev(struct mtd_blktrans_dev *new) if (new->devnum > (MINORMASK >> tr->part_bits) || (tr->part_bits && new->devnum >= 27 * 26)) { mutex_unlock(&blktrans_ref_mutex); - goto error1; + return ret; } list_add_tail(&new->list, &tr->devs); @@ -366,17 +364,28 @@ int add_mtd_blktrans_dev(struct mtd_blktrans_dev *new) if (!tr->writesect) new->readonly = 1; - /* Create gendisk */ ret = -ENOMEM; - gd = alloc_disk(1 << tr->part_bits); + new->tag_set = kzalloc(sizeof(*new->tag_set), GFP_KERNEL); + if (!new->tag_set) + goto out_list_del; - if (!gd) - goto error2; + ret = blk_mq_alloc_sq_tag_set(new->tag_set, &mtd_mq_ops, 2, + BLK_MQ_F_SHOULD_MERGE | BLK_MQ_F_BLOCKING); + if (ret) + goto out_kfree_tag_set; + + /* Create gendisk */ + gd = blk_mq_alloc_disk(new->tag_set, new); + if (IS_ERR(gd)) { + ret = PTR_ERR(gd); + goto out_free_tag_set; + } new->disk = gd; gd->private_data = new; gd->major = tr->major; gd->first_minor = (new->devnum) << tr->part_bits; + gd->minors = 1 << tr->part_bits; gd->fops = &mtd_block_ops; if (tr->part_bits) @@ -398,22 +407,9 @@ int add_mtd_blktrans_dev(struct mtd_blktrans_dev *new) spin_lock_init(&new->queue_lock); INIT_LIST_HEAD(&new->rq_list); - new->tag_set = kzalloc(sizeof(*new->tag_set), GFP_KERNEL); - if (!new->tag_set) - goto error3; - - new->rq = blk_mq_init_sq_queue(new->tag_set, &mtd_mq_ops, 2, - BLK_MQ_F_SHOULD_MERGE | BLK_MQ_F_BLOCKING); - if (IS_ERR(new->rq)) { - ret = PTR_ERR(new->rq); - new->rq = NULL; - goto error4; - } - if (tr->flush) blk_queue_write_cache(new->rq, true, false); - new->rq->queuedata = new; blk_queue_logical_block_size(new->rq, tr->blksize); blk_queue_flag_set(QUEUE_FLAG_NONROT, new->rq); @@ -437,13 +433,13 @@ int add_mtd_blktrans_dev(struct mtd_blktrans_dev *new) WARN_ON(ret); } return 0; -error4: + +out_free_tag_set: + blk_mq_free_tag_set(new->tag_set); +out_kfree_tag_set: kfree(new->tag_set); -error3: - put_disk(new->disk); -error2: +out_list_del: list_del(&new->list); -error1: return ret; }
Use the blk_mq_alloc_disk API to simplify the gendisk and request_queue allocation. Signed-off-by: Christoph Hellwig <hch@lst.de> --- drivers/mtd/mtd_blkdevs.c | 48 ++++++++++++++++++--------------------- 1 file changed, 22 insertions(+), 26 deletions(-)