From: Luis Chamberlain <mcgrof@kernel.org> Date: 2021-09-27 22:01:25
This is the second series of driver conversions for add_disk()
error handling. You can find this set and the rest of the 7th set of
driver conversions on my 20210927-for-axboe-add-disk-error-handling
branch [0].
Changes on this v2 since the last first version of this
patch series:
- rebased onto linux-next tag 20210927
- nvme-multipath: used test_and_set_bit() as suggested by Keith Busch,
and justified this in the code with a comment as this race was not
obvious
- Added reviewed-by / Acked-by tags where one was provided
[0] https://git.kernel.org/pub/scm/linux/kernel/git/mcgrof/linux-next.git/log/?h=20210927-for-axboe-add-disk-error-handling
Luis Chamberlain (10):
block/brd: add error handling support for add_disk()
bcache: add error handling support for add_disk()
nvme-multipath: add error handling support for add_disk()
nvdimm/btt: do not call del_gendisk() if not needed
nvdimm/btt: use goto error labels on btt_blk_init()
nvdimm/btt: add error handling support for add_disk()
nvdimm/blk: avoid calling del_gendisk() on early failures
nvdimm/blk: add error handling support for add_disk()
xen-blkfront: add error handling support for add_disk()
zram: add error handling support for add_disk()
drivers/block/brd.c | 10 ++++++++--
drivers/block/xen-blkfront.c | 8 +++++++-
drivers/block/zram/zram_drv.c | 6 +++++-
drivers/md/bcache/super.c | 17 ++++++++++++-----
drivers/nvdimm/blk.c | 21 +++++++++++++++------
drivers/nvdimm/btt.c | 24 +++++++++++++++---------
drivers/nvme/host/multipath.c | 13 +++++++++++--
7 files changed, 73 insertions(+), 26 deletions(-)
--
2.30.2
From: Luis Chamberlain <mcgrof@kernel.org> Date: 2021-09-27 22:01:03
This will make it easier to share common error paths.
Signed-off-by: Luis Chamberlain <mcgrof@kernel.org>
---
drivers/nvdimm/btt.c | 19 ++++++++++++-------
1 file changed, 12 insertions(+), 7 deletions(-)
From: Luis Chamberlain <mcgrof@kernel.org> Date: 2021-09-27 22:01:11
We never checked for errors on add_disk() as this function
returned void. Now that this is fixed, use the shiny new
error handling.
Since we now can tell for sure when a disk was added, move
setting the bit NVME_NSHEAD_DISK_LIVE only when we did
add the disk successfully.
Nothing to do here as the cleanup is done elsewhere. We take
care and use test_and_set_bit() because it is protects against
two nvme paths simultaneously calling device_add_disk() on the
same namespace head.
Signed-off-by: Luis Chamberlain <mcgrof@kernel.org>
---
drivers/nvme/host/multipath.c | 13 +++++++++++--
1 file changed, 11 insertions(+), 2 deletions(-)
From: Keith Busch <kbusch@kernel.org> Date: 2021-09-27 22:13:20
On Mon, Sep 27, 2021 at 03:00:32PM -0700, Luis Chamberlain wrote:
+ /*
+ * test_and_set_bit() is used because it is protecting against two nvme
+ * paths simultaneously calling device_add_disk() on the same namespace
+ * head.
+ */
if (!test_and_set_bit(NVME_NSHEAD_DISK_LIVE, &head->flags)) {
- device_add_disk(&head->subsys->dev, head->disk,
- nvme_ns_id_attr_groups);
+ rc = device_add_disk(&head->subsys->dev, head->disk,
+ nvme_ns_id_attr_groups);
+ if (rc)
+ return;
+ set_bit(NVME_NSHEAD_DISK_LIVE, &head->flags);
No need to set_bit() here since the test_and_set_bit() already took care
of that.
From: Hannes Reinecke <hare@suse.de> Date: 2021-09-28 05:39:59
On 9/28/21 12:00 AM, Luis Chamberlain wrote:
quoted hunk
We never checked for errors on add_disk() as this function
returned void. Now that this is fixed, use the shiny new
error handling.
Since we now can tell for sure when a disk was added, move
setting the bit NVME_NSHEAD_DISK_LIVE only when we did
add the disk successfully.
Nothing to do here as the cleanup is done elsewhere. We take
care and use test_and_set_bit() because it is protects against
two nvme paths simultaneously calling device_add_disk() on the
same namespace head.
Signed-off-by: Luis Chamberlain <mcgrof@kernel.org>
---
drivers/nvme/host/multipath.c | 13 +++++++++++--
1 file changed, 11 insertions(+), 2 deletions(-)
Setting the same bit twice?
And shouldn't you unset the bit if 'device_add_disk()' fails?
Cheers,
Hannes
--
Dr. Hannes Reinecke Kernel Storage Architect
hare@suse.de +49 911 74053 688
SUSE Software Solutions GmbH, Maxfeldstr. 5, 90409 Nürnberg
HRB 36809 (AG Nürnberg), Geschäftsführer: Felix Imendörffer
From: Luis Chamberlain <mcgrof@kernel.org> Date: 2021-09-27 22:01:12
We never checked for errors on add_disk() as this function
returned void. Now that this is fixed, use the shiny new
error handling.
This driver doesn't do any unwinding with blk_cleanup_disk()
even on errors after add_disk() and so we follow that
tradition.
Acked-by: Coly Li <redacted>
Signed-off-by: Luis Chamberlain <mcgrof@kernel.org>
---
drivers/md/bcache/super.c | 17 ++++++++++++-----
1 file changed, 12 insertions(+), 5 deletions(-)
From: Luis Chamberlain <mcgrof@kernel.org> Date: 2021-09-27 22:01:14
We never checked for errors on device_add_disk() as this function
returned void. Now that this is fixed, use the shiny new error
handling. The function xlvbd_alloc_gendisk() typically does the
unwinding on error on allocating the disk and creating the tag,
but since all that error handling was stuffed inside
xlvbd_alloc_gendisk() we must repeat the tag free'ing as well.
We set the info->rq to NULL to ensure blkif_free() doesn't crash
on blk_mq_stop_hw_queues() on device_add_disk() error as the queue
will be long gone by then.
Signed-off-by: Luis Chamberlain <mcgrof@kernel.org>
---
drivers/block/xen-blkfront.c | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
We never checked for errors on device_add_disk() as this function
returned void. Now that this is fixed, use the shiny new error
handling. The function xlvbd_alloc_gendisk() typically does the
unwinding on error on allocating the disk and creating the tag,
but since all that error handling was stuffed inside
xlvbd_alloc_gendisk() we must repeat the tag free'ing as well.
We set the info->rq to NULL to ensure blkif_free() doesn't crash
on blk_mq_stop_hw_queues() on device_add_disk() error as the queue
will be long gone by then.
Signed-off-by: Luis Chamberlain <mcgrof@kernel.org>
From: Luis Chamberlain <mcgrof@kernel.org> Date: 2021-09-27 22:01:16
If nd_integrity_init() fails we'd get del_gendisk() called,
but that's not correct as we should only call that if we're
done with device_add_disk(). Fix this by providing unwinding
prior to the devm call being registered and moving the devm
registration to the very end.
This should fix calling del_gendisk() if nd_integrity_init()
fails. I only spotted this issue through code inspection. It
does not fix any real world bug.
Signed-off-by: Luis Chamberlain <mcgrof@kernel.org>
---
drivers/nvdimm/blk.c | 17 ++++++++++++-----
1 file changed, 12 insertions(+), 5 deletions(-)
@@ -240,6 +240,7 @@ static int nsblk_attach_disk(struct nd_namespace_blk *nsblk)resource_size_tavailable_disk_size;structgendisk*disk;u64internal_nlba;+intrc;internal_nlba=div_u64(nsblk->size,nsblk_internal_lbasize(nsblk));available_disk_size=internal_nlba*nsblk_sector_size(nsblk);
@@ -256,20 +257,26 @@ static int nsblk_attach_disk(struct nd_namespace_blk *nsblk)blk_queue_logical_block_size(disk->queue,nsblk_sector_size(nsblk));blk_queue_flag_set(QUEUE_FLAG_NONROT,disk->queue);-if(devm_add_action_or_reset(dev,nd_blk_release_disk,disk))-return-ENOMEM;-if(nsblk_meta_size(nsblk)){-intrc=nd_integrity_init(disk,nsblk_meta_size(nsblk));+rc=nd_integrity_init(disk,nsblk_meta_size(nsblk));if(rc)-returnrc;+gotoout_before_devm_err;}set_capacity(disk,available_disk_size>>SECTOR_SHIFT);device_add_disk(dev,disk,NULL);++/* nd_blk_release_disk() is called if this fails */+if(devm_add_action_or_reset(dev,nd_blk_release_disk,disk))+return-ENOMEM;+nvdimm_check_and_set_ro(disk);return0;++out_before_devm_err:+blk_cleanup_disk(disk);+returnrc;}staticintnd_blk_probe(structdevice*dev)
From: Luis Chamberlain <mcgrof@kernel.org> Date: 2021-09-27 22:01:20
We never checked for errors on add_disk() as this function
returned void. Now that this is fixed, use the shiny new
error handling.
Since nvdimm/blk uses devm we just need to move the devm
registration towards the end. And in hindsight, that seems
to also provide a fix given del_gendisk() should not be
called unless the disk was already added via add_disk().
The probably of that issue happening is low though, like
OOM while calling devm_add_action(), so the fix is minor.
We manually unwind in case of add_disk() failure prior
to the devm registration.
Signed-off-by: Luis Chamberlain <mcgrof@kernel.org>
---
drivers/nvdimm/blk.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
@@ -265,7 +265,9 @@ static int nsblk_attach_disk(struct nd_namespace_blk *nsblk)}set_capacity(disk,available_disk_size>>SECTOR_SHIFT);-device_add_disk(dev,disk,NULL);+rc=device_add_disk(dev,disk,NULL);+if(rc)+gotoout_before_devm_err;/* nd_blk_release_disk() is called if this fails */if(devm_add_action_or_reset(dev,nd_blk_release_disk,disk))
From: Luis Chamberlain <mcgrof@kernel.org> Date: 2021-09-27 22:01:23
We know we don't need del_gendisk() if we haven't added
the disk, so just skip it. This should fix a bug on older
kernels, as del_gendisk() became able to deal with
disks not added only recently, after the patch titled
"block: add flag for add_disk() completion notation".
Signed-off-by: Luis Chamberlain <mcgrof@kernel.org>
---
drivers/nvdimm/btt.c | 1 -
1 file changed, 1 deletion(-)
From: Luis Chamberlain <mcgrof@kernel.org> Date: 2021-09-27 22:01:31
We never checked for errors on add_disk() as this function
returned void. Now that this is fixed, use the shiny new
error handling.
Signed-off-by: Luis Chamberlain <mcgrof@kernel.org>
---
drivers/block/zram/zram_drv.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
From: Luis Chamberlain <mcgrof@kernel.org> Date: 2021-09-27 22:01:34
We never checked for errors on add_disk() as this function
returned void. Now that this is fixed, use the shiny new
error handling.
Signed-off-by: Luis Chamberlain <mcgrof@kernel.org>
---
drivers/nvdimm/btt.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
From: Luis Chamberlain <mcgrof@kernel.org> Date: 2021-09-27 22:01:39
We never checked for errors on add_disk() as this function
returned void. Now that this is fixed, use the shiny new
error handling.
Signed-off-by: Luis Chamberlain <mcgrof@kernel.org>
---
drivers/block/brd.c | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
@@ -372,6 +372,7 @@ static int brd_alloc(int i)structbrd_device*brd;structgendisk*disk;charbuf[DISK_NAME_LEN];+interr=-ENOMEM;brd=kzalloc(sizeof(*brd),GFP_KERNEL);if(!brd)
@@ -410,14 +411,19 @@ static int brd_alloc(int i)/* Tell the block layer that this is not a rotational device */blk_queue_flag_set(QUEUE_FLAG_NONROT,disk->queue);blk_queue_flag_clear(QUEUE_FLAG_ADD_RANDOM,disk->queue);-add_disk(disk);+err=add_disk(disk);+if(err)+gotoout_cleanup_disk;+list_add_tail(&brd->brd_list,&brd_devices);return0;+out_cleanup_disk:+blk_cleanup_disk(disk);out_free_dev:kfree(brd);-return-ENOMEM;+returnerr;}staticvoidbrd_probe(dev_tdev)
This is the second series of driver conversions for add_disk()
error handling. You can find this set and the rest of the 7th set of
driver conversions on my 20210927-for-axboe-add-disk-error-handling
branch [0].