[systemd/f21] RFE: journal: automatically rotate the file if it is unlinked (#1171719)

jsynacek jsynacek at fedoraproject.org
Thu Feb 5 08:44:47 UTC 2015


commit 282d355552a4ba221e21b69570bf3ceb940be77e
Author: Jan Synacek <jsynacek at redhat.com>
Date:   Thu Feb 5 08:43:14 2015 +0100

    RFE: journal: automatically rotate the file if it is unlinked (#1171719)

 ...en-we-detect-the-journal-file-we-are-abou.patch |  216 ++++++++++++++++++++
 systemd.spec                                       |    6 +-
 2 files changed, 221 insertions(+), 1 deletions(-)
---
diff --git a/0203-journald-when-we-detect-the-journal-file-we-are-abou.patch b/0203-journald-when-we-detect-the-journal-file-we-are-abou.patch
new file mode 100644
index 0000000..a1a1fe6
--- /dev/null
+++ b/0203-journald-when-we-detect-the-journal-file-we-are-abou.patch
@@ -0,0 +1,216 @@
+From 8c28f30191fa51fb1165cfa513e43c3cb98cc569 Mon Sep 17 00:00:00 2001
+From: Fedora systemd team <systemd-maint at redhat.com>
+Date: Wed, 7 Jan 2015 14:08:43 +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 8a2c0fc..d754167 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 12735c4..c2a579f 100644
+--- a/src/journal/journald-server.c
++++ b/src/journal/journald-server.c
+@@ -314,6 +314,7 @@ static int do_rotate(Server *s, JournalFile **f, const char* name,
+                                   name, strerror(-r));
+         else
+                 server_fix_perms(s, *f, uid);
++
+         return r;
+ }
+ 
+@@ -456,7 +457,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);
+@@ -468,6 +470,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 d3c7012..7e129b5 100644
--- a/systemd.spec
+++ b/systemd.spec
@@ -16,7 +16,7 @@
 Name:           systemd
 Url:            http://www.freedesktop.org/wiki/Software/systemd
 Version:        216
-Release:        17%{?gitcommit:.git%{gitcommit}}%{?dist}
+Release:        18%{?gitcommit:.git%{gitcommit}}%{?dist}
 # For a breakdown of the licensing, see README
 License:        LGPLv2+ and MIT and GPLv2+
 Summary:        A System and Service Manager
@@ -243,6 +243,7 @@ Patch0199:      0199-util-Add-some-missing-hidden_file-suffixes.patch
 Patch0200:      0200-tmpfiles-make-sure-not-to-concatenate-non-absolute-p.patch
 Patch0201:      0201-sysv-generator-only-allow-regular-files-in-enumerate.patch
 Patch0202:      0202-logind-fix-sd_eviocrevoke-ioctl-call.patch
+Patch0203:      0203-journald-when-we-detect-the-journal-file-we-are-abou.patch
 
 
 Patch0997:      units-remove-dev-log-to-always-create-symlink.patch
@@ -1032,6 +1033,9 @@ getent passwd systemd-journal-upload >/dev/null 2>&1 || useradd -r -l -g systemd
 %{_datadir}/systemd/gatewayd
 
 %changelog
+* Wed Feb  4 2015 Jan Synáček <jsynacek at redhat.com> - 216-18
+- RFE: journal: automatically rotate the file if it is unlinked (#1171719)
+
 * Thu Jan 22 2015 Zbigniew Jędrzejewski-Szmek <zbyszek at in.waw.pl> - 216-17
 - Fix syslog forwarding in containers, make sysv generator more robust, fix logind revoke call
 


More information about the scm-commits mailing list