[Suspend2][ 18/32] [Suspend2] Prepare to do i/o on a page.

From: Nigel Cunningham
Date: Mon Jun 26 2006 - 19:14:49 EST


Prepare to do i/o on a page, either directly submitting the resulting
io_info struct, or adding it to a batch.

Signed-off-by: Nigel Cunningham <nigel@xxxxxxxxxxxx>

kernel/power/suspend_block_io.c | 90 +++++++++++++++++++++++++++++++++++++++
1 files changed, 90 insertions(+), 0 deletions(-)

diff --git a/kernel/power/suspend_block_io.c b/kernel/power/suspend_block_io.c
index 48a2d09..0d01483 100644
--- a/kernel/power/suspend_block_io.c
+++ b/kernel/power/suspend_block_io.c
@@ -632,3 +632,93 @@ static struct io_info *get_io_info_struc
return this;
}

+/*
+ * start_one
+ *
+ * Description: Prepare and start a read or write operation.
+ * Note that we use our own buffer for reading or writing.
+ * This simplifies doing readahead and asynchronous writing.
+ * We can begin a read without knowing the location into which
+ * the data will eventually be placed, and the buffer passed
+ * for a write can be reused immediately (essential for the
+ * modules system).
+ * Failure? What's that?
+ * Returns: The io_info struct created.
+ */
+static struct io_info *start_one(int rw, struct submit_params *submit_info)
+{
+ struct io_info *io_info = get_io_info_struct();
+ unsigned long buffer_virt = 0;
+ char *to, *from;
+ struct page *buffer_page;
+
+ if (!io_info)
+ return NULL;
+
+ /* Get our local buffer */
+ suspend_message(SUSPEND_WRITER, SUSPEND_HIGH, 1,
+ "Start_IO: [%p]", io_info);
+
+ /* Copy settings to the io_info struct */
+ io_info->data_page = submit_info->page;
+ io_info->readahead_index = submit_info->readahead_index;
+
+ if (io_info->readahead_index == -1) {
+ while (!(buffer_virt = get_zeroed_page(GFP_ATOMIC)))
+ do_bio_wait(5);
+
+ atomic_inc(&buffer_allocs);
+ suspend_message(SUSPEND_WRITER, SUSPEND_HIGH, 0,
+ "[ALLOC BUFFER]->%d",
+ real_nr_free_pages());
+ buffer_page = virt_to_page(buffer_virt);
+
+ io_info->buffer_page = buffer_page;
+ } else {
+ unsigned long flags;
+ int index = io_info->readahead_index / BITS_PER_LONG;
+ int bit = io_info->readahead_index - index * BITS_PER_LONG;
+
+ spin_lock_irqsave(&suspend_readahead_flags_lock, flags);
+ clear_bit(bit, &suspend_readahead_flags[index]);
+ spin_unlock_irqrestore(&suspend_readahead_flags_lock, flags);
+
+ io_info->buffer_page = buffer_page = submit_info->page;
+ }
+
+ /* If writing, copy our data. The data is probably in
+ * lowmem, but we cannot be certain. If there is no
+ * compression/encryption, we might be passed the
+ * actual source page's address. */
+ if (rw == WRITE) {
+ to = (char *) buffer_virt;
+ from = kmap_atomic(io_info->data_page, KM_USER1);
+ memcpy(to, from, PAGE_SIZE);
+ kunmap_atomic(from, KM_USER1);
+ }
+
+ /* Submit the page */
+ get_page(buffer_page);
+
+ io_info->dev = submit_info->dev;
+ io_info->block[0] = submit_info->block[0];
+
+ if (rw == READ)
+ set_bit(IO_AWAITING_READ, &io_info->flags);
+
+ suspend_message(SUSPEND_WRITER, SUSPEND_HIGH, 1,
+ "-> (PRE BRW) %d\n",
+ real_nr_free_pages());
+
+ if (submit_batch_size > 1)
+ add_to_batch(io_info);
+ else
+ submit(rw, io_info);
+
+ atomic_inc(&outstanding_io);
+ if (atomic_read(&outstanding_io) > max_outstanding_io)
+ max_outstanding_io++;
+
+ return io_info;
+}
+

--
Nigel Cunningham nigel at suspend2 dot net
-
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/