Skip to content

Commit 6d4448c

Browse files
Mikulas Patockagregkh
Mikulas Patocka
authored andcommitted
dm integrity: fix integrity recalculation that is improperly skipped
commit 5df96f2 upstream. Commit adc0daa ("dm: report suspended device during destroy") broke integrity recalculation. The problem is dm_suspended() returns true not only during suspend, but also during resume. So this race condition could occur: 1. dm_integrity_resume calls queue_work(ic->recalc_wq, &ic->recalc_work) 2. integrity_recalc (&ic->recalc_work) preempts the current thread 3. integrity_recalc calls if (unlikely(dm_suspended(ic->ti))) goto unlock_ret; 4. integrity_recalc exits and no recalculating is done. To fix this race condition, add a function dm_post_suspending that is only true during the postsuspend phase and use it instead of dm_suspended(). Signed-off-by: Mikulas Patocka <mpatocka redhat com> Fixes: adc0daa ("dm: report suspended device during destroy") Cc: stable vger kernel org # v4.18+ Signed-off-by: Mike Snitzer <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 2ca71b8 commit 6d4448c

File tree

3 files changed

+20
-2
lines changed

3 files changed

+20
-2
lines changed

drivers/md/dm-integrity.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2298,7 +2298,7 @@ static void integrity_writer(struct work_struct *w)
22982298
unsigned prev_free_sectors;
22992299

23002300
/* the following test is not needed, but it tests the replay code */
2301-
if (unlikely(dm_suspended(ic->ti)) && !ic->meta_dev)
2301+
if (unlikely(dm_post_suspending(ic->ti)) && !ic->meta_dev)
23022302
return;
23032303

23042304
spin_lock_irq(&ic->endio_wait.lock);
@@ -2359,7 +2359,7 @@ static void integrity_recalc(struct work_struct *w)
23592359

23602360
next_chunk:
23612361

2362-
if (unlikely(dm_suspended(ic->ti)))
2362+
if (unlikely(dm_post_suspending(ic->ti)))
23632363
goto unlock_ret;
23642364

23652365
range.logical_sector = le64_to_cpu(ic->sb->recalc_sector);

drivers/md/dm.c

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,7 @@ EXPORT_SYMBOL_GPL(dm_bio_get_target_bio_nr);
141141
#define DMF_NOFLUSH_SUSPENDING 5
142142
#define DMF_DEFERRED_REMOVE 6
143143
#define DMF_SUSPENDED_INTERNALLY 7
144+
#define DMF_POST_SUSPENDING 8
144145

145146
#define DM_NUMA_NODE NUMA_NO_NODE
146147
static int dm_numa_node = DM_NUMA_NODE;
@@ -2390,6 +2391,7 @@ static void __dm_destroy(struct mapped_device *md, bool wait)
23902391
if (!dm_suspended_md(md)) {
23912392
dm_table_presuspend_targets(map);
23922393
set_bit(DMF_SUSPENDED, &md->flags);
2394+
set_bit(DMF_POST_SUSPENDING, &md->flags);
23932395
dm_table_postsuspend_targets(map);
23942396
}
23952397
/* dm_put_live_table must be before msleep, otherwise deadlock is possible */
@@ -2712,7 +2714,9 @@ int dm_suspend(struct mapped_device *md, unsigned suspend_flags)
27122714
if (r)
27132715
goto out_unlock;
27142716

2717+
set_bit(DMF_POST_SUSPENDING, &md->flags);
27152718
dm_table_postsuspend_targets(map);
2719+
clear_bit(DMF_POST_SUSPENDING, &md->flags);
27162720

27172721
out_unlock:
27182722
mutex_unlock(&md->suspend_lock);
@@ -2809,7 +2813,9 @@ static void __dm_internal_suspend(struct mapped_device *md, unsigned suspend_fla
28092813
(void) __dm_suspend(md, map, suspend_flags, TASK_UNINTERRUPTIBLE,
28102814
DMF_SUSPENDED_INTERNALLY);
28112815

2816+
set_bit(DMF_POST_SUSPENDING, &md->flags);
28122817
dm_table_postsuspend_targets(map);
2818+
clear_bit(DMF_POST_SUSPENDING, &md->flags);
28132819
}
28142820

28152821
static void __dm_internal_resume(struct mapped_device *md)
@@ -2970,6 +2976,11 @@ int dm_suspended_md(struct mapped_device *md)
29702976
return test_bit(DMF_SUSPENDED, &md->flags);
29712977
}
29722978

2979+
static int dm_post_suspending_md(struct mapped_device *md)
2980+
{
2981+
return test_bit(DMF_POST_SUSPENDING, &md->flags);
2982+
}
2983+
29732984
int dm_suspended_internally_md(struct mapped_device *md)
29742985
{
29752986
return test_bit(DMF_SUSPENDED_INTERNALLY, &md->flags);
@@ -2986,6 +2997,12 @@ int dm_suspended(struct dm_target *ti)
29862997
}
29872998
EXPORT_SYMBOL_GPL(dm_suspended);
29882999

3000+
int dm_post_suspending(struct dm_target *ti)
3001+
{
3002+
return dm_post_suspending_md(dm_table_get_md(ti->table));
3003+
}
3004+
EXPORT_SYMBOL_GPL(dm_post_suspending);
3005+
29893006
int dm_noflush_suspending(struct dm_target *ti)
29903007
{
29913008
return __noflush_suspending(dm_table_get_md(ti->table));

include/linux/device-mapper.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -420,6 +420,7 @@ const char *dm_device_name(struct mapped_device *md);
420420
int dm_copy_name_and_uuid(struct mapped_device *md, char *name, char *uuid);
421421
struct gendisk *dm_disk(struct mapped_device *md);
422422
int dm_suspended(struct dm_target *ti);
423+
int dm_post_suspending(struct dm_target *ti);
423424
int dm_noflush_suspending(struct dm_target *ti);
424425
void dm_accept_partial_bio(struct bio *bio, unsigned n_sectors);
425426
void dm_remap_zone_report(struct dm_target *ti, sector_t start,

0 commit comments

Comments
 (0)