aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--kernel/power/snapshot.c54
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
728static 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
728static int memory_bm_test_bit(struct memory_bitmap *bm, unsigned long pfn) 736static 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
1334void swsusp_free(void) 1342void 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) && 1352loop:
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
1376out:
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;