diff options
-rw-r--r-- | src/journal/journal-file.c | 13 | ||||
-rw-r--r-- | src/journal/journal-file.h | 1 | ||||
-rw-r--r-- | src/shared/btrfs-util.c | 19 | ||||
-rw-r--r-- | src/shared/btrfs-util.h | 3 |
4 files changed, 36 insertions, 0 deletions
diff --git a/src/journal/journal-file.c b/src/journal/journal-file.c index 304ce03bdd..4c7dd242e1 100644 --- a/src/journal/journal-file.c +++ b/src/journal/journal-file.c @@ -27,6 +27,7 @@ #include <fcntl.h> #include <stddef.h> +#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 b3a0679b9e..6812385e1e 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 164ac9f337..e648121b47 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 1532c120df..1bff9171d7 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); |