From f27a386430cc7a27ebd06899d93310fb3bd4cee7 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 6 Jan 2015 19:51:03 +0100 Subject: [PATCH] journald: whenever we rotate a file, btrfs defrag it 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 | 13 +++++++++++++ src/journal/journal-file.h | 1 + src/shared/btrfs-util.c | 19 +++++++++++++++++++ src/shared/btrfs-util.h | 3 +++ 4 files changed, 36 insertions(+) diff --git a/src/journal/journal-file.c b/src/journal/journal-file.c index 304ce03bd..4c7dd242e 100644 --- a/src/journal/journal-file.c +++ b/src/journal/journal-file.c @@ -27,6 +27,7 @@ #include #include +#include "btrfs-util.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->fd >= 0 && f->defrag_on_close) + btrfs_defrag_fd(f->fd); + 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; + /* 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); @@ -2796,6 +2805,10 @@ 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) 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, diff --git a/src/journal/journal-file.h b/src/journal/journal-file.h index b3a0679b9..6812385e1 100644 --- a/src/journal/journal-file.h +++ b/src/journal/journal-file.h @@ -73,6 +73,7 @@ typedef struct JournalFile { bool compress_xz:1; bool compress_lz4:1; bool seal:1; + bool defrag_on_close:1; bool tail_entry_monotonic_valid:1; diff --git a/src/shared/btrfs-util.c b/src/shared/btrfs-util.c index 164ac9f33..e648121b4 100644 --- a/src/shared/btrfs-util.c +++ b/src/shared/btrfs-util.c @@ -531,3 +531,22 @@ finish: 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); +} diff --git a/src/shared/btrfs-util.h b/src/shared/btrfs-util.h index 1532c120d..1bff9171d 100644 --- a/src/shared/btrfs-util.h +++ b/src/shared/btrfs-util.h @@ -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_defrag_fd(int fd); +int btrfs_defrag(const char *p); -- 2.30.2