diff options
author | Mike Larkin <mlarkin@cvs.openbsd.org> | 2011-11-17 23:18:14 +0000 |
---|---|---|
committer | Mike Larkin <mlarkin@cvs.openbsd.org> | 2011-11-17 23:18:14 +0000 |
commit | 3434462854897626683f8d9e0e67cee703de92f8 (patch) | |
tree | 73ad5a125daceffa6d8191597d82f1157e74697c /sys/kern | |
parent | 18f4e835cc63dad1aebd3cd4ef9f3af307e885ac (diff) |
physmem run length encoding (rle) for hibernate - don't compress or write
pages that are free
Diffstat (limited to 'sys/kern')
-rw-r--r-- | sys/kern/subr_hibernate.c | 93 |
1 files changed, 84 insertions, 9 deletions
diff --git a/sys/kern/subr_hibernate.c b/sys/kern/subr_hibernate.c index a41c647dfd1..6a974501124 100644 --- a/sys/kern/subr_hibernate.c +++ b/sys/kern/subr_hibernate.c @@ -1,4 +1,4 @@ -/* $OpenBSD: subr_hibernate.c,v 1.24 2011/11/16 23:52:27 mlarkin Exp $ */ +/* $OpenBSD: subr_hibernate.c,v 1.25 2011/11/17 23:18:13 mlarkin Exp $ */ /* * Copyright (c) 2011 Ariane van der Steldt <ariane@stack.nl> @@ -711,11 +711,6 @@ hibernate_zlib_free(void *unused, void *addr) * Inflate size bytes from src into dest, skipping any pages in * [src..dest] that are special (see hibernate_inflate_skip) * - * For each page of output data, we map HIBERNATE_TEMP_PAGE - * to the current output page, and tell inflate() to inflate - * its data there, resulting in the inflated data being placed - * at the proper paddr. - * * This function executes while using the resume-time stack * and pmap, and therefore cannot use ddb/printf/etc. Doing so * will likely hang or reset the machine. @@ -725,6 +720,7 @@ hibernate_inflate(union hibernate_info *hiber_info, paddr_t dest, paddr_t src, size_t size) { int i; + psize_t rle; hibernate_state->hib_stream.avail_in = size; hibernate_state->hib_stream.next_in = (char *)src; @@ -745,6 +741,38 @@ hibernate_inflate(union hibernate_info *hiber_info, paddr_t dest, hibernate_enter_resume_mapping( HIBERNATE_INFLATE_PAGE, dest, 0); + /* Read RLE code */ + hibernate_state->hib_stream.avail_out = sizeof(psize_t); + hibernate_state->hib_stream.next_out = (char *)&rle; + + i = inflate(&hibernate_state->hib_stream, Z_FULL_FLUSH); + if (i != Z_OK && i != Z_STREAM_END) { + /* + * XXX - this will likely reboot/hang most machines, + * but there's not much else we can do here. + */ + panic("inflate rle error"); + } + + /* Skip while RLE code is != 0 */ + while (rle != 0) { + dest += (rle * PAGE_SIZE); + hibernate_state->hib_stream.avail_out = + sizeof(psize_t); + hibernate_state->hib_stream.next_out = (char *)&rle; + + i = inflate(&hibernate_state->hib_stream, + Z_FULL_FLUSH); + if (i != Z_OK && i != Z_STREAM_END) { + /* + * XXX - this will likely reboot/hang most + * machines but there's not much else + * we can do here. + */ + panic("inflate rle error 2"); + } + } + /* Set up the stream for inflate */ hibernate_state->hib_stream.avail_out = PAGE_SIZE; hibernate_state->hib_stream.next_out = @@ -1153,6 +1181,7 @@ hibernate_write_chunks(union hibernate_info *hiber_info) vaddr_t hibernate_io_page = hiber_info->piglet_va + PAGE_SIZE; daddr_t blkctr = hiber_info->image_offset; int i; + psize_t rle; hiber_info->chunk_ctr = 0; @@ -1237,9 +1266,55 @@ hibernate_write_chunks(union hibernate_info *hiber_info) temp_inaddr = (inaddr & PAGE_MASK) + hibernate_copy_page; + rle = uvm_page_rle(inaddr); + while (rle > 0 && inaddr < range_end) { + hibernate_state->hib_stream.avail_in = + sizeof(psize_t); + hibernate_state->hib_stream.avail_out = + out_remaining; + hibernate_state->hib_stream.next_in = + (char *)&rle; + hibernate_state->hib_stream.next_out = + (caddr_t)hibernate_io_page + + (PAGE_SIZE - out_remaining); + + if (deflate(&hibernate_state->hib_stream, + Z_PARTIAL_FLUSH) != Z_OK) + return (1); + + out_remaining = + hibernate_state->hib_stream.avail_out; + inaddr += (rle * PAGE_SIZE); + if (inaddr > range_end) + inaddr = range_end; + else + rle = uvm_page_rle(inaddr); + } + + /* Write '0' RLE code */ + if (inaddr < range_end) { + hibernate_state->hib_stream.avail_in = + sizeof(psize_t); + hibernate_state->hib_stream.avail_out = + out_remaining; + hibernate_state->hib_stream.next_in = + (char *)&rle; + hibernate_state->hib_stream.next_out = + (caddr_t)hibernate_io_page + + (PAGE_SIZE - out_remaining); + + if (deflate(&hibernate_state->hib_stream, + Z_PARTIAL_FLUSH) != Z_OK) + return (1); + + out_remaining = + hibernate_state->hib_stream.avail_out; + } + /* Deflate from temp_inaddr to IO page */ - inaddr += hibernate_deflate(hiber_info, - temp_inaddr, &out_remaining); + if (inaddr != range_end) + inaddr += hibernate_deflate(hiber_info, + temp_inaddr, &out_remaining); } if (out_remaining == 0) { @@ -1334,7 +1409,7 @@ hibernate_zlib_reset(union hibernate_info *hiber_info, int deflate) if (deflate) { return deflateInit(&hibernate_state->hib_stream, - Z_DEFAULT_COMPRESSION); + Z_BEST_SPEED); } else return inflateInit(&hibernate_state->hib_stream); } |