Commit 96b26c8c authored by Mikulas Patocka's avatar Mikulas Patocka Committed by Mike Snitzer

dm: fix handling of multiple internal suspends

Commit ffcc3936 ("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: default avatarMikulas Patocka <mpatocka@redhat.com>
Signed-off-by: default avatarMike Snitzer <snitzer@redhat.com>
parent a59db676
...@@ -206,6 +206,9 @@ struct mapped_device { ...@@ -206,6 +206,9 @@ struct mapped_device {
/* zero-length flush that will be cloned and submitted to targets */ /* zero-length flush that will be cloned and submitted to targets */
struct bio flush_bio; struct bio flush_bio;
/* the number of internal suspends */
unsigned internal_suspend_count;
struct dm_stats stats; struct dm_stats stats;
}; };
...@@ -2928,7 +2931,7 @@ static void __dm_internal_suspend(struct mapped_device *md, unsigned suspend_fla ...@@ -2928,7 +2931,7 @@ static void __dm_internal_suspend(struct mapped_device *md, unsigned suspend_fla
{ {
struct dm_table *map = NULL; struct dm_table *map = NULL;
if (dm_suspended_internally_md(md)) if (md->internal_suspend_count++)
return; /* nested internal suspend */ return; /* nested internal suspend */
if (dm_suspended_md(md)) { if (dm_suspended_md(md)) {
...@@ -2953,7 +2956,9 @@ static void __dm_internal_suspend(struct mapped_device *md, unsigned suspend_fla ...@@ -2953,7 +2956,9 @@ static void __dm_internal_suspend(struct mapped_device *md, unsigned suspend_fla
static void __dm_internal_resume(struct mapped_device *md) static void __dm_internal_resume(struct mapped_device *md)
{ {
if (!dm_suspended_internally_md(md)) BUG_ON(!md->internal_suspend_count);
if (--md->internal_suspend_count)
return; /* resume from nested internal suspend */ return; /* resume from nested internal suspend */
if (dm_suspended_md(md)) if (dm_suspended_md(md))
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment