aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/power
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/power')
-rw-r--r--kernel/power/swap.c93
1 files changed, 75 insertions, 18 deletions
diff --git a/kernel/power/swap.c b/kernel/power/swap.c
index 79b66e734bdb..2dc883d361d5 100644
--- a/kernel/power/swap.c
+++ b/kernel/power/swap.c
@@ -49,18 +49,16 @@ static int mark_swapfiles(swp_entry_t start)
49{ 49{
50 int error; 50 int error;
51 51
52 rw_swap_page_sync(READ, 52 rw_swap_page_sync(READ, swp_entry(root_swap, 0),
53 swp_entry(root_swap, 0), 53 virt_to_page((unsigned long)&swsusp_header), NULL);
54 virt_to_page((unsigned long)&swsusp_header));
55 if (!memcmp("SWAP-SPACE",swsusp_header.sig, 10) || 54 if (!memcmp("SWAP-SPACE",swsusp_header.sig, 10) ||
56 !memcmp("SWAPSPACE2",swsusp_header.sig, 10)) { 55 !memcmp("SWAPSPACE2",swsusp_header.sig, 10)) {
57 memcpy(swsusp_header.orig_sig,swsusp_header.sig, 10); 56 memcpy(swsusp_header.orig_sig,swsusp_header.sig, 10);
58 memcpy(swsusp_header.sig,SWSUSP_SIG, 10); 57 memcpy(swsusp_header.sig,SWSUSP_SIG, 10);
59 swsusp_header.image = start; 58 swsusp_header.image = start;
60 error = rw_swap_page_sync(WRITE, 59 error = rw_swap_page_sync(WRITE, swp_entry(root_swap, 0),
61 swp_entry(root_swap, 0), 60 virt_to_page((unsigned long)&swsusp_header),
62 virt_to_page((unsigned long) 61 NULL);
63 &swsusp_header));
64 } else { 62 } else {
65 pr_debug("swsusp: Partition is not swap space.\n"); 63 pr_debug("swsusp: Partition is not swap space.\n");
66 error = -ENODEV; 64 error = -ENODEV;
@@ -88,16 +86,37 @@ static int swsusp_swap_check(void) /* This is called before saving image */
88 * write_page - Write one page to given swap location. 86 * write_page - Write one page to given swap location.
89 * @buf: Address we're writing. 87 * @buf: Address we're writing.
90 * @offset: Offset of the swap page we're writing to. 88 * @offset: Offset of the swap page we're writing to.
89 * @bio_chain: Link the next write BIO here
91 */ 90 */
92 91
93static int write_page(void *buf, unsigned long offset) 92static int write_page(void *buf, unsigned long offset, struct bio **bio_chain)
94{ 93{
95 swp_entry_t entry; 94 swp_entry_t entry;
96 int error = -ENOSPC; 95 int error = -ENOSPC;
97 96
98 if (offset) { 97 if (offset) {
98 struct page *page = virt_to_page(buf);
99
100 if (bio_chain) {
101 /*
102 * Whether or not we successfully allocated a copy page,
103 * we take a ref on the page here. It gets undone in
104 * wait_on_bio_chain().
105 */
106 struct page *page_copy;
107 page_copy = alloc_page(GFP_ATOMIC);
108 if (page_copy == NULL) {
109 WARN_ON_ONCE(1);
110 bio_chain = NULL; /* Go synchronous */
111 get_page(page);
112 } else {
113 memcpy(page_address(page_copy),
114 page_address(page), PAGE_SIZE);
115 page = page_copy;
116 }
117 }
99 entry = swp_entry(root_swap, offset); 118 entry = swp_entry(root_swap, offset);
100 error = rw_swap_page_sync(WRITE, entry, virt_to_page(buf)); 119 error = rw_swap_page_sync(WRITE, entry, page, bio_chain);
101 } 120 }
102 return error; 121 return error;
103} 122}
@@ -185,37 +204,68 @@ static int get_swap_writer(struct swap_map_handle *handle)
185 return 0; 204 return 0;
186} 205}
187 206
188static int swap_write_page(struct swap_map_handle *handle, void *buf) 207static int wait_on_bio_chain(struct bio **bio_chain)
189{ 208{
190 int error; 209 struct bio *bio;
210 struct bio *next_bio;
211 int ret = 0;
212
213 if (bio_chain == NULL)
214 return 0;
215
216 bio = *bio_chain;
217 while (bio) {
218 struct page *page;
219
220 next_bio = bio->bi_private;
221 page = bio->bi_io_vec[0].bv_page;
222 wait_on_page_locked(page);
223 if (!PageUptodate(page) || PageError(page))
224 ret = -EIO;
225 put_page(page);
226 bio_put(bio);
227 bio = next_bio;
228 }
229 *bio_chain = NULL;
230 return ret;
231}
232
233static int swap_write_page(struct swap_map_handle *handle, void *buf,
234 struct bio **bio_chain)
235{
236 int error = 0;
191 unsigned long offset; 237 unsigned long offset;
192 238
193 if (!handle->cur) 239 if (!handle->cur)
194 return -EINVAL; 240 return -EINVAL;
195 offset = alloc_swap_page(root_swap, handle->bitmap); 241 offset = alloc_swap_page(root_swap, handle->bitmap);
196 error = write_page(buf, offset); 242 error = write_page(buf, offset, bio_chain);
197 if (error) 243 if (error)
198 return error; 244 return error;
199 handle->cur->entries[handle->k++] = offset; 245 handle->cur->entries[handle->k++] = offset;
200 if (handle->k >= MAP_PAGE_ENTRIES) { 246 if (handle->k >= MAP_PAGE_ENTRIES) {
247 error = wait_on_bio_chain(bio_chain);
248 if (error)
249 goto out;
201 offset = alloc_swap_page(root_swap, handle->bitmap); 250 offset = alloc_swap_page(root_swap, handle->bitmap);
202 if (!offset) 251 if (!offset)
203 return -ENOSPC; 252 return -ENOSPC;
204 handle->cur->next_swap = offset; 253 handle->cur->next_swap = offset;
205 error = write_page(handle->cur, handle->cur_swap); 254 error = write_page(handle->cur, handle->cur_swap, NULL);
206 if (error) 255 if (error)
207 return error; 256 goto out;
208 memset(handle->cur, 0, PAGE_SIZE); 257 memset(handle->cur, 0, PAGE_SIZE);
209 handle->cur_swap = offset; 258 handle->cur_swap = offset;
210 handle->k = 0; 259 handle->k = 0;
211 } 260 }
212 return 0; 261out:
262 return error;
213} 263}
214 264
215static int flush_swap_writer(struct swap_map_handle *handle) 265static int flush_swap_writer(struct swap_map_handle *handle)
216{ 266{
217 if (handle->cur && handle->cur_swap) 267 if (handle->cur && handle->cur_swap)
218 return write_page(handle->cur, handle->cur_swap); 268 return write_page(handle->cur, handle->cur_swap, NULL);
219 else 269 else
220 return -EINVAL; 270 return -EINVAL;
221} 271}
@@ -232,6 +282,8 @@ static int save_image(struct swap_map_handle *handle,
232 int ret; 282 int ret;
233 int error = 0; 283 int error = 0;
234 int nr_pages; 284 int nr_pages;
285 int err2;
286 struct bio *bio;
235 struct timeval start; 287 struct timeval start;
236 struct timeval stop; 288 struct timeval stop;
237 289
@@ -240,11 +292,13 @@ static int save_image(struct swap_map_handle *handle,
240 if (!m) 292 if (!m)
241 m = 1; 293 m = 1;
242 nr_pages = 0; 294 nr_pages = 0;
295 bio = NULL;
243 do_gettimeofday(&start); 296 do_gettimeofday(&start);
244 do { 297 do {
245 ret = snapshot_read_next(snapshot, PAGE_SIZE); 298 ret = snapshot_read_next(snapshot, PAGE_SIZE);
246 if (ret > 0) { 299 if (ret > 0) {
247 error = swap_write_page(handle, data_of(*snapshot)); 300 error = swap_write_page(handle, data_of(*snapshot),
301 &bio);
248 if (error) 302 if (error)
249 break; 303 break;
250 if (!(nr_pages % m)) 304 if (!(nr_pages % m))
@@ -252,8 +306,11 @@ static int save_image(struct swap_map_handle *handle,
252 nr_pages++; 306 nr_pages++;
253 } 307 }
254 } while (ret > 0); 308 } while (ret > 0);
309 err2 = wait_on_bio_chain(&bio);
255 do_gettimeofday(&stop); 310 do_gettimeofday(&stop);
256 if (!error) 311 if (!error)
312 error = err2;
313 if (!error)
257 printk("\b\b\b\bdone\n"); 314 printk("\b\b\b\bdone\n");
258 show_speed(&start, &stop, nr_to_write, "Wrote"); 315 show_speed(&start, &stop, nr_to_write, "Wrote");
259 return error; 316 return error;
@@ -307,7 +364,7 @@ int swsusp_write(void)
307 error = get_swap_writer(&handle); 364 error = get_swap_writer(&handle);
308 if (!error) { 365 if (!error) {
309 unsigned long start = handle.cur_swap; 366 unsigned long start = handle.cur_swap;
310 error = swap_write_page(&handle, header); 367 error = swap_write_page(&handle, header, NULL);
311 if (!error) 368 if (!error)
312 error = save_image(&handle, &snapshot, 369 error = save_image(&handle, &snapshot,
313 header->pages - 1); 370 header->pages - 1);