chiark / gitweb /
fix gcc warnings about uninitialized variables
[elogind.git] / src / journal / journal-file.c
index 304ce03bdd6f480e29b0eb2b67d701f43214a9b3..5a4e7cbd7daee68d5302819b4f114c290128545c 100644 (file)
 #include <sys/statvfs.h>
 #include <fcntl.h>
 #include <stddef.h>
+#include <linux/fs.h>
 
+#include "btrfs-util.h"
 #include "journal-def.h"
 #include "journal-file.h"
 #include "journal-authenticate.h"
 #include "lookup3.h"
 #include "compress.h"
-#include "fsprg.h"
 
 #define DEFAULT_DATA_HASH_TABLE_SIZE (2047ULL*sizeof(HashItem))
 #define DEFAULT_FIELD_HASH_TABLE_SIZE (333ULL*sizeof(HashItem))
@@ -140,6 +141,18 @@ void journal_file_close(JournalFile *f) {
         if (f->mmap && f->fd >= 0)
                 mmap_cache_close_fd(f->mmap, f->fd);
 
+        if (f->fd >= 0 && f->defrag_on_close) {
+
+                /* Be friendly to btrfs: turn COW back on again now,
+                 * and defragment the file. We won't write to the file
+                 * ever again, hence remove all fragmentation, and
+                 * reenable all the good bits COW usually provides
+                 * (such as data checksumming). */
+
+                (void) chattr_fd(f->fd, false, FS_NOCOW_FL);
+                (void) btrfs_defrag_fd(f->fd);
+        }
+
         safe_close(f->fd);
         free(f->path);
 
@@ -309,7 +322,7 @@ static int journal_file_verify_header(JournalFile *f) {
                 } else if (state == STATE_ARCHIVED)
                         return -ESHUTDOWN;
                 else if (state != STATE_OFFLINE) {
-                        log_debug("Journal file %s has unknown state %u.", f->path, state);
+                        log_debug("Journal file %s has unknown state %i.", f->path, state);
                         return -EBUSY;
                 }
         }
