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:
committed by
Zbigniew Jędrzejewski-Szmek
parent
6f4a5f25fc
commit
4c54768c97
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user