From f524b4a4be549871997868dd0b3860cae5bad4ed Mon Sep 17 00:00:00 2001 From: Jan Synacek Date: Jan 07 2015 13:00:52 +0000 Subject: RFE: journal: automatically rotate the file if it is unlinked (#1171719) --- diff --git a/0002-journald-when-we-detect-the-journal-file-we-are-abou.patch b/0002-journald-when-we-detect-the-journal-file-we-are-abou.patch new file mode 100644 index 0000000..1081d47 --- /dev/null +++ b/0002-journald-when-we-detect-the-journal-file-we-are-abou.patch @@ -0,0 +1,216 @@ +From 8ea1f4267bae6b37a4a4d474aec2692a4d211621 Mon Sep 17 00:00:00 2001 +From: Fedora systemd team +Date: Wed, 7 Jan 2015 13:34:02 +0100 +Subject: [PATCH] journald: when we detect the journal file we are about to + write to has been deleted, rotate + +https://bugzilla.redhat.com/show_bug.cgi?id=1171719 + +(cherry-picked from 2678031a179a9b91fc799f8ef951a548c66c4b49) +--- + src/journal/journal-file.c | 65 ++++++++++++++++++++++++++++++---------- + src/journal/journal-file.h | 1 + + src/journal/journald-server.c | 6 +++- + src/journal/test-journal-flush.c | 3 +- + 4 files changed, 57 insertions(+), 18 deletions(-) + +diff --git a/src/journal/journal-file.c b/src/journal/journal-file.c +index c5d2d19..a99265b 100644 +--- a/src/journal/journal-file.c ++++ b/src/journal/journal-file.c +@@ -68,6 +68,9 @@ + /* How much to increase the journal file size at once each time we allocate something new. */ + #define FILE_SIZE_INCREASE (8ULL*1024ULL*1024ULL) /* 8MB */ + ++/* Reread fstat() of the file for detecting deletions at least this often */ ++#define LAST_STAT_REFRESH_USEC (5*USEC_PER_SEC) ++ + static int journal_file_set_online(JournalFile *f) { + assert(f); + +@@ -312,6 +315,22 @@ static int journal_file_verify_header(JournalFile *f) { + return 0; + } + ++static int journal_file_fstat(JournalFile *f) { ++ assert(f); ++ assert(f->fd >= 0); ++ ++ if (fstat(f->fd, &f->last_stat) < 0) ++ return -errno; ++ ++ f->last_stat_usec = now(CLOCK_MONOTONIC); ++ ++ /* Refuse appending to files that are already deleted */ ++ if (f->last_stat.st_nlink <= 0) ++ return -EIDRM; ++ ++ return 0; ++} ++ + static int journal_file_allocate(JournalFile *f, uint64_t offset, uint64_t size) { + uint64_t old_size, new_size; + int r; +@@ -330,8 +349,21 @@ static int journal_file_allocate(JournalFile *f, uint64_t offset, uint64_t size) + if (new_size < le64toh(f->header->header_size)) + new_size = le64toh(f->header->header_size); + +- if (new_size <= old_size) +- return 0; ++ if (new_size <= old_size) { ++ ++ /* We already pre-allocated enough space, but before ++ * we write to it, let's check with fstat() if the ++ * file got deleted, in order make sure we don't throw ++ * away the data immediately. Don't check fstat() for ++ * all writes though, but only once ever 10s. */ ++ ++ if (f->last_stat_usec + LAST_STAT_REFRESH_USEC > now(CLOCK_MONOTONIC)) ++ return 0; ++ ++ return journal_file_fstat(f); ++ } ++ ++ /* Allocate more space. */ + + if (f->metrics.max_size > 0 && new_size > f->metrics.max_size) + return -E2BIG; +@@ -366,15 +398,14 @@ static int journal_file_allocate(JournalFile *f, uint64_t offset, uint64_t size) + if (r != 0) + return -r; + +- if (fstat(f->fd, &f->last_stat) < 0) +- return -errno; +- + f->header->arena_size = htole64(new_size - le64toh(f->header->header_size)); + +- return 0; ++ return journal_file_fstat(f); + } + + static int journal_file_move_to(JournalFile *f, int context, bool keep_always, uint64_t offset, uint64_t size, void **ret) { ++ int r; ++ + assert(f); + assert(ret); + +@@ -386,8 +417,11 @@ static int journal_file_move_to(JournalFile *f, int context, bool keep_always, u + /* Hmm, out of range? Let's refresh the fstat() data + * first, before we trust that check. */ + +- if (fstat(f->fd, &f->last_stat) < 0 || +- offset + size > (uint64_t) f->last_stat.st_size) ++ r = journal_file_fstat(f); ++ if (r < 0) ++ return r; ++ ++ if (offset + size > (uint64_t) f->last_stat.st_size) + return -EADDRNOTAVAIL; + } + +@@ -2511,10 +2545,9 @@ int journal_file_open( + goto fail; + } + +- if (fstat(f->fd, &f->last_stat) < 0) { +- r = -errno; ++ r = journal_file_fstat(f); ++ if (r < 0) + goto fail; +- } + + if (f->last_stat.st_size == 0 && f->writable) { + uint64_t crtime; +@@ -2546,10 +2579,9 @@ int journal_file_open( + if (r < 0) + goto fail; + +- if (fstat(f->fd, &f->last_stat) < 0) { +- r = -errno; ++ r = journal_file_fstat(f); ++ if (r < 0) + goto fail; +- } + + newly_created = true; + } +@@ -2657,8 +2689,11 @@ int journal_file_rotate(JournalFile **f, bool compress, bool seal) { + if (r < 0) + return -ENOMEM; + ++ /* Try to rename the file to the archived version. If the file ++ * already was deleted, we'll get ENOENT, let's ignore that ++ * case. */ + r = rename(old_file->path, p); +- if (r < 0) ++ if (r < 0 && errno != ENOENT) + return -errno; + + old_file->header->state = STATE_ARCHIVED; +diff --git a/src/journal/journal-file.h b/src/journal/journal-file.h +index 211e121..15f1301 100644 +--- a/src/journal/journal-file.h ++++ b/src/journal/journal-file.h +@@ -66,6 +66,7 @@ typedef struct JournalFile { + + char *path; + struct stat last_stat; ++ usec_t last_stat_usec; + + Header *header; + HashItem *data_hash_table; +diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c +index 80c9736..24c4d3c 100644 +--- a/src/journal/journald-server.c ++++ b/src/journal/journald-server.c +@@ -315,6 +315,7 @@ static int do_rotate(Server *s, JournalFile **f, const char* name, + name); + else + server_fix_perms(s, *f, uid); ++ + return r; + } + +@@ -457,7 +458,8 @@ bool shall_try_append_again(JournalFile *f, int r) { + -EPROTONOSUPPORT Unsupported feature + -EBADMSG Corrupted + -ENODATA Truncated +- -ESHUTDOWN Already archived */ ++ -ESHUTDOWN Already archived ++ -EIDRM Journal file has been deleted */ + + if (r == -E2BIG || r == -EFBIG || r == -EDQUOT || r == -ENOSPC) + log_debug("%s: Allocation limit reached, rotating.", f->path); +@@ -469,6 +471,8 @@ bool shall_try_append_again(JournalFile *f, int r) { + log_info("%s: Unsupported feature, rotating.", f->path); + else if (r == -EBADMSG || r == -ENODATA || r == ESHUTDOWN) + log_warning("%s: Journal file corrupted, rotating.", f->path); ++ else if (r == -EIDRM) ++ log_warning("%s: Journal file has been deleted, rotating.", f->path); + else + return false; + +diff --git a/src/journal/test-journal-flush.c b/src/journal/test-journal-flush.c +index 0ca24e0..40ede4a 100644 +--- a/src/journal/test-journal-flush.c ++++ b/src/journal/test-journal-flush.c +@@ -39,8 +39,6 @@ int main(int argc, char *argv[]) { + r = journal_file_open(fn, O_CREAT|O_RDWR, 0644, false, false, NULL, NULL, NULL, &new_journal); + assert_se(r >= 0); + +- unlink(fn); +- + r = sd_journal_open(&j, 0); + assert_se(r >= 0); + +@@ -68,6 +66,7 @@ int main(int argc, char *argv[]) { + + journal_file_close(new_journal); + ++ unlink(fn); + assert_se(rmdir(dn) == 0); + + return 0; +-- +2.2.0 + diff --git a/systemd.spec b/systemd.spec index c6a1be1..162fbf6 100644 --- a/systemd.spec +++ b/systemd.spec @@ -42,6 +42,7 @@ Source8: systemd-journal-gatewayd.xml # GIT_DIR=~/src/systemd/.git git format-patch-ab -M -N --no-signature v218..v218-stable # i=1; for p in 0*patch;do printf "Patch%04d: %s\n" $i $p; ((i++));done Patch0001: 0001-nspawn-fix-invocation-of-the-raw-clone-system-call-o.patch +Patch0002: 0002-journald-when-we-detect-the-journal-file-we-are-abou.patch Patch0998: fedora-disable-resolv.conf-symlink.patch Patch0999: fedora-add-bridge-sysctl-configuration.patch @@ -848,6 +849,9 @@ getent passwd systemd-journal-upload >/dev/null 2>&1 || useradd -r -l -g systemd /usr/lib/firewalld/services/* %changelog +* Wed Jan 7 2015 Jan Synáček - 218-3 +- RFE: journal: automatically rotate the file if it is unlinked (#1171719) + * Mon Jan 05 2015 Zbigniew Jędrzejewski-Szmek - 218-3 - Add firewall description files (#1176626)