summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/journal/journal-file.c13
-rw-r--r--src/journal/journal-file.h1
-rw-r--r--src/shared/btrfs-util.c19
-rw-r--r--src/shared/btrfs-util.h3
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);