summaryrefslogtreecommitdiff
path: root/drivers/md
diff options
context:
space:
mode:
authorBenjamin Marzinski <bmarzins@redhat.com>2025-04-10 15:49:38 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2025-06-27 11:07:14 +0100
commit44133e7ba86ae253ea365416e68f41235e127afb (patch)
treeb004830bc0ab3eaa8b440019b5adf1a5ea199729 /drivers/md
parent9ace5644f5eeed1bade5b68ea960e1f0da08d25e (diff)
downloadlinux-44133e7ba86ae253ea365416e68f41235e127afb.tar.gz
linux-44133e7ba86ae253ea365416e68f41235e127afb.tar.bz2
linux-44133e7ba86ae253ea365416e68f41235e127afb.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.c22
1 files changed, 12 insertions, 10 deletions
diff --git a/drivers/md/dm.c b/drivers/md/dm.c
index 4767265793de..2b8fe98c515e 100644
--- a/drivers/md/dm.c
+++ b/drivers/md/dm.c
@@ -2165,21 +2165,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)) {
@@ -2212,12 +2220,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);