@@ -874,7 +887,7 @@ int journal_file_find_data_object_with_hash(
                 if (o->object.flags & OBJECT_COMPRESSION_MASK) {
 #if defined(HAVE_XZ) || defined(HAVE_LZ4)
                         uint64_t l;
-                        size_t rsize;
+                        size_t rsize = 0;
 
                         l = le64toh(o->object.size);
                         if (l <= offsetof(Object, data.payload))
@@ -1039,7 +1052,7 @@ static int journal_file_append_data(
 #if defined(HAVE_XZ) || defined(HAVE_LZ4)
         if (f->compress_xz &&
             size >= COMPRESSION_SIZE_THRESHOLD) {
-                size_t rsize;
+                size_t rsize = 0;
 
                 compression = compress_blob(data, size, o->data.payload, &rsize);
 
@@ -1949,11 +1962,12 @@ static int test_object_monotonic(JournalFile *f, uint64_t p, uint64_t needle) {
                 return TEST_RIGHT;
 }
 
-static inline int find_data_object_by_boot_id(
+static int find_data_object_by_boot_id(
                 JournalFile *f,
                 sd_id128_t boot_id,
                 Object **o,
                 uint64_t *b) {
+
         char t[sizeof("_BOOT_ID=")-1 + 32 + 1] = "_BOOT_ID=";
 
         sd_id128_to_string(boot_id, t + 9);
@@ -1999,8 +2013,7 @@ void journal_file_reset_location(JournalFile *f) {
         f->current_xor_hash = 0;
 }
 
-void journal_file_save_location(JournalFile *f, direction_t direction, Object *o, uint64_t offset) {
-        f->last_direction = direction;
+void journal_file_save_location(JournalFile *f, Object *o, uint64_t offset) {
         f->location_type = LOCATION_SEEK;
         f->current_offset = offset;
         f->current_seqnum = le64toh(o->entry.seqnum);
@@ -2403,7 +2416,7 @@ void journal_file_dump(JournalFile *f) {
                         break;
 
                 default:
-                        printf("Type: unknown (%u)\n", o->object.type);
+                        printf("Type: unknown (%i)\n", o->object.type);
                         break;
                 }
 
@@ -2587,6 +2600,18 @@ int journal_file_open(
                 goto fail;
 
         if (f->last_stat.st_size == 0 && f->writable) {
+
+                /* Before we write anything, turn off COW logic. Given
+                 * our write pattern that is quite unfriendly to COW
+                 * file systems this should greatly improve
+                 * performance on COW file systems, such as btrfs, at
+                 * the expense of data integrity features (which
+                 * shouldn't be too bad, given that we do our own
+                 * checksumming). */
+                r = chattr_fd(f->fd, true, FS_NOCOW_FL);
+                if (r < 0 && r != -ENOTTY)
+                        log_warning_errno(r, "Failed to set file attributes: %m");
+
                 /* Let's attach the creation time to the journal file,
                  * so that the vacuuming code knows the age of this
                  * file even if the file might end up corrupted one
@@ -2597,7 +2622,7 @@ int journal_file_open(
                  * attributes are not supported we'll just skip this,
                  * and rely solely on mtime/atime/ctime of the file. */
 
-                fd_setcrtime(f->fd, now(CLOCK_REALTIME));
+                fd_setcrtime(f->fd, 0);
 
 #ifdef HAVE_GCRYPT
                 /* Try to load the FSPRG state, and if we can't, then
@@ -2626,10 +2651,8 @@ int journal_file_open(
         }
 
         r = mmap_cache_get(f->mmap, f->fd, f->prot, CONTEXT_HEADER, true, 0, PAGE_ALIGN(sizeof(Header)), &f->last_stat, &h);
-        if (r < 0) {
-                r = -errno;
+        if (r < 0)
                 goto fail;
-        }
 
         f->header = h;
 
@@ -2741,6 +2764,11 @@ int journal_file_rotate(JournalFile **f, bool compress, bool seal) {
 
         old_file->header->state = STATE_ARCHIVED;
 
+        /* Currently, btrfs is not very good with out write patterns
+         * and fragments heavily. Let's defrag our journal files when
+         * we archive them */
+        old_file->defrag_on_close = true;
+
         r = journal_file_open(old_file->path, old_file->flags, old_file->mode, compress, seal, NULL, old_file->mmap, old_file, &new_file);
         journal_file_close(old_file);
 
@@ -2765,13 +2793,15 @@ int journal_file_open_reliably(
 
         r = journal_file_open(fname, flags, mode, compress, seal,
                               metrics, mmap_cache, template, ret);
-        if (r != -EBADMSG && /* corrupted */
-            r != -ENODATA && /* truncated */
-            r != -EHOSTDOWN && /* other machine */
-            r != -EPROTONOSUPPORT && /* incompatible feature */
-            r != -EBUSY && /* unclean shutdown */
-            r != -ESHUTDOWN && /* already archived */
-            r != -EIO /* IO error, including SIGBUS on mmap */)
+        if (!IN_SET(r,
+                    -EBADMSG,           /* corrupted */
+                    -ENODATA,           /* truncated */
+                    -EHOSTDOWN,         /* other machine */
+                    -EPROTONOSUPPORT,   /* incompatible feature */
+                    -EBUSY,             /* unclean shutdown */
+                    -ESHUTDOWN,         /* already archived */
+                    -EIO,               /* IO error, including SIGBUS on mmap */
+                    -EIDRM              /* File has been deleted */))
                 return r;
 
         if ((flags & O_ACCMODE) == O_RDONLY)
@@ -2786,9 +2816,9 @@ int journal_file_open_reliably(
         /* The file is corrupted. Rotate it away and try it again (but only once) */
 
         l = strlen(fname);
-        if (asprintf(&p, "%.*s@%016llx-%016" PRIx64 ".journal~",
+        if (asprintf(&p, "%.*s@%016"PRIx64 "-%016"PRIx64 ".journal~",
                      (int) l - 8, fname,
-                     (unsigned long long) now(CLOCK_REALTIME),
+                     now(CLOCK_REALTIME),
                      random_u64()) < 0)
                 return -ENOMEM;
 
@@ -2796,6 +2826,12 @@ int journal_file_open_reliably(
         if (r < 0)
                 return -errno;
 
+        /* btrfs doesn't cope well with our write pattern and
+         * fragments heavily. Let's defrag all files we rotate */
+
+        (void) chattr_path(p, false, FS_NOCOW_FL);
+        (void) btrfs_defrag(p);
+
         log_warning("File %s corrupted or uncleanly shut down, renaming and replacing.", fname);
 
         return journal_file_open(fname, flags, mode, compress, seal,
@@ -2850,7 +2886,7 @@ int journal_file_copy_entry(JournalFile *from, JournalFile *to, Object *o, uint6
 
                 if (o->object.flags & OBJECT_COMPRESSION_MASK) {
 #if defined(HAVE_XZ) || defined(HAVE_LZ4)
-                        size_t rsize;
+                        size_t rsize = 0;
 
                         r = decompress_blob(o->object.flags & OBJECT_COMPRESSION_MASK,
                                             o->data.payload, l, &from->compress_buffer, &from->compress_buffer_size, &rsize, 0);