summaryrefslogtreecommitdiff
path: root/src/shared/sleep-config.c
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2018-04-11 10:26:27 +0200
committerGitHub <noreply@github.com>2018-04-11 10:26:27 +0200
commitb667d50d3443be7fd861d319b5acd525aa15329c (patch)
treed9f1f328c2fa39b7efc7513b3b36f224ae94ea13 /src/shared/sleep-config.c
parentcf45dd36282368d5cdf757cac2cf1fc2b562dab2 (diff)
parent4638cd39af495d89014c31b449f62a2618c390f3 (diff)
downloadsystemd-b667d50d3443be7fd861d319b5acd525aa15329c.tar.gz
Merge pull request #8700 from keszybz/hibernation
Various improvements related to hibernation
Diffstat (limited to 'src/shared/sleep-config.c')
-rw-r--r--src/shared/sleep-config.c60
1 files changed, 30 insertions, 30 deletions
diff --git a/src/shared/sleep-config.c b/src/shared/sleep-config.c
index 36677f6f58..fba58ef367 100644
--- a/src/shared/sleep-config.c
+++ b/src/shared/sleep-config.c
@@ -226,7 +226,7 @@ int find_hibernate_location(char **device, char **type, size_t *size, size_t *us
return -ENOSYS;
}
-static bool enough_memory_for_hibernation(void) {
+static bool enough_swap_for_hibernation(void) {
_cleanup_free_ char *active = NULL;
unsigned long long act = 0;
size_t size = 0, used = 0;
@@ -261,11 +261,11 @@ static bool enough_memory_for_hibernation(void) {
int read_fiemap(int fd, struct fiemap **ret) {
_cleanup_free_ struct fiemap *fiemap = NULL, *result_fiemap = NULL;
- int extents_size;
struct stat statinfo;
uint32_t result_extents = 0;
uint64_t fiemap_start = 0, fiemap_length;
- size_t fiemap_size = 1, result_fiemap_size = 1;
+ const size_t n_extra = DIV_ROUND_UP(sizeof(struct fiemap), sizeof(struct fiemap_extent));
+ size_t fiemap_allocated = n_extra, result_fiemap_allocated = n_extra;
if (fstat(fd, &statinfo) < 0)
return log_debug_errno(errno, "Cannot determine file size: %m");
@@ -273,12 +273,12 @@ int read_fiemap(int fd, struct fiemap **ret) {
return -ENOTTY;
fiemap_length = statinfo.st_size;
- /* zero this out in case we run on a file with no extents */
- fiemap = new0(struct fiemap, 1);
+ /* Zero this out in case we run on a file with no extents */
+ fiemap = calloc(n_extra, sizeof(struct fiemap_extent));
if (!fiemap)
return -ENOMEM;
- result_fiemap = new(struct fiemap, 1);
+ result_fiemap = malloc_multiply(n_extra, sizeof(struct fiemap_extent));
if (!result_fiemap)
return -ENOMEM;
@@ -302,12 +302,10 @@ int read_fiemap(int fd, struct fiemap **ret) {
if (fiemap->fm_mapped_extents == 0)
break;
- /* Result fiemap has to hold all the extents for the whole file */
- extents_size = DIV_ROUND_UP(sizeof(struct fiemap_extent) * fiemap->fm_mapped_extents,
- sizeof(struct fiemap));
-
- /* Resize fiemap to allow us to read in the extents */
- if (!GREEDY_REALLOC0(fiemap, fiemap_size, extents_size))
+ /* Resize fiemap to allow us to read in the extents, result fiemap has to hold all
+ * the extents for the whole file. Add space for the initial struct fiemap. */
+ if (!greedy_realloc0((void**) &fiemap, &fiemap_allocated,
+ n_extra + fiemap->fm_mapped_extents, sizeof(struct fiemap_extent)))
return -ENOMEM;
fiemap->fm_extent_count = fiemap->fm_mapped_extents;
@@ -316,12 +314,9 @@ int read_fiemap(int fd, struct fiemap **ret) {
if (ioctl(fd, FS_IOC_FIEMAP, fiemap) < 0)
return log_debug_errno(errno, "Failed to read extents: %m");
- extents_size = DIV_ROUND_UP(sizeof(struct fiemap_extent) * (result_extents + fiemap->fm_mapped_extents),
- sizeof(struct fiemap));
-
- /* Resize result_fiemap to allow us to read in the extents */
- if (!GREEDY_REALLOC(result_fiemap, result_fiemap_size,
- extents_size))
+ /* Resize result_fiemap to allow us to copy in the extents */
+ if (!greedy_realloc((void**) &result_fiemap, &result_fiemap_allocated,
+ n_extra + result_extents + fiemap->fm_mapped_extents, sizeof(struct fiemap_extent)))
return -ENOMEM;
memcpy(result_fiemap->fm_extents + result_extents,
@@ -331,7 +326,7 @@ int read_fiemap(int fd, struct fiemap **ret) {
result_extents += fiemap->fm_mapped_extents;
/* Highly unlikely that it is zero */
- if (fiemap->fm_mapped_extents > 0) {
+ if (_likely_(fiemap->fm_mapped_extents > 0)) {
uint32_t i = fiemap->fm_mapped_extents - 1;
fiemap_start = fiemap->fm_extents[i].fe_logical +
@@ -349,6 +344,7 @@ int read_fiemap(int fd, struct fiemap **ret) {
}
static bool can_s2h(void) {
+ const char *p;
int r;
r = access("/sys/class/rtc/rtc0/wakealarm", W_OK);
@@ -358,16 +354,14 @@ static bool can_s2h(void) {
return false;
}
- r = can_sleep("suspend");
- if (r < 0) {
- log_debug_errno(r, "Unable to suspend system.");
- return false;
- }
-
- r = can_sleep("hibernate");
- if (r < 0) {
- log_debug_errno(r, "Unable to hibernate system.");
- return false;
+ FOREACH_STRING(p, "suspend", "hibernate") {
+ r = can_sleep(p);
+ if (IN_SET(r, 0, -ENOSPC)) {
+ log_debug("Unable to %s system.", p);
+ return false;
+ }
+ if (r < 0)
+ return log_debug_errno(r, "Failed to check if %s is possible: %m", p);
}
return true;
@@ -389,5 +383,11 @@ 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;
+
+ if (!enough_swap_for_hibernation())
+ return -ENOSPC;
+
+ return true;
}