diff options
| author | Rafael J. Wysocki <rjw@sisk.pl> | 2006-09-26 02:32:45 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-09-26 11:48:58 -0400 |
| commit | ae83c5eef59ffe6eb61110b8c8fd1ea3e0881712 (patch) | |
| tree | 731e4d382ff408387624df1fc59e82ab50436f50 | |
| parent | 546e0d271941dd1ff6961e2a1f7eac75f1fc277e (diff) | |
[PATCH] swsusp: clean up browsing of pfns
Clean up some loops over pfns for each zone in snapshot.c: reduce the
number of additions to perform, rework detection of saveable pages and make
the code a bit less difficult to understand, hopefully.
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
Acked-by: Pavel Machek <pavel@ucw.cz>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
| -rw-r--r-- | kernel/power/snapshot.c | 62 |
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;} | |||
| 156 | static inline int restore_highmem(void) {return 0;} | 156 | static inline int restore_highmem(void) {return 0;} |
| 157 | #endif | 157 | #endif |
| 158 | 158 | ||
| 159 | static int pfn_is_nosave(unsigned long pfn) | 159 | static 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 | ||
| 175 | static int saveable(struct zone *zone, unsigned long *zone_pfn) | 175 | static 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 | ||
| 195 | unsigned int count_data_pages(void) | 194 | unsigned 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) | |||
| 211 | static void copy_data_pages(struct pbe *pblist) | 211 | static 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, | |||
| 383 | void swsusp_free(void) | 384 | void 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) | |||
| 598 | static int mark_unsafe_pages(struct pbe *pblist) | 600 | static 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 */ |
