#include <sys/statvfs.h>
#include <fcntl.h>
#include <stddef.h>
+#include <linux/fs.h>
#include "btrfs-util.h"
#include "journal-def.h"
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);
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
/* 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);
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;
/* 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);
#include <sys/xattr.h>
#include <libgen.h>
#include <sys/statvfs.h>
+#include <linux/fs.h>
#undef basename
#ifdef HAVE_SYS_AUXV_H
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);
+}
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);