diff options
author | Jiri Slaby <jslaby@suse.cz> | 2010-05-01 17:54:02 -0400 |
---|---|---|
committer | Rafael J. Wysocki <rjw@sisk.pl> | 2010-05-10 17:08:18 -0400 |
commit | 6f612af57821c637b7eaca4374ac7b85f800d6e2 (patch) | |
tree | 0483931c6871f3526c488d6c71fe8ed1c18e4584 /kernel/power | |
parent | 51fb352b2c586b29c7bba38178b3b5389a7fb074 (diff) |
PM / Hibernate: Group swap ops
Move all the swap processing into one function. It will make swap
calls from a non-swap code easier.
Signed-off-by: Jiri Slaby <jslaby@suse.cz>
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
Diffstat (limited to 'kernel/power')
-rw-r--r-- | kernel/power/swap.c | 117 |
1 files changed, 74 insertions, 43 deletions
diff --git a/kernel/power/swap.c b/kernel/power/swap.c index 63e80628a326..b0bb21778391 100644 --- a/kernel/power/swap.c +++ b/kernel/power/swap.c | |||
@@ -208,9 +208,10 @@ static int mark_swapfiles(struct swap_map_handle *handle, unsigned int flags) | |||
208 | /** | 208 | /** |
209 | * swsusp_swap_check - check if the resume device is a swap device | 209 | * swsusp_swap_check - check if the resume device is a swap device |
210 | * and get its index (if so) | 210 | * and get its index (if so) |
211 | * | ||
212 | * This is called before saving image | ||
211 | */ | 213 | */ |
212 | 214 | static int swsusp_swap_check(void) | |
213 | static int swsusp_swap_check(void) /* This is called before saving image */ | ||
214 | { | 215 | { |
215 | int res; | 216 | int res; |
216 | 217 | ||
@@ -269,17 +270,33 @@ static void release_swap_writer(struct swap_map_handle *handle) | |||
269 | 270 | ||
270 | static int get_swap_writer(struct swap_map_handle *handle) | 271 | static int get_swap_writer(struct swap_map_handle *handle) |
271 | { | 272 | { |
273 | int ret; | ||
274 | |||
275 | ret = swsusp_swap_check(); | ||
276 | if (ret) { | ||
277 | if (ret != -ENOSPC) | ||
278 | printk(KERN_ERR "PM: Cannot find swap device, try " | ||
279 | "swapon -a.\n"); | ||
280 | return ret; | ||
281 | } | ||
272 | handle->cur = (struct swap_map_page *)get_zeroed_page(GFP_KERNEL); | 282 | handle->cur = (struct swap_map_page *)get_zeroed_page(GFP_KERNEL); |
273 | if (!handle->cur) | 283 | if (!handle->cur) { |
274 | return -ENOMEM; | 284 | ret = -ENOMEM; |
285 | goto err_close; | ||
286 | } | ||
275 | handle->cur_swap = alloc_swapdev_block(root_swap); | 287 | handle->cur_swap = alloc_swapdev_block(root_swap); |
276 | if (!handle->cur_swap) { | 288 | if (!handle->cur_swap) { |
277 | release_swap_writer(handle); | 289 | ret = -ENOSPC; |
278 | return -ENOSPC; | 290 | goto err_rel; |
279 | } | 291 | } |
280 | handle->k = 0; | 292 | handle->k = 0; |
281 | handle->first_sector = handle->cur_swap; | 293 | handle->first_sector = handle->cur_swap; |
282 | return 0; | 294 | return 0; |
295 | err_rel: | ||
296 | release_swap_writer(handle); | ||
297 | err_close: | ||
298 | swsusp_close(FMODE_WRITE); | ||
299 | return ret; | ||
283 | } | 300 | } |
284 | 301 | ||
285 | static int swap_write_page(struct swap_map_handle *handle, void *buf, | 302 | static int swap_write_page(struct swap_map_handle *handle, void *buf, |
@@ -322,6 +339,24 @@ static int flush_swap_writer(struct swap_map_handle *handle) | |||
322 | return -EINVAL; | 339 | return -EINVAL; |
323 | } | 340 | } |
324 | 341 | ||
342 | static int swap_writer_finish(struct swap_map_handle *handle, | ||
343 | unsigned int flags, int error) | ||
344 | { | ||
345 | if (!error) { | ||
346 | flush_swap_writer(handle); | ||
347 | printk(KERN_INFO "PM: S"); | ||
348 | error = mark_swapfiles(handle, flags); | ||
349 | printk("|\n"); | ||
350 | } | ||
351 | |||
352 | if (error) | ||
353 | free_all_swap_pages(root_swap); | ||
354 | release_swap_writer(handle); | ||
355 | swsusp_close(FMODE_WRITE); | ||
356 | |||
357 | return error; | ||
358 | } | ||
359 | |||
325 | /** | 360 | /** |
326 | * save_image - save the suspend image data | 361 | * save_image - save the suspend image data |
327 | */ | 362 | */ |
@@ -399,48 +434,34 @@ int swsusp_write(unsigned int flags) | |||
399 | struct swap_map_handle handle; | 434 | struct swap_map_handle handle; |
400 | struct snapshot_handle snapshot; | 435 | struct snapshot_handle snapshot; |
401 | struct swsusp_info *header; | 436 | struct swsusp_info *header; |
437 | unsigned long pages; | ||
402 | int error; | 438 | int error; |
403 | 439 | ||
404 | error = swsusp_swap_check(); | 440 | pages = snapshot_get_image_size(); |
441 | error = get_swap_writer(&handle); | ||
405 | if (error) { | 442 | if (error) { |
406 | printk(KERN_ERR "PM: Cannot find swap device, try " | 443 | printk(KERN_ERR "PM: Cannot get swap writer\n"); |
407 | "swapon -a.\n"); | ||
408 | return error; | 444 | return error; |
409 | } | 445 | } |
446 | if (!enough_swap(pages)) { | ||
447 | printk(KERN_ERR "PM: Not enough free swap\n"); | ||
448 | error = -ENOSPC; | ||
449 | goto out_finish; | ||
450 | } | ||
410 | memset(&snapshot, 0, sizeof(struct snapshot_handle)); | 451 | memset(&snapshot, 0, sizeof(struct snapshot_handle)); |
411 | error = snapshot_read_next(&snapshot); | 452 | error = snapshot_read_next(&snapshot); |
412 | if (error < PAGE_SIZE) { | 453 | if (error < PAGE_SIZE) { |
413 | if (error >= 0) | 454 | if (error >= 0) |
414 | error = -EFAULT; | 455 | error = -EFAULT; |
415 | 456 | ||
416 | goto out; | 457 | goto out_finish; |
417 | } | 458 | } |
418 | header = (struct swsusp_info *)data_of(snapshot); | 459 | header = (struct swsusp_info *)data_of(snapshot); |
419 | if (!enough_swap(header->pages)) { | 460 | error = swap_write_page(&handle, header, NULL); |
420 | printk(KERN_ERR "PM: Not enough free swap\n"); | 461 | if (!error) |
421 | error = -ENOSPC; | 462 | error = save_image(&handle, &snapshot, pages - 1); |
422 | goto out; | 463 | out_finish: |
423 | } | 464 | error = swap_writer_finish(&handle, flags, error); |
424 | error = get_swap_writer(&handle); | ||
425 | if (!error) { | ||
426 | error = swap_write_page(&handle, header, NULL); | ||
427 | if (!error) | ||
428 | error = save_image(&handle, &snapshot, | ||
429 | header->pages - 1); | ||
430 | |||
431 | if (!error) { | ||
432 | flush_swap_writer(&handle); | ||
433 | printk(KERN_INFO "PM: S"); | ||
434 | error = mark_swapfiles(&handle, flags); | ||
435 | printk("|\n"); | ||
436 | } | ||
437 | } | ||
438 | if (error) | ||
439 | free_all_swap_pages(root_swap); | ||
440 | |||
441 | release_swap_writer(&handle); | ||
442 | out: | ||
443 | swsusp_close(FMODE_WRITE); | ||
444 | return error; | 465 | return error; |
445 | } | 466 | } |
446 | 467 | ||
@@ -456,18 +477,21 @@ static void release_swap_reader(struct swap_map_handle *handle) | |||
456 | handle->cur = NULL; | 477 | handle->cur = NULL; |
457 | } | 478 | } |
458 | 479 | ||
459 | static int get_swap_reader(struct swap_map_handle *handle, sector_t start) | 480 | static int get_swap_reader(struct swap_map_handle *handle, |
481 | unsigned int *flags_p) | ||
460 | { | 482 | { |
461 | int error; | 483 | int error; |
462 | 484 | ||
463 | if (!start) | 485 | *flags_p = swsusp_header->flags; |
486 | |||
487 | if (!swsusp_header->image) /* how can this happen? */ | ||
464 | return -EINVAL; | 488 | return -EINVAL; |
465 | 489 | ||
466 | handle->cur = (struct swap_map_page *)get_zeroed_page(__GFP_WAIT | __GFP_HIGH); | 490 | handle->cur = (struct swap_map_page *)get_zeroed_page(__GFP_WAIT | __GFP_HIGH); |
467 | if (!handle->cur) | 491 | if (!handle->cur) |
468 | return -ENOMEM; | 492 | return -ENOMEM; |
469 | 493 | ||
470 | error = hib_bio_read_page(start, handle->cur, NULL); | 494 | error = hib_bio_read_page(swsusp_header->image, handle->cur, NULL); |
471 | if (error) { | 495 | if (error) { |
472 | release_swap_reader(handle); | 496 | release_swap_reader(handle); |
473 | return error; | 497 | return error; |
@@ -502,6 +526,13 @@ static int swap_read_page(struct swap_map_handle *handle, void *buf, | |||
502 | return error; | 526 | return error; |
503 | } | 527 | } |
504 | 528 | ||
529 | static int swap_reader_finish(struct swap_map_handle *handle) | ||
530 | { | ||
531 | release_swap_reader(handle); | ||
532 | |||
533 | return 0; | ||
534 | } | ||
535 | |||
505 | /** | 536 | /** |
506 | * load_image - load the image using the swap map handle | 537 | * load_image - load the image using the swap map handle |
507 | * @handle and the snapshot handle @snapshot | 538 | * @handle and the snapshot handle @snapshot |
@@ -571,20 +602,20 @@ int swsusp_read(unsigned int *flags_p) | |||
571 | struct snapshot_handle snapshot; | 602 | struct snapshot_handle snapshot; |
572 | struct swsusp_info *header; | 603 | struct swsusp_info *header; |
573 | 604 | ||
574 | *flags_p = swsusp_header->flags; | ||
575 | |||
576 | memset(&snapshot, 0, sizeof(struct snapshot_handle)); | 605 | memset(&snapshot, 0, sizeof(struct snapshot_handle)); |
577 | error = snapshot_write_next(&snapshot); | 606 | error = snapshot_write_next(&snapshot); |
578 | if (error < PAGE_SIZE) | 607 | if (error < PAGE_SIZE) |
579 | return error < 0 ? error : -EFAULT; | 608 | return error < 0 ? error : -EFAULT; |
580 | header = (struct swsusp_info *)data_of(snapshot); | 609 | header = (struct swsusp_info *)data_of(snapshot); |
581 | error = get_swap_reader(&handle, swsusp_header->image); | 610 | error = get_swap_reader(&handle, flags_p); |
611 | if (error) | ||
612 | goto end; | ||
582 | if (!error) | 613 | if (!error) |
583 | error = swap_read_page(&handle, header, NULL); | 614 | error = swap_read_page(&handle, header, NULL); |
584 | if (!error) | 615 | if (!error) |
585 | error = load_image(&handle, &snapshot, header->pages - 1); | 616 | error = load_image(&handle, &snapshot, header->pages - 1); |
586 | release_swap_reader(&handle); | 617 | swap_reader_finish(&handle); |
587 | 618 | end: | |
588 | if (!error) | 619 | if (!error) |
589 | pr_debug("PM: Image successfully loaded\n"); | 620 | pr_debug("PM: Image successfully loaded\n"); |
590 | else | 621 | else |