aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/power/swap.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/power/swap.c')
-rw-r--r--kernel/power/swap.c146
1 files changed, 124 insertions, 22 deletions
diff --git a/kernel/power/swap.c b/kernel/power/swap.c
index b101cdc4df3f..09b2b0ae9e9d 100644
--- a/kernel/power/swap.c
+++ b/kernel/power/swap.c
@@ -38,6 +38,107 @@ struct swsusp_header {
38 38
39static struct swsusp_header *swsusp_header; 39static struct swsusp_header *swsusp_header;
40 40
41/**
42 * The following functions are used for tracing the allocated
43 * swap pages, so that they can be freed in case of an error.
44 */
45
46struct swsusp_extent {
47 struct rb_node node;
48 unsigned long start;
49 unsigned long end;
50};
51
52static struct rb_root swsusp_extents = RB_ROOT;
53
54static int swsusp_extents_insert(unsigned long swap_offset)
55{
56 struct rb_node **new = &(swsusp_extents.rb_node);
57 struct rb_node *parent = NULL;
58 struct swsusp_extent *ext;
59
60 /* Figure out where to put the new node */
61 while (*new) {
62 ext = container_of(*new, struct swsusp_extent, node);
63 parent = *new;
64 if (swap_offset < ext->start) {
65 /* Try to merge */
66 if (swap_offset == ext->start - 1) {
67 ext->start--;
68 return 0;
69 }
70 new = &((*new)->rb_left);
71 } else if (swap_offset > ext->end) {
72 /* Try to merge */
73 if (swap_offset == ext->end + 1) {
74 ext->end++;
75 return 0;
76 }
77 new = &((*new)->rb_right);
78 } else {
79 /* It already is in the tree */
80 return -EINVAL;
81 }
82 }
83 /* Add the new node and rebalance the tree. */
84 ext = kzalloc(sizeof(struct swsusp_extent), GFP_KERNEL);
85 if (!ext)
86 return -ENOMEM;
87
88 ext->start = swap_offset;
89 ext->end = swap_offset;
90 rb_link_node(&ext->node, parent, new);
91 rb_insert_color(&ext->node, &swsusp_extents);
92 return 0;
93}
94
95/**
96 * alloc_swapdev_block - allocate a swap page and register that it has
97 * been allocated, so that it can be freed in case of an error.
98 */
99
100sector_t alloc_swapdev_block(int swap)
101{
102 unsigned long offset;
103
104 offset = swp_offset(get_swap_page_of_type(swap));
105 if (offset) {
106 if (swsusp_extents_insert(offset))
107 swap_free(swp_entry(swap, offset));
108 else
109 return swapdev_block(swap, offset);
110 }
111 return 0;
112}
113
114/**
115 * free_all_swap_pages - free swap pages allocated for saving image data.
116 * It also frees the extents used to register which swap entres had been
117 * allocated.
118 */
119
120void free_all_swap_pages(int swap)
121{
122 struct rb_node *node;
123
124 while ((node = swsusp_extents.rb_node)) {
125 struct swsusp_extent *ext;
126 unsigned long offset;
127
128 ext = container_of(node, struct swsusp_extent, node);
129 rb_erase(node, &swsusp_extents);
130 for (offset = ext->start; offset <= ext->end; offset++)
131 swap_free(swp_entry(swap, offset));
132
133 kfree(ext);
134 }
135}
136
137int swsusp_swap_in_use(void)
138{
139 return (swsusp_extents.rb_node != NULL);
140}
141
41/* 142/*
42 * General things 143 * General things
43 */ 144 */
@@ -314,7 +415,6 @@ static int save_image(struct swap_map_handle *handle,
314{ 415{
315 unsigned int m; 416 unsigned int m;
316 int ret; 417 int ret;
317 int error = 0;
318 int nr_pages; 418 int nr_pages;
319 int err2; 419 int err2;
320 struct bio *bio; 420 struct bio *bio;
@@ -329,26 +429,27 @@ static int save_image(struct swap_map_handle *handle,
329 nr_pages = 0; 429 nr_pages = 0;
330 bio = NULL; 430 bio = NULL;
331 do_gettimeofday(&start); 431 do_gettimeofday(&start);
332 do { 432 while (1) {
333 ret = snapshot_read_next(snapshot, PAGE_SIZE); 433 ret = snapshot_read_next(snapshot, PAGE_SIZE);
334 if (ret > 0) { 434 if (ret <= 0)
335 error = swap_write_page(handle, data_of(*snapshot), 435 break;
336 &bio); 436 ret = swap_write_page(handle, data_of(*snapshot), &bio);
337 if (error) 437 if (ret)
338 break; 438 break;
339 if (!(nr_pages % m)) 439 if (!(nr_pages % m))
340 printk("\b\b\b\b%3d%%", nr_pages / m); 440 printk(KERN_CONT "\b\b\b\b%3d%%", nr_pages / m);
341 nr_pages++; 441 nr_pages++;
342 } 442 }
343 } while (ret > 0);
344 err2 = wait_on_bio_chain(&bio); 443 err2 = wait_on_bio_chain(&bio);
345 do_gettimeofday(&stop); 444 do_gettimeofday(&stop);
346 if (!error) 445 if (!ret)
347 error = err2; 446 ret = err2;
348 if (!error) 447 if (!ret)
349 printk("\b\b\b\bdone\n"); 448 printk(KERN_CONT "\b\b\b\bdone\n");
449 else
450 printk(KERN_CONT "\n");
350 swsusp_show_speed(&start, &stop, nr_to_write, "Wrote"); 451 swsusp_show_speed(&start, &stop, nr_to_write, "Wrote");
351 return error; 452 return ret;
352} 453}
353 454
354/** 455/**
@@ -536,7 +637,8 @@ static int load_image(struct swap_map_handle *handle,
536 snapshot_write_finalize(snapshot); 637 snapshot_write_finalize(snapshot);
537 if (!snapshot_image_loaded(snapshot)) 638 if (!snapshot_image_loaded(snapshot))
538 error = -ENODATA; 639 error = -ENODATA;
539 } 640 } else
641 printk("\n");
540 swsusp_show_speed(&start, &stop, nr_to_read, "Read"); 642 swsusp_show_speed(&start, &stop, nr_to_read, "Read");
541 return error; 643 return error;
542} 644}
@@ -572,8 +674,6 @@ int swsusp_read(unsigned int *flags_p)
572 error = load_image(&handle, &snapshot, header->pages - 1); 674 error = load_image(&handle, &snapshot, header->pages - 1);
573 release_swap_reader(&handle); 675 release_swap_reader(&handle);
574 676
575 blkdev_put(resume_bdev, FMODE_READ);
576
577 if (!error) 677 if (!error)
578 pr_debug("PM: Image successfully loaded\n"); 678 pr_debug("PM: Image successfully loaded\n");
579 else 679 else
@@ -596,7 +696,7 @@ int swsusp_check(void)
596 error = bio_read_page(swsusp_resume_block, 696 error = bio_read_page(swsusp_resume_block,
597 swsusp_header, NULL); 697 swsusp_header, NULL);
598 if (error) 698 if (error)
599 return error; 699 goto put;
600 700
601 if (!memcmp(SWSUSP_SIG, swsusp_header->sig, 10)) { 701 if (!memcmp(SWSUSP_SIG, swsusp_header->sig, 10)) {
602 memcpy(swsusp_header->sig, swsusp_header->orig_sig, 10); 702 memcpy(swsusp_header->sig, swsusp_header->orig_sig, 10);
@@ -604,8 +704,10 @@ int swsusp_check(void)
604 error = bio_write_page(swsusp_resume_block, 704 error = bio_write_page(swsusp_resume_block,
605 swsusp_header, NULL); 705 swsusp_header, NULL);
606 } else { 706 } else {
607 return -EINVAL; 707 error = -EINVAL;
608 } 708 }
709
710put:
609 if (error) 711 if (error)
610 blkdev_put(resume_bdev, FMODE_READ); 712 blkdev_put(resume_bdev, FMODE_READ);
611 else 713 else