diff options
author | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
---|---|---|
committer | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
commit | ada47b5fe13d89735805b566185f4885f5a3f750 (patch) | |
tree | 644b88f8a71896307d71438e9b3af49126ffb22b /kernel/power/swap.c | |
parent | 43e98717ad40a4ae64545b5ba047c7b86aa44f4f (diff) | |
parent | 3280f21d43ee541f97f8cda5792150d2dbec20d5 (diff) |
Merge branch 'wip-2.6.34' into old-private-masterarchived-private-master
Diffstat (limited to 'kernel/power/swap.c')
-rw-r--r-- | kernel/power/swap.c | 112 |
1 files changed, 105 insertions, 7 deletions
diff --git a/kernel/power/swap.c b/kernel/power/swap.c index 890f6b11b1d3..66824d71983a 100644 --- a/kernel/power/swap.c +++ b/kernel/power/swap.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <linux/swap.h> | 23 | #include <linux/swap.h> |
24 | #include <linux/swapops.h> | 24 | #include <linux/swapops.h> |
25 | #include <linux/pm.h> | 25 | #include <linux/pm.h> |
26 | #include <linux/slab.h> | ||
26 | 27 | ||
27 | #include "power.h" | 28 | #include "power.h" |
28 | 29 | ||
@@ -38,6 +39,107 @@ struct swsusp_header { | |||
38 | 39 | ||
39 | static struct swsusp_header *swsusp_header; | 40 | static struct swsusp_header *swsusp_header; |
40 | 41 | ||
42 | /** | ||
43 | * The following functions are used for tracing the allocated | ||
44 | * swap pages, so that they can be freed in case of an error. | ||
45 | */ | ||
46 | |||
47 | struct swsusp_extent { | ||
48 | struct rb_node node; | ||
49 | unsigned long start; | ||
50 | unsigned long end; | ||
51 | }; | ||
52 | |||
53 | static struct rb_root swsusp_extents = RB_ROOT; | ||
54 | |||
55 | static int swsusp_extents_insert(unsigned long swap_offset) | ||
56 | { | ||
57 | struct rb_node **new = &(swsusp_extents.rb_node); | ||
58 | struct rb_node *parent = NULL; | ||
59 | struct swsusp_extent *ext; | ||
60 | |||
61 | /* Figure out where to put the new node */ | ||
62 | while (*new) { | ||
63 | ext = container_of(*new, struct swsusp_extent, node); | ||
64 | parent = *new; | ||
65 | if (swap_offset < ext->start) { | ||
66 | /* Try to merge */ | ||
67 | if (swap_offset == ext->start - 1) { | ||
68 | ext->start--; | ||
69 | return 0; | ||
70 | } | ||
71 | new = &((*new)->rb_left); | ||
72 | } else if (swap_offset > ext->end) { | ||
73 | /* Try to merge */ | ||
74 | if (swap_offset == ext->end + 1) { | ||
75 | ext->end++; | ||
76 | return 0; | ||
77 | } | ||
78 | new = &((*new)->rb_right); | ||
79 | } else { | ||
80 | /* It already is in the tree */ | ||
81 | return -EINVAL; | ||
82 | } | ||
83 | } | ||
84 | /* Add the new node and rebalance the tree. */ | ||
85 | ext = kzalloc(sizeof(struct swsusp_extent), GFP_KERNEL); | ||
86 | if (!ext) | ||
87 | return -ENOMEM; | ||
88 | |||
89 | ext->start = swap_offset; | ||
90 | ext->end = swap_offset; | ||
91 | rb_link_node(&ext->node, parent, new); | ||
92 | rb_insert_color(&ext->node, &swsusp_extents); | ||
93 | return 0; | ||
94 | } | ||
95 | |||
96 | /** | ||
97 | * alloc_swapdev_block - allocate a swap page and register that it has | ||
98 | * been allocated, so that it can be freed in case of an error. | ||
99 | */ | ||
100 | |||
101 | sector_t alloc_swapdev_block(int swap) | ||
102 | { | ||
103 | unsigned long offset; | ||
104 | |||
105 | offset = swp_offset(get_swap_page_of_type(swap)); | ||
106 | if (offset) { | ||
107 | if (swsusp_extents_insert(offset)) | ||
108 | swap_free(swp_entry(swap, offset)); | ||
109 | else | ||
110 | return swapdev_block(swap, offset); | ||
111 | } | ||
112 | return 0; | ||
113 | } | ||
114 | |||
115 | /** | ||
116 | * free_all_swap_pages - free swap pages allocated for saving image data. | ||
117 | * It also frees the extents used to register which swap entres had been | ||
118 | * allocated. | ||
119 | */ | ||
120 | |||
121 | void free_all_swap_pages(int swap) | ||
122 | { | ||
123 | struct rb_node *node; | ||
124 | |||
125 | while ((node = swsusp_extents.rb_node)) { | ||
126 | struct swsusp_extent *ext; | ||
127 | unsigned long offset; | ||
128 | |||
129 | ext = container_of(node, struct swsusp_extent, node); | ||
130 | rb_erase(node, &swsusp_extents); | ||
131 | for (offset = ext->start; offset <= ext->end; offset++) | ||
132 | swap_free(swp_entry(swap, offset)); | ||
133 | |||
134 | kfree(ext); | ||
135 | } | ||
136 | } | ||
137 | |||
138 | int swsusp_swap_in_use(void) | ||
139 | { | ||
140 | return (swsusp_extents.rb_node != NULL); | ||
141 | } | ||
142 | |||
41 | /* | 143 | /* |
42 | * General things | 144 | * General things |
43 | */ | 145 | */ |
@@ -336,7 +438,7 @@ static int save_image(struct swap_map_handle *handle, | |||
336 | if (ret) | 438 | if (ret) |
337 | break; | 439 | break; |
338 | if (!(nr_pages % m)) | 440 | if (!(nr_pages % m)) |
339 | printk("\b\b\b\b%3d%%", nr_pages / m); | 441 | printk(KERN_CONT "\b\b\b\b%3d%%", nr_pages / m); |
340 | nr_pages++; | 442 | nr_pages++; |
341 | } | 443 | } |
342 | err2 = wait_on_bio_chain(&bio); | 444 | err2 = wait_on_bio_chain(&bio); |
@@ -344,9 +446,9 @@ static int save_image(struct swap_map_handle *handle, | |||
344 | if (!ret) | 446 | if (!ret) |
345 | ret = err2; | 447 | ret = err2; |
346 | if (!ret) | 448 | if (!ret) |
347 | printk("\b\b\b\bdone\n"); | 449 | printk(KERN_CONT "\b\b\b\bdone\n"); |
348 | else | 450 | else |
349 | printk("\n"); | 451 | printk(KERN_CONT "\n"); |
350 | swsusp_show_speed(&start, &stop, nr_to_write, "Wrote"); | 452 | swsusp_show_speed(&start, &stop, nr_to_write, "Wrote"); |
351 | return ret; | 453 | return ret; |
352 | } | 454 | } |
@@ -556,10 +658,6 @@ int swsusp_read(unsigned int *flags_p) | |||
556 | struct swsusp_info *header; | 658 | struct swsusp_info *header; |
557 | 659 | ||
558 | *flags_p = swsusp_header->flags; | 660 | *flags_p = swsusp_header->flags; |
559 | if (IS_ERR(resume_bdev)) { | ||
560 | pr_debug("PM: Image device not initialised\n"); | ||
561 | return PTR_ERR(resume_bdev); | ||
562 | } | ||
563 | 661 | ||
564 | memset(&snapshot, 0, sizeof(struct snapshot_handle)); | 662 | memset(&snapshot, 0, sizeof(struct snapshot_handle)); |
565 | error = snapshot_write_next(&snapshot, PAGE_SIZE); | 663 | error = snapshot_write_next(&snapshot, PAGE_SIZE); |