summaryrefslogtreecommitdiffstats
path: root/sys/kern/subr_hibernate.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/kern/subr_hibernate.c')
-rw-r--r--sys/kern/subr_hibernate.c89
1 files changed, 56 insertions, 33 deletions
diff --git a/sys/kern/subr_hibernate.c b/sys/kern/subr_hibernate.c
index 61cec64182f..3ec92ad6782 100644
--- a/sys/kern/subr_hibernate.c
+++ b/sys/kern/subr_hibernate.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: subr_hibernate.c,v 1.60 2013/09/29 15:47:35 mlarkin Exp $ */
+/* $OpenBSD: subr_hibernate.c,v 1.61 2013/10/03 03:51:16 mlarkin Exp $ */
/*
* Copyright (c) 2011 Ariane van der Steldt <ariane@stack.nl>
@@ -67,6 +67,16 @@ union hibernate_info disk_hiber_info;
paddr_t global_pig_start;
vaddr_t global_piglet_va;
+/* #define HIB_DEBUG */
+#ifdef HIB_DEBUG
+int hib_debug = 99;
+#define DPRINTF(x...) do { if (hib_debug) printf(x); } while (0)
+#define DNPRINTF(n,x...) do { if (hib_debug > (n)) printf(x); } while (0)
+#else
+#define DPRINTF(x...)
+#define DNPRINTF(n,x...)
+#endif
+
void hibernate_copy_chunk_to_piglet(paddr_t, vaddr_t, size_t);
/*
@@ -950,7 +960,7 @@ hibernate_write_chunktable(union hibernate_info *hiber_info)
vaddr_t hibernate_chunk_table_start;
size_t hibernate_chunk_table_size;
daddr_t chunkbase;
- int i;
+ int i, err;
hibernate_chunk_table_size = HIBERNATE_CHUNK_TABLE_SIZE;
@@ -965,11 +975,13 @@ hibernate_write_chunktable(union hibernate_info *hiber_info)
/* Write chunk table */
for (i = 0; i < hibernate_chunk_table_size; i += MAXPHYS) {
- if (hiber_info->io_func(hiber_info->device,
+ if ((err = hiber_info->io_func(hiber_info->device,
chunkbase + (i/hiber_info->secsize),
(vaddr_t)(hibernate_chunk_table_start + i),
- MAXPHYS, HIB_W, hiber_info->io_page))
+ MAXPHYS, HIB_W, hiber_info->io_page))) {
+ DPRINTF("chunktable write error: %d\n", err);
return (EIO);
+ }
}
return (0);
@@ -993,10 +1005,8 @@ hibernate_clear_signature(void)
return (1);
/* Write (zeroed) hibernate info to disk */
-#ifdef HIBERNATE_DEBUG
- printf("clearing hibernate signature block location: %lld\n",
+ DPRINTF("clearing hibernate signature block location: %lld\n",
hiber_info.sig_offset - hiber_info.swap_offset);
-#endif /* HIBERNATE_DEBUG */
if (hibernate_block_io(&hiber_info,
hiber_info.sig_offset - hiber_info.swap_offset,
hiber_info.secsize, (vaddr_t)&blank_hiber_info, 1))
@@ -1047,27 +1057,21 @@ hibernate_compare_signature(union hibernate_info *mine,
u_int i;
if (mine->nranges != disk->nranges) {
-#ifdef HIBERNATE_DEBUG
- printf("hibernate memory range count mismatch\n");
-#endif
+ DPRINTF("hibernate memory range count mismatch\n");
return (1);
}
if (strcmp(mine->kernel_version, disk->kernel_version) != 0) {
-#ifdef HIBERNATE_DEBUG
- printf("hibernate kernel version mismatch\n");
-#endif
+ DPRINTF("hibernate kernel version mismatch\n");
return (1);
}
for (i = 0; i < mine->nranges; i++) {
if ((mine->ranges[i].base != disk->ranges[i].base) ||
(mine->ranges[i].end != disk->ranges[i].end) ) {
-#ifdef HIBERNATE_DEBUG
- printf("hib range %d mismatch [%p-%p != %p-%p]\n",
+ DPRINTF("hib range %d mismatch [%p-%p != %p-%p]\n",
i, mine->ranges[i].base, mine->ranges[i].end,
disk->ranges[i].base, disk->ranges[i].end);
-#endif
return (1);
}
}
@@ -1158,10 +1162,8 @@ hibernate_resume(void)
/* Read hibernate info from disk */
s = splbio();
-#ifdef HIBERNATE_DEBUG
- printf("reading hibernate signature block location: %lld\n",
+ DPRINTF("reading hibernate signature block location: %lld\n",
hiber_info.sig_offset - hiber_info.swap_offset);
-#endif /* HIBERNATE_DEBUG */
if (hibernate_block_io(&hiber_info,
hiber_info.sig_offset - hiber_info.swap_offset,
@@ -1379,7 +1381,7 @@ hibernate_write_chunks(union hibernate_info *hiber_info)
struct hibernate_disk_chunk *chunks;
vaddr_t hibernate_io_page = hiber_info->piglet_va + PAGE_SIZE;
daddr_t blkctr = hiber_info->image_offset, offset = 0;
- int i;
+ int i, err;
struct hibernate_zlib_state *hibernate_state;
hibernate_state =
@@ -1400,8 +1402,10 @@ hibernate_write_chunks(union hibernate_info *hiber_info)
hibernate_copy_page = (vaddr_t)km_alloc(PAGE_SIZE, &kv_any,
&kp_none, &kd_nowait);
- if (!hibernate_copy_page)
+ if (!hibernate_copy_page) {
+ DPRINTF("out of memory allocating hibernate_copy_page\n");
return (ENOMEM);
+ }
pmap_kenter_pa(hibernate_copy_page,
(hiber_info->piglet_pa + 3*PAGE_SIZE), VM_PROT_ALL);
@@ -1439,8 +1443,10 @@ hibernate_write_chunks(union hibernate_info *hiber_info)
chunks[i].offset = blkctr;
/* Reset zlib for deflate */
- if (hibernate_zlib_reset(hiber_info, 1) != Z_OK)
+ if (hibernate_zlib_reset(hiber_info, 1) != Z_OK) {
+ DPRINTF("hibernate_zlib_reset failed for deflate\n");
return (ENOMEM);
+ }
inaddr = range_base;
@@ -1480,20 +1486,25 @@ hibernate_write_chunks(union hibernate_info *hiber_info)
nblocks =
PAGE_SIZE / hiber_info->secsize;
- if (hiber_info->io_func(
+ if ((err = hiber_info->io_func(
hiber_info->device,
blkctr, (vaddr_t)hibernate_io_page,
PAGE_SIZE, HIB_W,
- hiber_info->io_page))
+ hiber_info->io_page))) {
+ DPRINTF("hib write error %d\n",
+ err);
return (EIO);
+ }
blkctr += nblocks;
}
}
}
- if (inaddr != range_end)
+ if (inaddr != range_end) {
+ DPRINTF("deflate range ended prematurely\n");
return (EINVAL);
+ }
/*
* End of range. Round up to next secsize bytes
@@ -1509,9 +1520,11 @@ hibernate_write_chunks(union hibernate_info *hiber_info)
(caddr_t)hibernate_io_page + (PAGE_SIZE - out_remaining);
hibernate_state->hib_stream.avail_out = out_remaining;
- if (deflate(&hibernate_state->hib_stream, Z_FINISH) !=
- Z_STREAM_END)
+ if ((err = deflate(&hibernate_state->hib_stream, Z_FINISH)) !=
+ Z_STREAM_END) {
+ DPRINTF("deflate error in output stream: %d\n", err);
return (EIO);
+ }
out_remaining = hibernate_state->hib_stream.avail_out;
@@ -1523,10 +1536,12 @@ hibernate_write_chunks(union hibernate_info *hiber_info)
nblocks ++;
/* Write final block(s) for this chunk */
- if (hiber_info->io_func(hiber_info->device, blkctr,
+ if ((err = hiber_info->io_func(hiber_info->device, blkctr,
(vaddr_t)hibernate_io_page, nblocks*hiber_info->secsize,
- HIB_W, hiber_info->io_page))
+ HIB_W, hiber_info->io_page))) {
+ DPRINTF("hib final write error %d\n", err);
return (EIO);
+ }
blkctr += nblocks;
@@ -1901,8 +1916,10 @@ hibernate_suspend(void)
* This also allocates a piglet whose physaddr is stored in
* hib_info->piglet_pa and vaddr stored in hib_info->piglet_va
*/
- if (get_hibernate_info(&hib_info, 1))
+ if (get_hibernate_info(&hib_info, 1)) {
+ DPRINTF("failed to obtain hibernate info\n");
return (1);
+ }
swap_size = hib_info.image_size + hib_info.secsize +
HIBERNATE_CHUNK_TABLE_SIZE;
@@ -1919,14 +1936,20 @@ hibernate_suspend(void)
/* Stash the piglet VA so we can free it in the resuming kernel */
global_piglet_va = hib_info.piglet_va;
- if (hibernate_write_chunks(&hib_info))
+ if (hibernate_write_chunks(&hib_info)) {
+ DPRINTF("hibernate_write_chunks failed\n");
return (1);
+ }
- if (hibernate_write_chunktable(&hib_info))
+ if (hibernate_write_chunktable(&hib_info)) {
+ DPRINTF("hibernate_write_chunktable failed\n");
return (1);
+ }
- if (hibernate_write_signature(&hib_info))
+ if (hibernate_write_signature(&hib_info)) {
+ DPRINTF("hibernate_write_signature failed\n");
return (1);
+ }
/* Allow the disk to settle */
delay(500000);