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 | |
| 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>
| -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 |
