chiark / gitweb /
journal: if we encounter a corrupted file, rotate and go on
[elogind.git] / src / journal / journal-file.c
index 95a5aafc9e30aed5197c1f8d864be1563b79799b..1e6d78cfa43606414b4b4d026491d9b1e0bdaf1a 100644 (file)
@@ -37,7 +37,7 @@
 
 #define DEFAULT_WINDOW_SIZE (128ULL*1024ULL*1024ULL)
 
-#define COMPRESSION_SIZE_THRESHOLD (64ULL)
+#define COMPRESSION_SIZE_THRESHOLD (512ULL)
 
 /* This is the minimum journal file size */
 #define JOURNAL_FILE_SIZE_MIN (64ULL*1024ULL)
@@ -238,7 +238,7 @@ static int journal_file_allocate(JournalFile *f, uint64_t offset, uint64_t size)
         if (fstat(f->fd, &f->last_stat) < 0)
                 return -errno;
 
-        f->header->arena_size = new_size - htole64(f->header->arena_offset);
+        f->header->arena_size = htole64(new_size - le64toh(f->header->arena_offset));
 
         return 0;
 }
@@ -330,7 +330,7 @@ static int journal_file_move_to(JournalFile *f, int wt, uint64_t offset, uint64_
                  * the window space before and half behind the
                  * requested mapping */
 
-                delta = PAGE_ALIGN((DEFAULT_WINDOW_SIZE - size) / 2);
+                delta = (DEFAULT_WINDOW_SIZE - size) / 2;
 
                 if (delta > offset)
                         delta = offset;
@@ -341,7 +341,7 @@ static int journal_file_move_to(JournalFile *f, int wt, uint64_t offset, uint64_
                 delta = 0;
 
         if (offset + size > (uint64_t) f->last_stat.st_size)
-                size = PAGE_ALIGN((uint64_t) f->last_stat.st_size - offset);
+                size = (uint64_t) f->last_stat.st_size - offset;
 
         if (size <= 0)
                 return -EADDRNOTAVAIL;
@@ -581,6 +581,8 @@ static int journal_file_link_data(JournalFile *f, Object *o, uint64_t offset, ui
         assert(offset > 0);
         assert(o->object.type == OBJECT_DATA);
 
+        /* This might alter the window we are looking at */
+
         o->data.next_hash_offset = o->data.next_field_offset = 0;
         o->data.entry_offset = o->data.entry_array_offset = 0;
         o->data.n_entries = 0;
@@ -591,18 +593,14 @@ static int journal_file_link_data(JournalFile *f, Object *o, uint64_t offset, ui
                 /* Only entry in the hash table is easy */
                 f->data_hash_table[h].head_hash_offset = htole64(offset);
         } else {
-                /* Temporarily move back to the previous data object,
-                 * to patch in pointer */
+                /* Move back to the previous data object, to patch in
+                 * pointer */
 
                 r = journal_file_move_to_object(f, OBJECT_DATA, p, &o);
                 if (r < 0)
                         return r;
 
                 o->data.next_hash_offset = htole64(offset);
-
-                r = journal_file_move_to_object(f, OBJECT_DATA, offset, &o);
-                if (r < 0)
-                        return r;
         }
 
         f->data_hash_table[h].tail_hash_offset = htole64(offset);
@@ -614,6 +612,7 @@ int journal_file_find_data_object_with_hash(
                 JournalFile *f,
                 const void *data, uint64_t size, uint64_t hash,
                 Object **ret, uint64_t *offset) {
+
         uint64_t p, osize, h;
         int r;
 
@@ -702,7 +701,11 @@ int journal_file_find_data_object(
                                                        ret, offset);
 }
 
-static int journal_file_append_data(JournalFile *f, const void *data, uint64_t size, Object **ret, uint64_t *offset) {
+static int journal_file_append_data(
+                JournalFile *f,
+                const void *data, uint64_t size,
+                Object **ret, uint64_t *offset) {
+
         uint64_t hash, p;
         uint64_t osize;
         Object *o;
@@ -760,6 +763,12 @@ static int journal_file_append_data(JournalFile *f, const void *data, uint64_t s
         if (r < 0)
                 return r;
 
+        /* The linking might have altered the window, so let's
+         * refresh our pointer */
+        r = journal_file_move_to_object(f, OBJECT_DATA, p, &o);
+        if (r < 0)
+                return r;
+
         if (ret)
                 *ret = o;
 
@@ -771,14 +780,14 @@ static int journal_file_append_data(JournalFile *f, const void *data, uint64_t s
 
 uint64_t journal_file_entry_n_items(Object *o) {
         assert(o);
-        assert(o->object.type == htole64(OBJECT_ENTRY));
+        assert(o->object.type == OBJECT_ENTRY);
 
         return (le64toh(o->object.size) - offsetof(Object, entry.items)) / sizeof(EntryItem);
 }
 
 static uint64_t journal_file_entry_array_n_items(Object *o) {
         assert(o);
-        assert(o->object.type == htole64(OBJECT_ENTRY_ARRAY));
+        assert(o->object.type == OBJECT_ENTRY_ARRAY);
 
         return (le64toh(o->object.size) - offsetof(Object, entry_array.items)) / sizeof(uint64_t);
 }
@@ -833,7 +842,7 @@ static int link_entry_into_array(JournalFile *f,
         o->entry_array.items[i] = htole64(p);
 
         if (ap == 0)
-                *first = q;
+                *first = htole64(q);
         else {
                 r = journal_file_move_to_object(f, OBJECT_ENTRY_ARRAY, ap, &o);
                 if (r < 0)
@@ -866,7 +875,7 @@ static int link_entry_into_array_plus_one(JournalFile *f,
         else {
                 uint64_t i;
 
-                i = le64toh(*idx) - 1;
+                i = htole64(le64toh(*idx) - 1);
                 r = link_entry_into_array(f, first, &i, p);
                 if (r < 0)
                         return r;
@@ -917,7 +926,7 @@ static int journal_file_link_entry(JournalFile *f, Object *o, uint64_t offset) {
         if (r < 0)
                 return r;
 
-        log_error("=> %s seqnr=%lu n_entries=%lu", f->path, (unsigned long) o->entry.seqnum, (unsigned long) f->header->n_entries);
+        /* log_debug("=> %s seqnr=%lu n_entries=%lu", f->path, (unsigned long) o->entry.seqnum, (unsigned long) f->header->n_entries); */
 
         if (f->header->head_entry_realtime == 0)
                 f->header->head_entry_realtime = o->entry.realtime;
@@ -1016,9 +1025,6 @@ int journal_file_append_entry(JournalFile *f, const dual_timestamp *ts, const st
             ts->monotonic < le64toh(f->header->tail_entry_monotonic))
                 return -EINVAL;
 
-        if (ts->realtime < le64toh(f->header->tail_entry_realtime))
-                return -EINVAL;
-
         items = alloca(sizeof(EntryItem) * n_iovec);
 
         for (i = 0; i < n_iovec; i++) {
@@ -1721,6 +1727,9 @@ int journal_file_open(
             (flags & O_ACCMODE) != O_RDWR)
                 return -EINVAL;
 
+        if (!endswith(fname, ".journal"))
+                return -EINVAL;
+
         f = new0(JournalFile, 1);
         if (!f)
                 return -ENOMEM;
@@ -1834,7 +1843,7 @@ int journal_file_rotate(JournalFile **f) {
 
         l = strlen(old_file->path);
 
-        p = new(char, l + 1 + 16 + 1 + 32 + 1 + 16 + 1);
+        p = new(char, l + 1 + 32 + 1 + 16 + 1 + 16 + 1);
         if (!p)
                 return -ENOMEM;
 
@@ -1861,6 +1870,44 @@ int journal_file_rotate(JournalFile **f) {
         return r;
 }
 
+int journal_file_open_reliably(
+                const char *fname,
+                int flags,
+                mode_t mode,
+                JournalFile *template,
+                JournalFile **ret) {
+
+        int r;
+        size_t l;
+        char *p;
+
+        r = journal_file_open(fname, flags, mode, template, ret);
+        if (r != -EBADMSG)
+                return r;
+
+        if ((flags & O_ACCMODE) == O_RDONLY)
+                return r;
+
+        if (!(flags & O_CREAT))
+                return r;
+
+        l = strlen(fname);
+        if (asprintf(&p, "%.*s@%016llx-%016llx.journal~",
+                     (int) (l-8), fname,
+                     (unsigned long long) now(CLOCK_REALTIME),
+                     random_ull()) < 0)
+                return -ENOMEM;
+
+        r = rename(fname, p);
+        free(p);
+        if (r < 0)
+                return -errno;
+
+        log_warning("File %s corrupted, renaming and replacing.", fname);
+
+        return journal_file_open(fname, flags, mode, template, ret);
+}
+
 struct vacuum_info {
         off_t usage;
         char *filename;
@@ -2106,7 +2153,7 @@ int journal_file_copy_entry(JournalFile *from, JournalFile *to, Object *o, uint6
 void journal_default_metrics(JournalMetrics *m, int fd) {
         uint64_t fs_size = 0;
         struct statvfs ss;
-        char a[64], b[64], c[64], d[64];
+        char a[FORMAT_BYTES_MAX], b[FORMAT_BYTES_MAX], c[FORMAT_BYTES_MAX], d[FORMAT_BYTES_MAX];
 
         assert(m);
         assert(fd >= 0);