diff options
-rw-r--r-- | kernel/power/snapshot.c | 54 |
1 files changed, 39 insertions, 15 deletions
diff --git a/kernel/power/snapshot.c b/kernel/power/snapshot.c index f1604d8cf489..791a61892bb5 100644 --- a/kernel/power/snapshot.c +++ b/kernel/power/snapshot.c | |||
@@ -725,6 +725,14 @@ static void memory_bm_clear_bit(struct memory_bitmap *bm, unsigned long pfn) | |||
725 | clear_bit(bit, addr); | 725 | clear_bit(bit, addr); |
726 | } | 726 | } |
727 | 727 | ||
728 | static void memory_bm_clear_current(struct memory_bitmap *bm) | ||
729 | { | ||
730 | int bit; | ||
731 | |||
732 | bit = max(bm->cur.node_bit - 1, 0); | ||
733 | clear_bit(bit, bm->cur.node->data); | ||
734 | } | ||
735 | |||
728 | static int memory_bm_test_bit(struct memory_bitmap *bm, unsigned long pfn) | 736 | static int memory_bm_test_bit(struct memory_bitmap *bm, unsigned long pfn) |
729 | { | 737 | { |
730 | void *addr; | 738 | void *addr; |
@@ -1333,23 +1341,39 @@ static struct memory_bitmap copy_bm; | |||
1333 | 1341 | ||
1334 | void swsusp_free(void) | 1342 | void swsusp_free(void) |
1335 | { | 1343 | { |
1336 | struct zone *zone; | 1344 | unsigned long fb_pfn, fr_pfn; |
1337 | unsigned long pfn, max_zone_pfn; | ||
1338 | 1345 | ||
1339 | for_each_populated_zone(zone) { | 1346 | if (!forbidden_pages_map || !free_pages_map) |
1340 | max_zone_pfn = zone_end_pfn(zone); | 1347 | goto out; |
1341 | for (pfn = zone->zone_start_pfn; pfn < max_zone_pfn; pfn++) | 1348 | |
1342 | if (pfn_valid(pfn)) { | 1349 | memory_bm_position_reset(forbidden_pages_map); |
1343 | struct page *page = pfn_to_page(pfn); | 1350 | memory_bm_position_reset(free_pages_map); |
1344 | 1351 | ||
1345 | if (swsusp_page_is_forbidden(page) && | 1352 | loop: |
1346 | swsusp_page_is_free(page)) { | 1353 | fr_pfn = memory_bm_next_pfn(free_pages_map); |
1347 | swsusp_unset_page_forbidden(page); | 1354 | fb_pfn = memory_bm_next_pfn(forbidden_pages_map); |
1348 | swsusp_unset_page_free(page); | 1355 | |
1349 | __free_page(page); | 1356 | /* |
1350 | } | 1357 | * Find the next bit set in both bitmaps. This is guaranteed to |
1351 | } | 1358 | * terminate when fb_pfn == fr_pfn == BM_END_OF_MAP. |
1359 | */ | ||
1360 | do { | ||
1361 | if (fb_pfn < fr_pfn) | ||
1362 | fb_pfn = memory_bm_next_pfn(forbidden_pages_map); | ||
1363 | if (fr_pfn < fb_pfn) | ||
1364 | fr_pfn = memory_bm_next_pfn(free_pages_map); | ||
1365 | } while (fb_pfn != fr_pfn); | ||
1366 | |||
1367 | if (fr_pfn != BM_END_OF_MAP && pfn_valid(fr_pfn)) { | ||
1368 | struct page *page = pfn_to_page(fr_pfn); | ||
1369 | |||
1370 | memory_bm_clear_current(forbidden_pages_map); | ||
1371 | memory_bm_clear_current(free_pages_map); | ||
1372 | __free_page(page); | ||
1373 | goto loop; | ||
1352 | } | 1374 | } |
1375 | |||
1376 | out: | ||
1353 | nr_copy_pages = 0; | 1377 | nr_copy_pages = 0; |
1354 | nr_meta_pages = 0; | 1378 | nr_meta_pages = 0; |
1355 | restore_pblist = NULL; | 1379 | restore_pblist = NULL; |