Skip to content

Commit 4ea30ec

Browse files
bmarzinsMikulas Patocka
authored andcommitted
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 <[email protected]> Tested-by: Damien Le Moal <[email protected]> Signed-off-by: Benjamin Marzinski <[email protected]> Signed-off-by: Mikulas Patocka <[email protected]>
1 parent e8819e7 commit 4ea30ec

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
@@ -1835,6 +1835,7 @@ int dm_table_set_restrictions(struct dm_table *t, struct request_queue *q,
18351835
struct queue_limits *limits)
18361836
{
18371837
int r;
1838+
struct queue_limits old_limits;
18381839

18391840
if (!dm_table_supports_nowait(t))
18401841
limits->features &= ~BLK_FEAT_NOWAIT;
@@ -1861,16 +1862,11 @@ int dm_table_set_restrictions(struct dm_table *t, struct request_queue *q,
18611862
if (dm_table_supports_flush(t))
18621863
limits->features |= BLK_FEAT_WRITE_CACHE | BLK_FEAT_FUA;
18631864

1864-
if (dm_table_supports_dax(t, device_not_dax_capable)) {
1865+
if (dm_table_supports_dax(t, device_not_dax_capable))
18651866
limits->features |= BLK_FEAT_DAX;
1866-
if (dm_table_supports_dax(t, device_not_dax_synchronous_capable))
1867-
set_dax_synchronous(t->md->dax_dev);
1868-
} else
1867+
else
18691868
limits->features &= ~BLK_FEAT_DAX;
18701869

1871-
if (dm_table_any_dev_attr(t, device_dax_write_cache_enabled, NULL))
1872-
dax_write_cache(t->md->dax_dev, true);
1873-
18741870
/* For a zoned table, setup the zone related queue attributes. */
18751871
if (IS_ENABLED(CONFIG_BLK_DEV_ZONED) &&
18761872
(limits->features & BLK_FEAT_ZONED)) {
@@ -1882,7 +1878,8 @@ int dm_table_set_restrictions(struct dm_table *t, struct request_queue *q,
18821878
if (dm_table_supports_atomic_writes(t))
18831879
limits->features |= BLK_FEAT_ATOMIC_WRITES;
18841880

1885-
r = queue_limits_set(q, limits);
1881+
old_limits = queue_limits_start_update(q);
1882+
r = queue_limits_commit_update(q, limits);
18861883
if (r)
18871884
return r;
18881885

@@ -1893,10 +1890,21 @@ int dm_table_set_restrictions(struct dm_table *t, struct request_queue *q,
18931890
if (IS_ENABLED(CONFIG_BLK_DEV_ZONED) &&
18941891
(limits->features & BLK_FEAT_ZONED)) {
18951892
r = dm_revalidate_zones(t, q);
1896-
if (r)
1893+
if (r) {
1894+
queue_limits_set(q, &old_limits);
18971895
return r;
1896+
}
18981897
}
18991898

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

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)