diff options
author | Christoph Hellwig <hch@lst.de> | 2015-05-19 03:23:23 -0400 |
---|---|---|
committer | Jens Axboe <axboe@fb.com> | 2015-05-19 11:19:59 -0400 |
commit | 343df3c79c62b644ce6ff5dff96c9e0be1ecb242 (patch) | |
tree | e9fda2a8f83de9c33a824551603e2cbfd883db53 | |
parent | b2dbe0a60f1bcf4db5c701f1577b3135c3159eb5 (diff) |
suspend: simplify block I/O handling
Stop abusing struct page functionality and the swap end_io handler, and
instead add a modified version of the blk-lib.c bio_batch helpers.
Also move the block I/O code into swap.c as they are directly tied into
each other.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Tested-by: Pavel Machek <pavel@ucw.cz>
Tested-by: Ming Lin <mlin@kernel.org>
Acked-by: Pavel Machek <pavel@ucw.cz>
Acked-by: Rafael J. Wysocki <rjw@rjwysocki.net>
Signed-off-by: Jens Axboe <axboe@fb.com>
-rw-r--r-- | include/linux/swap.h | 1 | ||||
-rw-r--r-- | kernel/power/Makefile | 3 | ||||
-rw-r--r-- | kernel/power/block_io.c | 103 | ||||
-rw-r--r-- | kernel/power/power.h | 9 | ||||
-rw-r--r-- | kernel/power/swap.c | 159 | ||||
-rw-r--r-- | mm/page_io.c | 2 |
6 files changed, 122 insertions, 155 deletions
diff --git a/include/linux/swap.h b/include/linux/swap.h index cee108cbe2d5..38874729dc5f 100644 --- a/include/linux/swap.h +++ b/include/linux/swap.h | |||
@@ -377,7 +377,6 @@ extern void end_swap_bio_write(struct bio *bio, int err); | |||
377 | extern int __swap_writepage(struct page *page, struct writeback_control *wbc, | 377 | extern int __swap_writepage(struct page *page, struct writeback_control *wbc, |
378 | void (*end_write_func)(struct bio *, int)); | 378 | void (*end_write_func)(struct bio *, int)); |
379 | extern int swap_set_page_dirty(struct page *page); | 379 | extern int swap_set_page_dirty(struct page *page); |
380 | extern void end_swap_bio_read(struct bio *bio, int err); | ||
381 | 380 | ||
382 | int add_swap_extent(struct swap_info_struct *sis, unsigned long start_page, | 381 | int add_swap_extent(struct swap_info_struct *sis, unsigned long start_page, |
383 | unsigned long nr_pages, sector_t start_block); | 382 | unsigned long nr_pages, sector_t start_block); |
diff --git a/kernel/power/Makefile b/kernel/power/Makefile index 29472bff11ef..cb880a14cc39 100644 --- a/kernel/power/Makefile +++ b/kernel/power/Makefile | |||
@@ -7,8 +7,7 @@ obj-$(CONFIG_VT_CONSOLE_SLEEP) += console.o | |||
7 | obj-$(CONFIG_FREEZER) += process.o | 7 | obj-$(CONFIG_FREEZER) += process.o |
8 | obj-$(CONFIG_SUSPEND) += suspend.o | 8 | obj-$(CONFIG_SUSPEND) += suspend.o |
9 | obj-$(CONFIG_PM_TEST_SUSPEND) += suspend_test.o | 9 | obj-$(CONFIG_PM_TEST_SUSPEND) += suspend_test.o |
10 | obj-$(CONFIG_HIBERNATION) += hibernate.o snapshot.o swap.o user.o \ | 10 | obj-$(CONFIG_HIBERNATION) += hibernate.o snapshot.o swap.o user.o |
11 | block_io.o | ||
12 | obj-$(CONFIG_PM_AUTOSLEEP) += autosleep.o | 11 | obj-$(CONFIG_PM_AUTOSLEEP) += autosleep.o |
13 | obj-$(CONFIG_PM_WAKELOCKS) += wakelock.o | 12 | obj-$(CONFIG_PM_WAKELOCKS) += wakelock.o |
14 | 13 | ||
diff --git a/kernel/power/block_io.c b/kernel/power/block_io.c deleted file mode 100644 index 9a58bc258810..000000000000 --- a/kernel/power/block_io.c +++ /dev/null | |||
@@ -1,103 +0,0 @@ | |||
1 | /* | ||
2 | * This file provides functions for block I/O operations on swap/file. | ||
3 | * | ||
4 | * Copyright (C) 1998,2001-2005 Pavel Machek <pavel@ucw.cz> | ||
5 | * Copyright (C) 2006 Rafael J. Wysocki <rjw@sisk.pl> | ||
6 | * | ||
7 | * This file is released under the GPLv2. | ||
8 | */ | ||
9 | |||
10 | #include <linux/bio.h> | ||
11 | #include <linux/kernel.h> | ||
12 | #include <linux/pagemap.h> | ||
13 | #include <linux/swap.h> | ||
14 | |||
15 | #include "power.h" | ||
16 | |||
17 | /** | ||
18 | * submit - submit BIO request. | ||
19 | * @rw: READ or WRITE. | ||
20 | * @off physical offset of page. | ||
21 | * @page: page we're reading or writing. | ||
22 | * @bio_chain: list of pending biod (for async reading) | ||
23 | * | ||
24 | * Straight from the textbook - allocate and initialize the bio. | ||
25 | * If we're reading, make sure the page is marked as dirty. | ||
26 | * Then submit it and, if @bio_chain == NULL, wait. | ||
27 | */ | ||
28 | static int submit(int rw, struct block_device *bdev, sector_t sector, | ||
29 | struct page *page, struct bio **bio_chain) | ||
30 | { | ||
31 | const int bio_rw = rw | REQ_SYNC; | ||
32 | struct bio *bio; | ||
33 | |||
34 | bio = bio_alloc(__GFP_WAIT | __GFP_HIGH, 1); | ||
35 | bio->bi_iter.bi_sector = sector; | ||
36 | bio->bi_bdev = bdev; | ||
37 | bio->bi_end_io = end_swap_bio_read; | ||
38 | |||
39 | if (bio_add_page(bio, page, PAGE_SIZE, 0) < PAGE_SIZE) { | ||
40 | printk(KERN_ERR "PM: Adding page to bio failed at %llu\n", | ||
41 | (unsigned long long)sector); | ||
42 | bio_put(bio); | ||
43 | return -EFAULT; | ||
44 | } | ||
45 | |||
46 | lock_page(page); | ||
47 | bio_get(bio); | ||
48 | |||
49 | if (bio_chain == NULL) { | ||
50 | submit_bio(bio_rw, bio); | ||
51 | wait_on_page_locked(page); | ||
52 | if (rw == READ) | ||
53 | bio_set_pages_dirty(bio); | ||
54 | bio_put(bio); | ||
55 | } else { | ||
56 | if (rw == READ) | ||
57 | get_page(page); /* These pages are freed later */ | ||
58 | bio->bi_private = *bio_chain; | ||
59 | *bio_chain = bio; | ||
60 | submit_bio(bio_rw, bio); | ||
61 | } | ||
62 | return 0; | ||
63 | } | ||
64 | |||
65 | int hib_bio_read_page(pgoff_t page_off, void *addr, struct bio **bio_chain) | ||
66 | { | ||
67 | return submit(READ, hib_resume_bdev, page_off * (PAGE_SIZE >> 9), | ||
68 | virt_to_page(addr), bio_chain); | ||
69 | } | ||
70 | |||
71 | int hib_bio_write_page(pgoff_t page_off, void *addr, struct bio **bio_chain) | ||
72 | { | ||
73 | return submit(WRITE, hib_resume_bdev, page_off * (PAGE_SIZE >> 9), | ||
74 | virt_to_page(addr), bio_chain); | ||
75 | } | ||
76 | |||
77 | int hib_wait_on_bio_chain(struct bio **bio_chain) | ||
78 | { | ||
79 | struct bio *bio; | ||
80 | struct bio *next_bio; | ||
81 | int ret = 0; | ||
82 | |||
83 | if (bio_chain == NULL) | ||
84 | return 0; | ||
85 | |||
86 | bio = *bio_chain; | ||
87 | if (bio == NULL) | ||
88 | return 0; | ||
89 | while (bio) { | ||
90 | struct page *page; | ||
91 | |||
92 | next_bio = bio->bi_private; | ||
93 | page = bio->bi_io_vec[0].bv_page; | ||
94 | wait_on_page_locked(page); | ||
95 | if (!PageUptodate(page) || PageError(page)) | ||
96 | ret = -EIO; | ||
97 | put_page(page); | ||
98 | bio_put(bio); | ||
99 | bio = next_bio; | ||
100 | } | ||
101 | *bio_chain = NULL; | ||
102 | return ret; | ||
103 | } | ||
diff --git a/kernel/power/power.h b/kernel/power/power.h index ce9b8328a689..caadb566e82b 100644 --- a/kernel/power/power.h +++ b/kernel/power/power.h | |||
@@ -163,15 +163,6 @@ extern void swsusp_close(fmode_t); | |||
163 | extern int swsusp_unmark(void); | 163 | extern int swsusp_unmark(void); |
164 | #endif | 164 | #endif |
165 | 165 | ||
166 | /* kernel/power/block_io.c */ | ||
167 | extern struct block_device *hib_resume_bdev; | ||
168 | |||
169 | extern int hib_bio_read_page(pgoff_t page_off, void *addr, | ||
170 | struct bio **bio_chain); | ||
171 | extern int hib_bio_write_page(pgoff_t page_off, void *addr, | ||
172 | struct bio **bio_chain); | ||
173 | extern int hib_wait_on_bio_chain(struct bio **bio_chain); | ||
174 | |||
175 | struct timeval; | 166 | struct timeval; |
176 | /* kernel/power/swsusp.c */ | 167 | /* kernel/power/swsusp.c */ |
177 | extern void swsusp_show_speed(ktime_t, ktime_t, unsigned int, char *); | 168 | extern void swsusp_show_speed(ktime_t, ktime_t, unsigned int, char *); |
diff --git a/kernel/power/swap.c b/kernel/power/swap.c index 570aff817543..2f30ca91e4fa 100644 --- a/kernel/power/swap.c +++ b/kernel/power/swap.c | |||
@@ -212,7 +212,84 @@ int swsusp_swap_in_use(void) | |||
212 | */ | 212 | */ |
213 | 213 | ||
214 | static unsigned short root_swap = 0xffff; | 214 | static unsigned short root_swap = 0xffff; |
215 | struct block_device *hib_resume_bdev; | 215 | static struct block_device *hib_resume_bdev; |
216 | |||
217 | struct hib_bio_batch { | ||
218 | atomic_t count; | ||
219 | wait_queue_head_t wait; | ||
220 | int error; | ||
221 | }; | ||
222 | |||
223 | static void hib_init_batch(struct hib_bio_batch *hb) | ||
224 | { | ||
225 | atomic_set(&hb->count, 0); | ||
226 | init_waitqueue_head(&hb->wait); | ||
227 | hb->error = 0; | ||
228 | } | ||
229 | |||
230 | static void hib_end_io(struct bio *bio, int error) | ||
231 | { | ||
232 | struct hib_bio_batch *hb = bio->bi_private; | ||
233 | const int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags); | ||
234 | struct page *page = bio->bi_io_vec[0].bv_page; | ||
235 | |||
236 | if (!uptodate || error) { | ||
237 | printk(KERN_ALERT "Read-error on swap-device (%u:%u:%Lu)\n", | ||
238 | imajor(bio->bi_bdev->bd_inode), | ||
239 | iminor(bio->bi_bdev->bd_inode), | ||
240 | (unsigned long long)bio->bi_iter.bi_sector); | ||
241 | |||
242 | if (!error) | ||
243 | error = -EIO; | ||
244 | } | ||
245 | |||
246 | if (bio_data_dir(bio) == WRITE) | ||
247 | put_page(page); | ||
248 | |||
249 | if (error && !hb->error) | ||
250 | hb->error = error; | ||
251 | if (atomic_dec_and_test(&hb->count)) | ||
252 | wake_up(&hb->wait); | ||
253 | |||
254 | bio_put(bio); | ||
255 | } | ||
256 | |||
257 | static int hib_submit_io(int rw, pgoff_t page_off, void *addr, | ||
258 | struct hib_bio_batch *hb) | ||
259 | { | ||
260 | struct page *page = virt_to_page(addr); | ||
261 | struct bio *bio; | ||
262 | int error = 0; | ||
263 | |||
264 | bio = bio_alloc(__GFP_WAIT | __GFP_HIGH, 1); | ||
265 | bio->bi_iter.bi_sector = page_off * (PAGE_SIZE >> 9); | ||
266 | bio->bi_bdev = hib_resume_bdev; | ||
267 | |||
268 | if (bio_add_page(bio, page, PAGE_SIZE, 0) < PAGE_SIZE) { | ||
269 | printk(KERN_ERR "PM: Adding page to bio failed at %llu\n", | ||
270 | (unsigned long long)bio->bi_iter.bi_sector); | ||
271 | bio_put(bio); | ||
272 | return -EFAULT; | ||
273 | } | ||
274 | |||
275 | if (hb) { | ||
276 | bio->bi_end_io = hib_end_io; | ||
277 | bio->bi_private = hb; | ||
278 | atomic_inc(&hb->count); | ||
279 | submit_bio(rw, bio); | ||
280 | } else { | ||
281 | error = submit_bio_wait(rw, bio); | ||
282 | bio_put(bio); | ||
283 | } | ||
284 | |||
285 | return error; | ||
286 | } | ||
287 | |||
288 | static int hib_wait_io(struct hib_bio_batch *hb) | ||
289 | { | ||
290 | wait_event(hb->wait, atomic_read(&hb->count) == 0); | ||
291 | return hb->error; | ||
292 | } | ||
216 | 293 | ||
217 | /* | 294 | /* |
218 | * Saving part | 295 | * Saving part |
@@ -222,7 +299,7 @@ static int mark_swapfiles(struct swap_map_handle *handle, unsigned int flags) | |||
222 | { | 299 | { |
223 | int error; | 300 | int error; |
224 | 301 | ||
225 | hib_bio_read_page(swsusp_resume_block, swsusp_header, NULL); | 302 | hib_submit_io(READ_SYNC, swsusp_resume_block, swsusp_header, NULL); |
226 | if (!memcmp("SWAP-SPACE",swsusp_header->sig, 10) || | 303 | if (!memcmp("SWAP-SPACE",swsusp_header->sig, 10) || |
227 | !memcmp("SWAPSPACE2",swsusp_header->sig, 10)) { | 304 | !memcmp("SWAPSPACE2",swsusp_header->sig, 10)) { |
228 | memcpy(swsusp_header->orig_sig,swsusp_header->sig, 10); | 305 | memcpy(swsusp_header->orig_sig,swsusp_header->sig, 10); |
@@ -231,7 +308,7 @@ static int mark_swapfiles(struct swap_map_handle *handle, unsigned int flags) | |||
231 | swsusp_header->flags = flags; | 308 | swsusp_header->flags = flags; |
232 | if (flags & SF_CRC32_MODE) | 309 | if (flags & SF_CRC32_MODE) |
233 | swsusp_header->crc32 = handle->crc32; | 310 | swsusp_header->crc32 = handle->crc32; |
234 | error = hib_bio_write_page(swsusp_resume_block, | 311 | error = hib_submit_io(WRITE_SYNC, swsusp_resume_block, |
235 | swsusp_header, NULL); | 312 | swsusp_header, NULL); |
236 | } else { | 313 | } else { |
237 | printk(KERN_ERR "PM: Swap header not found!\n"); | 314 | printk(KERN_ERR "PM: Swap header not found!\n"); |
@@ -271,10 +348,10 @@ static int swsusp_swap_check(void) | |||
271 | * write_page - Write one page to given swap location. | 348 | * write_page - Write one page to given swap location. |
272 | * @buf: Address we're writing. | 349 | * @buf: Address we're writing. |
273 | * @offset: Offset of the swap page we're writing to. | 350 | * @offset: Offset of the swap page we're writing to. |
274 | * @bio_chain: Link the next write BIO here | 351 | * @hb: bio completion batch |
275 | */ | 352 | */ |
276 | 353 | ||
277 | static int write_page(void *buf, sector_t offset, struct bio **bio_chain) | 354 | static int write_page(void *buf, sector_t offset, struct hib_bio_batch *hb) |
278 | { | 355 | { |
279 | void *src; | 356 | void *src; |
280 | int ret; | 357 | int ret; |
@@ -282,13 +359,13 @@ static int write_page(void *buf, sector_t offset, struct bio **bio_chain) | |||
282 | if (!offset) | 359 | if (!offset) |
283 | return -ENOSPC; | 360 | return -ENOSPC; |
284 | 361 | ||
285 | if (bio_chain) { | 362 | if (hb) { |
286 | src = (void *)__get_free_page(__GFP_WAIT | __GFP_NOWARN | | 363 | src = (void *)__get_free_page(__GFP_WAIT | __GFP_NOWARN | |
287 | __GFP_NORETRY); | 364 | __GFP_NORETRY); |
288 | if (src) { | 365 | if (src) { |
289 | copy_page(src, buf); | 366 | copy_page(src, buf); |
290 | } else { | 367 | } else { |
291 | ret = hib_wait_on_bio_chain(bio_chain); /* Free pages */ | 368 | ret = hib_wait_io(hb); /* Free pages */ |
292 | if (ret) | 369 | if (ret) |
293 | return ret; | 370 | return ret; |
294 | src = (void *)__get_free_page(__GFP_WAIT | | 371 | src = (void *)__get_free_page(__GFP_WAIT | |
@@ -298,14 +375,14 @@ static int write_page(void *buf, sector_t offset, struct bio **bio_chain) | |||
298 | copy_page(src, buf); | 375 | copy_page(src, buf); |
299 | } else { | 376 | } else { |
300 | WARN_ON_ONCE(1); | 377 | WARN_ON_ONCE(1); |
301 | bio_chain = NULL; /* Go synchronous */ | 378 | hb = NULL; /* Go synchronous */ |
302 | src = buf; | 379 | src = buf; |
303 | } | 380 | } |
304 | } | 381 | } |
305 | } else { | 382 | } else { |
306 | src = buf; | 383 | src = buf; |
307 | } | 384 | } |
308 | return hib_bio_write_page(offset, src, bio_chain); | 385 | return hib_submit_io(WRITE_SYNC, offset, src, hb); |
309 | } | 386 | } |
310 | 387 | ||
311 | static void release_swap_writer(struct swap_map_handle *handle) | 388 | static void release_swap_writer(struct swap_map_handle *handle) |
@@ -348,7 +425,7 @@ err_close: | |||
348 | } | 425 | } |
349 | 426 | ||
350 | static int swap_write_page(struct swap_map_handle *handle, void *buf, | 427 | static int swap_write_page(struct swap_map_handle *handle, void *buf, |
351 | struct bio **bio_chain) | 428 | struct hib_bio_batch *hb) |
352 | { | 429 | { |
353 | int error = 0; | 430 | int error = 0; |
354 | sector_t offset; | 431 | sector_t offset; |
@@ -356,7 +433,7 @@ static int swap_write_page(struct swap_map_handle *handle, void *buf, | |||
356 | if (!handle->cur) | 433 | if (!handle->cur) |
357 | return -EINVAL; | 434 | return -EINVAL; |
358 | offset = alloc_swapdev_block(root_swap); | 435 | offset = alloc_swapdev_block(root_swap); |
359 | error = write_page(buf, offset, bio_chain); | 436 | error = write_page(buf, offset, hb); |
360 | if (error) | 437 | if (error) |
361 | return error; | 438 | return error; |
362 | handle->cur->entries[handle->k++] = offset; | 439 | handle->cur->entries[handle->k++] = offset; |
@@ -365,15 +442,15 @@ static int swap_write_page(struct swap_map_handle *handle, void *buf, | |||
365 | if (!offset) | 442 | if (!offset) |
366 | return -ENOSPC; | 443 | return -ENOSPC; |
367 | handle->cur->next_swap = offset; | 444 | handle->cur->next_swap = offset; |
368 | error = write_page(handle->cur, handle->cur_swap, bio_chain); | 445 | error = write_page(handle->cur, handle->cur_swap, hb); |
369 | if (error) | 446 | if (error) |
370 | goto out; | 447 | goto out; |
371 | clear_page(handle->cur); | 448 | clear_page(handle->cur); |
372 | handle->cur_swap = offset; | 449 | handle->cur_swap = offset; |
373 | handle->k = 0; | 450 | handle->k = 0; |
374 | 451 | ||
375 | if (bio_chain && low_free_pages() <= handle->reqd_free_pages) { | 452 | if (hb && low_free_pages() <= handle->reqd_free_pages) { |
376 | error = hib_wait_on_bio_chain(bio_chain); | 453 | error = hib_wait_io(hb); |
377 | if (error) | 454 | if (error) |
378 | goto out; | 455 | goto out; |
379 | /* | 456 | /* |
@@ -445,23 +522,24 @@ static int save_image(struct swap_map_handle *handle, | |||
445 | int ret; | 522 | int ret; |
446 | int nr_pages; | 523 | int nr_pages; |
447 | int err2; | 524 | int err2; |
448 | struct bio *bio; | 525 | struct hib_bio_batch hb; |
449 | ktime_t start; | 526 | ktime_t start; |
450 | ktime_t stop; | 527 | ktime_t stop; |
451 | 528 | ||
529 | hib_init_batch(&hb); | ||
530 | |||
452 | printk(KERN_INFO "PM: Saving image data pages (%u pages)...\n", | 531 | printk(KERN_INFO "PM: Saving image data pages (%u pages)...\n", |
453 | nr_to_write); | 532 | nr_to_write); |
454 | m = nr_to_write / 10; | 533 | m = nr_to_write / 10; |
455 | if (!m) | 534 | if (!m) |
456 | m = 1; | 535 | m = 1; |
457 | nr_pages = 0; | 536 | nr_pages = 0; |
458 | bio = NULL; | ||
459 | start = ktime_get(); | 537 | start = ktime_get(); |
460 | while (1) { | 538 | while (1) { |
461 | ret = snapshot_read_next(snapshot); | 539 | ret = snapshot_read_next(snapshot); |
462 | if (ret <= 0) | 540 | if (ret <= 0) |
463 | break; | 541 | break; |
464 | ret = swap_write_page(handle, data_of(*snapshot), &bio); | 542 | ret = swap_write_page(handle, data_of(*snapshot), &hb); |
465 | if (ret) | 543 | if (ret) |
466 | break; | 544 | break; |
467 | if (!(nr_pages % m)) | 545 | if (!(nr_pages % m)) |
@@ -469,7 +547,7 @@ static int save_image(struct swap_map_handle *handle, | |||
469 | nr_pages / m * 10); | 547 | nr_pages / m * 10); |
470 | nr_pages++; | 548 | nr_pages++; |
471 | } | 549 | } |
472 | err2 = hib_wait_on_bio_chain(&bio); | 550 | err2 = hib_wait_io(&hb); |
473 | stop = ktime_get(); | 551 | stop = ktime_get(); |
474 | if (!ret) | 552 | if (!ret) |
475 | ret = err2; | 553 | ret = err2; |
@@ -580,7 +658,7 @@ static int save_image_lzo(struct swap_map_handle *handle, | |||
580 | int ret = 0; | 658 | int ret = 0; |
581 | int nr_pages; | 659 | int nr_pages; |
582 | int err2; | 660 | int err2; |
583 | struct bio *bio; | 661 | struct hib_bio_batch hb; |
584 | ktime_t start; | 662 | ktime_t start; |
585 | ktime_t stop; | 663 | ktime_t stop; |
586 | size_t off; | 664 | size_t off; |
@@ -589,6 +667,8 @@ static int save_image_lzo(struct swap_map_handle *handle, | |||
589 | struct cmp_data *data = NULL; | 667 | struct cmp_data *data = NULL; |
590 | struct crc_data *crc = NULL; | 668 | struct crc_data *crc = NULL; |
591 | 669 | ||
670 | hib_init_batch(&hb); | ||
671 | |||
592 | /* | 672 | /* |
593 | * We'll limit the number of threads for compression to limit memory | 673 | * We'll limit the number of threads for compression to limit memory |
594 | * footprint. | 674 | * footprint. |
@@ -674,7 +754,6 @@ static int save_image_lzo(struct swap_map_handle *handle, | |||
674 | if (!m) | 754 | if (!m) |
675 | m = 1; | 755 | m = 1; |
676 | nr_pages = 0; | 756 | nr_pages = 0; |
677 | bio = NULL; | ||
678 | start = ktime_get(); | 757 | start = ktime_get(); |
679 | for (;;) { | 758 | for (;;) { |
680 | for (thr = 0; thr < nr_threads; thr++) { | 759 | for (thr = 0; thr < nr_threads; thr++) { |
@@ -748,7 +827,7 @@ static int save_image_lzo(struct swap_map_handle *handle, | |||
748 | off += PAGE_SIZE) { | 827 | off += PAGE_SIZE) { |
749 | memcpy(page, data[thr].cmp + off, PAGE_SIZE); | 828 | memcpy(page, data[thr].cmp + off, PAGE_SIZE); |
750 | 829 | ||
751 | ret = swap_write_page(handle, page, &bio); | 830 | ret = swap_write_page(handle, page, &hb); |
752 | if (ret) | 831 | if (ret) |
753 | goto out_finish; | 832 | goto out_finish; |
754 | } | 833 | } |
@@ -759,7 +838,7 @@ static int save_image_lzo(struct swap_map_handle *handle, | |||
759 | } | 838 | } |
760 | 839 | ||
761 | out_finish: | 840 | out_finish: |
762 | err2 = hib_wait_on_bio_chain(&bio); | 841 | err2 = hib_wait_io(&hb); |
763 | stop = ktime_get(); | 842 | stop = ktime_get(); |
764 | if (!ret) | 843 | if (!ret) |
765 | ret = err2; | 844 | ret = err2; |
@@ -906,7 +985,7 @@ static int get_swap_reader(struct swap_map_handle *handle, | |||
906 | return -ENOMEM; | 985 | return -ENOMEM; |
907 | } | 986 | } |
908 | 987 | ||
909 | error = hib_bio_read_page(offset, tmp->map, NULL); | 988 | error = hib_submit_io(READ_SYNC, offset, tmp->map, NULL); |
910 | if (error) { | 989 | if (error) { |
911 | release_swap_reader(handle); | 990 | release_swap_reader(handle); |
912 | return error; | 991 | return error; |
@@ -919,7 +998,7 @@ static int get_swap_reader(struct swap_map_handle *handle, | |||
919 | } | 998 | } |
920 | 999 | ||
921 | static int swap_read_page(struct swap_map_handle *handle, void *buf, | 1000 | static int swap_read_page(struct swap_map_handle *handle, void *buf, |
922 | struct bio **bio_chain) | 1001 | struct hib_bio_batch *hb) |
923 | { | 1002 | { |
924 | sector_t offset; | 1003 | sector_t offset; |
925 | int error; | 1004 | int error; |
@@ -930,7 +1009,7 @@ static int swap_read_page(struct swap_map_handle *handle, void *buf, | |||
930 | offset = handle->cur->entries[handle->k]; | 1009 | offset = handle->cur->entries[handle->k]; |
931 | if (!offset) | 1010 | if (!offset) |
932 | return -EFAULT; | 1011 | return -EFAULT; |
933 | error = hib_bio_read_page(offset, buf, bio_chain); | 1012 | error = hib_submit_io(READ_SYNC, offset, buf, hb); |
934 | if (error) | 1013 | if (error) |
935 | return error; | 1014 | return error; |
936 | if (++handle->k >= MAP_PAGE_ENTRIES) { | 1015 | if (++handle->k >= MAP_PAGE_ENTRIES) { |
@@ -968,27 +1047,28 @@ static int load_image(struct swap_map_handle *handle, | |||
968 | int ret = 0; | 1047 | int ret = 0; |
969 | ktime_t start; | 1048 | ktime_t start; |
970 | ktime_t stop; | 1049 | ktime_t stop; |
971 | struct bio *bio; | 1050 | struct hib_bio_batch hb; |
972 | int err2; | 1051 | int err2; |
973 | unsigned nr_pages; | 1052 | unsigned nr_pages; |
974 | 1053 | ||
1054 | hib_init_batch(&hb); | ||
1055 | |||
975 | printk(KERN_INFO "PM: Loading image data pages (%u pages)...\n", | 1056 | printk(KERN_INFO "PM: Loading image data pages (%u pages)...\n", |
976 | nr_to_read); | 1057 | nr_to_read); |
977 | m = nr_to_read / 10; | 1058 | m = nr_to_read / 10; |
978 | if (!m) | 1059 | if (!m) |
979 | m = 1; | 1060 | m = 1; |
980 | nr_pages = 0; | 1061 | nr_pages = 0; |
981 | bio = NULL; | ||
982 | start = ktime_get(); | 1062 | start = ktime_get(); |
983 | for ( ; ; ) { | 1063 | for ( ; ; ) { |
984 | ret = snapshot_write_next(snapshot); | 1064 | ret = snapshot_write_next(snapshot); |
985 | if (ret <= 0) | 1065 | if (ret <= 0) |
986 | break; | 1066 | break; |
987 | ret = swap_read_page(handle, data_of(*snapshot), &bio); | 1067 | ret = swap_read_page(handle, data_of(*snapshot), &hb); |
988 | if (ret) | 1068 | if (ret) |
989 | break; | 1069 | break; |
990 | if (snapshot->sync_read) | 1070 | if (snapshot->sync_read) |
991 | ret = hib_wait_on_bio_chain(&bio); | 1071 | ret = hib_wait_io(&hb); |
992 | if (ret) | 1072 | if (ret) |
993 | break; | 1073 | break; |
994 | if (!(nr_pages % m)) | 1074 | if (!(nr_pages % m)) |
@@ -996,7 +1076,7 @@ static int load_image(struct swap_map_handle *handle, | |||
996 | nr_pages / m * 10); | 1076 | nr_pages / m * 10); |
997 | nr_pages++; | 1077 | nr_pages++; |
998 | } | 1078 | } |
999 | err2 = hib_wait_on_bio_chain(&bio); | 1079 | err2 = hib_wait_io(&hb); |
1000 | stop = ktime_get(); | 1080 | stop = ktime_get(); |
1001 | if (!ret) | 1081 | if (!ret) |
1002 | ret = err2; | 1082 | ret = err2; |
@@ -1067,7 +1147,7 @@ static int load_image_lzo(struct swap_map_handle *handle, | |||
1067 | unsigned int m; | 1147 | unsigned int m; |
1068 | int ret = 0; | 1148 | int ret = 0; |
1069 | int eof = 0; | 1149 | int eof = 0; |
1070 | struct bio *bio; | 1150 | struct hib_bio_batch hb; |
1071 | ktime_t start; | 1151 | ktime_t start; |
1072 | ktime_t stop; | 1152 | ktime_t stop; |
1073 | unsigned nr_pages; | 1153 | unsigned nr_pages; |
@@ -1080,6 +1160,8 @@ static int load_image_lzo(struct swap_map_handle *handle, | |||
1080 | struct dec_data *data = NULL; | 1160 | struct dec_data *data = NULL; |
1081 | struct crc_data *crc = NULL; | 1161 | struct crc_data *crc = NULL; |
1082 | 1162 | ||
1163 | hib_init_batch(&hb); | ||
1164 | |||
1083 | /* | 1165 | /* |
1084 | * We'll limit the number of threads for decompression to limit memory | 1166 | * We'll limit the number of threads for decompression to limit memory |
1085 | * footprint. | 1167 | * footprint. |
@@ -1190,7 +1272,6 @@ static int load_image_lzo(struct swap_map_handle *handle, | |||
1190 | if (!m) | 1272 | if (!m) |
1191 | m = 1; | 1273 | m = 1; |
1192 | nr_pages = 0; | 1274 | nr_pages = 0; |
1193 | bio = NULL; | ||
1194 | start = ktime_get(); | 1275 | start = ktime_get(); |
1195 | 1276 | ||
1196 | ret = snapshot_write_next(snapshot); | 1277 | ret = snapshot_write_next(snapshot); |
@@ -1199,7 +1280,7 @@ static int load_image_lzo(struct swap_map_handle *handle, | |||
1199 | 1280 | ||
1200 | for(;;) { | 1281 | for(;;) { |
1201 | for (i = 0; !eof && i < want; i++) { | 1282 | for (i = 0; !eof && i < want; i++) { |
1202 | ret = swap_read_page(handle, page[ring], &bio); | 1283 | ret = swap_read_page(handle, page[ring], &hb); |
1203 | if (ret) { | 1284 | if (ret) { |
1204 | /* | 1285 | /* |
1205 | * On real read error, finish. On end of data, | 1286 | * On real read error, finish. On end of data, |
@@ -1226,7 +1307,7 @@ static int load_image_lzo(struct swap_map_handle *handle, | |||
1226 | if (!asked) | 1307 | if (!asked) |
1227 | break; | 1308 | break; |
1228 | 1309 | ||
1229 | ret = hib_wait_on_bio_chain(&bio); | 1310 | ret = hib_wait_io(&hb); |
1230 | if (ret) | 1311 | if (ret) |
1231 | goto out_finish; | 1312 | goto out_finish; |
1232 | have += asked; | 1313 | have += asked; |
@@ -1281,7 +1362,7 @@ static int load_image_lzo(struct swap_map_handle *handle, | |||
1281 | * Wait for more data while we are decompressing. | 1362 | * Wait for more data while we are decompressing. |
1282 | */ | 1363 | */ |
1283 | if (have < LZO_CMP_PAGES && asked) { | 1364 | if (have < LZO_CMP_PAGES && asked) { |
1284 | ret = hib_wait_on_bio_chain(&bio); | 1365 | ret = hib_wait_io(&hb); |
1285 | if (ret) | 1366 | if (ret) |
1286 | goto out_finish; | 1367 | goto out_finish; |
1287 | have += asked; | 1368 | have += asked; |
@@ -1430,7 +1511,7 @@ int swsusp_check(void) | |||
1430 | if (!IS_ERR(hib_resume_bdev)) { | 1511 | if (!IS_ERR(hib_resume_bdev)) { |
1431 | set_blocksize(hib_resume_bdev, PAGE_SIZE); | 1512 | set_blocksize(hib_resume_bdev, PAGE_SIZE); |
1432 | clear_page(swsusp_header); | 1513 | clear_page(swsusp_header); |
1433 | error = hib_bio_read_page(swsusp_resume_block, | 1514 | error = hib_submit_io(READ_SYNC, swsusp_resume_block, |
1434 | swsusp_header, NULL); | 1515 | swsusp_header, NULL); |
1435 | if (error) | 1516 | if (error) |
1436 | goto put; | 1517 | goto put; |
@@ -1438,7 +1519,7 @@ int swsusp_check(void) | |||
1438 | if (!memcmp(HIBERNATE_SIG, swsusp_header->sig, 10)) { | 1519 | if (!memcmp(HIBERNATE_SIG, swsusp_header->sig, 10)) { |
1439 | memcpy(swsusp_header->sig, swsusp_header->orig_sig, 10); | 1520 | memcpy(swsusp_header->sig, swsusp_header->orig_sig, 10); |
1440 | /* Reset swap signature now */ | 1521 | /* Reset swap signature now */ |
1441 | error = hib_bio_write_page(swsusp_resume_block, | 1522 | error = hib_submit_io(WRITE_SYNC, swsusp_resume_block, |
1442 | swsusp_header, NULL); | 1523 | swsusp_header, NULL); |
1443 | } else { | 1524 | } else { |
1444 | error = -EINVAL; | 1525 | error = -EINVAL; |
@@ -1482,10 +1563,10 @@ int swsusp_unmark(void) | |||
1482 | { | 1563 | { |
1483 | int error; | 1564 | int error; |
1484 | 1565 | ||
1485 | hib_bio_read_page(swsusp_resume_block, swsusp_header, NULL); | 1566 | hib_submit_io(READ_SYNC, swsusp_resume_block, swsusp_header, NULL); |
1486 | if (!memcmp(HIBERNATE_SIG,swsusp_header->sig, 10)) { | 1567 | if (!memcmp(HIBERNATE_SIG,swsusp_header->sig, 10)) { |
1487 | memcpy(swsusp_header->sig,swsusp_header->orig_sig, 10); | 1568 | memcpy(swsusp_header->sig,swsusp_header->orig_sig, 10); |
1488 | error = hib_bio_write_page(swsusp_resume_block, | 1569 | error = hib_submit_io(WRITE_SYNC, swsusp_resume_block, |
1489 | swsusp_header, NULL); | 1570 | swsusp_header, NULL); |
1490 | } else { | 1571 | } else { |
1491 | printk(KERN_ERR "PM: Cannot find swsusp signature!\n"); | 1572 | printk(KERN_ERR "PM: Cannot find swsusp signature!\n"); |
diff --git a/mm/page_io.c b/mm/page_io.c index 6424869e275e..520baa4b04d7 100644 --- a/mm/page_io.c +++ b/mm/page_io.c | |||
@@ -69,7 +69,7 @@ void end_swap_bio_write(struct bio *bio, int err) | |||
69 | bio_put(bio); | 69 | bio_put(bio); |
70 | } | 70 | } |
71 | 71 | ||
72 | void end_swap_bio_read(struct bio *bio, int err) | 72 | static void end_swap_bio_read(struct bio *bio, int err) |
73 | { | 73 | { |
74 | const int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags); | 74 | const int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags); |
75 | struct page *page = bio->bi_io_vec[0].bv_page; | 75 | struct page *page = bio->bi_io_vec[0].bv_page; |