Commit 96b26c8c64c7a30488b8b404f7a63346df4c3bff
Committed by
Mike Snitzer
1 parent
a59db67656
Exists in
ti-lsk-linux-4.1.y
and in
10 other branches
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
drivers/md/dm.c
... | ... | @@ -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)) |