Commit 96b26c8c64c7a30488b8b404f7a63346df4c3bff

Authored by Mikulas Patocka
Committed by Mike Snitzer
1 parent a59db67656

dm: fix handling of multiple internal suspends

Commit ffcc393641 ("dm: enhance internal suspend and resume interface")
attempted to handle multiple internal suspends on the same device, but
it did that incorrectly.  When these functions are called in this order
on the same device the device is no longer suspended, but it should be:
	dm_internal_suspend_noflush
	dm_internal_suspend_noflush
	dm_internal_resume

Fix this bug by maintaining an 'internal_suspend_count' and resuming
the device when this count drops to zero.

Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
Signed-off-by: Mike Snitzer <snitzer@redhat.com>

Showing 1 changed file with 7 additions and 2 deletions Side-by-side Diff

... ... @@ -206,6 +206,9 @@
206 206 /* zero-length flush that will be cloned and submitted to targets */
207 207 struct bio flush_bio;
208 208  
  209 + /* the number of internal suspends */
  210 + unsigned internal_suspend_count;
  211 +
209 212 struct dm_stats stats;
210 213 };
211 214  
... ... @@ -2928,7 +2931,7 @@
2928 2931 {
2929 2932 struct dm_table *map = NULL;
2930 2933  
2931   - if (dm_suspended_internally_md(md))
  2934 + if (md->internal_suspend_count++)
2932 2935 return; /* nested internal suspend */
2933 2936  
2934 2937 if (dm_suspended_md(md)) {
... ... @@ -2953,7 +2956,9 @@
2953 2956  
2954 2957 static void __dm_internal_resume(struct mapped_device *md)
2955 2958 {
2956   - if (!dm_suspended_internally_md(md))
  2959 + BUG_ON(!md->internal_suspend_count);
  2960 +
  2961 + if (--md->internal_suspend_count)
2957 2962 return; /* resume from nested internal suspend */
2958 2963  
2959 2964 if (dm_suspended_md(md))