Add functions that can be used for coalescing and splitting buffers that are smaller than PAGE_SIZE. These functions provide no method of determining where the boundaries of the smaller buffers are to be found - that is the caller's problem. Signed-off-by: Nigel Cunningham <nigel@xxxxxxxxxxxx> --- kernel/power/block_io.c | 90 +++++++++++++++++++++++++++++++++++++++++++++++ kernel/power/block_io.h | 4 ++ 2 files changed, 94 insertions(+), 0 deletions(-) diff --git a/kernel/power/block_io.c b/kernel/power/block_io.c index 5edcb08..bf6129b 100644 --- a/kernel/power/block_io.c +++ b/kernel/power/block_io.c @@ -17,6 +17,11 @@ 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); + /** * submit - submit BIO request. * @rw: READ or WRITE. @@ -301,3 +306,88 @@ int swap_read_page(void *buf, int sync) } return error; } + +/* Part Page I/O functions */ +static char *hib_ppio_buffer; +static int hib_ppio_buffer_posn; + +int hib_prepare_buffer(void) +{ + hib_ppio_buffer = (char *)__get_free_page(__GFP_WAIT); + hib_ppio_buffer_posn = 0; + return hib_ppio_buffer ? 0 : -ENOMEM; +} + +void hib_free_buffer(void) +{ + if (!hib_ppio_buffer) + return; + + free_page((unsigned long) hib_ppio_buffer); + hib_ppio_buffer = NULL; +} + +int hib_flush_write_buffer(void) +{ + return hib_ppio_buffer_posn ? swap_write_page(hib_ppio_buffer, 0) : 0; +} + +int hib_write_buffer(char *buffer, int buffer_size) +{ + int bytes_left = buffer_size, result = 0; + + while (bytes_left) { + char *from = buffer + buffer_size - bytes_left; + char *to = hib_ppio_buffer + hib_ppio_buffer_posn; + int capacity = PAGE_SIZE - hib_ppio_buffer_posn; + + if (bytes_left <= capacity) { + memcpy(to, from, bytes_left); + hib_ppio_buffer_posn += bytes_left; + return 0; + } + + /* Complete this page and start a new one */ + memcpy(to, from, capacity); + bytes_left -= capacity; + + result = swap_write_page(hib_ppio_buffer, 0); + if (result) + return result; + + hib_ppio_buffer_posn = 0; + } + + return 0; +} + +int hib_read_buffer(char *buffer, int buffer_size) +{ + int bytes_left = buffer_size, result = 0; + + while (bytes_left) { + char *to = buffer + buffer_size - bytes_left; + char *from = hib_ppio_buffer + hib_ppio_buffer_posn; + int capacity = PAGE_SIZE - hib_ppio_buffer_posn; + + if (bytes_left <= capacity) { + memcpy(to, from, bytes_left); + hib_ppio_buffer_posn += bytes_left; + return 0; + } + + /* Complete this page and start a new one */ + memcpy(to, from, capacity); + bytes_left -= capacity; + + result = swap_read_page(hib_ppio_buffer, 1); + if (result) { + printk("swap_read_page returned %d.\n", result); + return result; + } + + hib_ppio_buffer_posn = 0; + } + + return 0; +} diff --git a/kernel/power/block_io.h b/kernel/power/block_io.h index 2f91d6d..ac378c5 100644 --- a/kernel/power/block_io.h +++ b/kernel/power/block_io.h @@ -21,3 +21,7 @@ int swap_write_page(void *buf, int sync); int get_swap_reader(unsigned int *flags_p, sector_t first_page); void release_swap_reader(void); int swap_read_page(void *buf, int sync); +int hib_flush_write_buffer(void); + +int hib_write_buffer(char *buffer, int len); +int hib_read_buffer(char *buffer, int len); -- 1.7.0.4 _______________________________________________ linux-pm mailing list linux-pm@xxxxxxxxxxxxxxxxxxxxxxxxxx https://lists.linux-foundation.org/mailman/listinfo/linux-pm