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);