diff options
author | 2014-07-12 09:02:24 +0000 | |
---|---|---|
committer | 2014-07-12 09:02:24 +0000 | |
commit | f5db0a1ca2f526df2d850deeebfc87e3caa07428 (patch) | |
tree | decde2f335abbad7f55e27a7bbe36d9b82b7c1a3 | |
parent | *** empty log message *** (diff) | |
download | wireguard-openbsd-f5db0a1ca2f526df2d850deeebfc87e3caa07428.tar.xz wireguard-openbsd-f5db0a1ca2f526df2d850deeebfc87e3caa07428.zip |
Add a function to drop all clean pages on the page daemon queues and call
it when we hibernate.
ok mlarkin@, miod@, deraadt@
-rw-r--r-- | sys/dev/acpi/acpi.c | 6 | ||||
-rw-r--r-- | sys/sys/hibernate.h | 3 | ||||
-rw-r--r-- | sys/uvm/uvm_pdaemon.c | 60 |
3 files changed, 65 insertions, 4 deletions
diff --git a/sys/dev/acpi/acpi.c b/sys/dev/acpi/acpi.c index b6a5c155c66..b680f28487b 100644 --- a/sys/dev/acpi/acpi.c +++ b/sys/dev/acpi/acpi.c @@ -1,4 +1,4 @@ -/* $OpenBSD: acpi.c,v 1.263 2014/07/11 08:18:31 guenther Exp $ */ +/* $OpenBSD: acpi.c,v 1.264 2014/07/12 09:02:24 kettenis Exp $ */ /* * Copyright (c) 2005 Thorsten Lockert <tholo@sigmasoft.com> * Copyright (c) 2005 Jordan Hargrave <jordan@openbsd.org> @@ -2117,8 +2117,10 @@ acpi_sleep_state(struct acpi_softc *sc, int state) goto fail_quiesce; #ifdef HIBERNATE - if (state == ACPI_STATE_S4) + if (state == ACPI_STATE_S4) { + uvmpd_hibernate(); hibernate_suspend_bufcache(); + } #endif /* HIBERNATE */ bufq_quiesce(); diff --git a/sys/sys/hibernate.h b/sys/sys/hibernate.h index b1f546980fe..0def3c7f7e4 100644 --- a/sys/sys/hibernate.h +++ b/sys/sys/hibernate.h @@ -1,4 +1,4 @@ -/* $OpenBSD: hibernate.h,v 1.33 2014/07/11 03:06:08 mlarkin Exp $ */ +/* $OpenBSD: hibernate.h,v 1.34 2014/07/12 09:02:24 kettenis Exp $ */ /* * Copyright (c) 2011 Ariane van der Steldt <ariane@stack.nl> @@ -113,6 +113,7 @@ int uvm_pmr_alloc_pig(paddr_t*, psize_t); int uvm_pmr_alloc_piglet(vaddr_t*, paddr_t*, vsize_t, paddr_t); void uvm_pmr_free_piglet(vaddr_t, vsize_t); int uvm_page_rle(paddr_t); +void uvmpd_hibernate(void); hibio_fn get_hibernate_io_function(void); int get_hibernate_info(union hibernate_info *, int); diff --git a/sys/uvm/uvm_pdaemon.c b/sys/uvm/uvm_pdaemon.c index d6509cbba49..38cc8476f65 100644 --- a/sys/uvm/uvm_pdaemon.c +++ b/sys/uvm/uvm_pdaemon.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uvm_pdaemon.c,v 1.70 2014/07/11 16:35:40 jsg Exp $ */ +/* $OpenBSD: uvm_pdaemon.c,v 1.71 2014/07/12 09:02:24 kettenis Exp $ */ /* $NetBSD: uvm_pdaemon.c,v 1.23 2000/08/20 10:24:14 bjh21 Exp $ */ /* @@ -75,6 +75,10 @@ #include <sys/vnode.h> #include <sys/mount.h> +#ifdef HIBERNATE +#include <sys/hibernate.h> +#endif + #include <uvm/uvm.h> /* @@ -94,6 +98,7 @@ void uvmpd_scan(void); boolean_t uvmpd_scan_inactive(struct pglist *); void uvmpd_tune(void); +void uvmpd_drop(struct pglist *); /* * uvm_wait: wait (sleep) for the page daemon to free some pages @@ -920,3 +925,56 @@ uvmpd_scan(void) } } } + +#ifdef HIBERNATE + +/* + * uvmpd_drop: drop clean pages from list + */ +void +uvmpd_drop(struct pglist *pglst) +{ + struct vm_page *p, *nextpg; + + for (p = TAILQ_FIRST(pglst); p != NULL; p = nextpg) { + nextpg = TAILQ_NEXT(p, pageq); + + if (p->pg_flags & PQ_ANON || p->uobject == NULL) + continue; + + if (p->pg_flags & PG_BUSY) + continue; + + if (p->pg_flags & PG_CLEAN) { + /* + * we now have the page queues locked. + * the page is not busy. if the page is clean we + * can free it now and continue. + */ + if (p->pg_flags & PG_CLEAN) { + if (p->pg_flags & PQ_SWAPBACKED) { + /* this page now lives only in swap */ + uvmexp.swpgonly++; + } + + /* zap all mappings with pmap_page_protect... */ + pmap_page_protect(p, VM_PROT_NONE); + uvm_pagefree(p); + } + } + } +} + +void +uvmpd_hibernate(void) +{ + uvm_lock_pageq(); + + uvmpd_drop(&uvm.page_inactive_swp); + uvmpd_drop(&uvm.page_inactive_obj); + uvmpd_drop(&uvm.page_active); + + uvm_unlock_pageq(); +} + +#endif |