diff options
-rw-r--r-- | src/journal/journal-file.c | 28 | ||||
-rw-r--r-- | src/journal/journalctl.c | 12 | ||||
-rw-r--r-- | src/shared/util.c | 33 | ||||
-rw-r--r-- | src/shared/util.h | 3 |
4 files changed, 66 insertions, 10 deletions
diff --git a/src/journal/journal-file.c b/src/journal/journal-file.c index c9030c56ad..c20af5d9bf 100644 --- a/src/journal/journal-file.c +++ b/src/journal/journal-file.c @@ -26,6 +26,7 @@ #include <sys/statvfs.h> #include <fcntl.h> #include <stddef.h> +#include <linux/fs.h> #include "btrfs-util.h" #include "journal-def.h" @@ -141,8 +142,17 @@ 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); + 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); + } safe_close(f->fd); free(f->path); @@ -2591,6 +2601,18 @@ int journal_file_open( goto fail; if (f->last_stat.st_size == 0 && f->writable) { + + /* 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_errno(errno, "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 @@ -2808,6 +2830,8 @@ int journal_file_open_reliably( /* 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); diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index 386e3505c0..62931f14c9 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -1294,7 +1294,7 @@ static int setup_keys(void) { 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; @@ -1389,13 +1389,9 @@ static int setup_keys(void) { /* Enable secure remove, exclusion from dump, synchronous * writing and in-place updating */ - if (ioctl(fd, FS_IOC_GETFLAGS, &attr) < 0) - log_warning_errno(errno, "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_errno(errno, "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_errno(errno, "Failed to set file attributes: %m"); zero(h); memcpy(h.signature, "KSHHRHLP", 8); diff --git a/src/shared/util.c b/src/shared/util.c index 6293e967c8..88fd78ec8d 100644 --- a/src/shared/util.c +++ b/src/shared/util.c @@ -62,6 +62,7 @@ #include <sys/xattr.h> #include <libgen.h> #include <sys/statvfs.h> +#include <linux/fs.h> #undef basename #ifdef HAVE_SYS_AUXV_H @@ -7740,3 +7741,35 @@ int same_fd(int a, int b) { return fa == fb; } + +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 --git a/src/shared/util.h b/src/shared/util.h index 4b7e12e628..31103e957f 100644 --- a/src/shared/util.h +++ b/src/shared/util.h @@ -1071,3 +1071,6 @@ int path_getcrtime(const char *p, usec_t *usec); int fd_getcrtime_at(int dirfd, const char *name, usec_t *usec, int flags); int same_fd(int a, int b); + +int chattr_fd(int fd, bool b, int mask); +int chattr_path(const char *p, bool b, int mask); |