diff options
Diffstat (limited to 'kernel/power/snapshot.c')
-rw-r--r-- | kernel/power/snapshot.c | 32 |
1 files changed, 17 insertions, 15 deletions
diff --git a/kernel/power/snapshot.c b/kernel/power/snapshot.c index 7ad0c0465524..4ca372f2bc14 100644 --- a/kernel/power/snapshot.c +++ b/kernel/power/snapshot.c | |||
@@ -316,12 +316,12 @@ static void free_pagedir(struct pbe *pblist, int clear_nosave_free) | |||
316 | * fill_pb_page - Create a list of PBEs on a given memory page | 316 | * fill_pb_page - Create a list of PBEs on a given memory page |
317 | */ | 317 | */ |
318 | 318 | ||
319 | static inline void fill_pb_page(struct pbe *pbpage) | 319 | static inline void fill_pb_page(struct pbe *pbpage, unsigned int n) |
320 | { | 320 | { |
321 | struct pbe *p; | 321 | struct pbe *p; |
322 | 322 | ||
323 | p = pbpage; | 323 | p = pbpage; |
324 | pbpage += PB_PAGE_SKIP; | 324 | pbpage += n - 1; |
325 | do | 325 | do |
326 | p->next = p + 1; | 326 | p->next = p + 1; |
327 | while (++p < pbpage); | 327 | while (++p < pbpage); |
@@ -330,24 +330,26 @@ static inline void fill_pb_page(struct pbe *pbpage) | |||
330 | /** | 330 | /** |
331 | * create_pbe_list - Create a list of PBEs on top of a given chain | 331 | * create_pbe_list - Create a list of PBEs on top of a given chain |
332 | * of memory pages allocated with alloc_pagedir() | 332 | * of memory pages allocated with alloc_pagedir() |
333 | * | ||
334 | * This function assumes that pages allocated by alloc_image_page() will | ||
335 | * always be zeroed. | ||
333 | */ | 336 | */ |
334 | 337 | ||
335 | static inline void create_pbe_list(struct pbe *pblist, unsigned int nr_pages) | 338 | static inline void create_pbe_list(struct pbe *pblist, unsigned int nr_pages) |
336 | { | 339 | { |
337 | struct pbe *pbpage, *p; | 340 | struct pbe *pbpage; |
338 | unsigned int num = PBES_PER_PAGE; | 341 | unsigned int num = PBES_PER_PAGE; |
339 | 342 | ||
340 | for_each_pb_page (pbpage, pblist) { | 343 | for_each_pb_page (pbpage, pblist) { |
341 | if (num >= nr_pages) | 344 | if (num >= nr_pages) |
342 | break; | 345 | break; |
343 | 346 | ||
344 | fill_pb_page(pbpage); | 347 | fill_pb_page(pbpage, PBES_PER_PAGE); |
345 | num += PBES_PER_PAGE; | 348 | num += PBES_PER_PAGE; |
346 | } | 349 | } |
347 | if (pbpage) { | 350 | if (pbpage) { |
348 | for (num -= PBES_PER_PAGE - 1, p = pbpage; num < nr_pages; p++, num++) | 351 | num -= PBES_PER_PAGE; |
349 | p->next = p + 1; | 352 | fill_pb_page(pbpage, nr_pages - num); |
350 | p->next = NULL; | ||
351 | } | 353 | } |
352 | } | 354 | } |
353 | 355 | ||
@@ -374,17 +376,17 @@ static struct pbe *alloc_pagedir(unsigned int nr_pages, gfp_t gfp_mask, | |||
374 | return NULL; | 376 | return NULL; |
375 | 377 | ||
376 | pblist = alloc_image_page(gfp_mask, safe_needed); | 378 | pblist = alloc_image_page(gfp_mask, safe_needed); |
377 | /* FIXME: rewrite this ugly loop */ | 379 | pbe = pblist; |
378 | for (pbe = pblist, num = PBES_PER_PAGE; pbe && num < nr_pages; | 380 | for (num = PBES_PER_PAGE; num < nr_pages; num += PBES_PER_PAGE) { |
379 | pbe = pbe->next, num += PBES_PER_PAGE) { | 381 | if (!pbe) { |
382 | free_pagedir(pblist, 1); | ||
383 | return NULL; | ||
384 | } | ||
380 | pbe += PB_PAGE_SKIP; | 385 | pbe += PB_PAGE_SKIP; |
381 | pbe->next = alloc_image_page(gfp_mask, safe_needed); | 386 | pbe->next = alloc_image_page(gfp_mask, safe_needed); |
387 | pbe = pbe->next; | ||
382 | } | 388 | } |
383 | if (!pbe) { /* get_zeroed_page() failed */ | 389 | create_pbe_list(pblist, nr_pages); |
384 | free_pagedir(pblist, 1); | ||
385 | pblist = NULL; | ||
386 | } else | ||
387 | create_pbe_list(pblist, nr_pages); | ||
388 | return pblist; | 390 | return pblist; |
389 | } | 391 | } |
390 | 392 | ||