X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Fjournal%2Fjournal-file.c;h=4de1daf6a0b177bed7105fc32ea493cc8da4a95c;hb=fd8ee359a014916ac62ae2b58f6736ccb48c6d4e;hp=190bfb996b3a36feb890d94635606464f1a6d964;hpb=dc1ecd78e9f046880d10ddb45cf9b06df1084b10;p=elogind.git diff --git a/src/journal/journal-file.c b/src/journal/journal-file.c index 190bfb996..4de1daf6a 100644 --- a/src/journal/journal-file.c +++ b/src/journal/journal-file.c @@ -39,6 +39,25 @@ #define COMPRESSION_SIZE_THRESHOLD (64ULL) +/* This is the minimum journal file size */ +#define JOURNAL_FILE_SIZE_MIN (64ULL*1024ULL) + +/* These are the lower and upper bounds if we deduce the max_use value + * from the file system size */ +#define DEFAULT_MAX_USE_LOWER (1ULL*1024ULL*1024ULL) /* 1 MiB */ +#define DEFAULT_MAX_USE_UPPER (4ULL*1024ULL*1024ULL*1024ULL) /* 4 GiB */ + +/* This is the upper bound if we deduce max_size from max_use */ +#define DEFAULT_MAX_SIZE_UPPER (16ULL*1024ULL*1024ULL) /* 16 MiB */ + +/* This is the upper bound if we deduce the keep_free value from the + * file system size */ +#define DEFAULT_KEEP_FREE_UPPER (4ULL*1024ULL*1024ULL*1024ULL) /* 4 GiB */ + +/* This is the keep_free value when we can't determine the system + * size */ +#define DEFAULT_KEEP_FREE (1024ULL*1024ULL) /* 1 MB */ + static const char signature[] = { 'L', 'P', 'K', 'S', 'H', 'H', 'R', 'H' }; #define ALIGN64(x) (((x) + 7ULL) & ~7ULL) @@ -119,6 +138,9 @@ static int journal_file_refresh_header(JournalFile *f) { f->header->boot_id = boot_id; f->header->state = STATE_ONLINE; + + __sync_synchronize(); + return 0; } @@ -264,7 +286,7 @@ static int journal_file_map( } static int journal_file_move_to(JournalFile *f, int wt, uint64_t offset, uint64_t size, void **ret) { - void *p; + void *p = NULL; uint64_t delta; int r; Window *w; @@ -274,6 +296,15 @@ static int journal_file_move_to(JournalFile *f, int wt, uint64_t offset, uint64_ assert(wt >= 0); assert(wt < _WINDOW_MAX); + if (offset + size > (uint64_t) f->last_stat.st_size) { + /* Hmm, out of range? Let's refresh the fstat() data + * first, before we trust that check. */ + + if (fstat(f->fd, &f->last_stat) < 0 || + offset + size > (uint64_t) f->last_stat.st_size) + return -EADDRNOTAVAIL; + } + w = f->windows + wt; if (_likely_(w->ptr && @@ -301,17 +332,14 @@ static int journal_file_move_to(JournalFile *f, int wt, uint64_t offset, uint64_ delta = PAGE_ALIGN((DEFAULT_WINDOW_SIZE - size) / 2); - if (offset < delta) + if (delta > offset) delta = offset; offset -= delta; - size += (DEFAULT_WINDOW_SIZE - delta); + size = DEFAULT_WINDOW_SIZE; } else delta = 0; - if (offset > (uint64_t) f->last_stat.st_size) - return -EADDRNOTAVAIL; - if (offset + size > (uint64_t) f->last_stat.st_size) size = PAGE_ALIGN((uint64_t) f->last_stat.st_size - offset); @@ -879,6 +907,8 @@ static int journal_file_link_entry(JournalFile *f, Object *o, uint64_t offset) { assert(offset > 0); assert(o->object.type == OBJECT_ENTRY); + __sync_synchronize(); + /* Link up the entry itself */ r = link_entry_into_array(f, &f->header->entry_array_offset, @@ -986,9 +1016,6 @@ int journal_file_append_entry(JournalFile *f, const dual_timestamp *ts, const st ts->monotonic < le64toh(f->header->tail_entry_monotonic)) return -EINVAL; - if (ts->realtime < le64toh(f->header->tail_entry_realtime)) - return -EINVAL; - items = alloca(sizeof(EntryItem) * n_iovec); for (i = 0; i < n_iovec; i++) { @@ -1017,7 +1044,7 @@ static int generic_array_get(JournalFile *f, Object **ret, uint64_t *offset) { Object *o; - uint64_t p, a; + uint64_t p = 0, a; int r; assert(f); @@ -1701,10 +1728,6 @@ int journal_file_open( f->writable = (flags & O_ACCMODE) != O_RDONLY; f->prot = prot_from_flags(flags); - f->metrics.max_size = DEFAULT_MAX_SIZE; - f->metrics.min_size = DEFAULT_MIN_SIZE; - f->metrics.keep_free = DEFAULT_KEEP_FREE; - f->path = strdup(fname); if (!f->path) { r = -ENOMEM; @@ -1877,7 +1900,7 @@ int journal_directory_vacuum(const char *directory, uint64_t max_use, uint64_t m assert(directory); if (max_use <= 0) - max_use = DEFAULT_MAX_USE; + return 0; d = opendir(directory); if (!d) @@ -2076,3 +2099,78 @@ int journal_file_copy_entry(JournalFile *from, JournalFile *to, Object *o, uint6 return journal_file_append_entry_internal(to, &ts, xor_hash, items, n, seqnum, ret, offset); } + +void journal_default_metrics(JournalMetrics *m, int fd) { + uint64_t fs_size = 0; + struct statvfs ss; + char a[64], b[64], c[64], d[64]; + + assert(m); + assert(fd >= 0); + + if (fstatvfs(fd, &ss) >= 0) + fs_size = ss.f_frsize * ss.f_blocks; + + if (m->max_use == (uint64_t) -1) { + + if (fs_size > 0) { + m->max_use = PAGE_ALIGN(fs_size / 10); /* 10% of file system size */ + + if (m->max_use > DEFAULT_MAX_USE_UPPER) + m->max_use = DEFAULT_MAX_USE_UPPER; + + if (m->max_use < DEFAULT_MAX_USE_LOWER) + m->max_use = DEFAULT_MAX_USE_LOWER; + } else + m->max_use = DEFAULT_MAX_USE_LOWER; + } else { + m->max_use = PAGE_ALIGN(m->max_use); + + if (m->max_use < JOURNAL_FILE_SIZE_MIN*2) + m->max_use = JOURNAL_FILE_SIZE_MIN*2; + } + + if (m->max_size == (uint64_t) -1) { + m->max_size = PAGE_ALIGN(m->max_use / 8); /* 8 chunks */ + + if (m->max_size > DEFAULT_MAX_SIZE_UPPER) + m->max_size = DEFAULT_MAX_SIZE_UPPER; + } else + m->max_size = PAGE_ALIGN(m->max_size); + + if (m->max_size < JOURNAL_FILE_SIZE_MIN) + m->max_size = JOURNAL_FILE_SIZE_MIN; + + if (m->max_size*2 > m->max_use) + m->max_use = m->max_size*2; + + if (m->min_size == (uint64_t) -1) + m->min_size = JOURNAL_FILE_SIZE_MIN; + else { + m->min_size = PAGE_ALIGN(m->min_size); + + if (m->min_size < JOURNAL_FILE_SIZE_MIN) + m->min_size = JOURNAL_FILE_SIZE_MIN; + + if (m->min_size > m->max_size) + m->max_size = m->min_size; + } + + if (m->keep_free == (uint64_t) -1) { + + if (fs_size > 0) { + m->keep_free = PAGE_ALIGN(fs_size / 20); /* 5% of file system size */ + + if (m->keep_free > DEFAULT_KEEP_FREE_UPPER) + m->keep_free = DEFAULT_KEEP_FREE_UPPER; + + } else + m->keep_free = DEFAULT_KEEP_FREE; + } + + log_debug("Fixed max_use=%s max_size=%s min_size=%s keep_free=%s", + format_bytes(a, sizeof(a), m->max_use), + format_bytes(b, sizeof(b), m->max_size), + format_bytes(c, sizeof(c), m->min_size), + format_bytes(d, sizeof(d), m->keep_free)); +}