From: Nigel Cunningham <nigel@tuxonice.net>
To: "Rafael J. Wysocki" <rjw@sisk.pl>,
Linux PM <linux-pm@lists.linux-foundation.org>,
LKML <linux-kernel@vger.kernel.org>,
TuxOnIce-devel <tuxonice-devel@tuxonice.net>
Subject: [PATCH 16/21] Hibernation: Replace bio chain
Date: Wed, 2 Jun 2010 22:19:15 +1000 [thread overview]
Message-ID: <1275481160-31150-17-git-send-email-nigel@tuxonice.net> (raw)
In-Reply-To: <1275481160-31150-1-git-send-email-nigel@tuxonice.net>
Replace the bio_chain concept with:
(1) simple atomic_t recording how many pages are in flight
(2) a wait queue for waiting for all I/O to complete
(3) a custom completion routine that frees bio structs and pages used
for async writes as they complete, undates the atomic_t and
wakes any waiters.
Signed-off-by: Nigel Cunningham <nigel@tuxonice.net>
---
kernel/power/block_io.c | 77 ++++++++++++++++++++++++++++------------------
1 files changed, 47 insertions(+), 30 deletions(-)
diff --git a/kernel/power/block_io.c b/kernel/power/block_io.c
index 9028f74..c9569e5 100644
--- a/kernel/power/block_io.c
+++ b/kernel/power/block_io.c
@@ -16,23 +16,61 @@
#include "extents.h"
#include "block_io.h"
-static struct bio *bio_chain;
-
static char *hib_ppio_buffer;
static int hib_ppio_buffer_posn;
int hib_prepare_buffer(void);
void hib_free_buffer(void);
+static atomic_t hib_io_in_progress;
+static DECLARE_WAIT_QUEUE_HEAD(num_in_progress_wait);
+
+/**
+ * hib_end_bio - bio completion function.
+ * @bio: bio that has completed.
+ * @err: Error value. Yes, like end_swap_bio_read, we ignore it.
+ *
+ * Function called by the block driver from interrupt context when I/O is
+ * completed. If we were writing the page, we want to free it and will have
+ * set bio->bi_private to the parameter we should use in telling the page
+ * allocation accounting code what the page was allocated for. If we're
+ * reading the page, it will be in the singly linked list made from
+ * page->private pointers.
+ **/
+static void hib_end_bio(struct bio *bio, int err)
+{
+ const int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
+ struct page *page = bio->bi_io_vec[0].bv_page;
+
+ if (!uptodate) {
+ SetPageError(page);
+ ClearPageUptodate(page);
+ printk(KERN_ALERT "I/O on swap-device (%u:%u:%Lu)\n",
+ imajor(bio->bi_bdev->bd_inode),
+ iminor(bio->bi_bdev->bd_inode),
+ (unsigned long long)bio->bi_sector);
+ } else {
+ SetPageUptodate(page);
+ }
+ unlock_page(page);
+ bio_put(bio);
+
+ if (bio->bi_private)
+ __free_page(page);
+
+ atomic_dec(&hib_io_in_progress);
+ wake_up(&num_in_progress_wait);
+}
+
/**
* submit - submit BIO request.
* @rw: READ or WRITE.
* @off physical offset of page.
* @page: page we're reading or writing.
- * @bio_chain: list of pending biod (for async reading)
+ * @sync: whether the i/o should be done synchronously
*
* Straight from the textbook - allocate and initialize the bio.
* If we're reading, make sure the page is marked as dirty.
- * Then submit it and, if @bio_chain == NULL, wait.
+ * Then submit it and, if @sync, wait.
*/
static int submit(int rw, struct block_device *bdev, sector_t sector,
struct page *page, int sync)
@@ -43,7 +81,8 @@ static int submit(int rw, struct block_device *bdev, sector_t sector,
bio = bio_alloc(__GFP_WAIT | __GFP_HIGH, 1);
bio->bi_sector = sector;
bio->bi_bdev = bdev;
- bio->bi_end_io = end_swap_bio_read;
+ bio->bi_private = (void *) (rw && !sync);
+ bio->bi_end_io = hib_end_bio;
if (bio_add_page(bio, page, PAGE_SIZE, 0) < PAGE_SIZE) {
printk(KERN_ERR "PM: Adding page to bio failed at %llu\n",
@@ -54,6 +93,7 @@ static int submit(int rw, struct block_device *bdev, sector_t sector,
lock_page(page);
bio_get(bio);
+ atomic_inc(&hib_io_in_progress);
if (sync) {
submit_bio(bio_rw, bio);
@@ -64,8 +104,6 @@ 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;
submit_bio(bio_rw, bio);
}
return 0;
@@ -85,29 +123,8 @@ int hib_bio_write_page(pgoff_t page_off, void *addr, int sync)
int hib_wait_on_bio_chain(void)
{
- struct bio *bio;
- struct bio *next_bio;
- int ret = 0;
-
- if (bio_chain == NULL)
- return 0;
-
- bio = bio_chain;
-
- while (bio) {
- struct page *page;
-
- next_bio = bio->bi_private;
- page = bio->bi_io_vec[0].bv_page;
- wait_on_page_locked(page);
- if (!PageUptodate(page) || PageError(page))
- ret = -EIO;
- put_page(page);
- bio_put(bio);
- bio = next_bio;
- }
- bio_chain = NULL;
- return ret;
+ wait_event(num_in_progress_wait, !atomic_read(&hib_io_in_progress));
+ return 0;
}
/*
--
1.7.0.4
next prev parent reply other threads:[~2010-06-02 12:20 UTC|newest]
Thread overview: 24+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-06-02 12:18 Nigel's current for-rafael queue Nigel Cunningham
2010-06-02 12:19 ` [PATCH 01/21] Hibernation: Swap iteration functions Nigel Cunningham
2010-06-02 12:19 ` [PATCH 02/21] Hibernation: Move root_swap declaration Nigel Cunningham
2010-06-02 12:19 ` [PATCH 03/21] Hibernation: Add mass swap allocation routine Nigel Cunningham
2010-06-02 12:19 ` [PATCH 04/21] Hibernation: Switch to preallocating swap Nigel Cunningham
2010-06-02 12:19 ` [PATCH 05/21] Hiberation: Fix speed display Nigel Cunningham
2010-06-02 12:19 ` [PATCH 06/21] Hibernation: Generic extents support Nigel Cunningham
2010-06-02 12:19 ` [PATCH 07/21] Hibernation: Iterate over sectors not swap entries Nigel Cunningham
2010-06-02 12:19 ` [PATCH 08/21] Hibernation: Stop passing swap_map_handle struct Nigel Cunningham
2010-06-02 12:19 ` [PATCH 09/21] Hibernation: Stop passing bio_chain around Nigel Cunningham
2010-06-02 12:19 ` [PATCH 10/21] Hibernation: Move block i/o fns to block_io.c Nigel Cunningham
2010-06-02 12:19 ` [PATCH 11/21] Hibernation: Partial page I/O support Nigel Cunningham
2010-06-02 12:19 ` [PATCH 12/21] Hibernation: Extent save/load routines Nigel Cunningham
2010-06-02 12:19 ` [PATCH 13/21] Hibernation: Store block extents at start of image Nigel Cunningham
2010-06-02 12:19 ` [PATCH 14/21] Hibernation: Use block extents for reading image Nigel Cunningham
2010-06-02 12:19 ` [PATCH 15/21] Remove first_sector from swap_map_handle Nigel Cunningham
2010-06-02 12:19 ` Nigel Cunningham [this message]
2010-06-02 12:19 ` [PATCH 17/21] Hibernation: Remove swap_map_pages Nigel Cunningham
2010-06-02 12:19 ` [PATCH 18/21] Hibernation: Remove wait_on_bio_chain result Nigel Cunningham
2010-06-02 12:19 ` [PATCH 19/21] Hibernation: Prepare for handle.cur removal Nigel Cunningham
2010-06-02 12:19 ` [PATCH 20/21] Hibernation: Remove swap_map structure Nigel Cunningham
2010-06-02 12:19 ` [PATCH 21/21] Hibernation: Remove now-empty routines Nigel Cunningham
2010-08-03 6:55 ` Nigel's current for-rafael queue Pavel Machek
2010-08-03 7:00 ` Nigel Cunningham
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1275481160-31150-17-git-send-email-nigel@tuxonice.net \
--to=nigel@tuxonice.net \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-pm@lists.linux-foundation.org \
--cc=rjw@sisk.pl \
--cc=tuxonice-devel@tuxonice.net \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).