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.c62
1 files changed, 32 insertions, 30 deletions
diff --git a/kernel/power/snapshot.c b/kernel/power/snapshot.c
index 591301ae8b7d..979096c27773 100644
--- a/kernel/power/snapshot.c
+++ b/kernel/power/snapshot.c
@@ -156,7 +156,7 @@ static inline int save_highmem(void) {return 0;}
156static inline int restore_highmem(void) {return 0;} 156static inline int restore_highmem(void) {return 0;}
157#endif 157#endif
158 158
159static int pfn_is_nosave(unsigned long pfn) 159static inline int pfn_is_nosave(unsigned long pfn)
160{ 160{
161 unsigned long nosave_begin_pfn = __pa(&__nosave_begin) >> PAGE_SHIFT; 161 unsigned long nosave_begin_pfn = __pa(&__nosave_begin) >> PAGE_SHIFT;
162 unsigned long nosave_end_pfn = PAGE_ALIGN(__pa(&__nosave_end)) >> PAGE_SHIFT; 162 unsigned long nosave_end_pfn = PAGE_ALIGN(__pa(&__nosave_end)) >> PAGE_SHIFT;
@@ -167,43 +167,43 @@ static int pfn_is_nosave(unsigned long pfn)
167 * saveable - Determine whether a page should be cloned or not. 167 * saveable - Determine whether a page should be cloned or not.
168 * @pfn: The page 168 * @pfn: The page
169 * 169 *
170 * We save a page if it's Reserved, and not in the range of pages 170 * We save a page if it isn't Nosave, and is not in the range of pages
171 * statically defined as 'unsaveable', or if it isn't reserved, and 171 * statically defined as 'unsaveable', and it
172 * isn't part of a free chunk of pages. 172 * isn't a part of a free chunk of pages.
173 */ 173 */
174 174
175static int saveable(struct zone *zone, unsigned long *zone_pfn) 175static struct page *saveable_page(unsigned long pfn)
176{ 176{
177 unsigned long pfn = *zone_pfn + zone->zone_start_pfn;
178 struct page *page; 177 struct page *page;
179 178
180 if (!pfn_valid(pfn)) 179 if (!pfn_valid(pfn))
181 return 0; 180 return NULL;
182 181
183 page = pfn_to_page(pfn); 182 page = pfn_to_page(pfn);
184 BUG_ON(PageReserved(page) && PageNosave(page)); 183
185 if (PageNosave(page)) 184 if (PageNosave(page))
186 return 0; 185 return NULL;
187 if (PageReserved(page) && pfn_is_nosave(pfn)) 186 if (PageReserved(page) && pfn_is_nosave(pfn))
188 return 0; 187 return NULL;
189 if (PageNosaveFree(page)) 188 if (PageNosaveFree(page))
190 return 0; 189 return NULL;
191 190
192 return 1; 191 return page;
193} 192}
194 193
195unsigned int count_data_pages(void) 194unsigned int count_data_pages(void)
196{ 195{
197 struct zone *zone; 196 struct zone *zone;
198 unsigned long zone_pfn; 197 unsigned long pfn, max_zone_pfn;
199 unsigned int n = 0; 198 unsigned int n = 0;
200 199
201 for_each_zone (zone) { 200 for_each_zone (zone) {
202 if (is_highmem(zone)) 201 if (is_highmem(zone))
203 continue; 202 continue;
204 mark_free_pages(zone); 203 mark_free_pages(zone);
205 for (zone_pfn = 0; zone_pfn < zone->spanned_pages; ++zone_pfn) 204 max_zone_pfn = zone->zone_start_pfn + zone->spanned_pages;
206 n += saveable(zone, &zone_pfn); 205 for (pfn = zone->zone_start_pfn; pfn < max_zone_pfn; pfn++)
206 n += !!saveable_page(pfn);
207 } 207 }
208 return n; 208 return n;
209} 209}
@@ -211,7 +211,7 @@ unsigned int count_data_pages(void)
211static void copy_data_pages(struct pbe *pblist) 211static void copy_data_pages(struct pbe *pblist)
212{ 212{
213 struct zone *zone; 213 struct zone *zone;
214 unsigned long zone_pfn; 214 unsigned long pfn, max_zone_pfn;
215 struct pbe *pbe, *p; 215 struct pbe *pbe, *p;
216 216
217 pbe = pblist; 217 pbe = pblist;
@@ -224,13 +224,14 @@ static void copy_data_pages(struct pbe *pblist)
224 SetPageNosaveFree(virt_to_page(p)); 224 SetPageNosaveFree(virt_to_page(p));
225 for_each_pbe (p, pblist) 225 for_each_pbe (p, pblist)
226 SetPageNosaveFree(virt_to_page(p->address)); 226 SetPageNosaveFree(virt_to_page(p->address));
227 for (zone_pfn = 0; zone_pfn < zone->spanned_pages; ++zone_pfn) { 227 max_zone_pfn = zone->zone_start_pfn + zone->spanned_pages;
228 if (saveable(zone, &zone_pfn)) { 228 for (pfn = zone->zone_start_pfn; pfn < max_zone_pfn; pfn++) {
229 struct page *page; 229 struct page *page = saveable_page(pfn);
230
231 if (page) {
230 long *src, *dst; 232 long *src, *dst;
231 int n; 233 int n;
232 234
233 page = pfn_to_page(zone_pfn + zone->zone_start_pfn);
234 BUG_ON(!pbe); 235 BUG_ON(!pbe);
235 pbe->orig_address = (unsigned long)page_address(page); 236 pbe->orig_address = (unsigned long)page_address(page);
236 /* copy_page and memcpy are not usable for copying task structs. */ 237 /* copy_page and memcpy are not usable for copying task structs. */
@@ -383,13 +384,14 @@ static struct pbe *alloc_pagedir(unsigned int nr_pages, gfp_t gfp_mask,
383void swsusp_free(void) 384void swsusp_free(void)
384{ 385{
385 struct zone *zone; 386 struct zone *zone;
386 unsigned long zone_pfn; 387 unsigned long pfn, max_zone_pfn;
387 388
388 for_each_zone(zone) { 389 for_each_zone(zone) {
389 for (zone_pfn = 0; zone_pfn < zone->spanned_pages; ++zone_pfn) 390 max_zone_pfn = zone->zone_start_pfn + zone->spanned_pages;
390 if (pfn_valid(zone_pfn + zone->zone_start_pfn)) { 391 for (pfn = zone->zone_start_pfn; pfn < max_zone_pfn; pfn++)
391 struct page *page; 392 if (pfn_valid(pfn)) {
392 page = pfn_to_page(zone_pfn + zone->zone_start_pfn); 393 struct page *page = pfn_to_page(pfn);
394
393 if (PageNosave(page) && PageNosaveFree(page)) { 395 if (PageNosave(page) && PageNosaveFree(page)) {
394 ClearPageNosave(page); 396 ClearPageNosave(page);
395 ClearPageNosaveFree(page); 397 ClearPageNosaveFree(page);
@@ -598,7 +600,7 @@ int snapshot_read_next(struct snapshot_handle *handle, size_t count)
598static int mark_unsafe_pages(struct pbe *pblist) 600static int mark_unsafe_pages(struct pbe *pblist)
599{ 601{
600 struct zone *zone; 602 struct zone *zone;
601 unsigned long zone_pfn; 603 unsigned long pfn, max_zone_pfn;
602 struct pbe *p; 604 struct pbe *p;
603 605
604 if (!pblist) /* a sanity check */ 606 if (!pblist) /* a sanity check */
@@ -606,10 +608,10 @@ static int mark_unsafe_pages(struct pbe *pblist)
606 608
607 /* Clear page flags */ 609 /* Clear page flags */
608 for_each_zone (zone) { 610 for_each_zone (zone) {
609 for (zone_pfn = 0; zone_pfn < zone->spanned_pages; ++zone_pfn) 611 max_zone_pfn = zone->zone_start_pfn + zone->spanned_pages;
610 if (pfn_valid(zone_pfn + zone->zone_start_pfn)) 612 for (pfn = zone->zone_start_pfn; pfn < max_zone_pfn; pfn++)
611 ClearPageNosaveFree(pfn_to_page(zone_pfn + 613 if (pfn_valid(pfn))
612 zone->zone_start_pfn)); 614 ClearPageNosaveFree(pfn_to_page(pfn));
613 } 615 }
614 616
615 /* Mark orig addresses */ 617 /* Mark orig addresses */