From 96aa32bb596c96dee4f6445db50ab312fd82b08c81e69a41646cb17eee0d3c6c Mon Sep 17 00:00:00 2001 From: Stephan Kulow Date: Wed, 20 Feb 2013 16:46:33 +0000 Subject: [PATCH] Accepting request 155884 from Base:System - Ensure journal is flushed on disk when systemd-logger is installed for the first time. - Add improve-journal-perf.patch: improve journal performance on query. - Add support-hybrid-suspend.patch: add support for hybrid suspend. - Add forward-to-pmutils.patch: forward suspend/hibernation calls to pm-utils, if installed (bnc#790157). (forwarded request 155834 from fcrozat) OBS-URL: https://build.opensuse.org/request/show/155884 OBS-URL: https://build.opensuse.org/package/show/openSUSE:Factory/systemd?expand=0&rev=132 --- forward-to-pmutils.patch | 93 +++++ improve-bash-completion.patch | 2 +- improve-journal-perf.patch | 304 +++++++++++++++ support-hybrid-suspend.patch | 680 ++++++++++++++++++++++++++++++++++ systemd-mini.changes | 11 + systemd-mini.spec | 19 + systemd.changes | 11 + systemd.spec | 19 + 8 files changed, 1138 insertions(+), 1 deletion(-) create mode 100644 forward-to-pmutils.patch create mode 100644 improve-journal-perf.patch create mode 100644 support-hybrid-suspend.patch diff --git a/forward-to-pmutils.patch b/forward-to-pmutils.patch new file mode 100644 index 00000000..2a40213d --- /dev/null +++ b/forward-to-pmutils.patch @@ -0,0 +1,93 @@ +Index: systemd-195/src/sleep/sleep.c +=================================================================== +--- systemd-195.orig/src/sleep/sleep.c ++++ systemd-195/src/sleep/sleep.c +@@ -22,6 +22,7 @@ + #include + #include + #include ++#include + + #include "log.h" + #include "util.h" +@@ -31,6 +32,9 @@ + int main(int argc, char *argv[]) { + const char *verb; + char* arguments[4]; ++ const char *pmtools; ++ bool delegate_to_pmutils = false; ++ struct stat buf; + int r; + FILE *f; + +@@ -44,17 +48,27 @@ int main(int argc, char *argv[]) { + goto finish; + } + +- if (streq(argv[1], "suspend")) ++ if (streq(argv[1], "suspend")) { + verb = "mem"; +- else if (streq(argv[1], "hibernate") || streq(argv[1], "hybrid-sleep")) ++ pmtools = "/usr/sbin/pm-suspend"; ++ } ++ else if (streq(argv[1], "hibernate") || streq(argv[1], "hybrid-sleep")) { + verb = "disk"; ++ if (streq(argv[1], "hibernate")) ++ pmtools = "/usr/sbin/pm-hibernate"; ++ else ++ pmtools = "/usr/sbin/pm-suspend-hybrid"; ++ } + else { + log_error("Unknown action '%s'.", argv[1]); + r = -EINVAL; + goto finish; + } + ++ delegate_to_pmutils = (stat(pmtools, &buf) >= 0 && S_ISREG(buf.st_mode) && (buf.st_mode & 0111)); ++ + /* Configure the hibernation mode */ ++ if (!delegate_to_pmutils) { + if (streq(argv[1], "hibernate")) { + if (write_one_line_file("/sys/power/disk", "platform") < 0) + write_one_line_file("/sys/power/disk", "shutdown"); +@@ -64,13 +78,14 @@ int main(int argc, char *argv[]) { + write_one_line_file("/sys/power/disk", "shutdown"); + } + ++ + f = fopen("/sys/power/state", "we"); + if (!f) { + log_error("Failed to open /sys/power/state: %m"); + r = -errno; + goto finish; + } +- ++ } + arguments[0] = NULL; + arguments[1] = (char*) "pre"; + arguments[2] = argv[1]; +@@ -96,11 +111,16 @@ int main(int argc, char *argv[]) { + "SLEEP=hybrid-sleep", + NULL); + ++ if (delegate_to_pmutils) { ++ r = -system(pmtools); ++ } ++ else { + fputs(verb, f); + fputc('\n', f); + fflush(f); + + r = ferror(f) ? -errno : 0; ++ } + + if (streq(argv[1], "suspend")) + log_struct(LOG_INFO, +@@ -118,6 +138,7 @@ int main(int argc, char *argv[]) { + arguments[1] = (char*) "post"; + execute_directory(SYSTEM_SLEEP_PATH, NULL, arguments); + ++ if (!delegate_to_pmutils) + fclose(f); + + finish: diff --git a/improve-bash-completion.patch b/improve-bash-completion.patch index 4621e3fd..b3580f99 100644 --- a/improve-bash-completion.patch +++ b/improve-bash-completion.patch @@ -8,7 +8,7 @@ Index: systemd-195/bash-completion/systemd-bash-completion.sh [STANDALONE]='daemon-reexec daemon-reload default dot dump - emergency exit halt kexec list-jobs list-units - list-unit-files poweroff reboot rescue show-environment' -+ emergency exit halt hibernate kexec list-jobs list-units ++ emergency exit halt hybrid-sleep hibernate kexec list-jobs list-units + list-unit-files poweroff reboot rescue show-environment suspend' [NAME]='snapshot load' [FILE]='link' diff --git a/improve-journal-perf.patch b/improve-journal-perf.patch new file mode 100644 index 00000000..8f0eb8f7 --- /dev/null +++ b/improve-journal-perf.patch @@ -0,0 +1,304 @@ +From a4bcff5ba36115495994e9f9ba66074471de76ab Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Fri, 26 Oct 2012 03:24:03 +0200 +Subject: [PATCH] journal: introduce entry array chain cache + +When traversing entry array chains for a bisection or for retrieving an +item by index we previously always started at the beginning of the +chain. Since we tend to look at the same chains repeatedly, let's cache +where we have been the last time, and maybe we can skip ahead with this +the next time. + +This turns most bisections and index lookups from O(log(n)*log(n)) into +O(log(n)). More importantly however, we seek around on disk much less, +which is good to reduce buffer cache and seek times on rotational disks. +--- + .gitignore | 1 + + Makefile.am | 9 ++++ + src/journal/journal-file.c | 109 +++++++++++++++++++++++++++++++++++++--- + src/journal/journal-file.h | 3 ++ + src/journal/test-journal-enum.c | 53 +++++++++++++++++++ + src/shared/hashmap.c | 19 +++++++ + src/shared/hashmap.h | 3 ++ + 7 files changed, 189 insertions(+), 8 deletions(-) + create mode 100644 src/journal/test-journal-enum.c + +diff --git a/src/journal/journal-file.c b/src/journal/journal-file.c +index edf8e7d..6c9deac 100644 +--- a/src/journal/journal-file.c ++++ b/src/journal/journal-file.c +@@ -65,6 +65,9 @@ + /* n_data was the first entry we added after the initial file format design */ + #define HEADER_SIZE_MIN ALIGN64(offsetof(Header, n_data)) + ++/* How many entries to keep in the entry array chain cache at max */ ++#define CHAIN_CACHE_MAX 20 ++ + void journal_file_close(JournalFile *f) { + assert(f); + +@@ -97,6 +100,8 @@ void journal_file_close(JournalFile *f) { + if (f->mmap) + mmap_cache_unref(f->mmap); + ++ hashmap_free_free(f->chain_cache); ++ + #ifdef HAVE_XZ + free(f->compress_buffer); + #endif +@@ -1307,37 +1312,89 @@ int journal_file_append_entry(JournalFile *f, const dual_timestamp *ts, const st + return r; + } + ++typedef struct ChainCacheItem { ++ uint64_t first; /* the array at the begin of the chain */ ++ uint64_t array; /* the cached array */ ++ uint64_t begin; /* the first item in the cached array */ ++ uint64_t total; /* the total number of items in all arrays before this one in the chain */ ++} ChainCacheItem; ++ ++static void chain_cache_put( ++ Hashmap *h, ++ ChainCacheItem *ci, ++ uint64_t first, ++ uint64_t array, ++ uint64_t begin, ++ uint64_t total) { ++ ++ if (!ci) { ++ if (hashmap_size(h) >= CHAIN_CACHE_MAX) ++ ci = hashmap_steal_first(h); ++ else { ++ ci = new(ChainCacheItem, 1); ++ if (!ci) ++ return; ++ } ++ ++ ci->first = first; ++ ++ if (hashmap_put(h, &ci->first, ci) < 0) { ++ free(ci); ++ return; ++ } ++ } else ++ assert(ci->first == first); ++ ++ ci->array = array; ++ ci->begin = begin; ++ ci->total = total; ++} ++ + static int generic_array_get(JournalFile *f, + uint64_t first, + uint64_t i, + Object **ret, uint64_t *offset) { + + Object *o; +- uint64_t p = 0, a; ++ uint64_t p = 0, a, t = 0; + int r; ++ ChainCacheItem *ci; + + assert(f); + + a = first; ++ ++ /* Try the chain cache first */ ++ ci = hashmap_get(f->chain_cache, &first); ++ if (ci && i > ci->total) { ++ a = ci->array; ++ i -= ci->total; ++ t = ci->total; ++ } ++ + while (a > 0) { +- uint64_t n; ++ uint64_t k; + + r = journal_file_move_to_object(f, OBJECT_ENTRY_ARRAY, a, &o); + if (r < 0) + return r; + +- n = journal_file_entry_array_n_items(o); +- if (i < n) { ++ k = journal_file_entry_array_n_items(o); ++ if (i < k) { + p = le64toh(o->entry_array.items[i]); +- break; ++ goto found; + } + +- i -= n; ++ i -= k; ++ t += k; + a = le64toh(o->entry_array.next_entry_array_offset); + } + +- if (a <= 0 || p <= 0) +- return 0; ++ return 0; ++ ++found: ++ /* Let's cache this item for the next invocation */ ++ chain_cache_put(f->chain_cache, ci, first, a, o->entry_array.items[0], t); + + r = journal_file_move_to_object(f, OBJECT_ENTRY, p, &o); + if (r < 0) +@@ -1401,11 +1458,38 @@ static int generic_array_bisect(JournalFile *f, + bool subtract_one = false; + Object *o, *array = NULL; + int r; ++ ChainCacheItem *ci; + + assert(f); + assert(test_object); + ++ /* Start with the first array in the chain */ + a = first; ++ ++ ci = hashmap_get(f->chain_cache, &first); ++ if (ci && n > ci->total) { ++ /* Ah, we have iterated this bisection array chain ++ * previously! Let's see if we can skip ahead in the ++ * chain, as far as the last time. But we can't jump ++ * backwards in the chain, so let's check that ++ * first. */ ++ ++ r = test_object(f, ci->begin, needle); ++ if (r < 0) ++ return r; ++ ++ if (r == TEST_LEFT) { ++ /* OK, what we are looking for is right of th ++ * begin of this EntryArray, so let's jump ++ * straight to previously cached array in the ++ * chain */ ++ ++ a = ci->array; ++ n -= ci->total; ++ t = ci->total; ++ } ++ } ++ + while (a > 0) { + uint64_t left, right, k, lp; + +@@ -1486,6 +1570,9 @@ found: + if (subtract_one && t == 0 && i == 0) + return 0; + ++ /* Let's cache this item for the next invocation */ ++ chain_cache_put(f->chain_cache, ci, first, a, array->entry_array.items[0], t); ++ + if (subtract_one && i == 0) + p = last_p; + else if (subtract_one) +@@ -2265,6 +2352,12 @@ int journal_file_open( + goto fail; + } + ++ f->chain_cache = hashmap_new(uint64_hash_func, uint64_compare_func); ++ if (!f->chain_cache) { ++ r = -ENOMEM; ++ goto fail; ++ } ++ + f->fd = open(f->path, f->flags|O_CLOEXEC, f->mode); + if (f->fd < 0) { + r = -errno; +diff --git a/src/journal/journal-file.h b/src/journal/journal-file.h +index d87cbe4..cdbc8e4 100644 +--- a/src/journal/journal-file.h ++++ b/src/journal/journal-file.h +@@ -33,6 +33,7 @@ + #include "journal-def.h" + #include "util.h" + #include "mmap-cache.h" ++#include "hashmap.h" + + typedef struct JournalMetrics { + uint64_t max_use; +@@ -64,6 +65,8 @@ typedef struct JournalFile { + JournalMetrics metrics; + MMapCache *mmap; + ++ Hashmap *chain_cache; ++ + #ifdef HAVE_XZ + void *compress_buffer; + uint64_t compress_buffer_size; +diff --git a/src/shared/hashmap.c b/src/shared/hashmap.c +index ef78070..dcfbb67 100644 +--- a/src/shared/hashmap.c ++++ b/src/shared/hashmap.c +@@ -147,6 +147,25 @@ int trivial_compare_func(const void *a, const void *b) { + return a < b ? -1 : (a > b ? 1 : 0); + } + ++unsigned uint64_hash_func(const void *p) { ++ uint64_t u; ++ ++ assert_cc(sizeof(uint64_t) == 2*sizeof(unsigned)); ++ ++ u = *(const uint64_t*) p; ++ ++ return (unsigned) ((u >> 32) ^ u); ++} ++ ++int uint64_compare_func(const void *_a, const void *_b) { ++ uint64_t a, b; ++ ++ a = *(const uint64_t*) _a; ++ b = *(const uint64_t*) _b; ++ ++ return a < b ? -1 : (a > b ? 1 : 0); ++} ++ + Hashmap *hashmap_new(hash_func_t hash_func, compare_func_t compare_func) { + bool b; + Hashmap *h; +diff --git a/src/shared/hashmap.h b/src/shared/hashmap.h +index 55dea0a..6fd71cf 100644 +--- a/src/shared/hashmap.h ++++ b/src/shared/hashmap.h +@@ -44,6 +44,9 @@ int string_compare_func(const void *a, const void *b); + unsigned trivial_hash_func(const void *p); + int trivial_compare_func(const void *a, const void *b); + ++unsigned uint64_hash_func(const void *p); ++int uint64_compare_func(const void *a, const void *b); ++ + Hashmap *hashmap_new(hash_func_t hash_func, compare_func_t compare_func); + void hashmap_free(Hashmap *h); + void hashmap_free_free(Hashmap *h); +-- +1.8.1.1 + +From 34741aa3e2ee1e67a4cc735b7492aec13f0d822c Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Fri, 26 Oct 2012 20:25:36 +0200 +Subject: [PATCH] journal: special case the trivial cache chain cache entry + +--- + src/journal/journal-file.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/src/journal/journal-file.c b/src/journal/journal-file.c +index 6c9deac..3df099d 100644 +--- a/src/journal/journal-file.c ++++ b/src/journal/journal-file.c +@@ -1328,6 +1328,11 @@ static void chain_cache_put( + uint64_t total) { + + if (!ci) { ++ /* If the chain item to cache for this chain is the ++ * first one it's not worth caching anything */ ++ if (array == first) ++ return; ++ + if (hashmap_size(h) >= CHAIN_CACHE_MAX) + ci = hashmap_steal_first(h); + else { +-- +1.8.1.1 + diff --git a/support-hybrid-suspend.patch b/support-hybrid-suspend.patch new file mode 100644 index 00000000..ad6b2bda --- /dev/null +++ b/support-hybrid-suspend.patch @@ -0,0 +1,680 @@ +From 6524990fdc98370ecba5d9f73e67161e8798c010 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Sun, 28 Oct 2012 00:49:04 +0200 +Subject: [PATCH] logind: support for hybrid sleep (i.e. suspend+hibernate at + the same time) + +--- + .gitignore | 1 + + Makefile.am | 17 ++++++++- + man/logind.conf.xml | 5 ++- + man/systemctl.xml | 5 +++ + man/systemd-suspend.service.xml | 42 +++++++++++++-------- + man/systemd.special.xml | 15 ++++++-- + src/core/special.h | 1 + + src/login/logind-button.c | 21 ++++++----- + src/login/logind-button.h | 1 + + src/login/logind-dbus.c | 69 +++++++++++++++++++++++++++++++---- + src/shared/util.c | 24 ++++++++++++ + src/shared/util.h | 1 + + src/sleep/sleep.c | 20 +++++++++- + src/systemctl/systemctl.c | 17 +++++++-- + src/test/test-sleep.c | 39 ++++++++++++++++++++ + units/.gitignore | 1 + + units/hybrid-sleep.target | 13 +++++++ + units/systemd-hybrid-sleep.service.in | 17 +++++++++ + 18 files changed, 264 insertions(+), 45 deletions(-) + create mode 100644 src/test/test-sleep.c + create mode 100644 units/hybrid-sleep.target + create mode 100644 units/systemd-hybrid-sleep.service.in + +Index: systemd-195/Makefile.am +=================================================================== +--- systemd-195.orig/Makefile.am ++++ systemd-195/Makefile.am +@@ -272,6 +272,7 @@ dist_systemunit_DATA = \ + units/nss-user-lookup.target \ + units/mail-transfer-agent.target \ + units/hibernate.target \ ++ units/hybrid-sleep.target \ + units/http-daemon.target \ + units/poweroff.target \ + units/reboot.target \ +@@ -334,6 +335,7 @@ nodist_systemunit_DATA = \ + units/rescue.service \ + units/user@.service \ + units/systemd-hibernate.service \ ++ units/systemd-hybrid-sleep.service \ + units/systemd-suspend.service \ + units/systemd-halt.service \ + units/systemd-poweroff.service \ +@@ -384,6 +386,7 @@ EXTRA_DIST += \ + units/systemd-udev-settle.service \ + units/debug-shell.service.in \ + units/systemd-hibernate.service.in \ ++ units/systemd-hybrid-sleep.service.in \ + units/systemd-suspend.service.in \ + units/quotaon.service.in \ + introspect.awk \ +@@ -539,6 +542,7 @@ MANPAGES_ALIAS = \ + man/systemd-shutdownd.socket.8 \ + man/systemd-shutdownd.8 \ + man/systemd-hibernate.service.8 \ ++ man/systemd-hybrid-sleep.service.8 \ + man/systemd-sleep.8 \ + man/systemd-shutdown.8 \ + man/systemd-poweroff.service.8 \ +@@ -612,6 +616,7 @@ man/systemd-initctl.8: man/systemd-initc + man/systemd-shutdownd.socket.8: man/systemd-shutdownd.service.8 + man/systemd-shutdownd.8: man/systemd-shutdownd.service.8 + man/systemd-hibernate.service.8: man/systemd-suspend.service.8 ++man/systemd-hybrid-sleep.service.8: man/systemd-suspend.service.8 + man/systemd-sleep.8: man/systemd-suspend.service.8 + man/systemd-shutdown.8: man/systemd-halt.service.8 + man/systemd-poweroff.service.8: man/systemd-halt.service.8 +Index: systemd-195/man/logind.conf.xml +=================================================================== +--- systemd-195.orig/man/logind.conf.xml ++++ systemd-195/man/logind.conf.xml +@@ -211,8 +211,10 @@ + poweroff, + reboot, + halt, +- kexec and +- hibernate. If ++ kexec, ++ suspend, ++ hibernate, and ++ hybrid-sleep. If + ignore logind will + never handle these keys. Otherwise the + specified action will be taken in the +Index: systemd-195/man/systemctl.xml +=================================================================== +--- systemd-195.orig/man/systemctl.xml ++++ systemd-195/man/systemctl.xml +@@ -1181,6 +1181,11 @@ + Hibernate the system. + + ++ hybrid-sleep ++ ++ Hibernate and suspend the system. ++ ++ + switch-root [ROOT] [INIT] + + Switches to a +Index: systemd-195/man/systemd-suspend.service.xml +=================================================================== +--- systemd-195.orig/man/systemd-suspend.service.xml ++++ systemd-195/man/systemd-suspend.service.xml +@@ -45,6 +45,7 @@ + + systemd-suspend.service + systemd-hibernate.service ++ systemd-hybrid-sleep.service + systemd-sleep + System sleep state logic + +@@ -52,6 +53,7 @@ + + systemd-suspend.service + systemd-hibernate.service ++ systemd-hybrid-sleep.service + /usr/lib/systemd/systemd-sleep + + +@@ -63,20 +65,26 @@ + suspend.target and is responsible + for the actual system suspend. Similar, + systemd-hibernate.service is +- pulled in by hibernate.target to +- executed the actual hibernation. +- +- Immediately before entering system suspend and +- hibernation +- systemd-suspend.service will run +- all executables in ++ pulled in by hibernate.target to ++ execute the actual hibernation. Finally, ++ systemd-hybrid-sleep.service is ++ pulled in by hybrid-sleep.target ++ to execute hybrid hibernation with system ++ suspend. ++ ++ Immediately before entering system suspend ++ and/or hibernation ++ systemd-suspend.service (and the ++ other mentioned units, respectively) will run all ++ executables in + /usr/lib/systemd/system-sleep/ + and pass two arguments to them. The first argument + will be "pre", the second either +- "suspend" or +- "hibernate", depending on the ++ "suspend", ++ "hibernate", or ++ "hybrid-sleep" depending on the + chosen action. Immediately after leaving system +- suspend and hibernation the same executables are run, ++ suspend and/or hibernation the same executables are run, + but the first argument is now + "post". All executables in this + directory are executed in parallel, and execution of +@@ -87,15 +95,17 @@ + /usr/lib/systemd/system-sleep/ + are intended for local use only and should be + considered hacks. If applications want to be notified +- of system suspend and resume there are much nicer +- interfaces available. ++ of system suspend/hibernation and resume there are ++ much nicer interfaces available. + + Note that +- systemd-suspend.service and +- systemd-hibernate.service should +- never be executed directly. Instead, trigger system +- sleep states with a command such as "systemctl +- suspend" or suchlike. ++ systemd-suspend.service, ++ systemd-hibernate.service and ++ systemd-hybrid-sleep.service ++ should never be executed directly. Instead, trigger ++ system sleep states with a command such as ++ "systemctl suspend" or ++ similar. + + + +Index: systemd-195/man/systemd.special.xml +=================================================================== +--- systemd-195.orig/man/systemd.special.xml ++++ systemd-195/man/systemd.special.xml +@@ -63,6 +63,7 @@ + graphical.target, + hibernate.target, + http-daemon.target, ++ hybrid-sleep.target, + halt.target, + kbrequest.target, + kexec.target, +@@ -303,6 +304,15 @@ + + + ++ hybrid-sleep.target ++ ++ A special target unit ++ for hibernating and suspending the ++ system at the same time. This pulls in ++ sleep.target. ++ ++ ++ + halt.target + + A special target unit +@@ -652,9 +662,8 @@ + + A special target unit + that is pulled in by +- suspend.target +- and +- hibernate.target ++ suspend.target, ++ hibernate.target and hybrid-sleep.target + and may be used to hook units + into the sleep state + logic. +Index: systemd-195/src/core/special.h +=================================================================== +--- systemd-195.orig/src/core/special.h ++++ systemd-195/src/core/special.h +@@ -37,6 +37,7 @@ + #define SPECIAL_EXIT_TARGET "exit.target" + #define SPECIAL_SUSPEND_TARGET "suspend.target" + #define SPECIAL_HIBERNATE_TARGET "hibernate.target" ++#define SPECIAL_HYBRID_SLEEP_TARGET "hybrid-sleep.target" + + /* Special boot targets */ + #define SPECIAL_RESCUE_TARGET "rescue.target" +Index: systemd-195/src/login/logind-button.c +=================================================================== +--- systemd-195.orig/src/login/logind-button.c ++++ systemd-195/src/login/logind-button.c +@@ -163,16 +163,18 @@ static int button_handle( + [HANDLE_HALT] = "Halting...", + [HANDLE_KEXEC] = "Rebooting via kexec...", + [HANDLE_SUSPEND] = "Suspending...", +- [HANDLE_HIBERNATE] = "Hibernating..." ++ [HANDLE_HIBERNATE] = "Hibernating...", ++ [HANDLE_HYBRID_SLEEP] = "Hibernating and suspend...", + }; + + static const char * const target_table[_HANDLE_BUTTON_MAX] = { +- [HANDLE_POWEROFF] = "poweroff.target", +- [HANDLE_REBOOT] = "reboot.target", +- [HANDLE_HALT] = "halt.target", +- [HANDLE_KEXEC] = "kexec.target", +- [HANDLE_SUSPEND] = "suspend.target", +- [HANDLE_HIBERNATE] = "hibernate.target" ++ [HANDLE_POWEROFF] = SPECIAL_POWEROFF_TARGET, ++ [HANDLE_REBOOT] = SPECIAL_REBOOT_TARGET, ++ [HANDLE_HALT] = SPECIAL_HALT_TARGET, ++ [HANDLE_KEXEC] = SPECIAL_KEXEC_TARGET, ++ [HANDLE_SUSPEND] = SPECIAL_SUSPEND_TARGET, ++ [HANDLE_HIBERNATE] = SPECIAL_HIBERNATE_TARGET, ++ [HANDLE_HYBRID_SLEEP] = SPECIAL_HYBRID_SLEEP_TARGET + }; + + DBusError error; +@@ -193,7 +195,7 @@ static int button_handle( + return 0; + } + +- inhibit_operation = handle == HANDLE_SUSPEND || handle == HANDLE_HIBERNATE ? INHIBIT_SLEEP : INHIBIT_SHUTDOWN; ++ inhibit_operation = handle == HANDLE_SUSPEND || handle == HANDLE_HIBERNATE || handle == HANDLE_HYBRID_SLEEP ? INHIBIT_SLEEP : INHIBIT_SHUTDOWN; + + /* If the actual operation is inhibited, warn and fail */ + if (!ignore_inhibited && +@@ -305,7 +307,8 @@ static const char* const handle_button_t + [HANDLE_HALT] = "halt", + [HANDLE_KEXEC] = "kexec", + [HANDLE_SUSPEND] = "suspend", +- [HANDLE_HIBERNATE] = "hibernate" ++ [HANDLE_HIBERNATE] = "hibernate", ++ [HANDLE_HYBRID_SLEEP] = "hybrid-sleep", + }; + DEFINE_STRING_TABLE_LOOKUP(handle_button, HandleButton); + DEFINE_CONFIG_PARSE_ENUM(config_parse_handle_button, handle_button, HandleButton, "Failed to parse handle button setting"); +Index: systemd-195/src/login/logind-button.h +=================================================================== +--- systemd-195.orig/src/login/logind-button.h ++++ systemd-195/src/login/logind-button.h +@@ -32,6 +32,7 @@ typedef enum HandleButton { + HANDLE_KEXEC, + HANDLE_SUSPEND, + HANDLE_HIBERNATE, ++ HANDLE_HYBRID_SLEEP, + _HANDLE_BUTTON_MAX, + _HANDLE_BUTTON_INVALID = -1 + } HandleButton; +Index: systemd-195/src/login/logind-dbus.c +=================================================================== +--- systemd-195.orig/src/login/logind-dbus.c ++++ systemd-195/src/login/logind-dbus.c +@@ -145,6 +145,9 @@ + " \n" \ + " \n" \ + " \n" \ ++ " \n" \ ++ " \n" \ ++ " \n" \ + " \n" \ + " \n" \ + " \n" \ +@@ -157,6 +160,9 @@ + " \n" \ + " \n" \ + " \n" \ ++ " \n" \ ++ " \n" \ ++ " \n" \ + " \n" \ + " \n" \ + " \n" \ +@@ -1056,6 +1062,7 @@ static int bus_manager_can_shutdown_or_s + const char *action_multiple_sessions, + const char *action_ignore_inhibit, + const char *sleep_type, ++ const char *sleep_disk_type, + DBusError *error, + DBusMessage **_reply) { + +@@ -1087,6 +1094,17 @@ static int bus_manager_can_shutdown_or_s + } + } + ++ if (sleep_disk_type) { ++ r = can_sleep_disk(sleep_disk_type); ++ if (r < 0) ++ return r; ++ ++ if (r == 0) { ++ result = "na"; ++ goto finish; ++ } ++ } ++ + ul = dbus_bus_get_unix_user(connection, dbus_message_get_sender(message), error); + if (ul == (unsigned long) -1) + return -EIO; +@@ -1236,6 +1254,7 @@ static int bus_manager_do_shutdown_or_sl + const char *action_multiple_sessions, + const char *action_ignore_inhibit, + const char *sleep_type, ++ const char *sleep_disk_type, + DBusError *error, + DBusMessage **_reply) { + +@@ -1273,6 +1292,15 @@ static int bus_manager_do_shutdown_or_sl + return -ENOTSUP; + } + ++ if (sleep_disk_type) { ++ r = can_sleep_disk(sleep_disk_type); ++ if (r < 0) ++ return r; ++ ++ if (r == 0) ++ return -ENOTSUP; ++ } ++ + ul = dbus_bus_get_unix_user(connection, dbus_message_get_sender(message), error); + if (ul == (unsigned long) -1) + return -EIO; +@@ -2067,7 +2095,7 @@ static DBusHandlerResult manager_message + "org.freedesktop.login1.power-off", + "org.freedesktop.login1.power-off-multiple-sessions", + "org.freedesktop.login1.power-off-ignore-inhibit", +- NULL, ++ NULL, NULL, + &error, &reply); + if (r < 0) + return bus_send_error_reply(connection, message, &error, r); +@@ -2079,7 +2107,7 @@ static DBusHandlerResult manager_message + "org.freedesktop.login1.reboot", + "org.freedesktop.login1.reboot-multiple-sessions", + "org.freedesktop.login1.reboot-ignore-inhibit", +- NULL, ++ NULL, NULL, + &error, &reply); + if (r < 0) + return bus_send_error_reply(connection, message, &error, r); +@@ -2092,7 +2120,7 @@ static DBusHandlerResult manager_message + "org.freedesktop.login1.suspend", + "org.freedesktop.login1.suspend-multiple-sessions", + "org.freedesktop.login1.suspend-ignore-inhibit", +- "mem", ++ "mem", NULL, + &error, &reply); + if (r < 0) + return bus_send_error_reply(connection, message, &error, r); +@@ -2104,7 +2132,20 @@ static DBusHandlerResult manager_message + "org.freedesktop.login1.hibernate", + "org.freedesktop.login1.hibernate-multiple-sessions", + "org.freedesktop.login1.hibernate-ignore-inhibit", +- "disk", ++ "disk", NULL, ++ &error, &reply); ++ if (r < 0) ++ return bus_send_error_reply(connection, message, &error, r); ++ ++ } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "HybridSleep")) { ++ r = bus_manager_do_shutdown_or_sleep( ++ m, connection, message, ++ SPECIAL_HYBRID_SLEEP_TARGET, ++ INHIBIT_SLEEP, ++ "org.freedesktop.login1.hibernate", ++ "org.freedesktop.login1.hibernate-multiple-sessions", ++ "org.freedesktop.login1.hibernate-ignore-inhibit", ++ "disk", "suspend", + &error, &reply); + if (r < 0) + return bus_send_error_reply(connection, message, &error, r); +@@ -2117,7 +2158,7 @@ static DBusHandlerResult manager_message + "org.freedesktop.login1.power-off", + "org.freedesktop.login1.power-off-multiple-sessions", + "org.freedesktop.login1.power-off-ignore-inhibit", +- NULL, ++ NULL, NULL, + &error, &reply); + if (r < 0) + return bus_send_error_reply(connection, message, &error, r); +@@ -2128,7 +2169,7 @@ static DBusHandlerResult manager_message + "org.freedesktop.login1.reboot", + "org.freedesktop.login1.reboot-multiple-sessions", + "org.freedesktop.login1.reboot-ignore-inhibit", +- NULL, ++ NULL, NULL, + &error, &reply); + if (r < 0) + return bus_send_error_reply(connection, message, &error, r); +@@ -2140,7 +2181,7 @@ static DBusHandlerResult manager_message + "org.freedesktop.login1.suspend", + "org.freedesktop.login1.suspend-multiple-sessions", + "org.freedesktop.login1.suspend-ignore-inhibit", +- "mem", ++ "mem", NULL, + &error, &reply); + if (r < 0) + return bus_send_error_reply(connection, message, &error, r); +@@ -2152,7 +2193,19 @@ static DBusHandlerResult manager_message + "org.freedesktop.login1.hibernate", + "org.freedesktop.login1.hibernate-multiple-sessions", + "org.freedesktop.login1.hibernate-ignore-inhibit", +- "disk", ++ "disk", NULL, ++ &error, &reply); ++ if (r < 0) ++ return bus_send_error_reply(connection, message, &error, r); ++ ++ } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "CanHybridSleep")) { ++ r = bus_manager_can_shutdown_or_sleep( ++ m, connection, message, ++ INHIBIT_SLEEP, ++ "org.freedesktop.login1.hibernate", ++ "org.freedesktop.login1.hibernate-multiple-sessions", ++ "org.freedesktop.login1.hibernate-ignore-inhibit", ++ "disk", "suspend", + &error, &reply); + if (r < 0) + return bus_send_error_reply(connection, message, &error, r); +Index: systemd-195/src/shared/util.c +=================================================================== +--- systemd-195.orig/src/shared/util.c ++++ systemd-195/src/shared/util.c +@@ -5726,6 +5726,30 @@ int can_sleep(const char *type) { + return false; + } + ++int can_sleep_disk(const char *type) { ++ char *w, *state; ++ size_t l, k; ++ int r; ++ _cleanup_free_ char *p = NULL; ++ ++ assert(type); ++ ++ r = read_one_line_file("/sys/power/disk", &p); ++ if (r < 0) ++ return r == -ENOENT ? 0 : r; ++ ++ k = strlen(type); ++ FOREACH_WORD_SEPARATOR(w, l, p, WHITESPACE, state) { ++ if (l == k && memcmp(w, type, l) == 0) ++ return true; ++ ++ if (l == k + 2 && w[0] == '[' && memcmp(w + 1, type, l - 2) == 0 && w[l-1] == ']') ++ return true; ++ } ++ ++ return false; ++} ++ + bool is_valid_documentation_url(const char *url) { + assert(url); + +Index: systemd-195/src/shared/util.h +=================================================================== +--- systemd-195.orig/src/shared/util.h ++++ systemd-195/src/shared/util.h +@@ -531,6 +531,7 @@ int setrlimit_closest(int resource, cons + int getenv_for_pid(pid_t pid, const char *field, char **_value); + + int can_sleep(const char *type); ++int can_sleep_disk(const char *type); + + bool is_valid_documentation_url(const char *url); + +Index: systemd-195/src/sleep/sleep.c +=================================================================== +--- systemd-195.orig/src/sleep/sleep.c ++++ systemd-195/src/sleep/sleep.c +@@ -46,7 +46,7 @@ int main(int argc, char *argv[]) { + + if (streq(argv[1], "suspend")) + verb = "mem"; +- else if (streq(argv[1], "hibernate")) ++ else if (streq(argv[1], "hibernate") || streq(argv[1], "hybrid-sleep")) + verb = "disk"; + else { + log_error("Unknown action '%s'.", argv[1]); +@@ -54,6 +54,16 @@ int main(int argc, char *argv[]) { + goto finish; + } + ++ /* Configure the hibernation mode */ ++ if (streq(argv[1], "hibernate")) { ++ if (write_one_line_file("/sys/power/disk", "platform") < 0) ++ write_one_line_file("/sys/power/disk", "shutdown"); ++ } else if (streq(argv[1], "hybrid-sleep")) { ++ if (write_one_line_file("/sys/power/disk", "suspend") < 0) ++ if (write_one_line_file("/sys/power/disk", "platform") < 0) ++ write_one_line_file("/sys/power/disk", "shutdown"); ++ } ++ + f = fopen("/sys/power/state", "we"); + if (!f) { + log_error("Failed to open /sys/power/state: %m"); +@@ -73,12 +83,18 @@ int main(int argc, char *argv[]) { + "MESSAGE=Suspending system...", + "SLEEP=suspend", + NULL); +- else ++ else if (streq(argv[1], "hibernate")) + log_struct(LOG_INFO, + MESSAGE_ID(SD_MESSAGE_SLEEP_START), + "MESSAGE=Hibernating system...", + "SLEEP=hibernate", + NULL); ++ else ++ log_struct(LOG_INFO, ++ MESSAGE_ID(SD_MESSAGE_SLEEP_START), ++ "MESSAGE=Hibernating and suspending system...", ++ "SLEEP=hybrid-sleep", ++ NULL); + + fputs(verb, f); + fputc('\n', f); +Index: systemd-195/src/systemctl/systemctl.c +=================================================================== +--- systemd-195.orig/src/systemctl/systemctl.c ++++ systemd-195/src/systemctl/systemctl.c +@@ -99,6 +99,7 @@ static enum action { + ACTION_EXIT, + ACTION_SUSPEND, + ACTION_HIBERNATE, ++ ACTION_HYBRID_SLEEP, + ACTION_RUNLEVEL2, + ACTION_RUNLEVEL3, + ACTION_RUNLEVEL4, +@@ -1608,6 +1609,8 @@ static enum action verb_to_action(const + return ACTION_SUSPEND; + else if (streq(verb, "hibernate")) + return ACTION_HIBERNATE; ++ else if (streq(verb, "hybrid-sleep")) ++ return ACTION_HYBRID_SLEEP; + else + return ACTION_INVALID; + } +@@ -1628,7 +1631,8 @@ static int start_unit(DBusConnection *bu + [ACTION_DEFAULT] = SPECIAL_DEFAULT_TARGET, + [ACTION_EXIT] = SPECIAL_EXIT_TARGET, + [ACTION_SUSPEND] = SPECIAL_SUSPEND_TARGET, +- [ACTION_HIBERNATE] = SPECIAL_HIBERNATE_TARGET ++ [ACTION_HIBERNATE] = SPECIAL_HIBERNATE_TARGET, ++ [ACTION_HYBRID_SLEEP] = SPECIAL_HYBRID_SLEEP_TARGET + }; + + int r, ret = 0; +@@ -1767,6 +1771,10 @@ static int reboot_with_logind(DBusConnec + method = "Hibernate"; + break; + ++ case ACTION_HYBRID_SLEEP: ++ method = "HybridSleep"; ++ break; ++ + default: + return -EINVAL; + } +@@ -1818,7 +1826,8 @@ static int start_special(DBusConnection + (a == ACTION_POWEROFF || + a == ACTION_REBOOT || + a == ACTION_SUSPEND || +- a == ACTION_HIBERNATE)) { ++ a == ACTION_HIBERNATE || ++ a == ACTION_HYBRID_SLEEP)) { + r = reboot_with_logind(bus, a); + if (r >= 0) + return r; +@@ -3999,7 +4008,8 @@ static int systemctl_help(void) { + " exit Request user instance exit\n" + " switch-root [ROOT] [INIT] Change to a different root file system\n" + " suspend Suspend the system\n" +- " hibernate Hibernate the system\n", ++ " hibernate Hibernate the system\n" ++ " hybrid-sleep Hibernate and suspend the system\n", + program_invocation_short_name); + + return 0; +@@ -4931,6 +4941,7 @@ static int systemctl_main(DBusConnection + { "kexec", EQUAL, 1, start_special }, + { "suspend", EQUAL, 1, start_special }, + { "hibernate", EQUAL, 1, start_special }, ++ { "hybrid-sleep", EQUAL, 1, start_special }, + { "default", EQUAL, 1, start_special }, + { "rescue", EQUAL, 1, start_special }, + { "emergency", EQUAL, 1, start_special }, +Index: systemd-195/units/hybrid-sleep.target +=================================================================== +--- /dev/null ++++ systemd-195/units/hybrid-sleep.target +@@ -0,0 +1,13 @@ ++# This file is part of systemd. ++# ++# systemd is free software; you can redistribute it and/or modify it ++# under the terms of the GNU Lesser General Public License as published by ++# the Free Software Foundation; either version 2.1 of the License, or ++# (at your option) any later version. ++ ++[Unit] ++Description=Hybrid Suspend+Hibernate ++Documentation=man:systemd.special(7) ++DefaultDependencies=no ++BindsTo=systemd-hybrid-sleep.service ++After=systemd-hybrid-sleep.service +Index: systemd-195/units/systemd-hybrid-sleep.service.in +=================================================================== +--- /dev/null ++++ systemd-195/units/systemd-hybrid-sleep.service.in +@@ -0,0 +1,17 @@ ++# This file is part of systemd. ++# ++# systemd is free software; you can redistribute it and/or modify it ++# under the terms of the GNU Lesser General Public License as published by ++# the Free Software Foundation; either version 2.1 of the License, or ++# (at your option) any later version. ++ ++[Unit] ++Description=Hybrid Suspend+Hibernate ++Documentation=man:systemd-suspend.service(8) ++DefaultDependencies=no ++Requires=sleep.target ++After=sleep.target ++ ++[Service] ++Type=oneshot ++ExecStart=@rootlibexecdir@/systemd-sleep hybrid-sleep diff --git a/systemd-mini.changes b/systemd-mini.changes index 5368f4e7..dfca29b1 100644 --- a/systemd-mini.changes +++ b/systemd-mini.changes @@ -1,3 +1,14 @@ +------------------------------------------------------------------- +Tue Feb 19 11:20:31 CET 2013 - fcrozat@suse.com + +- Ensure journal is flushed on disk when systemd-logger is + installed for the first time. +- Add improve-journal-perf.patch: improve journal performance on + query. +- Add support-hybrid-suspend.patch: add support for hybrid suspend. +- Add forward-to-pmutils.patch: forward suspend/hibernation calls + to pm-utils, if installed (bnc#790157). + ------------------------------------------------------------------- Tue Feb 19 09:51:18 UTC 2013 - rmilasan@suse.com diff --git a/systemd-mini.spec b/systemd-mini.spec index aed80312..61f18349 100644 --- a/systemd-mini.spec +++ b/systemd-mini.spec @@ -274,6 +274,12 @@ Patch129: handle-HOSTNAME.patch Patch130: systemctl-print-wall-on-if-successful.patch # PATCH-FIX-UPSTREAM improve-bash-completion.patch fcrozat@suse.com -- improve bash completion Patch131: improve-bash-completion.patch +# PATCH-FIX-UPSTREAM improve-journal-perf.patch fcrozat@suse.com -- improve journal performance +Patch132: improve-journal-perf.patch +# PATCH-FIX-UPSTREAM support-hybrid-suspend.patch fcrozat@suse.com -- support hybrid suspend +Patch133: support-hybrid-suspend.patch +# PATCH-FIX-OPENSUSE forward-to-pmutils.patch fcrozat@suse.com bnc#790157 -- forward to pm-utils +Patch134: forward-to-pmutils.patch # udev patches # PATCH-FIX-OPENSUSE 1001-Reinstate-TIMEOUT-handling.patch @@ -606,9 +612,15 @@ cp %{SOURCE7} m4/ %patch129 -p1 %patch130 -p1 %patch131 -p1 +%patch132 -p1 +%patch133 -p1 +%patch134 -p1 %build autoreconf -fiv +# to remove after upgrading to systemd 196+ +rm -f man/{systemd.exec.5,logind.conf.5,systemctl.1,systemd-suspend.service.8,systemd.special.7,tmpfiles.d.5} + # prevent pre-generated and distributed files from re-building find . -name "*.[1-8]" -exec touch '{}' '+'; export V=1 @@ -878,6 +890,13 @@ fi %post -n libgudev-1_0-0 -p /sbin/ldconfig %postun -n libgudev-1_0-0 -p /sbin/ldconfig + +%post logger +if [ "$1" -eq 1 ]; then +# tell journal to start logging on disk if directory didn't exist before + systemctl --no-block restart systemd-journal-flush.service >/dev/null 2>&1 || : +fi + %endif %clean diff --git a/systemd.changes b/systemd.changes index 5368f4e7..dfca29b1 100644 --- a/systemd.changes +++ b/systemd.changes @@ -1,3 +1,14 @@ +------------------------------------------------------------------- +Tue Feb 19 11:20:31 CET 2013 - fcrozat@suse.com + +- Ensure journal is flushed on disk when systemd-logger is + installed for the first time. +- Add improve-journal-perf.patch: improve journal performance on + query. +- Add support-hybrid-suspend.patch: add support for hybrid suspend. +- Add forward-to-pmutils.patch: forward suspend/hibernation calls + to pm-utils, if installed (bnc#790157). + ------------------------------------------------------------------- Tue Feb 19 09:51:18 UTC 2013 - rmilasan@suse.com diff --git a/systemd.spec b/systemd.spec index 9e0f143a..eb88b5b7 100644 --- a/systemd.spec +++ b/systemd.spec @@ -269,6 +269,12 @@ Patch129: handle-HOSTNAME.patch Patch130: systemctl-print-wall-on-if-successful.patch # PATCH-FIX-UPSTREAM improve-bash-completion.patch fcrozat@suse.com -- improve bash completion Patch131: improve-bash-completion.patch +# PATCH-FIX-UPSTREAM improve-journal-perf.patch fcrozat@suse.com -- improve journal performance +Patch132: improve-journal-perf.patch +# PATCH-FIX-UPSTREAM support-hybrid-suspend.patch fcrozat@suse.com -- support hybrid suspend +Patch133: support-hybrid-suspend.patch +# PATCH-FIX-OPENSUSE forward-to-pmutils.patch fcrozat@suse.com bnc#790157 -- forward to pm-utils +Patch134: forward-to-pmutils.patch # udev patches # PATCH-FIX-OPENSUSE 1001-Reinstate-TIMEOUT-handling.patch @@ -601,9 +607,15 @@ cp %{SOURCE7} m4/ %patch129 -p1 %patch130 -p1 %patch131 -p1 +%patch132 -p1 +%patch133 -p1 +%patch134 -p1 %build autoreconf -fiv +# to remove after upgrading to systemd 196+ +rm -f man/{systemd.exec.5,logind.conf.5,systemctl.1,systemd-suspend.service.8,systemd.special.7,tmpfiles.d.5} + # prevent pre-generated and distributed files from re-building find . -name "*.[1-8]" -exec touch '{}' '+'; export V=1 @@ -873,6 +885,13 @@ fi %post -n libgudev-1_0-0 -p /sbin/ldconfig %postun -n libgudev-1_0-0 -p /sbin/ldconfig + +%post logger +if [ "$1" -eq 1 ]; then +# tell journal to start logging on disk if directory didn't exist before + systemctl --no-block restart systemd-journal-flush.service >/dev/null 2>&1 || : +fi + %endif %clean