aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'kernel')
-rw-r--r--kernel/power/swap.c117
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 214static int swsusp_swap_check(void)
213static 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
270static int get_swap_writer(struct swap_map_handle *handle) 271static 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;
295err_rel:
296 release_swap_writer(handle);
297err_close:
298 swsusp_close(FMODE_WRITE);
299 return ret;
283} 300}
284 301
285static int swap_write_page(struct swap_map_handle *handle, void *buf, 302static 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
342static 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; 463out_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
459static int get_swap_reader(struct swap_map_handle *handle, sector_t start) 480static 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
529static 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 618end:
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