systemd/0027-check-for-valid-resume...

87 lines
2.7 KiB
Diff

From 313f86d98c7232354d1d877f94f263dfcbcb7dd4 Mon Sep 17 00:00:00 2001
From: James Hogarth <james.hogarth@gmail.com>
Date: Tue, 17 May 2016 11:33:33 +0100
Subject: [PATCH] check for valid resume= in order to allow a hibernate
---
src/shared/sleep-config.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 53 insertions(+), 1 deletion(-)
diff --git a/src/shared/sleep-config.c b/src/shared/sleep-config.c
index a0aef66bc8..c516a6dc8a 100644
--- a/src/shared/sleep-config.c
+++ b/src/shared/sleep-config.c
@@ -36,6 +36,10 @@
#include "sleep-config.h"
#include "string-util.h"
#include "strv.h"
+#include "proc-cmdline.h"
+#include "fstab-util.h"
+
+static char *arg_resume_dev = NULL;
#define USE(x, y) do{ (x) = (y); (y) = NULL; } while(0)
@@ -255,6 +259,51 @@ static bool enough_memory_for_hibernation(void) {
return r;
}
+static int parse_proc_cmdline_item(const char *key, const char *value) {
+
+ assert(key);
+
+ if (streq(key, "resume") && value) {
+ free(arg_resume_dev);
+ arg_resume_dev = fstab_node_to_udev_node(value);
+ if (!arg_resume_dev)
+ return log_oom();
+ }
+
+ return 0;
+
+}
+
+static bool resume_passed_to_kernel(void) {
+ int r = 0;
+ struct stat rd;
+
+ r = parse_proc_cmdline(parse_proc_cmdline_item);
+ if (r < 0) {
+ log_warning("Failed to parse kernel command line, disabling hibernation.");
+ return false;
+ }
+
+ if (arg_resume_dev == NULL) {
+ log_warning("No resume= argument specified in the kernel command line, disabling hibernation.");
+ return false;
+ }
+
+ if (stat(arg_resume_dev, &rd) < 0) {
+ log_warning("Could not stat device %s specified in resume=, disabling hibernation.",
+ arg_resume_dev);
+ return false;
+ }
+
+ if (!S_ISBLK(rd.st_mode)) {
+ log_warning("Device %s specified in resume= is not a block device, disabling hibernation.",
+ arg_resume_dev);
+ return false;
+ }
+
+ return true;
+}
+
int can_sleep(const char *verb) {
_cleanup_strv_free_ char **modes = NULL, **states = NULL;
int r;
@@ -270,5 +319,8 @@ int can_sleep(const char *verb) {
if (!can_sleep_state(states) || !can_sleep_disk(modes))
return false;
- return streq(verb, "suspend") || enough_memory_for_hibernation();
+ if (streq(verb, "suspend"))
+ return true;
+
+ return enough_memory_for_hibernation() && resume_passed_to_kernel();
}