static inline void free_list_of_pages(struct linked_page *list, int clear_page_nosave) { while (list) { struct linked_page *lp = list->next; free_image_page(list, clear_page_nosave); list = lp; } }
static void memory_bm_free(struct memory_bitmap *bm, int clear_nosave_free) { struct zone_bitmap *zone_bm; /* Free the list of bit blocks for each zone_bitmap object */ zone_bm = bm->zone_bm_list; while (zone_bm) { struct bm_block *bb; bb = zone_bm->bm_blocks; while (bb) { if (bb->data) free_image_page(bb->data, clear_nosave_free); bb = bb->next; } zone_bm = zone_bm->next; } free_list_of_pages(bm->p_list, clear_nosave_free); bm->zone_bm_list = NULL; }
static int prepare_image(struct memory_bitmap *new_bm, struct memory_bitmap *bm) { unsigned int nr_pages; struct linked_page *sp_list, *lp; int error; error = mark_unsafe_pages(bm); if (error) goto Free; error = memory_bm_create(new_bm, GFP_ATOMIC, PG_SAFE); if (error) goto Free; duplicate_memory_bitmap(new_bm, bm); memory_bm_free(bm, PG_UNSAFE_KEEP); /* Reserve some safe pages for potential later use. * * NOTE: This way we make sure there will be enough safe pages for the * chain_alloc() in get_buffer(). It is a bit wasteful, but * nr_copy_pages cannot be greater than 50% of the memory anyway. */ sp_list = NULL; /* nr_copy_pages cannot be lesser than allocated_unsafe_pages */ nr_pages = nr_copy_pages - allocated_unsafe_pages; nr_pages = DIV_ROUND_UP(nr_pages, PBES_PER_LINKED_PAGE); while (nr_pages > 0) { lp = alloc_image_page(GFP_ATOMIC, PG_SAFE); if (!lp) { error = -ENOMEM; goto Free; } lp->next = sp_list; sp_list = lp; nr_pages--; } /* Preallocate memory for the image */ safe_pages_list = NULL; nr_pages = nr_copy_pages - allocated_unsafe_pages; while (nr_pages > 0) { lp = (struct linked_page *)get_zeroed_page(GFP_ATOMIC); if (!lp) { error = -ENOMEM; goto Free; } if (!PageNosaveFree(virt_to_page(lp))) { /* The page is "safe", add it to the list */ lp->next = safe_pages_list; safe_pages_list = lp; } /* Mark the page as allocated */ SetPageNosave(virt_to_page(lp)); SetPageNosaveFree(virt_to_page(lp)); nr_pages--; } /* Free the reserved safe pages so that chain_alloc() can use them */ while (sp_list) { lp = sp_list->next; free_image_page(sp_list, PG_UNSAFE_CLEAR); sp_list = lp; } return 0; Free: swsusp_free(); return error; }