diff options
author | 2013-11-05 06:02:44 +0000 | |
---|---|---|
committer | 2013-11-05 06:02:44 +0000 | |
commit | 73ac9b723569e28f6fc1f2fad8cc2131745ff17b (patch) | |
tree | ba7c05e430d0284e7cb3ed5aabe9757f7c5a962f | |
parent | Mention the TX checksum offload support. (diff) | |
download | wireguard-openbsd-73ac9b723569e28f6fc1f2fad8cc2131745ff17b.tar.xz wireguard-openbsd-73ac9b723569e28f6fc1f2fad8cc2131745ff17b.zip |
new function uvm_hibswap() finds a the largest free zone in swap, which
hibernate can use place the data.
ok mlarkin
-rw-r--r-- | sys/kern/subr_hibernate.c | 36 | ||||
-rw-r--r-- | sys/uvm/uvm_swap.c | 53 | ||||
-rw-r--r-- | sys/uvm/uvm_swap.h | 4 |
3 files changed, 50 insertions, 43 deletions
diff --git a/sys/kern/subr_hibernate.c b/sys/kern/subr_hibernate.c index bab98e515f5..703934159b4 100644 --- a/sys/kern/subr_hibernate.c +++ b/sys/kern/subr_hibernate.c @@ -1,4 +1,4 @@ -/* $OpenBSD: subr_hibernate.c,v 1.67 2013/11/05 00:51:58 krw Exp $ */ +/* $OpenBSD: subr_hibernate.c,v 1.68 2013/11/05 06:02:44 deraadt Exp $ */ /* * Copyright (c) 2011 Ariane van der Steldt <ariane@stack.nl> @@ -728,12 +728,6 @@ get_hibernate_info(union hibernate_info *hiber_info, int suspend) if (get_hibernate_info_md(hiber_info)) goto fail; - /* Calculate memory image location in swap */ - hiber_info->image_offset = DL_GETPOFFSET(&dl.d_partitions[1]) + - DL_GETPSIZE(&dl.d_partitions[1]) - - (hiber_info->image_size / hiber_info->secsize) - - sizeof(union hibernate_info)/hiber_info->secsize - - chunktable_size; return (0); fail: @@ -1208,8 +1202,6 @@ hibernate_resume(void) hibernate_quiesce_cpus(); #endif /* MULTIPROCESSOR */ - printf("Unhibernating..."); - /* Read the image from disk into the image (pig) area */ if (hibernate_read_image(&disk_hiber_info)) goto fail; @@ -1671,7 +1663,9 @@ hibernate_read_image(union hibernate_info *hiber_info) disk_size = compressed_size; - printf(" (image size: %zu)\n", compressed_size); + printf("unhibernating @ block %lld length %lu blocks\n", + hiber_info->sig_offset - chunktable_size, + compressed_size); /* Allocate the pig area */ pig_sz = compressed_size + HIBERNATE_CHUNK_SIZE; @@ -1927,7 +1921,7 @@ int hibernate_suspend(void) { union hibernate_info hib_info; - size_t swap_size; + u_long start, end; /* * Calculate memory ranges, swap offsets, etc. @@ -1939,14 +1933,26 @@ hibernate_suspend(void) return (1); } - swap_size = hib_info.image_size + hib_info.secsize + - HIBERNATE_CHUNK_TABLE_SIZE; + /* Find a page-addressed region in swap [start,end] */ + if (uvm_hibswap(hib_info.device, &start, &end)) { + printf("cannot find any swap\n"); + return (1); + } - if (uvm_swap_check_range(hib_info.device, swap_size)) { - printf("insufficient swap space for hibernate\n"); + if (end - start < 1000) { + printf("%lu\n is too small", end - start); return (1); } + /* Calculate block offsets in swap */ + hib_info.image_offset = ctod(start) + hib_info.swap_offset; + +#if 0 + /* XXX side effect */ + printf("hibernate @ block %lld max-length %lu blocks\n", + hib_info.image_offset, ctod(end) - ctod(start)); +#endif + pmap_kenter_pa(HIBERNATE_HIBALLOC_PAGE, HIBERNATE_HIBALLOC_PAGE, VM_PROT_ALL); pmap_activate(curproc); diff --git a/sys/uvm/uvm_swap.c b/sys/uvm/uvm_swap.c index 75362c5aaca..348a0a3623f 100644 --- a/sys/uvm/uvm_swap.c +++ b/sys/uvm/uvm_swap.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uvm_swap.c,v 1.119 2013/11/04 19:42:47 deraadt Exp $ */ +/* $OpenBSD: uvm_swap.c,v 1.120 2013/11/05 06:02:45 deraadt Exp $ */ /* $NetBSD: uvm_swap.c,v 1.40 2000/11/17 11:39:39 mrg Exp $ */ /* @@ -2024,21 +2024,16 @@ gotit: } #ifdef HIBERNATE -/* - * Check if free swap available at end of swap dev swdev. - * Used by hibernate to check for usable swap area before writing the image - */ int -uvm_swap_check_range(dev_t swdev, size_t size) +uvm_hibswap(dev_t dev, u_long *sp, u_long *ep) { struct swapdev *sdp, *swd = NULL; struct swappri *spp; - struct extent *ex; - struct extent_region *exr; - int r = 0, start, npages = size / PAGE_SIZE; + struct extent_region *exr, *exrn; + u_long start = 0, end = 0, size = 0; /* no swap devices configured yet? */ - if (uvmexp.nswapdev < 1) + if (uvmexp.nswapdev < 1 || dev != swdevt[0].sw_dev) return (1); for (spp = LIST_FIRST(&swap_priority); spp != NULL; @@ -2046,28 +2041,34 @@ uvm_swap_check_range(dev_t swdev, size_t size) for (sdp = CIRCLEQ_FIRST(&spp->spi_swapdev); sdp != (void *)&spp->spi_swapdev; sdp = CIRCLEQ_NEXT(sdp,swd_next)) { - if (sdp->swd_dev == swdev) + if (sdp->swd_dev == dev) swd = sdp; } - if (swd == NULL) - return (1); - - if ((swd->swd_flags & SWF_ENABLE) == 0) + if (swd == NULL || (swd->swd_flags & SWF_ENABLE) == 0) return (1); - ex = swd->swd_ex; - start = swd->swd_drumsize-npages; - - if (npages > swd->swd_drumsize) - return (1); - - LIST_FOREACH(exr, &ex->ex_regions, er_link) - { - if (exr->er_end >= start) - r = 1; + LIST_FOREACH(exr, &swd->swd_ex->ex_regions, er_link) { + u_long gapstart, gapend, gapsize; + + gapstart = exr->er_end + 1; + exrn = LIST_NEXT(exr, er_link); + if (!exrn) + break; + gapend = exrn->er_start - 1; + gapsize = gapend - gapstart; + if (gapsize > size) { + start = gapstart; + end = gapend; + size = gapsize; } + } - return (r); + if (size) { + *sp = start; + *ep = end; + return (0); + } + return (1); } #endif /* HIBERNATE */ diff --git a/sys/uvm/uvm_swap.h b/sys/uvm/uvm_swap.h index 0dbcf23c60f..bd3ff0a1809 100644 --- a/sys/uvm/uvm_swap.h +++ b/sys/uvm/uvm_swap.h @@ -1,4 +1,4 @@ -/* $OpenBSD: uvm_swap.h,v 1.15 2012/07/11 16:00:15 mlarkin Exp $ */ +/* $OpenBSD: uvm_swap.h,v 1.16 2013/11/05 06:02:45 deraadt Exp $ */ /* $NetBSD: uvm_swap.h,v 1.5 2000/01/11 06:57:51 chs Exp $ */ /* @@ -45,7 +45,7 @@ void uvm_swap_free(int, int); void uvm_swap_markbad(int, int); void uvm_swap_freepages(struct vm_page **, int); #ifdef HIBERNATE -int uvm_swap_check_range(dev_t, size_t); +int uvm_hibswap(dev_t, u_long *, u_long *); #endif /* HIBERNATE */ #ifdef UVM_SWAP_ENCRYPT void uvm_swap_initcrypt_all(void); |