#include <sys/statvfs.h>
#include <fcntl.h>
#include <stddef.h>
+#include <linux/fs.h>
#include "btrfs-util.h"
#include "journal-def.h"
#include "journal-authenticate.h"
#include "lookup3.h"
#include "compress.h"
-#include "fsprg.h"
#define DEFAULT_DATA_HASH_TABLE_SIZE (2047ULL*sizeof(HashItem))
#define DEFAULT_FIELD_HASH_TABLE_SIZE (333ULL*sizeof(HashItem))
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);
} 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;
}
}
return TEST_RIGHT;
}
-static inline int find_data_object_by_boot_id(
+static int find_data_object_by_boot_id(
JournalFile *f,
sd_id128_t boot_id,
Object **o,
uint64_t *b) {
+
char t[sizeof("_BOOT_ID=")-1 + 32 + 1] = "_BOOT_ID=";
sd_id128_to_string(boot_id, t + 9);
f->current_xor_hash = 0;
}
-void journal_file_save_location(JournalFile *f, direction_t direction, Object *o, uint64_t offset) {
- f->last_direction = direction;
+void journal_file_save_location(JournalFile *f, Object *o, uint64_t offset) {
f->location_type = LOCATION_SEEK;
f->current_offset = offset;
f->current_seqnum = le64toh(o->entry.seqnum);
break;
default:
- printf("Type: unknown (%u)\n", o->object.type);
+ printf("Type: unknown (%i)\n", o->object.type);
break;
}
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 && r != -ENOTTY)
+ log_warning_errno(r, "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
* 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
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)
/* 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);