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 <i.zhbanov@omprussia.ru>
This commit is contained in:
Igor Zhbanov
2021-04-21 23:08:35 +02:00
committed by Zbigniew Jędrzejewski-Szmek
parent 6f4a5f25fc
commit 4c54768c97
5 changed files with 31 additions and 6 deletions
+21
View File
@@ -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;
}
+2
View File
@@ -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);
+3 -2
View File
@@ -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;
}
+3 -3
View File
@@ -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);
+2 -1
View File
@@ -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);