diff options
Diffstat (limited to 'kernel/power/swap.c')
-rw-r--r-- | kernel/power/swap.c | 347 |
1 files changed, 171 insertions, 176 deletions
diff --git a/kernel/power/swap.c b/kernel/power/swap.c index 1a3b0dd2c3fc..f133d4a6d817 100644 --- a/kernel/power/swap.c +++ b/kernel/power/swap.c | |||
@@ -34,34 +34,123 @@ extern char resume_file[]; | |||
34 | #define SWSUSP_SIG "S1SUSPEND" | 34 | #define SWSUSP_SIG "S1SUSPEND" |
35 | 35 | ||
36 | static struct swsusp_header { | 36 | static struct swsusp_header { |
37 | char reserved[PAGE_SIZE - 20 - sizeof(swp_entry_t)]; | 37 | char reserved[PAGE_SIZE - 20 - sizeof(sector_t)]; |
38 | swp_entry_t image; | 38 | sector_t image; |
39 | char orig_sig[10]; | 39 | char orig_sig[10]; |
40 | char sig[10]; | 40 | char sig[10]; |
41 | } __attribute__((packed, aligned(PAGE_SIZE))) swsusp_header; | 41 | } __attribute__((packed, aligned(PAGE_SIZE))) swsusp_header; |
42 | 42 | ||
43 | /* | 43 | /* |
44 | * Saving part... | 44 | * General things |
45 | */ | 45 | */ |
46 | 46 | ||
47 | static unsigned short root_swap = 0xffff; | 47 | static unsigned short root_swap = 0xffff; |
48 | static struct block_device *resume_bdev; | ||
49 | |||
50 | /** | ||
51 | * submit - submit BIO request. | ||
52 | * @rw: READ or WRITE. | ||
53 | * @off physical offset of page. | ||
54 | * @page: page we're reading or writing. | ||
55 | * @bio_chain: list of pending biod (for async reading) | ||
56 | * | ||
57 | * Straight from the textbook - allocate and initialize the bio. | ||
58 | * If we're reading, make sure the page is marked as dirty. | ||
59 | * Then submit it and, if @bio_chain == NULL, wait. | ||
60 | */ | ||
61 | static int submit(int rw, pgoff_t page_off, struct page *page, | ||
62 | struct bio **bio_chain) | ||
63 | { | ||
64 | struct bio *bio; | ||
65 | |||
66 | bio = bio_alloc(__GFP_WAIT | __GFP_HIGH, 1); | ||
67 | if (!bio) | ||
68 | return -ENOMEM; | ||
69 | bio->bi_sector = page_off * (PAGE_SIZE >> 9); | ||
70 | bio->bi_bdev = resume_bdev; | ||
71 | bio->bi_end_io = end_swap_bio_read; | ||
72 | |||
73 | if (bio_add_page(bio, page, PAGE_SIZE, 0) < PAGE_SIZE) { | ||
74 | printk("swsusp: ERROR: adding page to bio at %ld\n", page_off); | ||
75 | bio_put(bio); | ||
76 | return -EFAULT; | ||
77 | } | ||
78 | |||
79 | lock_page(page); | ||
80 | bio_get(bio); | ||
81 | |||
82 | if (bio_chain == NULL) { | ||
83 | submit_bio(rw | (1 << BIO_RW_SYNC), bio); | ||
84 | wait_on_page_locked(page); | ||
85 | if (rw == READ) | ||
86 | bio_set_pages_dirty(bio); | ||
87 | bio_put(bio); | ||
88 | } else { | ||
89 | if (rw == READ) | ||
90 | get_page(page); /* These pages are freed later */ | ||
91 | bio->bi_private = *bio_chain; | ||
92 | *bio_chain = bio; | ||
93 | submit_bio(rw | (1 << BIO_RW_SYNC), bio); | ||
94 | } | ||
95 | return 0; | ||
96 | } | ||
97 | |||
98 | static int bio_read_page(pgoff_t page_off, void *addr, struct bio **bio_chain) | ||
99 | { | ||
100 | return submit(READ, page_off, virt_to_page(addr), bio_chain); | ||
101 | } | ||
102 | |||
103 | static int bio_write_page(pgoff_t page_off, void *addr, struct bio **bio_chain) | ||
104 | { | ||
105 | return submit(WRITE, page_off, virt_to_page(addr), bio_chain); | ||
106 | } | ||
107 | |||
108 | static int wait_on_bio_chain(struct bio **bio_chain) | ||
109 | { | ||
110 | struct bio *bio; | ||
111 | struct bio *next_bio; | ||
112 | int ret = 0; | ||
113 | |||
114 | if (bio_chain == NULL) | ||
115 | return 0; | ||
116 | |||
117 | bio = *bio_chain; | ||
118 | if (bio == NULL) | ||
119 | return 0; | ||
120 | while (bio) { | ||
121 | struct page *page; | ||
122 | |||
123 | next_bio = bio->bi_private; | ||
124 | page = bio->bi_io_vec[0].bv_page; | ||
125 | wait_on_page_locked(page); | ||
126 | if (!PageUptodate(page) || PageError(page)) | ||
127 | ret = -EIO; | ||
128 | put_page(page); | ||
129 | bio_put(bio); | ||
130 | bio = next_bio; | ||
131 | } | ||
132 | *bio_chain = NULL; | ||
133 | return ret; | ||
134 | } | ||
135 | |||
136 | /* | ||
137 | * Saving part | ||
138 | */ | ||
48 | 139 | ||
49 | static int mark_swapfiles(swp_entry_t start) | 140 | static int mark_swapfiles(sector_t start) |
50 | { | 141 | { |
51 | int error; | 142 | int error; |
52 | 143 | ||
53 | rw_swap_page_sync(READ, swp_entry(root_swap, 0), | 144 | bio_read_page(swsusp_resume_block, &swsusp_header, NULL); |
54 | virt_to_page((unsigned long)&swsusp_header), NULL); | ||
55 | if (!memcmp("SWAP-SPACE",swsusp_header.sig, 10) || | 145 | if (!memcmp("SWAP-SPACE",swsusp_header.sig, 10) || |
56 | !memcmp("SWAPSPACE2",swsusp_header.sig, 10)) { | 146 | !memcmp("SWAPSPACE2",swsusp_header.sig, 10)) { |
57 | memcpy(swsusp_header.orig_sig,swsusp_header.sig, 10); | 147 | memcpy(swsusp_header.orig_sig,swsusp_header.sig, 10); |
58 | memcpy(swsusp_header.sig,SWSUSP_SIG, 10); | 148 | memcpy(swsusp_header.sig,SWSUSP_SIG, 10); |
59 | swsusp_header.image = start; | 149 | swsusp_header.image = start; |
60 | error = rw_swap_page_sync(WRITE, swp_entry(root_swap, 0), | 150 | error = bio_write_page(swsusp_resume_block, |
61 | virt_to_page((unsigned long)&swsusp_header), | 151 | &swsusp_header, NULL); |
62 | NULL); | ||
63 | } else { | 152 | } else { |
64 | pr_debug("swsusp: Partition is not swap space.\n"); | 153 | printk(KERN_ERR "swsusp: Swap header not found!\n"); |
65 | error = -ENODEV; | 154 | error = -ENODEV; |
66 | } | 155 | } |
67 | return error; | 156 | return error; |
@@ -74,12 +163,21 @@ static int mark_swapfiles(swp_entry_t start) | |||
74 | 163 | ||
75 | static int swsusp_swap_check(void) /* This is called before saving image */ | 164 | static int swsusp_swap_check(void) /* This is called before saving image */ |
76 | { | 165 | { |
77 | int res = swap_type_of(swsusp_resume_device); | 166 | int res; |
167 | |||
168 | res = swap_type_of(swsusp_resume_device, swsusp_resume_block); | ||
169 | if (res < 0) | ||
170 | return res; | ||
171 | |||
172 | root_swap = res; | ||
173 | resume_bdev = open_by_devnum(swsusp_resume_device, FMODE_WRITE); | ||
174 | if (IS_ERR(resume_bdev)) | ||
175 | return PTR_ERR(resume_bdev); | ||
176 | |||
177 | res = set_blocksize(resume_bdev, PAGE_SIZE); | ||
178 | if (res < 0) | ||
179 | blkdev_put(resume_bdev); | ||
78 | 180 | ||
79 | if (res >= 0) { | ||
80 | root_swap = res; | ||
81 | return 0; | ||
82 | } | ||
83 | return res; | 181 | return res; |
84 | } | 182 | } |
85 | 183 | ||
@@ -90,36 +188,26 @@ static int swsusp_swap_check(void) /* This is called before saving image */ | |||
90 | * @bio_chain: Link the next write BIO here | 188 | * @bio_chain: Link the next write BIO here |
91 | */ | 189 | */ |
92 | 190 | ||
93 | static int write_page(void *buf, unsigned long offset, struct bio **bio_chain) | 191 | static int write_page(void *buf, sector_t offset, struct bio **bio_chain) |
94 | { | 192 | { |
95 | swp_entry_t entry; | 193 | void *src; |
96 | int error = -ENOSPC; | 194 | |
97 | 195 | if (!offset) | |
98 | if (offset) { | 196 | return -ENOSPC; |
99 | struct page *page = virt_to_page(buf); | 197 | |
100 | 198 | if (bio_chain) { | |
101 | if (bio_chain) { | 199 | src = (void *)__get_free_page(__GFP_WAIT | __GFP_HIGH); |
102 | /* | 200 | if (src) { |
103 | * Whether or not we successfully allocated a copy page, | 201 | memcpy(src, buf, PAGE_SIZE); |
104 | * we take a ref on the page here. It gets undone in | 202 | } else { |
105 | * wait_on_bio_chain(). | 203 | WARN_ON_ONCE(1); |
106 | */ | 204 | bio_chain = NULL; /* Go synchronous */ |
107 | struct page *page_copy; | 205 | src = buf; |
108 | page_copy = alloc_page(GFP_ATOMIC); | ||
109 | if (page_copy == NULL) { | ||
110 | WARN_ON_ONCE(1); | ||
111 | bio_chain = NULL; /* Go synchronous */ | ||
112 | get_page(page); | ||
113 | } else { | ||
114 | memcpy(page_address(page_copy), | ||
115 | page_address(page), PAGE_SIZE); | ||
116 | page = page_copy; | ||
117 | } | ||
118 | } | 206 | } |
119 | entry = swp_entry(root_swap, offset); | 207 | } else { |
120 | error = rw_swap_page_sync(WRITE, entry, page, bio_chain); | 208 | src = buf; |
121 | } | 209 | } |
122 | return error; | 210 | return bio_write_page(offset, src, bio_chain); |
123 | } | 211 | } |
124 | 212 | ||
125 | /* | 213 | /* |
@@ -137,11 +225,11 @@ static int write_page(void *buf, unsigned long offset, struct bio **bio_chain) | |||
137 | * at a time. | 225 | * at a time. |
138 | */ | 226 | */ |
139 | 227 | ||
140 | #define MAP_PAGE_ENTRIES (PAGE_SIZE / sizeof(long) - 1) | 228 | #define MAP_PAGE_ENTRIES (PAGE_SIZE / sizeof(sector_t) - 1) |
141 | 229 | ||
142 | struct swap_map_page { | 230 | struct swap_map_page { |
143 | unsigned long entries[MAP_PAGE_ENTRIES]; | 231 | sector_t entries[MAP_PAGE_ENTRIES]; |
144 | unsigned long next_swap; | 232 | sector_t next_swap; |
145 | }; | 233 | }; |
146 | 234 | ||
147 | /** | 235 | /** |
@@ -151,7 +239,7 @@ struct swap_map_page { | |||
151 | 239 | ||
152 | struct swap_map_handle { | 240 | struct swap_map_handle { |
153 | struct swap_map_page *cur; | 241 | struct swap_map_page *cur; |
154 | unsigned long cur_swap; | 242 | sector_t cur_swap; |
155 | struct bitmap_page *bitmap; | 243 | struct bitmap_page *bitmap; |
156 | unsigned int k; | 244 | unsigned int k; |
157 | }; | 245 | }; |
@@ -166,26 +254,6 @@ static void release_swap_writer(struct swap_map_handle *handle) | |||
166 | handle->bitmap = NULL; | 254 | handle->bitmap = NULL; |
167 | } | 255 | } |
168 | 256 | ||
169 | static void show_speed(struct timeval *start, struct timeval *stop, | ||
170 | unsigned nr_pages, char *msg) | ||
171 | { | ||
172 | s64 elapsed_centisecs64; | ||
173 | int centisecs; | ||
174 | int k; | ||
175 | int kps; | ||
176 | |||
177 | elapsed_centisecs64 = timeval_to_ns(stop) - timeval_to_ns(start); | ||
178 | do_div(elapsed_centisecs64, NSEC_PER_SEC / 100); | ||
179 | centisecs = elapsed_centisecs64; | ||
180 | if (centisecs == 0) | ||
181 | centisecs = 1; /* avoid div-by-zero */ | ||
182 | k = nr_pages * (PAGE_SIZE / 1024); | ||
183 | kps = (k * 100) / centisecs; | ||
184 | printk("%s %d kbytes in %d.%02d seconds (%d.%02d MB/s)\n", msg, k, | ||
185 | centisecs / 100, centisecs % 100, | ||
186 | kps / 1000, (kps % 1000) / 10); | ||
187 | } | ||
188 | |||
189 | static int get_swap_writer(struct swap_map_handle *handle) | 257 | static int get_swap_writer(struct swap_map_handle *handle) |
190 | { | 258 | { |
191 | handle->cur = (struct swap_map_page *)get_zeroed_page(GFP_KERNEL); | 259 | handle->cur = (struct swap_map_page *)get_zeroed_page(GFP_KERNEL); |
@@ -196,7 +264,7 @@ static int get_swap_writer(struct swap_map_handle *handle) | |||
196 | release_swap_writer(handle); | 264 | release_swap_writer(handle); |
197 | return -ENOMEM; | 265 | return -ENOMEM; |
198 | } | 266 | } |
199 | handle->cur_swap = alloc_swap_page(root_swap, handle->bitmap); | 267 | handle->cur_swap = alloc_swapdev_block(root_swap, handle->bitmap); |
200 | if (!handle->cur_swap) { | 268 | if (!handle->cur_swap) { |
201 | release_swap_writer(handle); | 269 | release_swap_writer(handle); |
202 | return -ENOSPC; | 270 | return -ENOSPC; |
@@ -205,43 +273,15 @@ static int get_swap_writer(struct swap_map_handle *handle) | |||
205 | return 0; | 273 | return 0; |
206 | } | 274 | } |
207 | 275 | ||
208 | static int wait_on_bio_chain(struct bio **bio_chain) | ||
209 | { | ||
210 | struct bio *bio; | ||
211 | struct bio *next_bio; | ||
212 | int ret = 0; | ||
213 | |||
214 | if (bio_chain == NULL) | ||
215 | return 0; | ||
216 | |||
217 | bio = *bio_chain; | ||
218 | if (bio == NULL) | ||
219 | return 0; | ||
220 | while (bio) { | ||
221 | struct page *page; | ||
222 | |||
223 | next_bio = bio->bi_private; | ||
224 | page = bio->bi_io_vec[0].bv_page; | ||
225 | wait_on_page_locked(page); | ||
226 | if (!PageUptodate(page) || PageError(page)) | ||
227 | ret = -EIO; | ||
228 | put_page(page); | ||
229 | bio_put(bio); | ||
230 | bio = next_bio; | ||
231 | } | ||
232 | *bio_chain = NULL; | ||
233 | return ret; | ||
234 | } | ||
235 | |||
236 | static int swap_write_page(struct swap_map_handle *handle, void *buf, | 276 | static int swap_write_page(struct swap_map_handle *handle, void *buf, |
237 | struct bio **bio_chain) | 277 | struct bio **bio_chain) |
238 | { | 278 | { |
239 | int error = 0; | 279 | int error = 0; |
240 | unsigned long offset; | 280 | sector_t offset; |
241 | 281 | ||
242 | if (!handle->cur) | 282 | if (!handle->cur) |
243 | return -EINVAL; | 283 | return -EINVAL; |
244 | offset = alloc_swap_page(root_swap, handle->bitmap); | 284 | offset = alloc_swapdev_block(root_swap, handle->bitmap); |
245 | error = write_page(buf, offset, bio_chain); | 285 | error = write_page(buf, offset, bio_chain); |
246 | if (error) | 286 | if (error) |
247 | return error; | 287 | return error; |
@@ -250,7 +290,7 @@ static int swap_write_page(struct swap_map_handle *handle, void *buf, | |||
250 | error = wait_on_bio_chain(bio_chain); | 290 | error = wait_on_bio_chain(bio_chain); |
251 | if (error) | 291 | if (error) |
252 | goto out; | 292 | goto out; |
253 | offset = alloc_swap_page(root_swap, handle->bitmap); | 293 | offset = alloc_swapdev_block(root_swap, handle->bitmap); |
254 | if (!offset) | 294 | if (!offset) |
255 | return -ENOSPC; | 295 | return -ENOSPC; |
256 | handle->cur->next_swap = offset; | 296 | handle->cur->next_swap = offset; |
@@ -261,7 +301,7 @@ static int swap_write_page(struct swap_map_handle *handle, void *buf, | |||
261 | handle->cur_swap = offset; | 301 | handle->cur_swap = offset; |
262 | handle->k = 0; | 302 | handle->k = 0; |
263 | } | 303 | } |
264 | out: | 304 | out: |
265 | return error; | 305 | return error; |
266 | } | 306 | } |
267 | 307 | ||
@@ -315,7 +355,7 @@ static int save_image(struct swap_map_handle *handle, | |||
315 | error = err2; | 355 | error = err2; |
316 | if (!error) | 356 | if (!error) |
317 | printk("\b\b\b\bdone\n"); | 357 | printk("\b\b\b\bdone\n"); |
318 | show_speed(&start, &stop, nr_to_write, "Wrote"); | 358 | swsusp_show_speed(&start, &stop, nr_to_write, "Wrote"); |
319 | return error; | 359 | return error; |
320 | } | 360 | } |
321 | 361 | ||
@@ -350,100 +390,50 @@ int swsusp_write(void) | |||
350 | struct swsusp_info *header; | 390 | struct swsusp_info *header; |
351 | int error; | 391 | int error; |
352 | 392 | ||
353 | if ((error = swsusp_swap_check())) { | 393 | error = swsusp_swap_check(); |
394 | if (error) { | ||
354 | printk(KERN_ERR "swsusp: Cannot find swap device, try " | 395 | printk(KERN_ERR "swsusp: Cannot find swap device, try " |
355 | "swapon -a.\n"); | 396 | "swapon -a.\n"); |
356 | return error; | 397 | return error; |
357 | } | 398 | } |
358 | memset(&snapshot, 0, sizeof(struct snapshot_handle)); | 399 | memset(&snapshot, 0, sizeof(struct snapshot_handle)); |
359 | error = snapshot_read_next(&snapshot, PAGE_SIZE); | 400 | error = snapshot_read_next(&snapshot, PAGE_SIZE); |
360 | if (error < PAGE_SIZE) | 401 | if (error < PAGE_SIZE) { |
361 | return error < 0 ? error : -EFAULT; | 402 | if (error >= 0) |
403 | error = -EFAULT; | ||
404 | |||
405 | goto out; | ||
406 | } | ||
362 | header = (struct swsusp_info *)data_of(snapshot); | 407 | header = (struct swsusp_info *)data_of(snapshot); |
363 | if (!enough_swap(header->pages)) { | 408 | if (!enough_swap(header->pages)) { |
364 | printk(KERN_ERR "swsusp: Not enough free swap\n"); | 409 | printk(KERN_ERR "swsusp: Not enough free swap\n"); |
365 | return -ENOSPC; | 410 | error = -ENOSPC; |
411 | goto out; | ||
366 | } | 412 | } |
367 | error = get_swap_writer(&handle); | 413 | error = get_swap_writer(&handle); |
368 | if (!error) { | 414 | if (!error) { |
369 | unsigned long start = handle.cur_swap; | 415 | sector_t start = handle.cur_swap; |
416 | |||
370 | error = swap_write_page(&handle, header, NULL); | 417 | error = swap_write_page(&handle, header, NULL); |
371 | if (!error) | 418 | if (!error) |
372 | error = save_image(&handle, &snapshot, | 419 | error = save_image(&handle, &snapshot, |
373 | header->pages - 1); | 420 | header->pages - 1); |
421 | |||
374 | if (!error) { | 422 | if (!error) { |
375 | flush_swap_writer(&handle); | 423 | flush_swap_writer(&handle); |
376 | printk("S"); | 424 | printk("S"); |
377 | error = mark_swapfiles(swp_entry(root_swap, start)); | 425 | error = mark_swapfiles(start); |
378 | printk("|\n"); | 426 | printk("|\n"); |
379 | } | 427 | } |
380 | } | 428 | } |
381 | if (error) | 429 | if (error) |
382 | free_all_swap_pages(root_swap, handle.bitmap); | 430 | free_all_swap_pages(root_swap, handle.bitmap); |
383 | release_swap_writer(&handle); | 431 | release_swap_writer(&handle); |
432 | out: | ||
433 | swsusp_close(); | ||
384 | return error; | 434 | return error; |
385 | } | 435 | } |
386 | 436 | ||
387 | static struct block_device *resume_bdev; | ||
388 | |||
389 | /** | ||
390 | * submit - submit BIO request. | ||
391 | * @rw: READ or WRITE. | ||
392 | * @off physical offset of page. | ||
393 | * @page: page we're reading or writing. | ||
394 | * @bio_chain: list of pending biod (for async reading) | ||
395 | * | ||
396 | * Straight from the textbook - allocate and initialize the bio. | ||
397 | * If we're reading, make sure the page is marked as dirty. | ||
398 | * Then submit it and, if @bio_chain == NULL, wait. | ||
399 | */ | ||
400 | static int submit(int rw, pgoff_t page_off, struct page *page, | ||
401 | struct bio **bio_chain) | ||
402 | { | ||
403 | struct bio *bio; | ||
404 | |||
405 | bio = bio_alloc(GFP_ATOMIC, 1); | ||
406 | if (!bio) | ||
407 | return -ENOMEM; | ||
408 | bio->bi_sector = page_off * (PAGE_SIZE >> 9); | ||
409 | bio->bi_bdev = resume_bdev; | ||
410 | bio->bi_end_io = end_swap_bio_read; | ||
411 | |||
412 | if (bio_add_page(bio, page, PAGE_SIZE, 0) < PAGE_SIZE) { | ||
413 | printk("swsusp: ERROR: adding page to bio at %ld\n", page_off); | ||
414 | bio_put(bio); | ||
415 | return -EFAULT; | ||
416 | } | ||
417 | |||
418 | lock_page(page); | ||
419 | bio_get(bio); | ||
420 | |||
421 | if (bio_chain == NULL) { | ||
422 | submit_bio(rw | (1 << BIO_RW_SYNC), bio); | ||
423 | wait_on_page_locked(page); | ||
424 | if (rw == READ) | ||
425 | bio_set_pages_dirty(bio); | ||
426 | bio_put(bio); | ||
427 | } else { | ||
428 | if (rw == READ) | ||
429 | get_page(page); /* These pages are freed later */ | ||
430 | bio->bi_private = *bio_chain; | ||
431 | *bio_chain = bio; | ||
432 | submit_bio(rw | (1 << BIO_RW_SYNC), bio); | ||
433 | } | ||
434 | return 0; | ||
435 | } | ||
436 | |||
437 | static int bio_read_page(pgoff_t page_off, void *addr, struct bio **bio_chain) | ||
438 | { | ||
439 | return submit(READ, page_off, virt_to_page(addr), bio_chain); | ||
440 | } | ||
441 | |||
442 | static int bio_write_page(pgoff_t page_off, void *addr) | ||
443 | { | ||
444 | return submit(WRITE, page_off, virt_to_page(addr), NULL); | ||
445 | } | ||
446 | |||
447 | /** | 437 | /** |
448 | * The following functions allow us to read data using a swap map | 438 | * The following functions allow us to read data using a swap map |
449 | * in a file-alike way | 439 | * in a file-alike way |
@@ -456,17 +446,18 @@ static void release_swap_reader(struct swap_map_handle *handle) | |||
456 | handle->cur = NULL; | 446 | handle->cur = NULL; |
457 | } | 447 | } |
458 | 448 | ||
459 | static int get_swap_reader(struct swap_map_handle *handle, | 449 | static int get_swap_reader(struct swap_map_handle *handle, sector_t start) |
460 | swp_entry_t start) | ||
461 | { | 450 | { |
462 | int error; | 451 | int error; |
463 | 452 | ||
464 | if (!swp_offset(start)) | 453 | if (!start) |
465 | return -EINVAL; | 454 | return -EINVAL; |
466 | handle->cur = (struct swap_map_page *)get_zeroed_page(GFP_ATOMIC); | 455 | |
456 | handle->cur = (struct swap_map_page *)get_zeroed_page(__GFP_WAIT | __GFP_HIGH); | ||
467 | if (!handle->cur) | 457 | if (!handle->cur) |
468 | return -ENOMEM; | 458 | return -ENOMEM; |
469 | error = bio_read_page(swp_offset(start), handle->cur, NULL); | 459 | |
460 | error = bio_read_page(start, handle->cur, NULL); | ||
470 | if (error) { | 461 | if (error) { |
471 | release_swap_reader(handle); | 462 | release_swap_reader(handle); |
472 | return error; | 463 | return error; |
@@ -478,7 +469,7 @@ static int get_swap_reader(struct swap_map_handle *handle, | |||
478 | static int swap_read_page(struct swap_map_handle *handle, void *buf, | 469 | static int swap_read_page(struct swap_map_handle *handle, void *buf, |
479 | struct bio **bio_chain) | 470 | struct bio **bio_chain) |
480 | { | 471 | { |
481 | unsigned long offset; | 472 | sector_t offset; |
482 | int error; | 473 | int error; |
483 | 474 | ||
484 | if (!handle->cur) | 475 | if (!handle->cur) |
@@ -547,11 +538,11 @@ static int load_image(struct swap_map_handle *handle, | |||
547 | error = err2; | 538 | error = err2; |
548 | if (!error) { | 539 | if (!error) { |
549 | printk("\b\b\b\bdone\n"); | 540 | printk("\b\b\b\bdone\n"); |
550 | snapshot_free_unused_memory(snapshot); | 541 | snapshot_write_finalize(snapshot); |
551 | if (!snapshot_image_loaded(snapshot)) | 542 | if (!snapshot_image_loaded(snapshot)) |
552 | error = -ENODATA; | 543 | error = -ENODATA; |
553 | } | 544 | } |
554 | show_speed(&start, &stop, nr_to_read, "Read"); | 545 | swsusp_show_speed(&start, &stop, nr_to_read, "Read"); |
555 | return error; | 546 | return error; |
556 | } | 547 | } |
557 | 548 | ||
@@ -600,12 +591,16 @@ int swsusp_check(void) | |||
600 | if (!IS_ERR(resume_bdev)) { | 591 | if (!IS_ERR(resume_bdev)) { |
601 | set_blocksize(resume_bdev, PAGE_SIZE); | 592 | set_blocksize(resume_bdev, PAGE_SIZE); |
602 | memset(&swsusp_header, 0, sizeof(swsusp_header)); | 593 | memset(&swsusp_header, 0, sizeof(swsusp_header)); |
603 | if ((error = bio_read_page(0, &swsusp_header, NULL))) | 594 | error = bio_read_page(swsusp_resume_block, |
595 | &swsusp_header, NULL); | ||
596 | if (error) | ||
604 | return error; | 597 | return error; |
598 | |||
605 | if (!memcmp(SWSUSP_SIG, swsusp_header.sig, 10)) { | 599 | if (!memcmp(SWSUSP_SIG, swsusp_header.sig, 10)) { |
606 | memcpy(swsusp_header.sig, swsusp_header.orig_sig, 10); | 600 | memcpy(swsusp_header.sig, swsusp_header.orig_sig, 10); |
607 | /* Reset swap signature now */ | 601 | /* Reset swap signature now */ |
608 | error = bio_write_page(0, &swsusp_header); | 602 | error = bio_write_page(swsusp_resume_block, |
603 | &swsusp_header, NULL); | ||
609 | } else { | 604 | } else { |
610 | return -EINVAL; | 605 | return -EINVAL; |
611 | } | 606 | } |