X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Fjournal%2Fjournal-file.c;h=ec12e891a791a8d0b3b07f992b4bd21c350ef244;hb=56e6c2abb8f18bba2bb9d96d66ac7e633349ddfb;hp=304ce03bdd6f480e29b0eb2b67d701f43214a9b3;hpb=2678031a179a9b91fc799f8ef951a548c66c4b49;p=elogind.git diff --git a/src/journal/journal-file.c b/src/journal/journal-file.c index 304ce03bd..ec12e891a 100644 --- a/src/journal/journal-file.c +++ b/src/journal/journal-file.c @@ -26,7 +26,9 @@ #include #include #include +#include +#include "btrfs-util.h" #include "journal-def.h" #include "journal-file.h" #include "journal-authenticate.h" @@ -140,6 +142,18 @@ 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) { + + /* 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); @@ -309,7 +323,7 @@ static int journal_file_verify_header(JournalFile *f) { } else if (state == STATE_ARCHIVED) return -ESHUTDOWN; else if (state != STATE_OFFLINE) { - log_debug("Journal file %s has unknown state %u.", f->path, state); + log_debug("Journal file %s has unknown state %i.", f->path, state); return -EBUSY; } } @@ -2403,7 +2417,7 @@ void journal_file_dump(JournalFile *f) { break; default: - printf("Type: unknown (%u)\n", o->object.type); + printf("Type: unknown (%i)\n", o->object.type); break; } @@ -2587,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 @@ -2597,7 +2623,7 @@ int journal_file_open( * attributes are not supported we'll just skip this, * and rely solely on mtime/atime/ctime of the file. */ - fd_setcrtime(f->fd, now(CLOCK_REALTIME)); + fd_setcrtime(f->fd, 0); #ifdef HAVE_GCRYPT /* Try to load the FSPRG state, and if we can't, then @@ -2741,6 +2767,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); @@ -2771,7 +2802,8 @@ int journal_file_open_reliably( r != -EPROTONOSUPPORT && /* incompatible feature */ r != -EBUSY && /* unclean shutdown */ r != -ESHUTDOWN && /* already archived */ - r != -EIO /* IO error, including SIGBUS on mmap */) + r != -EIO && /* IO error, including SIGBUS on mmap */ + r != -EIDRM /* File has been deleted */) return r; if ((flags & O_ACCMODE) == O_RDONLY) @@ -2796,6 +2828,12 @@ 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) 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,