aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/power/snapshot.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/power/snapshot.c')
-rw-r--r--kernel/power/snapshot.c53
1 files changed, 38 insertions, 15 deletions
diff --git a/kernel/power/snapshot.c b/kernel/power/snapshot.c
index 802f2415408e..5b71caf43d32 100644
--- a/kernel/power/snapshot.c
+++ b/kernel/power/snapshot.c
@@ -848,6 +848,17 @@ static void memory_bm_clear_bit(struct memory_bitmap *bm, unsigned long pfn)
848 clear_bit(bit, addr); 848 clear_bit(bit, addr);
849} 849}
850 850
851static void memory_bm_clear_current(struct memory_bitmap *bm)
852{
853 int bit;
854
855 bit = max(bm->cur.node_bit - 1, 0);
856 clear_bit(bit, bm->cur.node->data);
857
858 bit = max(bm->cur.bit - 1, 0);
859 clear_bit(bit, bm->cur.block->data);
860}
861
851static int memory_bm_test_bit(struct memory_bitmap *bm, unsigned long pfn) 862static int memory_bm_test_bit(struct memory_bitmap *bm, unsigned long pfn)
852{ 863{
853 void *addr; 864 void *addr;
@@ -1491,23 +1502,35 @@ static struct memory_bitmap copy_bm;
1491 1502
1492void swsusp_free(void) 1503void swsusp_free(void)
1493{ 1504{
1494 struct zone *zone; 1505 unsigned long fb_pfn, fr_pfn;
1495 unsigned long pfn, max_zone_pfn;
1496 1506
1497 for_each_populated_zone(zone) { 1507 memory_bm_position_reset(forbidden_pages_map);
1498 max_zone_pfn = zone_end_pfn(zone); 1508 memory_bm_position_reset(free_pages_map);
1499 for (pfn = zone->zone_start_pfn; pfn < max_zone_pfn; pfn++) 1509
1500 if (pfn_valid(pfn)) { 1510loop:
1501 struct page *page = pfn_to_page(pfn); 1511 fr_pfn = memory_bm_next_pfn(free_pages_map);
1502 1512 fb_pfn = memory_bm_next_pfn(forbidden_pages_map);
1503 if (swsusp_page_is_forbidden(page) && 1513
1504 swsusp_page_is_free(page)) { 1514 /*
1505 swsusp_unset_page_forbidden(page); 1515 * Find the next bit set in both bitmaps. This is guaranteed to
1506 swsusp_unset_page_free(page); 1516 * terminate when fb_pfn == fr_pfn == BM_END_OF_MAP.
1507 __free_page(page); 1517 */
1508 } 1518 do {
1509 } 1519 if (fb_pfn < fr_pfn)
1520 fb_pfn = memory_bm_next_pfn(forbidden_pages_map);
1521 if (fr_pfn < fb_pfn)
1522 fr_pfn = memory_bm_next_pfn(free_pages_map);
1523 } while (fb_pfn != fr_pfn);
1524
1525 if (fr_pfn != BM_END_OF_MAP && pfn_valid(fr_pfn)) {
1526 struct page *page = pfn_to_page(fr_pfn);
1527
1528 memory_bm_clear_current(forbidden_pages_map);
1529 memory_bm_clear_current(free_pages_map);
1530 __free_page(page);
1531 goto loop;
1510 } 1532 }
1533
1511 nr_copy_pages = 0; 1534 nr_copy_pages = 0;
1512 nr_meta_pages = 0; 1535 nr_meta_pages = 0;
1513 restore_pblist = NULL; 1536 restore_pblist = NULL;