Clean up upon completion of the I/O for a page.
Signed-off-by: Nigel Cunningham <[email protected]>
kernel/power/suspend_block_io.c | 96 +++++++++++++++++++++++++++++++++++++++
1 files changed, 96 insertions(+), 0 deletions(-)
diff --git a/kernel/power/suspend_block_io.c b/kernel/power/suspend_block_io.c
index 09682c4..037535b 100644
--- a/kernel/power/suspend_block_io.c
+++ b/kernel/power/suspend_block_io.c
@@ -179,3 +179,99 @@ static void suspend_check_io_stats(void)
nr_schedule_calls[i]);
}
+/*
+ * __suspend_bio_cleanup_one
+ *
+ * Description: Clean up after completing I/O on a page.
+ * Arguments: struct io_info: Data for I/O to be completed.
+ */
+static void __suspend_bio_cleanup_one(struct io_info *io_info)
+{
+ struct page *buffer_page;
+ struct page *data_page;
+ char *buffer_address, *data_address;
+ int reading;
+
+ buffer_page = io_info->buffer_page;
+ data_page = io_info->data_page;
+
+ reading = test_bit(IO_AWAITING_READ, &io_info->flags);
+ suspend_message(SUSPEND_WRITER, SUSPEND_HIGH, 0,
+ "Cleanup IO: [%p]\n",
+ io_info);
+
+ if (reading && io_info->readahead_index == -1) {
+ /*
+ * Copy the page we read into the buffer our caller provided.
+ */
+ data_address = (char *) kmap(data_page);
+ buffer_address = (char *) kmap(buffer_page);
+ memcpy(data_address, buffer_address, PAGE_SIZE);
+ kunmap(data_page);
+ kunmap(buffer_page);
+
+ }
+
+ if (!reading || io_info->readahead_index == -1) {
+ /* Sanity check */
+ if (page_count(buffer_page) != 2)
+ printk(KERN_EMERG "Cleanup IO: Page count on page %p"
+ " is %d. Not good!\n",
+ buffer_page, page_count(buffer_page));
+ put_page(buffer_page);
+ __free_page(buffer_page);
+ atomic_inc(&buffer_frees);
+ } else
+ put_page(buffer_page);
+
+ bio_put(io_info->sys_struct);
+ io_info->sys_struct = NULL;
+ io_info->flags = 0;
+}
+
+/* suspend_bio_cleanup_one
+ */
+
+static int suspend_bio_cleanup_one(void *data)
+{
+ struct io_info *io_info = (struct io_info *) data;
+ int readahead_index;
+ unsigned long flags;
+
+ /*
+ * If this I/O was a readahead, remember its index.
+ */
+ readahead_index = io_info->readahead_index;
+
+ /*
+ * Add it to the free list.
+ */
+ list_del_init(&io_info->list);
+
+ /*
+ * Do the cleanup.
+ */
+ __suspend_bio_cleanup_one(io_info);
+
+ /*
+ * Record the readahead as done.
+ */
+ if (readahead_index > -1) {
+ int index = readahead_index/BITS_PER_LONG;
+ int bit = readahead_index - (index * BITS_PER_LONG);
+ spin_lock_irqsave(&suspend_readahead_flags_lock, flags);
+ set_bit(bit, &suspend_readahead_flags[index]);
+ spin_unlock_irqrestore(&suspend_readahead_flags_lock, flags);
+ }
+
+ spin_lock_irqsave(&ioinfo_free_lock, flags);
+ list_add_tail(&io_info->list, &ioinfo_free);
+ spin_unlock_irqrestore(&ioinfo_free_lock, flags);
+
+ /* Important: Must be last thing we do to avoid a race with
+ * finish_all_io when using keventd to do the cleanup */
+ atomic_dec(&outstanding_io);
+
+ return 0;
+}
+
--
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 [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[Index of Archives]
[Kernel Newbies]
[Netfilter]
[Bugtraq]
[Photo]
[Stuff]
[Gimp]
[Yosemite News]
[MIPS Linux]
[ARM Linux]
[Linux Security]
[Linux RAID]
[Video 4 Linux]
[Linux for the blind]
[Linux Resources]