chiark / gitweb /
journald: whenever we rotate a file, btrfs defrag it
authorLennart Poettering <lennart@poettering.net>
Tue, 6 Jan 2015 18:51:03 +0000 (19:51 +0100)
committerLennart Poettering <lennart@poettering.net>
Tue, 6 Jan 2015 19:31:40 +0000 (20:31 +0100)
Our write pattern is quite awful for CoW file systems (btrfs...), as we
keep updating file parts in the beginning of the file. This results in
fragmented journal files. Hence: when rotating files, defragment them,
since at that point we know that no further write accesses will be made.

src/journal/journal-file.c
src/journal/journal-file.h
src/shared/btrfs-util.c
src/shared/btrfs-util.h

index 304ce03bdd6f480e29b0eb2b67d701f43214a9b3..4c7dd242e1ecab850d06b47611864dbd14179a18 100644 (file)
@@ -27,6 +27,7 @@
 #include <fcntl.h>
 #include <stddef.h>
 
 #include <fcntl.h>
 #include <stddef.h>
 
+#include "btrfs-util.h"
 #include "journal-def.h"
 #include "journal-file.h"
 #include "journal-authenticate.h"
 #include "journal-def.h"
 #include "journal-file.h"
 #include "journal-authenticate.h"
@@ -140,6 +141,9 @@ void journal_file_close(JournalFile *f) {
         if (f->mmap && f->fd >= 0)
                 mmap_cache_close_fd(f->mmap, f->fd);
 
         if (f->mmap && f->fd >= 0)
                 mmap_cache_close_fd(f->mmap, f->fd);
 
+        if (f->fd >= 0 && f->defrag_on_close)
+                btrfs_defrag_fd(f->fd);
+
         safe_close(f->fd);
         free(f->path);
 
         safe_close(f->fd);
         free(f->path);
 
@@ -2741,6 +2745,11 @@ int journal_file_rotate(JournalFile **f, bool compress, bool seal) {
 
         old_file->header->state = STATE_ARCHIVED;
 
 
         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);
 
         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);
 
@@ -2796,6 +2805,10 @@ int journal_file_open_reliably(
         if (r < 0)
                 return -errno;
 
         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) 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,
         log_warning("File %s corrupted or uncleanly shut down, renaming and replacing.", fname);
 
         return journal_file_open(fname, flags, mode, compress, seal,
index b3a0679b9e25b5e859481d7a7022817f2f336bce..6812385e1ef63f3767089705a6ee800f1b4428b4 100644 (file)
@@ -73,6 +73,7 @@ typedef struct JournalFile {
         bool compress_xz:1;
         bool compress_lz4:1;
         bool seal:1;
         bool compress_xz:1;
         bool compress_lz4:1;
         bool seal:1;
+        bool defrag_on_close:1;
 
         bool tail_entry_monotonic_valid:1;
 
 
         bool tail_entry_monotonic_valid:1;
 
index 164ac9f337c8522c5ec393cd9f82ec7573918140..e648121b47fe593d0ad87cb8d125b63a1080c2e2 100644 (file)
@@ -531,3 +531,22 @@ finish:
 
         return 0;
 }
 
         return 0;
 }
+
+int btrfs_defrag_fd(int fd) {
+        assert(fd >= 0);
+
+        if (ioctl(fd, BTRFS_IOC_DEFRAG, NULL) < 0)
+                return -errno;
+
+        return 0;
+}
+
+int btrfs_defrag(const char *p) {
+        _cleanup_close_ int fd = -1;
+
+        fd = open(p, O_RDWR|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW);
+        if (fd < 0)
+                return -errno;
+
+        return btrfs_defrag_fd(fd);
+}
index 1532c120df127e803b07157dbb293f4c4eefd33a..1bff9171d7e1b96e76455e81021d9abb1dea8d77 100644 (file)
@@ -57,3 +57,6 @@ int btrfs_subvol_get_quota_fd(int fd, BtrfsQuotaInfo *quota);
 int btrfs_reflink(int infd, int outfd);
 
 int btrfs_get_block_device(const char *path, dev_t *dev);
 int btrfs_reflink(int infd, int outfd);
 
 int btrfs_get_block_device(const char *path, dev_t *dev);
+
+int btrfs_defrag_fd(int fd);
+int btrfs_defrag(const char *p);