* [PATCH v3 01/10] block: clear ->slave_dir when dropping the main slave_dir reference
2022-11-15 14:10 [PATCH v3 00/10] fix delayed holder tracking Yu Kuai
@ 2022-11-15 14:10 ` Yu Kuai
2022-11-16 22:10 ` Mike Snitzer
2022-11-15 14:10 ` [PATCH v3 02/10] dm: remove free_table_devices Yu Kuai
` (9 subsequent siblings)
10 siblings, 1 reply; 22+ messages in thread
From: Yu Kuai @ 2022-11-15 14:10 UTC (permalink / raw)
To: hch, axboe, agk, snitzer, dm-devel
Cc: linux-block, linux-kernel, yukuai3, yukuai1, yi.zhang
From: Christoph Hellwig <hch@lst.de>
Zero out the pointer to ->slave_dir so that the holder code doesn't
incorrectly treat the object as alive when add_disk failed or after
del_gendisk was called.
Fixes: 89f871af1b26 ("dm: delay registering the gendisk")
Reported-by: Yu Kuai <yukuai3@huawei.com>
Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Yu Kuai <yukuai3@huawei.com>
---
block/genhd.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/block/genhd.c b/block/genhd.c
index 74026ce31405..e9501c66ba4d 100644
--- a/block/genhd.c
+++ b/block/genhd.c
@@ -530,6 +530,7 @@ int __must_check device_add_disk(struct device *parent, struct gendisk *disk,
rq_qos_exit(disk->queue);
out_put_slave_dir:
kobject_put(disk->slave_dir);
+ disk->slave_dir = NULL;
out_put_holder_dir:
kobject_put(disk->part0->bd_holder_dir);
out_del_integrity:
@@ -634,6 +635,7 @@ void del_gendisk(struct gendisk *disk)
kobject_put(disk->part0->bd_holder_dir);
kobject_put(disk->slave_dir);
+ disk->slave_dir = NULL;
part_stat_set_all(disk->part0, 0);
disk->part0->bd_stamp = 0;
--
2.31.1
^ permalink raw reply related [flat|nested] 22+ messages in thread* Re: [PATCH v3 01/10] block: clear ->slave_dir when dropping the main slave_dir reference
2022-11-15 14:10 ` [PATCH v3 01/10] block: clear ->slave_dir when dropping the main slave_dir reference Yu Kuai
@ 2022-11-16 22:10 ` Mike Snitzer
0 siblings, 0 replies; 22+ messages in thread
From: Mike Snitzer @ 2022-11-16 22:10 UTC (permalink / raw)
To: Yu Kuai
Cc: hch, axboe, agk, snitzer, dm-devel, linux-block, linux-kernel,
yukuai3, yi.zhang
On Tue, Nov 15 2022 at 9:10P -0500,
Yu Kuai <yukuai1@huaweicloud.com> wrote:
> From: Christoph Hellwig <hch@lst.de>
>
> Zero out the pointer to ->slave_dir so that the holder code doesn't
> incorrectly treat the object as alive when add_disk failed or after
> del_gendisk was called.
>
> Fixes: 89f871af1b26 ("dm: delay registering the gendisk")
> Reported-by: Yu Kuai <yukuai3@huawei.com>
> Signed-off-by: Christoph Hellwig <hch@lst.de>
> Signed-off-by: Yu Kuai <yukuai3@huawei.com>
Reviewed-by: Mike Snitzer <snitzer@kernel.org>
^ permalink raw reply [flat|nested] 22+ messages in thread
* [PATCH v3 02/10] dm: remove free_table_devices
2022-11-15 14:10 [PATCH v3 00/10] fix delayed holder tracking Yu Kuai
2022-11-15 14:10 ` [PATCH v3 01/10] block: clear ->slave_dir when dropping the main slave_dir reference Yu Kuai
@ 2022-11-15 14:10 ` Yu Kuai
2022-11-16 21:50 ` Mike Snitzer
2022-11-15 14:10 ` [PATCH v3 03/10] dm: cleanup open_table_device Yu Kuai
` (8 subsequent siblings)
10 siblings, 1 reply; 22+ messages in thread
From: Yu Kuai @ 2022-11-15 14:10 UTC (permalink / raw)
To: hch, axboe, agk, snitzer, dm-devel
Cc: linux-block, linux-kernel, yukuai3, yukuai1, yi.zhang
From: Christoph Hellwig <hch@lst.de>
free_table_devices just warns and frees all table_device structures when
the target removal did not remove them. This should never happen, but
if it did, just freeing the structure without deleting them from the
list or cleaning up the resources would not help at all. So just WARN on
a non-empty list instead.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Yu Kuai <yukuai3@huawei.com>
---
drivers/md/dm.c | 15 +--------------
1 file changed, 1 insertion(+), 14 deletions(-)
diff --git a/drivers/md/dm.c b/drivers/md/dm.c
index 95a1ee3d314e..19d25bf997be 100644
--- a/drivers/md/dm.c
+++ b/drivers/md/dm.c
@@ -833,19 +833,6 @@ void dm_put_table_device(struct mapped_device *md, struct dm_dev *d)
mutex_unlock(&md->table_devices_lock);
}
-static void free_table_devices(struct list_head *devices)
-{
- struct list_head *tmp, *next;
-
- list_for_each_safe(tmp, next, devices) {
- struct table_device *td = list_entry(tmp, struct table_device, list);
-
- DMWARN("dm_destroy: %s still exists with %d references",
- td->dm_dev.name, refcount_read(&td->count));
- kfree(td);
- }
-}
-
/*
* Get the geometry associated with a dm device
*/
@@ -2122,7 +2109,7 @@ static void free_dev(struct mapped_device *md)
cleanup_mapped_device(md);
- free_table_devices(&md->table_devices);
+ WARN_ON_ONCE(!list_empty(&md->table_devices));
dm_stats_cleanup(&md->stats);
free_minor(minor);
--
2.31.1
^ permalink raw reply related [flat|nested] 22+ messages in thread* Re: [PATCH v3 02/10] dm: remove free_table_devices
2022-11-15 14:10 ` [PATCH v3 02/10] dm: remove free_table_devices Yu Kuai
@ 2022-11-16 21:50 ` Mike Snitzer
0 siblings, 0 replies; 22+ messages in thread
From: Mike Snitzer @ 2022-11-16 21:50 UTC (permalink / raw)
To: Yu Kuai
Cc: hch, axboe, agk, snitzer, dm-devel, linux-block, linux-kernel,
yukuai3, yi.zhang
On Tue, Nov 15 2022 at 9:10P -0500,
Yu Kuai <yukuai1@huaweicloud.com> wrote:
> From: Christoph Hellwig <hch@lst.de>
>
> free_table_devices just warns and frees all table_device structures when
> the target removal did not remove them. This should never happen, but
> if it did, just freeing the structure without deleting them from the
> list or cleaning up the resources would not help at all. So just WARN on
> a non-empty list instead.
>
> Signed-off-by: Christoph Hellwig <hch@lst.de>
> Signed-off-by: Yu Kuai <yukuai3@huawei.com>
Reviewed-by: Mike Snitzer <snitzer@kernel.org>
^ permalink raw reply [flat|nested] 22+ messages in thread
* [PATCH v3 03/10] dm: cleanup open_table_device
2022-11-15 14:10 [PATCH v3 00/10] fix delayed holder tracking Yu Kuai
2022-11-15 14:10 ` [PATCH v3 01/10] block: clear ->slave_dir when dropping the main slave_dir reference Yu Kuai
2022-11-15 14:10 ` [PATCH v3 02/10] dm: remove free_table_devices Yu Kuai
@ 2022-11-15 14:10 ` Yu Kuai
2022-11-16 21:19 ` Mike Snitzer
2022-11-15 14:10 ` [PATCH v3 04/10] dm: cleanup close_table_device Yu Kuai
` (7 subsequent siblings)
10 siblings, 1 reply; 22+ messages in thread
From: Yu Kuai @ 2022-11-15 14:10 UTC (permalink / raw)
To: hch, axboe, agk, snitzer, dm-devel
Cc: linux-block, linux-kernel, yukuai3, yukuai1, yi.zhang
From: Christoph Hellwig <hch@lst.de>
Move all the logic for allocation the table_device and linking it into
the list into the open_table_device. This keeps the code tidy and
ensures that the table_devices only exist in fully initialized state.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Yu Kuai <yukuai3@huawei.com>
---
drivers/md/dm.c | 56 ++++++++++++++++++++++++-------------------------
1 file changed, 27 insertions(+), 29 deletions(-)
diff --git a/drivers/md/dm.c b/drivers/md/dm.c
index 19d25bf997be..28d7581b6a82 100644
--- a/drivers/md/dm.c
+++ b/drivers/md/dm.c
@@ -732,28 +732,41 @@ static char *_dm_claim_ptr = "I belong to device-mapper";
/*
* Open a table device so we can use it as a map destination.
*/
-static int open_table_device(struct table_device *td, dev_t dev,
- struct mapped_device *md)
+static struct table_device *open_table_device(struct mapped_device *md,
+ dev_t dev, fmode_t mode)
{
+ struct table_device *td;
struct block_device *bdev;
u64 part_off;
int r;
- BUG_ON(td->dm_dev.bdev);
+ td = kmalloc_node(sizeof(*td), GFP_KERNEL, md->numa_node_id);
+ if (!td)
+ return ERR_PTR(-ENOMEM);
+ refcount_set(&td->count, 1);
- bdev = blkdev_get_by_dev(dev, td->dm_dev.mode | FMODE_EXCL, _dm_claim_ptr);
- if (IS_ERR(bdev))
- return PTR_ERR(bdev);
+ bdev = blkdev_get_by_dev(dev, mode | FMODE_EXCL, _dm_claim_ptr);
+ if (IS_ERR(bdev)) {
+ r = PTR_ERR(bdev);
+ goto out_free_td;
+ }
r = bd_link_disk_holder(bdev, dm_disk(md));
- if (r) {
- blkdev_put(bdev, td->dm_dev.mode | FMODE_EXCL);
- return r;
- }
+ if (r)
+ goto out_blkdev_put;
+ td->dm_dev.mode = mode;
td->dm_dev.bdev = bdev;
td->dm_dev.dax_dev = fs_dax_get_by_bdev(bdev, &part_off, NULL, NULL);
- return 0;
+ format_dev_t(td->dm_dev.name, dev);
+ list_add(&td->list, &md->table_devices);
+ return td;
+
+out_blkdev_put:
+ blkdev_put(bdev, mode | FMODE_EXCL);
+out_free_td:
+ kfree(td);
+ return ERR_PTR(r);
}
/*
@@ -786,31 +799,16 @@ static struct table_device *find_table_device(struct list_head *l, dev_t dev,
int dm_get_table_device(struct mapped_device *md, dev_t dev, fmode_t mode,
struct dm_dev **result)
{
- int r;
struct table_device *td;
mutex_lock(&md->table_devices_lock);
td = find_table_device(&md->table_devices, dev, mode);
if (!td) {
- td = kmalloc_node(sizeof(*td), GFP_KERNEL, md->numa_node_id);
- if (!td) {
- mutex_unlock(&md->table_devices_lock);
- return -ENOMEM;
- }
-
- td->dm_dev.mode = mode;
- td->dm_dev.bdev = NULL;
-
- if ((r = open_table_device(td, dev, md))) {
+ td = open_table_device(md, dev, mode);
+ if (IS_ERR(td)) {
mutex_unlock(&md->table_devices_lock);
- kfree(td);
- return r;
+ return PTR_ERR(td);
}
-
- format_dev_t(td->dm_dev.name, dev);
-
- refcount_set(&td->count, 1);
- list_add(&td->list, &md->table_devices);
} else {
refcount_inc(&td->count);
}
--
2.31.1
^ permalink raw reply related [flat|nested] 22+ messages in thread* Re: [PATCH v3 03/10] dm: cleanup open_table_device
2022-11-15 14:10 ` [PATCH v3 03/10] dm: cleanup open_table_device Yu Kuai
@ 2022-11-16 21:19 ` Mike Snitzer
0 siblings, 0 replies; 22+ messages in thread
From: Mike Snitzer @ 2022-11-16 21:19 UTC (permalink / raw)
To: Yu Kuai
Cc: hch, axboe, agk, snitzer, dm-devel, linux-block, linux-kernel,
yukuai3, yi.zhang
On Tue, Nov 15 2022 at 9:10P -0500,
Yu Kuai <yukuai1@huaweicloud.com> wrote:
> From: Christoph Hellwig <hch@lst.de>
>
> Move all the logic for allocation the table_device and linking it into
> the list into the open_table_device. This keeps the code tidy and
> ensures that the table_devices only exist in fully initialized state.
>
> Signed-off-by: Christoph Hellwig <hch@lst.de>
> Signed-off-by: Yu Kuai <yukuai3@huawei.com>
Reviewed-by: Mike Snitzer <snitzer@kernel.org>
^ permalink raw reply [flat|nested] 22+ messages in thread
* [PATCH v3 04/10] dm: cleanup close_table_device
2022-11-15 14:10 [PATCH v3 00/10] fix delayed holder tracking Yu Kuai
` (2 preceding siblings ...)
2022-11-15 14:10 ` [PATCH v3 03/10] dm: cleanup open_table_device Yu Kuai
@ 2022-11-15 14:10 ` Yu Kuai
2022-11-16 21:46 ` Mike Snitzer
2022-11-15 14:10 ` [PATCH RFC v3 05/10] dm: make sure create and remove dm device won't race with open and close table Yu Kuai
` (6 subsequent siblings)
10 siblings, 1 reply; 22+ messages in thread
From: Yu Kuai @ 2022-11-15 14:10 UTC (permalink / raw)
To: hch, axboe, agk, snitzer, dm-devel
Cc: linux-block, linux-kernel, yukuai3, yukuai1, yi.zhang
From: Christoph Hellwig <hch@lst.de>
Take the list unlink and free into close_table_device so that no half
torn down table_devices exist. Also remove the check for a NULL bdev
as that can't happen - open_table_device never adds a table_device to
the list that does not have a valid block_device.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Yu Kuai <yukuai3@huawei.com>
---
drivers/md/dm.c | 12 +++---------
1 file changed, 3 insertions(+), 9 deletions(-)
diff --git a/drivers/md/dm.c b/drivers/md/dm.c
index 28d7581b6a82..2917700b1e15 100644
--- a/drivers/md/dm.c
+++ b/drivers/md/dm.c
@@ -774,14 +774,11 @@ static struct table_device *open_table_device(struct mapped_device *md,
*/
static void close_table_device(struct table_device *td, struct mapped_device *md)
{
- if (!td->dm_dev.bdev)
- return;
-
bd_unlink_disk_holder(td->dm_dev.bdev, dm_disk(md));
blkdev_put(td->dm_dev.bdev, td->dm_dev.mode | FMODE_EXCL);
put_dax(td->dm_dev.dax_dev);
- td->dm_dev.bdev = NULL;
- td->dm_dev.dax_dev = NULL;
+ list_del(&td->list);
+ kfree(td);
}
static struct table_device *find_table_device(struct list_head *l, dev_t dev,
@@ -823,11 +820,8 @@ void dm_put_table_device(struct mapped_device *md, struct dm_dev *d)
struct table_device *td = container_of(d, struct table_device, dm_dev);
mutex_lock(&md->table_devices_lock);
- if (refcount_dec_and_test(&td->count)) {
+ if (refcount_dec_and_test(&td->count))
close_table_device(td, md);
- list_del(&td->list);
- kfree(td);
- }
mutex_unlock(&md->table_devices_lock);
}
--
2.31.1
^ permalink raw reply related [flat|nested] 22+ messages in thread* Re: [PATCH v3 04/10] dm: cleanup close_table_device
2022-11-15 14:10 ` [PATCH v3 04/10] dm: cleanup close_table_device Yu Kuai
@ 2022-11-16 21:46 ` Mike Snitzer
0 siblings, 0 replies; 22+ messages in thread
From: Mike Snitzer @ 2022-11-16 21:46 UTC (permalink / raw)
To: Yu Kuai
Cc: hch, axboe, agk, snitzer, dm-devel, linux-block, linux-kernel,
yukuai3, yi.zhang
On Tue, Nov 15 2022 at 9:10P -0500,
Yu Kuai <yukuai1@huaweicloud.com> wrote:
> From: Christoph Hellwig <hch@lst.de>
>
> Take the list unlink and free into close_table_device so that no half
> torn down table_devices exist. Also remove the check for a NULL bdev
> as that can't happen - open_table_device never adds a table_device to
> the list that does not have a valid block_device.
>
> Signed-off-by: Christoph Hellwig <hch@lst.de>
> Signed-off-by: Yu Kuai <yukuai3@huawei.com>
Reviewed-by: Mike Snitzer <snitzer@kernel.org>
^ permalink raw reply [flat|nested] 22+ messages in thread
* [PATCH RFC v3 05/10] dm: make sure create and remove dm device won't race with open and close table
2022-11-15 14:10 [PATCH v3 00/10] fix delayed holder tracking Yu Kuai
` (3 preceding siblings ...)
2022-11-15 14:10 ` [PATCH v3 04/10] dm: cleanup close_table_device Yu Kuai
@ 2022-11-15 14:10 ` Yu Kuai
2022-11-16 6:35 ` Christoph Hellwig
2022-11-16 21:48 ` Mike Snitzer
2022-11-15 14:10 ` [PATCH v3 06/10] dm: track per-add_disk holder relations in DM Yu Kuai
` (5 subsequent siblings)
10 siblings, 2 replies; 22+ messages in thread
From: Yu Kuai @ 2022-11-15 14:10 UTC (permalink / raw)
To: hch, axboe, agk, snitzer, dm-devel
Cc: linux-block, linux-kernel, yukuai3, yukuai1, yi.zhang
From: Yu Kuai <yukuai3@huawei.com>
open_table_device() and close_table_device() is protected by
table_devices_lock, hence use it to protect add_disk() and
del_gendisk().
Prepare to track per-add_disk holder relations in dm.
Signed-off-by: Yu Kuai <yukuai3@huawei.com>
---
drivers/md/dm.c | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
diff --git a/drivers/md/dm.c b/drivers/md/dm.c
index 2917700b1e15..3728b56b364b 100644
--- a/drivers/md/dm.c
+++ b/drivers/md/dm.c
@@ -1952,7 +1952,14 @@ static void cleanup_mapped_device(struct mapped_device *md)
spin_unlock(&_minor_lock);
if (dm_get_md_type(md) != DM_TYPE_NONE) {
dm_sysfs_exit(md);
+
+ /*
+ * Hold lock to make sure del_gendisk() won't concurrent
+ * with open/close_table_device().
+ */
+ mutex_lock(&md->table_devices_lock);
del_gendisk(md->disk);
+ mutex_unlock(&md->table_devices_lock);
}
dm_queue_destroy_crypto_profile(md->queue);
put_disk(md->disk);
@@ -2312,15 +2319,24 @@ int dm_setup_md_queue(struct mapped_device *md, struct dm_table *t)
if (r)
return r;
+ /*
+ * Hold lock to make sure add_disk() and del_gendisk() won't concurrent
+ * with open_table_device() and close_table_device().
+ */
+ mutex_lock(&md->table_devices_lock);
r = add_disk(md->disk);
+ mutex_unlock(&md->table_devices_lock);
if (r)
return r;
r = dm_sysfs_init(md);
if (r) {
+ mutex_lock(&md->table_devices_lock);
del_gendisk(md->disk);
+ mutex_unlock(&md->table_devices_lock);
return r;
}
+
md->type = type;
return 0;
}
--
2.31.1
^ permalink raw reply related [flat|nested] 22+ messages in thread* Re: [PATCH RFC v3 05/10] dm: make sure create and remove dm device won't race with open and close table
2022-11-15 14:10 ` [PATCH RFC v3 05/10] dm: make sure create and remove dm device won't race with open and close table Yu Kuai
@ 2022-11-16 6:35 ` Christoph Hellwig
2022-11-16 21:48 ` Mike Snitzer
1 sibling, 0 replies; 22+ messages in thread
From: Christoph Hellwig @ 2022-11-16 6:35 UTC (permalink / raw)
To: Yu Kuai
Cc: hch, axboe, agk, snitzer, dm-devel, linux-block, linux-kernel,
yukuai3, yi.zhang
Looks good:
Reviewed-by: Christoph Hellwig <hch@lst.de>
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH RFC v3 05/10] dm: make sure create and remove dm device won't race with open and close table
2022-11-15 14:10 ` [PATCH RFC v3 05/10] dm: make sure create and remove dm device won't race with open and close table Yu Kuai
2022-11-16 6:35 ` Christoph Hellwig
@ 2022-11-16 21:48 ` Mike Snitzer
1 sibling, 0 replies; 22+ messages in thread
From: Mike Snitzer @ 2022-11-16 21:48 UTC (permalink / raw)
To: Yu Kuai
Cc: hch, axboe, agk, snitzer, dm-devel, linux-block, linux-kernel,
yukuai3, yi.zhang
On Tue, Nov 15 2022 at 9:10P -0500,
Yu Kuai <yukuai1@huaweicloud.com> wrote:
> From: Yu Kuai <yukuai3@huawei.com>
>
> open_table_device() and close_table_device() is protected by
> table_devices_lock, hence use it to protect add_disk() and
> del_gendisk().
>
> Prepare to track per-add_disk holder relations in dm.
>
> Signed-off-by: Yu Kuai <yukuai3@huawei.com>
> ---
> drivers/md/dm.c | 16 ++++++++++++++++
> 1 file changed, 16 insertions(+)
>
> diff --git a/drivers/md/dm.c b/drivers/md/dm.c
> index 2917700b1e15..3728b56b364b 100644
> --- a/drivers/md/dm.c
> +++ b/drivers/md/dm.c
> @@ -1952,7 +1952,14 @@ static void cleanup_mapped_device(struct mapped_device *md)
> spin_unlock(&_minor_lock);
> if (dm_get_md_type(md) != DM_TYPE_NONE) {
> dm_sysfs_exit(md);
> +
> + /*
> + * Hold lock to make sure del_gendisk() won't concurrent
> + * with open/close_table_device().
> + */
> + mutex_lock(&md->table_devices_lock);
> del_gendisk(md->disk);
> + mutex_unlock(&md->table_devices_lock);
> }
> dm_queue_destroy_crypto_profile(md->queue);
> put_disk(md->disk);
> @@ -2312,15 +2319,24 @@ int dm_setup_md_queue(struct mapped_device *md, struct dm_table *t)
> if (r)
> return r;
>
> + /*
> + * Hold lock to make sure add_disk() and del_gendisk() won't concurrent
> + * with open_table_device() and close_table_device().
> + */
> + mutex_lock(&md->table_devices_lock);
> r = add_disk(md->disk);
> + mutex_unlock(&md->table_devices_lock);
> if (r)
> return r;
>
> r = dm_sysfs_init(md);
> if (r) {
> + mutex_lock(&md->table_devices_lock);
> del_gendisk(md->disk);
> + mutex_unlock(&md->table_devices_lock);
> return r;
> }
> +
> md->type = type;
> return 0;
> }
> --
> 2.31.1
>
In the new comments added: s/concurrent/race/ ?
But otherwise:
Reviewed-by: Mike Snitzer <snitzer@kernel.org>
^ permalink raw reply [flat|nested] 22+ messages in thread
* [PATCH v3 06/10] dm: track per-add_disk holder relations in DM
2022-11-15 14:10 [PATCH v3 00/10] fix delayed holder tracking Yu Kuai
` (4 preceding siblings ...)
2022-11-15 14:10 ` [PATCH RFC v3 05/10] dm: make sure create and remove dm device won't race with open and close table Yu Kuai
@ 2022-11-15 14:10 ` Yu Kuai
2022-11-16 21:49 ` Mike Snitzer
2022-11-15 14:10 ` [PATCH v3 07/10] block: remove delayed holder registration Yu Kuai
` (4 subsequent siblings)
10 siblings, 1 reply; 22+ messages in thread
From: Yu Kuai @ 2022-11-15 14:10 UTC (permalink / raw)
To: hch, axboe, agk, snitzer, dm-devel
Cc: linux-block, linux-kernel, yukuai3, yukuai1, yi.zhang
From: Christoph Hellwig <hch@lst.de>
dm is a bit special in that it opens the underlying devices. Commit
89f871af1b26 ("dm: delay registering the gendisk") tried to accommodate
that by allowing to add the holder to the list before add_gendisk and
then just add them to sysfs once add_disk is called. But that leads to
really odd lifetime problems and error handling problems as we can't
know the state of the kobjects and don't unwind properly. To fix this
switch to just registering all existing table_devices with the holder
code right after add_disk, and remove them before calling del_gendisk.
Fixes: 89f871af1b26 ("dm: delay registering the gendisk")
Reported-by: Yu Kuai <yukuai3@huawei.com>
Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Yu Kuai <yukuai3@huawei.com>
---
drivers/md/dm.c | 49 +++++++++++++++++++++++++++++++++++++++----------
1 file changed, 39 insertions(+), 10 deletions(-)
diff --git a/drivers/md/dm.c b/drivers/md/dm.c
index 3728b56b364b..e1ea3a7bd9d9 100644
--- a/drivers/md/dm.c
+++ b/drivers/md/dm.c
@@ -751,9 +751,16 @@ static struct table_device *open_table_device(struct mapped_device *md,
goto out_free_td;
}
- r = bd_link_disk_holder(bdev, dm_disk(md));
- if (r)
- goto out_blkdev_put;
+ /*
+ * We can be called before the dm disk is added. In that case we can't
+ * register the holder relation here. It will be done once add_disk was
+ * called.
+ */
+ if (md->disk->slave_dir) {
+ r = bd_link_disk_holder(bdev, md->disk);
+ if (r)
+ goto out_blkdev_put;
+ }
td->dm_dev.mode = mode;
td->dm_dev.bdev = bdev;
@@ -774,7 +781,8 @@ static struct table_device *open_table_device(struct mapped_device *md,
*/
static void close_table_device(struct table_device *td, struct mapped_device *md)
{
- bd_unlink_disk_holder(td->dm_dev.bdev, dm_disk(md));
+ if (md->disk->slave_dir)
+ bd_unlink_disk_holder(td->dm_dev.bdev, md->disk);
blkdev_put(td->dm_dev.bdev, td->dm_dev.mode | FMODE_EXCL);
put_dax(td->dm_dev.dax_dev);
list_del(&td->list);
@@ -1951,7 +1959,13 @@ static void cleanup_mapped_device(struct mapped_device *md)
md->disk->private_data = NULL;
spin_unlock(&_minor_lock);
if (dm_get_md_type(md) != DM_TYPE_NONE) {
+ struct table_device *td;
+
dm_sysfs_exit(md);
+ list_for_each_entry(td, &md->table_devices, list) {
+ bd_unlink_disk_holder(td->dm_dev.bdev,
+ md->disk);
+ }
/*
* Hold lock to make sure del_gendisk() won't concurrent
@@ -2291,6 +2305,7 @@ int dm_setup_md_queue(struct mapped_device *md, struct dm_table *t)
{
enum dm_queue_mode type = dm_table_get_type(t);
struct queue_limits limits;
+ struct table_device *td;
int r;
switch (type) {
@@ -2329,16 +2344,30 @@ int dm_setup_md_queue(struct mapped_device *md, struct dm_table *t)
if (r)
return r;
- r = dm_sysfs_init(md);
- if (r) {
- mutex_lock(&md->table_devices_lock);
- del_gendisk(md->disk);
- mutex_unlock(&md->table_devices_lock);
- return r;
+ /*
+ * Register the holder relationship for devices added before the disk
+ * was live.
+ */
+ list_for_each_entry(td, &md->table_devices, list) {
+ r = bd_link_disk_holder(td->dm_dev.bdev, md->disk);
+ if (r)
+ goto out_undo_holders;
}
+ r = dm_sysfs_init(md);
+ if (r)
+ goto out_undo_holders;
+
md->type = type;
return 0;
+
+out_undo_holders:
+ list_for_each_entry_continue_reverse(td, &md->table_devices, list)
+ bd_unlink_disk_holder(td->dm_dev.bdev, md->disk);
+ mutex_lock(&md->table_devices_lock);
+ del_gendisk(md->disk);
+ mutex_unlock(&md->table_devices_lock);
+ return r;
}
struct mapped_device *dm_get_md(dev_t dev)
--
2.31.1
^ permalink raw reply related [flat|nested] 22+ messages in thread* Re: [PATCH v3 06/10] dm: track per-add_disk holder relations in DM
2022-11-15 14:10 ` [PATCH v3 06/10] dm: track per-add_disk holder relations in DM Yu Kuai
@ 2022-11-16 21:49 ` Mike Snitzer
0 siblings, 0 replies; 22+ messages in thread
From: Mike Snitzer @ 2022-11-16 21:49 UTC (permalink / raw)
To: Yu Kuai
Cc: hch, axboe, agk, snitzer, dm-devel, linux-block, linux-kernel,
yukuai3, yi.zhang
On Tue, Nov 15 2022 at 9:10P -0500,
Yu Kuai <yukuai1@huaweicloud.com> wrote:
> From: Christoph Hellwig <hch@lst.de>
>
> dm is a bit special in that it opens the underlying devices. Commit
> 89f871af1b26 ("dm: delay registering the gendisk") tried to accommodate
> that by allowing to add the holder to the list before add_gendisk and
> then just add them to sysfs once add_disk is called. But that leads to
> really odd lifetime problems and error handling problems as we can't
> know the state of the kobjects and don't unwind properly. To fix this
> switch to just registering all existing table_devices with the holder
> code right after add_disk, and remove them before calling del_gendisk.
>
> Fixes: 89f871af1b26 ("dm: delay registering the gendisk")
> Reported-by: Yu Kuai <yukuai3@huawei.com>
> Signed-off-by: Christoph Hellwig <hch@lst.de>
> Signed-off-by: Yu Kuai <yukuai3@huawei.com>
Reviewed-by: Mike Snitzer <snitzer@kernel.org>
^ permalink raw reply [flat|nested] 22+ messages in thread
* [PATCH v3 07/10] block: remove delayed holder registration
2022-11-15 14:10 [PATCH v3 00/10] fix delayed holder tracking Yu Kuai
` (5 preceding siblings ...)
2022-11-15 14:10 ` [PATCH v3 06/10] dm: track per-add_disk holder relations in DM Yu Kuai
@ 2022-11-15 14:10 ` Yu Kuai
2022-11-15 14:10 ` [PATCH v3 08/10] block: fix use after free for bd_holder_dir Yu Kuai
` (3 subsequent siblings)
10 siblings, 0 replies; 22+ messages in thread
From: Yu Kuai @ 2022-11-15 14:10 UTC (permalink / raw)
To: hch, axboe, agk, snitzer, dm-devel
Cc: linux-block, linux-kernel, yukuai3, yukuai1, yi.zhang
From: Christoph Hellwig <hch@lst.de>
Now that dm has been fixed to track of holder registrations before
add_disk, the somewhat buggy block layer code can be safely removed.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Yu Kuai <yukuai3@huawei.com>
---
block/genhd.c | 4 ---
block/holder.c | 72 ++++++++++++------------------------------
include/linux/blkdev.h | 5 ---
3 files changed, 21 insertions(+), 60 deletions(-)
diff --git a/block/genhd.c b/block/genhd.c
index e9501c66ba4d..dcf200bcbd3e 100644
--- a/block/genhd.c
+++ b/block/genhd.c
@@ -479,10 +479,6 @@ int __must_check device_add_disk(struct device *parent, struct gendisk *disk,
goto out_put_holder_dir;
}
- ret = bd_register_pending_holders(disk);
- if (ret < 0)
- goto out_put_slave_dir;
-
ret = blk_register_queue(disk);
if (ret)
goto out_put_slave_dir;
diff --git a/block/holder.c b/block/holder.c
index 5283bc804cc1..dd9327b43ce0 100644
--- a/block/holder.c
+++ b/block/holder.c
@@ -29,19 +29,6 @@ static void del_symlink(struct kobject *from, struct kobject *to)
sysfs_remove_link(from, kobject_name(to));
}
-static int __link_disk_holder(struct block_device *bdev, struct gendisk *disk)
-{
- int ret;
-
- ret = add_symlink(disk->slave_dir, bdev_kobj(bdev));
- if (ret)
- return ret;
- ret = add_symlink(bdev->bd_holder_dir, &disk_to_dev(disk)->kobj);
- if (ret)
- del_symlink(disk->slave_dir, bdev_kobj(bdev));
- return ret;
-}
-
/**
* bd_link_disk_holder - create symlinks between holding disk and slave bdev
* @bdev: the claimed slave bdev
@@ -75,6 +62,9 @@ int bd_link_disk_holder(struct block_device *bdev, struct gendisk *disk)
struct bd_holder_disk *holder;
int ret = 0;
+ if (WARN_ON_ONCE(!disk->slave_dir))
+ return -EINVAL;
+
mutex_lock(&disk->open_mutex);
WARN_ON_ONCE(!bdev->bd_holder);
@@ -94,34 +84,32 @@ int bd_link_disk_holder(struct block_device *bdev, struct gendisk *disk)
INIT_LIST_HEAD(&holder->list);
holder->bdev = bdev;
holder->refcnt = 1;
- if (disk->slave_dir) {
- ret = __link_disk_holder(bdev, disk);
- if (ret) {
- kfree(holder);
- goto out_unlock;
- }
- }
-
+ ret = add_symlink(disk->slave_dir, bdev_kobj(bdev));
+ if (ret)
+ goto out_free_holder;
+ ret = add_symlink(bdev->bd_holder_dir, &disk_to_dev(disk)->kobj);
+ if (ret)
+ goto out_del_symlink;
list_add(&holder->list, &disk->slave_bdevs);
+
/*
* del_gendisk drops the initial reference to bd_holder_dir, so we need
* to keep our own here to allow for cleanup past that point.
*/
kobject_get(bdev->bd_holder_dir);
+ mutex_unlock(&disk->open_mutex);
+ return 0;
+out_del_symlink:
+ del_symlink(disk->slave_dir, bdev_kobj(bdev));
+out_free_holder:
+ kfree(holder);
out_unlock:
mutex_unlock(&disk->open_mutex);
return ret;
}
EXPORT_SYMBOL_GPL(bd_link_disk_holder);
-static void __unlink_disk_holder(struct block_device *bdev,
- struct gendisk *disk)
-{
- del_symlink(disk->slave_dir, bdev_kobj(bdev));
- del_symlink(bdev->bd_holder_dir, &disk_to_dev(disk)->kobj);
-}
-
/**
* bd_unlink_disk_holder - destroy symlinks created by bd_link_disk_holder()
* @bdev: the calimed slave bdev
@@ -136,11 +124,14 @@ void bd_unlink_disk_holder(struct block_device *bdev, struct gendisk *disk)
{
struct bd_holder_disk *holder;
+ if (WARN_ON_ONCE(!disk->slave_dir))
+ return;
+
mutex_lock(&disk->open_mutex);
holder = bd_find_holder_disk(bdev, disk);
if (!WARN_ON_ONCE(holder == NULL) && !--holder->refcnt) {
- if (disk->slave_dir)
- __unlink_disk_holder(bdev, disk);
+ del_symlink(disk->slave_dir, bdev_kobj(bdev));
+ del_symlink(bdev->bd_holder_dir, &disk_to_dev(disk)->kobj);
kobject_put(bdev->bd_holder_dir);
list_del_init(&holder->list);
kfree(holder);
@@ -148,24 +139,3 @@ void bd_unlink_disk_holder(struct block_device *bdev, struct gendisk *disk)
mutex_unlock(&disk->open_mutex);
}
EXPORT_SYMBOL_GPL(bd_unlink_disk_holder);
-
-int bd_register_pending_holders(struct gendisk *disk)
-{
- struct bd_holder_disk *holder;
- int ret;
-
- mutex_lock(&disk->open_mutex);
- list_for_each_entry(holder, &disk->slave_bdevs, list) {
- ret = __link_disk_holder(holder->bdev, disk);
- if (ret)
- goto out_undo;
- }
- mutex_unlock(&disk->open_mutex);
- return 0;
-
-out_undo:
- list_for_each_entry_continue_reverse(holder, &disk->slave_bdevs, list)
- __unlink_disk_holder(holder->bdev, disk);
- mutex_unlock(&disk->open_mutex);
- return ret;
-}
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index 9188aa3f6259..516e45246868 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -833,7 +833,6 @@ void set_capacity(struct gendisk *disk, sector_t size);
#ifdef CONFIG_BLOCK_HOLDER_DEPRECATED
int bd_link_disk_holder(struct block_device *bdev, struct gendisk *disk);
void bd_unlink_disk_holder(struct block_device *bdev, struct gendisk *disk);
-int bd_register_pending_holders(struct gendisk *disk);
#else
static inline int bd_link_disk_holder(struct block_device *bdev,
struct gendisk *disk)
@@ -844,10 +843,6 @@ static inline void bd_unlink_disk_holder(struct block_device *bdev,
struct gendisk *disk)
{
}
-static inline int bd_register_pending_holders(struct gendisk *disk)
-{
- return 0;
-}
#endif /* CONFIG_BLOCK_HOLDER_DEPRECATED */
dev_t part_devt(struct gendisk *disk, u8 partno);
--
2.31.1
^ permalink raw reply related [flat|nested] 22+ messages in thread* [PATCH v3 08/10] block: fix use after free for bd_holder_dir
2022-11-15 14:10 [PATCH v3 00/10] fix delayed holder tracking Yu Kuai
` (6 preceding siblings ...)
2022-11-15 14:10 ` [PATCH v3 07/10] block: remove delayed holder registration Yu Kuai
@ 2022-11-15 14:10 ` Yu Kuai
2022-11-16 6:35 ` Christoph Hellwig
2022-11-15 14:10 ` [PATCH v3 09/10] block: store the holder kobject in bd_holder_disk Yu Kuai
` (2 subsequent siblings)
10 siblings, 1 reply; 22+ messages in thread
From: Yu Kuai @ 2022-11-15 14:10 UTC (permalink / raw)
To: hch, axboe, agk, snitzer, dm-devel
Cc: linux-block, linux-kernel, yukuai3, yukuai1, yi.zhang
From: Yu Kuai <yukuai3@huawei.com>
Currently, the caller of bd_link_disk_holer() get 'bdev' by
blkdev_get_by_dev(), which will look up 'bdev' by inode number 'dev'.
Howerver, it's possible that del_gendisk() can be called currently, and
'bd_holder_dir' can be freed before bd_link_disk_holer() access it, thus
use after free is triggered.
t1: t2:
bdev = blkdev_get_by_dev
del_gendisk
kobject_put(bd_holder_dir)
kobject_free()
bd_link_disk_holder
Fix the problem by checking disk is still live and grabbing a reference
to 'bd_holder_dir' first in bd_link_disk_holder().
Signed-off-by: Yu Kuai <yukuai3@huawei.com>
---
block/holder.c | 21 +++++++++++++++------
1 file changed, 15 insertions(+), 6 deletions(-)
diff --git a/block/holder.c b/block/holder.c
index dd9327b43ce0..c8e462053f49 100644
--- a/block/holder.c
+++ b/block/holder.c
@@ -65,12 +65,24 @@ int bd_link_disk_holder(struct block_device *bdev, struct gendisk *disk)
if (WARN_ON_ONCE(!disk->slave_dir))
return -EINVAL;
- mutex_lock(&disk->open_mutex);
+ /*
+ * del_gendisk drops the initial reference to bd_holder_dir, so we
+ * need to keep our own here to allow for cleanup past that point.
+ */
+ mutex_lock(&bdev->bd_disk->open_mutex);
+ if (!disk_live(bdev->bd_disk)) {
+ mutex_unlock(&bdev->bd_disk->open_mutex);
+ return -ENODEV;
+ }
+ kobject_get(bdev->bd_holder_dir);
+ mutex_unlock(&bdev->bd_disk->open_mutex);
+ mutex_lock(&disk->open_mutex);
WARN_ON_ONCE(!bdev->bd_holder);
holder = bd_find_holder_disk(bdev, disk);
if (holder) {
+ kobject_put(bdev->bd_holder_dir);
holder->refcnt++;
goto out_unlock;
}
@@ -92,11 +104,6 @@ int bd_link_disk_holder(struct block_device *bdev, struct gendisk *disk)
goto out_del_symlink;
list_add(&holder->list, &disk->slave_bdevs);
- /*
- * del_gendisk drops the initial reference to bd_holder_dir, so we need
- * to keep our own here to allow for cleanup past that point.
- */
- kobject_get(bdev->bd_holder_dir);
mutex_unlock(&disk->open_mutex);
return 0;
@@ -106,6 +113,8 @@ int bd_link_disk_holder(struct block_device *bdev, struct gendisk *disk)
kfree(holder);
out_unlock:
mutex_unlock(&disk->open_mutex);
+ if (ret)
+ kobject_put(bdev->bd_holder_dir);
return ret;
}
EXPORT_SYMBOL_GPL(bd_link_disk_holder);
--
2.31.1
^ permalink raw reply related [flat|nested] 22+ messages in thread* [PATCH v3 09/10] block: store the holder kobject in bd_holder_disk
2022-11-15 14:10 [PATCH v3 00/10] fix delayed holder tracking Yu Kuai
` (7 preceding siblings ...)
2022-11-15 14:10 ` [PATCH v3 08/10] block: fix use after free for bd_holder_dir Yu Kuai
@ 2022-11-15 14:10 ` Yu Kuai
2022-11-16 6:36 ` Christoph Hellwig
2022-11-15 14:10 ` [PATCH v3 10/10] block: don't allow a disk link holder to itself Yu Kuai
2022-11-16 22:20 ` [PATCH v3 00/10] fix delayed holder tracking Jens Axboe
10 siblings, 1 reply; 22+ messages in thread
From: Yu Kuai @ 2022-11-15 14:10 UTC (permalink / raw)
To: hch, axboe, agk, snitzer, dm-devel
Cc: linux-block, linux-kernel, yukuai3, yukuai1, yi.zhang
From: Yu Kuai <yukuai3@huawei.com>
We hold a reference to the holder kobject for each bd_holder_disk,
so to make the code a bit more robust, use a reference to it instead
of the block_device. As long as no one clears ->bd_holder_dir in
before freeing the disk, this isn't strictly required, but it does
make the code more clear and more robust.
Orignally-From: Christoph Hellwig <hch@lst.de>
Signed-off-by: Yu Kuai <yukuai3@huawei.com>
---
block/holder.c | 11 ++++++-----
1 file changed, 6 insertions(+), 5 deletions(-)
diff --git a/block/holder.c b/block/holder.c
index c8e462053f49..3332142bb867 100644
--- a/block/holder.c
+++ b/block/holder.c
@@ -4,7 +4,7 @@
struct bd_holder_disk {
struct list_head list;
- struct block_device *bdev;
+ struct kobject *holder_dir;
int refcnt;
};
@@ -14,7 +14,7 @@ static struct bd_holder_disk *bd_find_holder_disk(struct block_device *bdev,
struct bd_holder_disk *holder;
list_for_each_entry(holder, &disk->slave_bdevs, list)
- if (holder->bdev == bdev)
+ if (holder->holder_dir == bdev->bd_holder_dir)
return holder;
return NULL;
}
@@ -94,8 +94,9 @@ int bd_link_disk_holder(struct block_device *bdev, struct gendisk *disk)
}
INIT_LIST_HEAD(&holder->list);
- holder->bdev = bdev;
holder->refcnt = 1;
+ holder->holder_dir = bdev->bd_holder_dir;
+
ret = add_symlink(disk->slave_dir, bdev_kobj(bdev));
if (ret)
goto out_free_holder;
@@ -140,8 +141,8 @@ void bd_unlink_disk_holder(struct block_device *bdev, struct gendisk *disk)
holder = bd_find_holder_disk(bdev, disk);
if (!WARN_ON_ONCE(holder == NULL) && !--holder->refcnt) {
del_symlink(disk->slave_dir, bdev_kobj(bdev));
- del_symlink(bdev->bd_holder_dir, &disk_to_dev(disk)->kobj);
- kobject_put(bdev->bd_holder_dir);
+ del_symlink(holder->holder_dir, &disk_to_dev(disk)->kobj);
+ kobject_put(holder->holder_dir);
list_del_init(&holder->list);
kfree(holder);
}
--
2.31.1
^ permalink raw reply related [flat|nested] 22+ messages in thread* [PATCH v3 10/10] block: don't allow a disk link holder to itself
2022-11-15 14:10 [PATCH v3 00/10] fix delayed holder tracking Yu Kuai
` (8 preceding siblings ...)
2022-11-15 14:10 ` [PATCH v3 09/10] block: store the holder kobject in bd_holder_disk Yu Kuai
@ 2022-11-15 14:10 ` Yu Kuai
2022-11-16 6:36 ` Christoph Hellwig
2022-11-16 22:20 ` [PATCH v3 00/10] fix delayed holder tracking Jens Axboe
10 siblings, 1 reply; 22+ messages in thread
From: Yu Kuai @ 2022-11-15 14:10 UTC (permalink / raw)
To: hch, axboe, agk, snitzer, dm-devel
Cc: linux-block, linux-kernel, yukuai3, yukuai1, yi.zhang
From: Yu Kuai <yukuai3@huawei.com>
After creating a dm device, then user can reload such dm with itself,
and dead loop will be triggered because dm keep looking up to itself.
Test procedures:
1) dmsetup create test --table "xxx sda", assume dm-0 is created
2) dmsetup suspend test
3) dmsetup reload test --table "xxx dm-0"
4) dmsetup resume test
Test result:
BUG: TASK stack guard page was hit at 00000000736a261f (stack is 000000008d12c88d..00000000c8dd82d5)
stack guard page: 0000 [#1] PREEMPT SMP
CPU: 29 PID: 946 Comm: systemd-udevd Not tainted 6.1.0-rc3-next-20221101-00006-g17640ca3b0ee #1295
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS ?-20190727_073836-buildvm-ppc64le-16.ppc.fedoraproject.org-3.fc31 04/01/2014
RIP: 0010:dm_prepare_ioctl+0xf/0x1e0
Code: da 48 83 05 4a 7c 99 0b 01 41 89 c4 eb cd e8 b8 1f 40 00 0f 1f 84 00 00 00 00 00 0f 1f 44 00 00 41 57 48 83 05 a1 5a 99 0b 01 <41> 56 49 89 d6 41 55 4c 8d af 90 02 00 00 9
RSP: 0018:ffffc90002090000 EFLAGS: 00010206
RAX: ffff8881049d6800 RBX: ffff88817e589000 RCX: 0000000000000000
RDX: ffffc90002090010 RSI: ffffc9000209001c RDI: ffff88817e589000
RBP: 00000000484a101d R08: 0000000000000000 R09: 0000000000000007
R10: 0000000000000000 R11: 0000000000000000 R12: 0000000000005331
R13: 0000000000005331 R14: 0000000000000000 R15: 0000000000000000
FS: 00007fddf9609200(0000) GS:ffff889fbfd40000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: ffffc9000208fff8 CR3: 0000000179043000 CR4: 00000000000006e0
DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
Call Trace:
<TASK>
dm_blk_ioctl+0x50/0x1c0
? dm_prepare_ioctl+0xe0/0x1e0
dm_blk_ioctl+0x88/0x1c0
dm_blk_ioctl+0x88/0x1c0
......(a lot of same lines)
dm_blk_ioctl+0x88/0x1c0
dm_blk_ioctl+0x88/0x1c0
blkdev_ioctl+0x184/0x3e0
__x64_sys_ioctl+0xa3/0x110
do_syscall_64+0x35/0x80
entry_SYSCALL_64_after_hwframe+0x63/0xcd
RIP: 0033:0x7fddf7306577
Code: b3 66 90 48 8b 05 11 89 2c 00 64 c7 00 26 00 00 00 48 c7 c0 ff ff ff ff c3 66 2e 0f 1f 84 00 00 00 00 00 b8 10 00 00 00 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 8b 0d e1 88 8
RSP: 002b:00007ffd0b2ec318 EFLAGS: 00000246 ORIG_RAX: 0000000000000010
RAX: ffffffffffffffda RBX: 00005634ef478320 RCX: 00007fddf7306577
RDX: 0000000000000000 RSI: 0000000000005331 RDI: 0000000000000007
RBP: 0000000000000007 R08: 00005634ef4843e0 R09: 0000000000000080
R10: 00007fddf75cfb38 R11: 0000000000000246 R12: 00000000030d4000
R13: 0000000000000000 R14: 0000000000000000 R15: 00005634ef48b800
</TASK>
Modules linked in:
---[ end trace 0000000000000000 ]---
RIP: 0010:dm_prepare_ioctl+0xf/0x1e0
Code: da 48 83 05 4a 7c 99 0b 01 41 89 c4 eb cd e8 b8 1f 40 00 0f 1f 84 00 00 00 00 00 0f 1f 44 00 00 41 57 48 83 05 a1 5a 99 0b 01 <41> 56 49 89 d6 41 55 4c 8d af 90 02 00 00 9
RSP: 0018:ffffc90002090000 EFLAGS: 00010206
RAX: ffff8881049d6800 RBX: ffff88817e589000 RCX: 0000000000000000
RDX: ffffc90002090010 RSI: ffffc9000209001c RDI: ffff88817e589000
RBP: 00000000484a101d R08: 0000000000000000 R09: 0000000000000007
R10: 0000000000000000 R11: 0000000000000000 R12: 0000000000005331
R13: 0000000000005331 R14: 0000000000000000 R15: 0000000000000000
FS: 00007fddf9609200(0000) GS:ffff889fbfd40000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: ffffc9000208fff8 CR3: 0000000179043000 CR4: 00000000000006e0
DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
Kernel panic - not syncing: Fatal exception in interrupt
Kernel Offset: disabled
---[ end Kernel panic - not syncing: Fatal exception in interrupt ]---
Fix the problem by forbidding a disk to create link to itself.
Signed-off-by: Yu Kuai <yukuai3@huawei.com>
---
block/holder.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/block/holder.c b/block/holder.c
index 3332142bb867..37d18c13d958 100644
--- a/block/holder.c
+++ b/block/holder.c
@@ -65,6 +65,9 @@ int bd_link_disk_holder(struct block_device *bdev, struct gendisk *disk)
if (WARN_ON_ONCE(!disk->slave_dir))
return -EINVAL;
+ if (bdev->bd_disk == disk)
+ return -EINVAL;
+
/*
* del_gendisk drops the initial reference to bd_holder_dir, so we
* need to keep our own here to allow for cleanup past that point.
--
2.31.1
^ permalink raw reply related [flat|nested] 22+ messages in thread* Re: [PATCH v3 00/10] fix delayed holder tracking
2022-11-15 14:10 [PATCH v3 00/10] fix delayed holder tracking Yu Kuai
` (9 preceding siblings ...)
2022-11-15 14:10 ` [PATCH v3 10/10] block: don't allow a disk link holder to itself Yu Kuai
@ 2022-11-16 22:20 ` Jens Axboe
10 siblings, 0 replies; 22+ messages in thread
From: Jens Axboe @ 2022-11-16 22:20 UTC (permalink / raw)
To: Yu Kuai, dm-devel, agk, snitzer, hch
Cc: yi.zhang, yukuai3, linux-kernel, linux-block
On Tue, 15 Nov 2022 22:10:44 +0800, Yu Kuai wrote:
> From: Yu Kuai <yukuai3@huawei.com>
>
> Hi all,
>
> this series tries to fix the delayed holder tracking that is only used by
> dm by moving it into dm, where we can track the lifetimes much better.
> v2 is from Christoph, here I send v3 with some additional fixes.
>
> [...]
Applied, thanks!
[01/10] block: clear ->slave_dir when dropping the main slave_dir reference
commit: d90db3b1c8676bc88b4309c5a571333de2263b8e
[02/10] dm: remove free_table_devices
commit: 992ec6a92ac315d3301353ff3beb818fcc34e4e4
[03/10] dm: cleanup open_table_device
commit: b9a785d2dc6567b2fd9fc60057a6a945a276927a
[04/10] dm: cleanup close_table_device
commit: 7b5865831c1003122f737df5e16adaa583f1a595
[05/10] dm: make sure create and remove dm device won't race with open and close table
commit: d563792c8933a810d28ce0f2831f0726c2b15a31
[06/10] dm: track per-add_disk holder relations in DM
commit: 1a581b72169968f4154b5793828f3bc28b258b35
[07/10] block: remove delayed holder registration
commit: 7abc077788363ac7194aefd355306f8e974feff7
[08/10] block: fix use after free for bd_holder_dir
commit: 62f535e1f061b4c2cc76061b6b59af9f9335ee34
[09/10] block: store the holder kobject in bd_holder_disk
commit: 3b3449c1e6c3fe19f62607ff4f353f8bb82d5c4e
[10/10] block: don't allow a disk link holder to itself
commit: 077a4033541fc96fb0a955985aab7d1f353da831
Best regards,
--
Jens Axboe
^ permalink raw reply [flat|nested] 22+ messages in thread