File add-upstream-btrfs-journal-fragmentation-fixes.patch of Package systemd.1059
diff -Naur systemd-210/Makefile.am systemd-210.mod/Makefile.am
--- systemd-210/Makefile.am 2015-01-15 14:00:36.153136568 +0100
+++ systemd-210.mod/Makefile.am 2015-01-19 14:38:08.150615856 +0100
@@ -779,7 +779,10 @@
src/shared/condition-util.c \
src/shared/condition-util.h \
src/shared/bus-label.c \
- src/shared/bus-label.h
+ src/shared/bus-label.h \
+ src/shared/btrfs-util.c \
+ src/shared/btrfs-util.h
+
nodist_libsystemd_shared_la_SOURCES = \
src/shared/errno-from-name.h \
@@ -820,7 +823,7 @@
src/shared/fileio-label.c \
src/shared/fileio-label.h \
src/shared/dev-setup.c \
- src/shared/dev-setup.h
+ src/shared/dev-setup.h
libsystemd_label_la_CFLAGS = \
$(AM_CFLAGS) \
diff -Naur systemd-210/src/journal/journalctl.c systemd-210.mod/src/journal/journalctl.c
--- systemd-210/src/journal/journalctl.c 2015-01-15 14:00:36.022136058 +0100
+++ systemd-210.mod/src/journal/journalctl.c 2015-01-19 13:22:39.747737834 +0100
@@ -1219,7 +1219,7 @@
size_t mpk_size, seed_size, state_size, i;
uint8_t *mpk, *seed, *state;
ssize_t l;
- int fd = -1, r, attr = 0;
+ int fd = -1, r;
sd_id128_t machine, boot;
char *p = NULL, *k = NULL;
struct FSSHeader h;
@@ -1320,13 +1320,9 @@
/* Enable secure remove, exclusion from dump, synchronous
* writing and in-place updating */
- if (ioctl(fd, FS_IOC_GETFLAGS, &attr) < 0)
- log_warning("FS_IOC_GETFLAGS failed: %m");
-
- attr |= FS_SECRM_FL|FS_NODUMP_FL|FS_SYNC_FL|FS_NOCOW_FL;
-
- if (ioctl(fd, FS_IOC_SETFLAGS, &attr) < 0)
- log_warning("FS_IOC_SETFLAGS failed: %m");
+ r = chattr_fd(fd, true, FS_SECRM_FL|FS_NODUMP_FL|FS_SYNC_FL|FS_NOCOW_FL);
+ if (r < 0)
+ log_warning("Failed to set file attributes: %m");
zero(h);
memcpy(h.signature, "KSHHRHLP", 8);
diff -Naur systemd-210/src/journal/journal-file.c systemd-210.mod/src/journal/journal-file.c
--- systemd-210/src/journal/journal-file.c 2015-01-15 14:00:36.016136035 +0100
+++ systemd-210.mod/src/journal/journal-file.c 2015-01-19 14:02:07.313619805 +0100
@@ -26,8 +26,10 @@
#include <sys/statvfs.h>
#include <fcntl.h>
#include <stddef.h>
+#include <linux/fs.h>
#include <sys/xattr.h>
+#include "btrfs-util.h"
#include "journal-def.h"
#include "journal-file.h"
#include "journal-authenticate.h"
@@ -125,6 +127,18 @@
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);
+ }
+
journal_file_set_offline(f);
if (f->header)
@@ -2514,6 +2528,17 @@
if (f->last_stat.st_size == 0 && f->writable) {
uint64_t crtime;
+ /* 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)
+ log_warning("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
@@ -2658,6 +2683,11 @@
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);
@@ -2712,6 +2742,11 @@
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,
diff -Naur systemd-210/src/journal/journal-file.h systemd-210.mod/src/journal/journal-file.h
--- systemd-210/src/journal/journal-file.h 2015-01-15 14:00:35.910135623 +0100
+++ systemd-210.mod/src/journal/journal-file.h 2015-01-16 16:54:26.846047051 +0100
@@ -58,7 +58,7 @@
bool writable:1;
bool compress:1;
bool seal:1;
-
+ bool defrag_on_close:1;
bool tail_entry_monotonic_valid:1;
direction_t last_direction;
diff -Naur systemd-210/src/shared/btrfs-util.c systemd-210.mod/src/shared/btrfs-util.c
--- systemd-210/src/shared/btrfs-util.c 1970-01-01 01:00:00.000000000 +0100
+++ systemd-210.mod/src/shared/btrfs-util.c 2015-01-19 12:12:45.502318392 +0100
@@ -0,0 +1,56 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+ This file is part of systemd.
+
+ Copyright 2014 Lennart Poettering
+
+ systemd is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ systemd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include <stdlib.h>
+#include <sys/vfs.h>
+#include <sys/stat.h>
+
+#ifdef HAVE_LINUX_BTRFS_H
+#include <linux/btrfs.h>
+#endif
+
+#include "missing.h"
+#include "util.h"
+#include "path-util.h"
+#include "macro.h"
+#include "strv.h"
+#include "selinux-util.h"
+#include "smack-util.h"
+#include "btrfs-util.h"
+
+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 -Naur systemd-210/src/shared/btrfs-util.h systemd-210.mod/src/shared/btrfs-util.h
--- systemd-210/src/shared/btrfs-util.h 1970-01-01 01:00:00.000000000 +0100
+++ systemd-210.mod/src/shared/btrfs-util.h 2015-01-16 16:48:29.746609450 +0100
@@ -0,0 +1,28 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+ This file is part of systemd.
+
+ Copyright 2014 Lennart Poettering
+
+ systemd is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ systemd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include <stdbool.h>
+#include <sys/types.h>
+
+#include "time-util.h"
+
+int btrfs_defrag_fd(int fd);
+int btrfs_defrag(const char *p);
diff -Naur systemd-210/src/shared/util.c systemd-210.mod/src/shared/util.c
--- systemd-210/src/shared/util.c 2015-01-15 14:00:36.027136078 +0100
+++ systemd-210.mod/src/shared/util.c 2015-01-16 17:18:22.601775285 +0100
@@ -61,6 +61,7 @@
#include <locale.h>
#include <sys/personality.h>
#include <libgen.h>
+#include <linux/fs.h>
#undef basename
#ifdef HAVE_SYS_AUXV_H
@@ -6518,3 +6519,35 @@
return NULL;
}
+
+int chattr_fd(int fd, bool b, int mask) {
+ int old_attr, new_attr;
+
+ assert(fd >= 0);
+
+ if (ioctl(fd, FS_IOC_GETFLAGS, &old_attr) < 0)
+ return -errno;
+
+ if (b)
+ new_attr = old_attr | mask;
+ else
+ new_attr = old_attr & ~mask;
+
+ if (new_attr == old_attr)
+ return 0;
+
+ if (ioctl(fd, FS_IOC_SETFLAGS, &new_attr) < 0)
+ return -errno;
+
+ return 0;
+}
+
+int chattr_path(const char *p, bool b, int mask) {
+ _cleanup_close_ int fd = -1;
+
+ fd = open(p, O_RDWR|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW);
+ if (fd < 0)
+ return -errno;
+
+ return chattr_fd(fd, b, mask);
+}
diff -Naur systemd-210/src/shared/util.h systemd-210.mod/src/shared/util.h
--- systemd-210/src/shared/util.h 2015-01-15 14:00:36.026136074 +0100
+++ systemd-210.mod/src/shared/util.h 2015-01-16 17:19:18.406996683 +0100
@@ -901,3 +901,6 @@
int umount_recursive(const char *target, int flags);
int sethostname_idempotent(const char *s);
+
+int chattr_fd(int fd, bool b, int mask);
+int chattr_path(const char *p, bool b, int mask);