Skip to content

Commit d928466

Browse files
committed
dm: handle failures in dm_table_set_restrictions
JIRA: https://issues.redhat.com/browse/RHEL-119009 Upstream Status: kernel/git/torvalds/linux.git commit 4ea30ec Author: Benjamin Marzinski <bmarzins@redhat.com> Date: Thu Apr 10 15:49:40 2025 -0400 dm: handle failures in dm_table_set_restrictions If dm_table_set_restrictions() fails while swapping tables, device-mapper will continue using the previous table. It must be sure to leave the mapped_device in it's previous state on failure. Otherwise device-mapper could end up using the old table with settings from the unused table. Do not update the mapped device in dm_set_zones_restrictions(). Wait till after dm_table_set_restrictions() is sure to succeed to update the md zoned settings. Do the same with the dax settings, and if dm_revalidate_zones() fails, restore the original queue limits. Fixes: 7f91ccd ("dm: Call dm_revalidate_zones() after setting the queue limits") 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: Benjamin Marzinski <bmarzins@redhat.com>
1 parent 9351e47 commit d928466

File tree

3 files changed

+36
-17
lines changed

3 files changed

+36
-17
lines changed

drivers/md/dm-table.c

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1833,6 +1833,7 @@ int dm_table_set_restrictions(struct dm_table *t, struct request_queue *q,
18331833
struct queue_limits *limits)
18341834
{
18351835
int r;
1836+
struct queue_limits old_limits;
18361837

18371838
if (!dm_table_supports_nowait(t))
18381839
limits->features &= ~BLK_FEAT_NOWAIT;
@@ -1859,16 +1860,11 @@ int dm_table_set_restrictions(struct dm_table *t, struct request_queue *q,
18591860
if (dm_table_supports_flush(t))
18601861
limits->features |= BLK_FEAT_WRITE_CACHE | BLK_FEAT_FUA;
18611862

1862-
if (dm_table_supports_dax(t, device_not_dax_capable)) {
1863+
if (dm_table_supports_dax(t, device_not_dax_capable))
18631864
limits->features |= BLK_FEAT_DAX;
1864-
if (dm_table_supports_dax(t, device_not_dax_synchronous_capable))
1865-
set_dax_synchronous(t->md->dax_dev);
1866-
} else
1865+
else
18671866
limits->features &= ~BLK_FEAT_DAX;
18681867

1869-
if (dm_table_any_dev_attr(t, device_dax_write_cache_enabled, NULL))
1870-
dax_write_cache(t->md->dax_dev, true);
1871-
18721868
/* For a zoned table, setup the zone related queue attributes. */
18731869
if (IS_ENABLED(CONFIG_BLK_DEV_ZONED) &&
18741870
(limits->features & BLK_FEAT_ZONED)) {
@@ -1880,7 +1876,8 @@ int dm_table_set_restrictions(struct dm_table *t, struct request_queue *q,
18801876
if (dm_table_supports_atomic_writes(t))
18811877
limits->features |= BLK_FEAT_ATOMIC_WRITES;
18821878

1883-
r = queue_limits_set(q, limits);
1879+
old_limits = queue_limits_start_update(q);
1880+
r = queue_limits_commit_update(q, limits);
18841881
if (r)
18851882
return r;
18861883

@@ -1891,10 +1888,21 @@ int dm_table_set_restrictions(struct dm_table *t, struct request_queue *q,
18911888
if (IS_ENABLED(CONFIG_BLK_DEV_ZONED) &&
18921889
(limits->features & BLK_FEAT_ZONED)) {
18931890
r = dm_revalidate_zones(t, q);
1894-
if (r)
1891+
if (r) {
1892+
queue_limits_set(q, &old_limits);
18951893
return r;
1894+
}
18961895
}
18971896

1897+
if (IS_ENABLED(CONFIG_BLK_DEV_ZONED))
1898+
dm_finalize_zone_settings(t, limits);
1899+
1900+
if (dm_table_supports_dax(t, device_not_dax_synchronous_capable))
1901+
set_dax_synchronous(t->md->dax_dev);
1902+
1903+
if (dm_table_any_dev_attr(t, device_dax_write_cache_enabled, NULL))
1904+
dax_write_cache(t->md->dax_dev, true);
1905+
18981906
dm_update_crypto_profile(q, t);
18991907
return 0;
19001908
}

drivers/md/dm-zone.c

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -340,12 +340,8 @@ int dm_set_zones_restrictions(struct dm_table *t, struct request_queue *q,
340340
* mapped device queue as needing zone append emulation.
341341
*/
342342
WARN_ON_ONCE(queue_is_mq(q));
343-
if (dm_table_supports_zone_append(t)) {
344-
clear_bit(DMF_EMULATE_ZONE_APPEND, &md->flags);
345-
} else {
346-
set_bit(DMF_EMULATE_ZONE_APPEND, &md->flags);
343+
if (!dm_table_supports_zone_append(t))
347344
lim->max_hw_zone_append_sectors = 0;
348-
}
349345

350346
/*
351347
* Determine the max open and max active zone limits for the mapped
@@ -383,9 +379,6 @@ int dm_set_zones_restrictions(struct dm_table *t, struct request_queue *q,
383379
lim->zone_write_granularity = 0;
384380
lim->chunk_sectors = 0;
385381
lim->features &= ~BLK_FEAT_ZONED;
386-
clear_bit(DMF_EMULATE_ZONE_APPEND, &md->flags);
387-
md->nr_zones = 0;
388-
disk->nr_zones = 0;
389382
return 0;
390383
}
391384

@@ -408,6 +401,23 @@ int dm_set_zones_restrictions(struct dm_table *t, struct request_queue *q,
408401
return 0;
409402
}
410403

404+
void dm_finalize_zone_settings(struct dm_table *t, struct queue_limits *lim)
405+
{
406+
struct mapped_device *md = t->md;
407+
408+
if (lim->features & BLK_FEAT_ZONED) {
409+
if (dm_table_supports_zone_append(t))
410+
clear_bit(DMF_EMULATE_ZONE_APPEND, &md->flags);
411+
else
412+
set_bit(DMF_EMULATE_ZONE_APPEND, &md->flags);
413+
} else {
414+
clear_bit(DMF_EMULATE_ZONE_APPEND, &md->flags);
415+
md->nr_zones = 0;
416+
md->disk->nr_zones = 0;
417+
}
418+
}
419+
420+
411421
/*
412422
* IO completion callback called from clone_endio().
413423
*/

drivers/md/dm.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@ int dm_setup_md_queue(struct mapped_device *md, struct dm_table *t);
102102
int dm_set_zones_restrictions(struct dm_table *t, struct request_queue *q,
103103
struct queue_limits *lim);
104104
int dm_revalidate_zones(struct dm_table *t, struct request_queue *q);
105+
void dm_finalize_zone_settings(struct dm_table *t, struct queue_limits *lim);
105106
void dm_zone_endio(struct dm_io *io, struct bio *clone);
106107
#ifdef CONFIG_BLK_DEV_ZONED
107108
int dm_blk_report_zones(struct gendisk *disk, sector_t sector,

0 commit comments

Comments
 (0)