diff options
| author | Benjamin Marzinski <bmarzins@redhat.com> | 2025-04-10 15:49:38 -0400 |
|---|---|---|
| committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2025-06-19 15:32:04 +0200 |
| commit | 2eeb181e76d4ef43ab884e6a67454003cec81dbb (patch) | |
| tree | 5447146a68d99280a89bf399bf29a31f8547e40b /drivers/md | |
| parent | baf8a7fed0ea26803398d4b1fd576b2b9a424d13 (diff) | |
| download | linux-2eeb181e76d4ef43ab884e6a67454003cec81dbb.tar.gz linux-2eeb181e76d4ef43ab884e6a67454003cec81dbb.tar.bz2 linux-2eeb181e76d4ef43ab884e6a67454003cec81dbb.zip | |
dm: don't change md if dm_table_set_restrictions() fails
[ Upstream commit 9eb7109a5bfc5b8226e9517e9f3cc6d414391884 ]
__bind was changing the disk capacity, geometry and mempools of the
mapped device before calling dm_table_set_restrictions() which could
fail, forcing dm to drop the new table. Failing here would leave the
device using the old table but with the wrong capacity and mempools.
Move dm_table_set_restrictions() earlier in __bind(). Since it needs the
capacity to be set, save the old version and restore it on failure.
Fixes: bb37d77239af2 ("dm: introduce zone append emulation")
Reviewed-by: Damien Le Moal <dlemoal@kernel.org>
Tested-by: Damien Le Moal <dlemoal@kernel.org>
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
Diffstat (limited to 'drivers/md')
| -rw-r--r-- | drivers/md/dm.c | 22 |
1 files changed, 12 insertions, 10 deletions
diff --git a/drivers/md/dm.c b/drivers/md/dm.c index d29125ee9e72..12d5f414a678 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c @@ -2410,21 +2410,29 @@ static struct dm_table *__bind(struct mapped_device *md, struct dm_table *t, struct queue_limits *limits) { struct dm_table *old_map; - sector_t size; + sector_t size, old_size; int ret; lockdep_assert_held(&md->suspend_lock); size = dm_table_get_size(t); + old_size = dm_get_size(md); + set_capacity(md->disk, size); + + ret = dm_table_set_restrictions(t, md->queue, limits); + if (ret) { + set_capacity(md->disk, old_size); + old_map = ERR_PTR(ret); + goto out; + } + /* * Wipe any geometry if the size of the table changed. */ - if (size != dm_get_size(md)) + if (size != old_size) memset(&md->geometry, 0, sizeof(md->geometry)); - set_capacity(md->disk, size); - dm_table_event_callback(t, event_callback, md); if (dm_table_request_based(t)) { @@ -2457,12 +2465,6 @@ static struct dm_table *__bind(struct mapped_device *md, struct dm_table *t, t->mempools = NULL; } - ret = dm_table_set_restrictions(t, md->queue, limits); - if (ret) { - old_map = ERR_PTR(ret); - goto out; - } - old_map = rcu_dereference_protected(md->map, lockdep_is_held(&md->suspend_lock)); rcu_assign_pointer(md->map, (void *)t); md->immutable_target_type = dm_table_get_immutable_target_type(t); |
