[PATCH 09/21] Hibernation: Stop passing bio_chain around

From: Nigel Cunningham
Date: Wed Jun 02 2010 - 08:22:48 EST


Stop using the struct bio **bio_chain as a means of tracking
outstanding i/o and signalling when we want synchronous i/o.
Instead, keep a bio_chain in the block_io code and use a flag
to explicitly request synchronous I/O.

Signed-off-by: Nigel Cunningham <nigel@xxxxxxxxxxxx>
---
kernel/power/block_io.c | 27 +++++++++++-----------
kernel/power/power.h | 8 ++----
kernel/power/swap.c | 56 +++++++++++++++++++++-------------------------
3 files changed, 43 insertions(+), 48 deletions(-)

diff --git a/kernel/power/block_io.c b/kernel/power/block_io.c
index 97024fd..c353d64 100644
--- a/kernel/power/block_io.c
+++ b/kernel/power/block_io.c
@@ -14,6 +14,8 @@

#include "power.h"

+static struct bio *bio_chain;
+
/**
* submit - submit BIO request.
* @rw: READ or WRITE.
@@ -26,7 +28,7 @@
* Then submit it and, if @bio_chain == NULL, wait.
*/
static int submit(int rw, struct block_device *bdev, sector_t sector,
- struct page *page, struct bio **bio_chain)
+ struct page *page, int sync)
{
const int bio_rw = rw | (1 << BIO_RW_SYNCIO) | (1 << BIO_RW_UNPLUG);
struct bio *bio;
@@ -46,7 +48,7 @@ static int submit(int rw, struct block_device *bdev, sector_t sector,
lock_page(page);
bio_get(bio);

- if (bio_chain == NULL) {
+ if (sync) {
submit_bio(bio_rw, bio);
wait_on_page_locked(page);
if (rw == READ)
@@ -55,26 +57,26 @@ static int submit(int rw, struct block_device *bdev, sector_t sector,
} else {
if (rw == READ)
get_page(page); /* These pages are freed later */
- bio->bi_private = *bio_chain;
- *bio_chain = bio;
+ bio->bi_private = bio_chain;
+ bio_chain = bio;
submit_bio(bio_rw, bio);
}
return 0;
}

-int hib_bio_read_page(pgoff_t page_off, void *addr, struct bio **bio_chain)
+int hib_bio_read_page(pgoff_t page_off, void *addr, int sync)
{
return submit(READ, hib_resume_bdev, page_off * (PAGE_SIZE >> 9),
- virt_to_page(addr), bio_chain);
+ virt_to_page(addr), sync);
}

-int hib_bio_write_page(pgoff_t page_off, void *addr, struct bio **bio_chain)
+int hib_bio_write_page(pgoff_t page_off, void *addr, int sync)
{
return submit(WRITE, hib_resume_bdev, page_off * (PAGE_SIZE >> 9),
- virt_to_page(addr), bio_chain);
+ virt_to_page(addr), sync);
}

-int hib_wait_on_bio_chain(struct bio **bio_chain)
+int hib_wait_on_bio_chain(void)
{
struct bio *bio;
struct bio *next_bio;
@@ -83,9 +85,8 @@ int hib_wait_on_bio_chain(struct bio **bio_chain)
if (bio_chain == NULL)
return 0;

- bio = *bio_chain;
- if (bio == NULL)
- return 0;
+ bio = bio_chain;
+
while (bio) {
struct page *page;

@@ -98,6 +99,6 @@ int hib_wait_on_bio_chain(struct bio **bio_chain)
bio_put(bio);
bio = next_bio;
}
- *bio_chain = NULL;
+ bio_chain = NULL;
return ret;
}
diff --git a/kernel/power/power.h b/kernel/power/power.h
index 006270f..9a046cd 100644
--- a/kernel/power/power.h
+++ b/kernel/power/power.h
@@ -145,11 +145,9 @@ extern void swsusp_close(fmode_t);
/* kernel/power/block_io.c */
extern struct block_device *hib_resume_bdev;

-extern int hib_bio_read_page(pgoff_t page_off, void *addr,
- struct bio **bio_chain);
-extern int hib_bio_write_page(pgoff_t page_off, void *addr,
- struct bio **bio_chain);
-extern int hib_wait_on_bio_chain(struct bio **bio_chain);
+extern int hib_bio_read_page(pgoff_t page_off, void *addr, int sync);
+extern int hib_bio_write_page(pgoff_t page_off, void *addr, int sync);
+extern int hib_wait_on_bio_chain(void);

struct timeval;
/* kernel/power/swsusp.c */
diff --git a/kernel/power/swap.c b/kernel/power/swap.c
index a038755..45f89dc 100644
--- a/kernel/power/swap.c
+++ b/kernel/power/swap.c
@@ -177,7 +177,7 @@ static int mark_swapfiles(unsigned int flags)
{
int error;

- hib_bio_read_page(swsusp_resume_block, swsusp_header, NULL);
+ hib_bio_read_page(swsusp_resume_block, swsusp_header, 1);
if (!memcmp("SWAP-SPACE",swsusp_header->sig, 10) ||
!memcmp("SWAPSPACE2",swsusp_header->sig, 10)) {
memcpy(swsusp_header->orig_sig,swsusp_header->sig, 10);
@@ -185,7 +185,7 @@ static int mark_swapfiles(unsigned int flags)
swsusp_header->image = handle.first_sector;
swsusp_header->flags = flags;
error = hib_bio_write_page(swsusp_resume_block,
- swsusp_header, NULL);
+ swsusp_header, 1);
} else {
printk(KERN_ERR "PM: Swap header not found!\n");
error = -ENODEV;
@@ -224,29 +224,29 @@ static int swsusp_swap_check(void)
* write_page - Write one page to given swap location.
* @buf: Address we're writing.
* @offset: Offset of the swap page we're writing to.
- * @bio_chain: Link the next write BIO here
+ * @sync: Whether to force synchronous i/o.
*/

-static int write_page(void *buf, sector_t offset, struct bio **bio_chain)
+static int write_page(void *buf, sector_t offset, int sync)
{
void *src;

if (!offset)
return -ENOSPC;

- if (bio_chain) {
+ if (!sync) {
src = (void *)__get_free_page(__GFP_WAIT | __GFP_HIGH);
if (src) {
memcpy(src, buf, PAGE_SIZE);
} else {
WARN_ON_ONCE(1);
- bio_chain = NULL; /* Go synchronous */
+ sync = 1; /* Go synchronous */
src = buf;
}
} else {
src = buf;
}
- return hib_bio_write_page(offset, src, bio_chain);
+ return hib_bio_write_page(offset, src, sync);
}

static void release_swap_writer(void)
@@ -292,7 +292,7 @@ err_close:
return ret;
}

-static int swap_write_page(void *buf, struct bio **bio_chain)
+static int swap_write_page(void *buf, int sync)
{
int error = 0;
sector_t offset;
@@ -300,19 +300,19 @@ static int swap_write_page(void *buf, struct bio **bio_chain)
if (!handle.cur)
return -EINVAL;
offset = hib_extent_next(&sector_extents);
- error = write_page(buf, offset, bio_chain);
+ error = write_page(buf, offset, sync);
if (error)
return error;
handle.cur->entries[handle.k++] = offset;
if (handle.k >= MAP_PAGE_ENTRIES) {
- error = hib_wait_on_bio_chain(bio_chain);
+ error = hib_wait_on_bio_chain();
if (error)
goto out;
offset = hib_extent_next(&sector_extents);
if (!offset)
return -ENOSPC;
handle.cur->next_swap = offset;
- error = write_page(handle.cur, handle.cur_swap, NULL);
+ error = write_page(handle.cur, handle.cur_swap, 1);
if (error)
goto out;
memset(handle.cur, 0, PAGE_SIZE);
@@ -326,7 +326,7 @@ static int swap_write_page(void *buf, struct bio **bio_chain)
static int flush_swap_writer(void)
{
if (handle.cur && handle.cur_swap)
- return write_page(handle.cur, handle.cur_swap, NULL);
+ return write_page(handle.cur, handle.cur_swap, 1);
else
return -EINVAL;
}
@@ -359,7 +359,6 @@ static int save_image(struct snapshot_handle *snapshot,
int ret;
int nr_pages;
int err2;
- struct bio *bio;
struct timeval start;
struct timeval stop;

@@ -369,20 +368,19 @@ static int save_image(struct snapshot_handle *snapshot,
if (!m)
m = 1;
nr_pages = 0;
- bio = NULL;
do_gettimeofday(&start);
while (1) {
ret = snapshot_read_next(snapshot);
if (ret <= 0)
break;
- ret = swap_write_page(data_of(*snapshot), &bio);
+ ret = swap_write_page(data_of(*snapshot), 0);
if (ret)
break;
if (!(nr_pages % m))
printk(KERN_CONT "\b\b\b\b%3d%%", nr_pages / m);
nr_pages++;
}
- err2 = hib_wait_on_bio_chain(&bio);
+ err2 = hib_wait_on_bio_chain();
do_gettimeofday(&stop);
if (!ret)
ret = err2;
@@ -426,7 +424,7 @@ int swsusp_write(unsigned int flags)
goto out_finish;
}
header = (struct swsusp_info *)data_of(snapshot);
- error = swap_write_page(header, NULL);
+ error = swap_write_page(header, 1);
if (!error)
error = save_image(&snapshot, pages - 1);
out_finish:
@@ -459,7 +457,7 @@ static int get_swap_reader(unsigned int *flags_p)
if (!handle.cur)
return -ENOMEM;

- error = hib_bio_read_page(swsusp_header->image, handle.cur, NULL);
+ error = hib_bio_read_page(swsusp_header->image, handle.cur, 1);
if (error) {
release_swap_reader();
return error;
@@ -468,7 +466,7 @@ static int get_swap_reader(unsigned int *flags_p)
return 0;
}

-static int swap_read_page(void *buf, struct bio **bio_chain)
+static int swap_read_page(void *buf, int sync)
{
sector_t offset;
int error;
@@ -478,17 +476,17 @@ static int swap_read_page(void *buf, struct bio **bio_chain)
offset = handle.cur->entries[handle.k];
if (!offset)
return -EFAULT;
- error = hib_bio_read_page(offset, buf, bio_chain);
+ error = hib_bio_read_page(offset, buf, sync);
if (error)
return error;
if (++handle.k >= MAP_PAGE_ENTRIES) {
- error = hib_wait_on_bio_chain(bio_chain);
+ error = hib_wait_on_bio_chain();
handle.k = 0;
offset = handle.cur->next_swap;
if (!offset)
release_swap_reader();
else if (!error)
- error = hib_bio_read_page(offset, handle.cur, NULL);
+ error = hib_bio_read_page(offset, handle.cur, 1);
}
return error;
}
@@ -512,7 +510,6 @@ static int load_image(struct snapshot_handle *snapshot, unsigned int nr_to_read)
int error = 0;
struct timeval start;
struct timeval stop;
- struct bio *bio;
int err2;
unsigned nr_pages;

@@ -522,24 +519,23 @@ static int load_image(struct snapshot_handle *snapshot, unsigned int nr_to_read)
if (!m)
m = 1;
nr_pages = 0;
- bio = NULL;
do_gettimeofday(&start);
for ( ; ; ) {
error = snapshot_write_next(snapshot);
if (error <= 0)
break;
- error = swap_read_page(data_of(*snapshot), &bio);
+ error = swap_read_page(data_of(*snapshot), 0);
if (error)
break;
if (snapshot->sync_read)
- error = hib_wait_on_bio_chain(&bio);
+ error = hib_wait_on_bio_chain();
if (error)
break;
if (!(nr_pages % m))
printk("\b\b\b\b%3d%%", nr_pages / m);
nr_pages++;
}
- err2 = hib_wait_on_bio_chain(&bio);
+ err2 = hib_wait_on_bio_chain();
do_gettimeofday(&stop);
if (!error)
error = err2;
@@ -575,7 +571,7 @@ int swsusp_read(unsigned int *flags_p)
if (error)
goto end;
if (!error)
- error = swap_read_page(header, NULL);
+ error = swap_read_page(header, 1);
if (!error)
error = load_image(&snapshot, header->pages - 1);
swap_reader_finish();
@@ -600,7 +596,7 @@ int swsusp_check(void)
set_blocksize(hib_resume_bdev, PAGE_SIZE);
memset(swsusp_header, 0, PAGE_SIZE);
error = hib_bio_read_page(swsusp_resume_block,
- swsusp_header, NULL);
+ swsusp_header, 1);
if (error)
goto put;

@@ -608,7 +604,7 @@ int swsusp_check(void)
memcpy(swsusp_header->sig, swsusp_header->orig_sig, 10);
/* Reset swap signature now */
error = hib_bio_write_page(swsusp_resume_block,
- swsusp_header, NULL);
+ swsusp_header, 1);
} else {
error = -EINVAL;
}
--
1.7.0.4

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/