From: Igor Zhbanov Date: Tue, 20 Apr 2021 17:22:28 +0000 (+0000) Subject: journald: Retry if posix_fallocate returned -1 (EINTR) X-Git-Tag: v249-rc1~366 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=4c54768c9732532f4e56eab1be3e5474769e0d7a;p=thirdparty%2Fsystemd.git journald: Retry if posix_fallocate returned -1 (EINTR) On some conditions (particularly when mobile CPUs are going to sleep), the posix_fallocate(), which is called when a new journal file is allocated, can return -1 (EINTR). This is counted as a fatal error. So the journald closes both old and journals, and simply throwing away further incoming events, because of no log files open. Introduce posix_fallocate_loop() that restarts the function in the case of EINTR. Also let's make code base more uniform by returning negative values on error. Fix assert in test-sigbus.c that incorrectly counted positive values as success. After changing the function return values, that will actually work. Fixes: #19041 Signed-off-by: Igor Zhbanov --- diff --git a/src/basic/fs-util.c b/src/basic/fs-util.c index b2a4e8036f8..46d6f7780e1 100644 --- a/src/basic/fs-util.c +++ b/src/basic/fs-util.c @@ -24,6 +24,7 @@ #include "path-util.h" #include "process-util.h" #include "random-util.h" +#include "ratelimit.h" #include "stat-util.h" #include "stdio-util.h" #include "string-util.h" @@ -1715,3 +1716,23 @@ do_rename: return 1; } + +int posix_fallocate_loop(int fd, uint64_t offset, uint64_t size) { + RateLimit rl; + int r; + + r = posix_fallocate(fd, offset, size); /* returns positive errnos on error */ + if (r != EINTR) + return -r; /* Let's return negative errnos, like common in our codebase */ + + /* On EINTR try a couple of times more, but protect against busy looping + * (not more than 16 times per 10s) */ + rl = (RateLimit) { 10 * USEC_PER_SEC, 16 }; + while (ratelimit_below(&rl)) { + r = posix_fallocate(fd, offset, size); + if (r != EINTR) + return -r; + } + + return -EINTR; +} diff --git a/src/basic/fs-util.h b/src/basic/fs-util.h index 45115fd3db1..027037f7a72 100644 --- a/src/basic/fs-util.h +++ b/src/basic/fs-util.h @@ -146,3 +146,5 @@ int conservative_renameat(int olddirfd, const char *oldpath, int newdirfd, const static inline int conservative_rename(const char *oldpath, const char *newpath) { return conservative_renameat(AT_FDCWD, oldpath, AT_FDCWD, newpath); } + +int posix_fallocate_loop(int fd, uint64_t offset, uint64_t size); diff --git a/src/journal/journald-kmsg.c b/src/journal/journald-kmsg.c index 29b8437fe29..c96b84e61f8 100644 --- a/src/journal/journald-kmsg.c +++ b/src/journal/journald-kmsg.c @@ -14,6 +14,7 @@ #include "escape.h" #include "fd-util.h" #include "format-util.h" +#include "fs-util.h" #include "io-util.h" #include "journald-kmsg.h" #include "journald-server.h" @@ -436,8 +437,8 @@ int server_open_kernel_seqnum(Server *s) { return 0; } - r = posix_fallocate(fd, 0, sizeof(uint64_t)); - if (r != 0) { + r = posix_fallocate_loop(fd, 0, sizeof(uint64_t)); + if (r < 0) { log_error_errno(r, "Failed to allocate sequential number file, ignoring: %m"); return 0; } diff --git a/src/libsystemd/sd-journal/journal-file.c b/src/libsystemd/sd-journal/journal-file.c index f8bb708e582..3cf26f8e443 100644 --- a/src/libsystemd/sd-journal/journal-file.c +++ b/src/libsystemd/sd-journal/journal-file.c @@ -707,9 +707,9 @@ static int journal_file_allocate(JournalFile *f, uint64_t offset, uint64_t size) /* Note that the glibc fallocate() fallback is very inefficient, hence we try to minimize the allocation area as we can. */ - r = posix_fallocate(f->fd, old_size, new_size - old_size); - if (r != 0) - return -r; + r = posix_fallocate_loop(f->fd, old_size, new_size - old_size); + if (r < 0) + return r; f->header->arena_size = htole64(new_size - old_header_size); diff --git a/src/test/test-sigbus.c b/src/test/test-sigbus.c index d141735320a..5262947c087 100644 --- a/src/test/test-sigbus.c +++ b/src/test/test-sigbus.c @@ -9,6 +9,7 @@ #endif #include "fd-util.h" +#include "fs-util.h" #include "memory-util.h" #include "sigbus.h" #include "tests.h" @@ -35,7 +36,7 @@ int main(int argc, char *argv[]) { assert_se((fd = mkostemp(template, O_RDWR|O_CREAT|O_EXCL)) >= 0); assert_se(unlink(template) >= 0); - assert_se(posix_fallocate(fd, 0, page_size() * 8) >= 0); + assert_se(posix_fallocate_loop(fd, 0, page_size() * 8) >= 0); p = mmap(NULL, page_size() * 16, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); assert_se(p != MAP_FAILED);