X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=src%2Fjournal%2Fjournal-file.c;h=9665a0535bc038d62ca16a7b756851e2239721d6;hp=c7ebcdb25cbe57315c4e1ada08a651760c61452b;hb=91a31dde6e92c0d4c42abadf970083f6faba87ec;hpb=4fd052aede13eb3041277c54ac2f5dee6e6c29cf diff --git a/src/journal/journal-file.c b/src/journal/journal-file.c index c7ebcdb25..9665a0535 100644 --- a/src/journal/journal-file.c +++ b/src/journal/journal-file.c @@ -6,16 +6,16 @@ Copyright 2011 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ @@ -35,7 +35,7 @@ #define DEFAULT_DATA_HASH_TABLE_SIZE (2047ULL*16ULL) #define DEFAULT_FIELD_HASH_TABLE_SIZE (2047ULL*16ULL) -#define DEFAULT_WINDOW_SIZE (128ULL*1024ULL*1024ULL) +#define DEFAULT_WINDOW_SIZE (8ULL*1024ULL*1024ULL) #define COMPRESSION_SIZE_THRESHOLD (512ULL) @@ -67,9 +67,12 @@ void journal_file_close(JournalFile *f) { assert(f); - if (f->header && f->writable) - f->header->state = STATE_OFFLINE; + if (f->header) { + if (f->writable) + f->header->state = STATE_OFFLINE; + munmap(f->header, PAGE_ALIGN(sizeof(Header))); + } for (t = 0; t < _WINDOW_MAX; t++) if (f->windows[t].ptr) @@ -96,7 +99,7 @@ static int journal_file_init_header(JournalFile *f, JournalFile *template) { zero(h); memcpy(h.signature, signature, 8); - h.arena_offset = htole64(ALIGN64(sizeof(h))); + h.header_size = htole64(ALIGN64(sizeof(h))); r = sd_id128_randomize(&h.file_id); if (r < 0) @@ -158,7 +161,10 @@ static int journal_file_verify_header(JournalFile *f) { return -EPROTONOSUPPORT; #endif - if ((uint64_t) f->last_stat.st_size < (le64toh(f->header->arena_offset) + le64toh(f->header->arena_size))) + if (f->header->header_size != htole64(ALIGN64(sizeof(*(f->header))))) + return -EBADMSG; + + if ((uint64_t) f->last_stat.st_size < (le64toh(f->header->header_size) + le64toh(f->header->arena_size))) return -ENODATA; if (f->writable) { @@ -177,6 +183,7 @@ static int journal_file_verify_header(JournalFile *f) { if (state == STATE_ONLINE) log_debug("Journal file %s is already online. Assuming unclean closing. Ignoring.", f->path); + /* FIXME: immediately rotate */ else if (state == STATE_ARCHIVED) return -ESHUTDOWN; else if (state != STATE_OFFLINE) @@ -188,6 +195,7 @@ static int journal_file_verify_header(JournalFile *f) { static int journal_file_allocate(JournalFile *f, uint64_t offset, uint64_t size) { uint64_t old_size, new_size; + int r; assert(f); @@ -196,12 +204,12 @@ static int journal_file_allocate(JournalFile *f, uint64_t offset, uint64_t size) * ourselves */ old_size = - le64toh(f->header->arena_offset) + + le64toh(f->header->header_size) + le64toh(f->header->arena_size); new_size = PAGE_ALIGN(offset + size); - if (new_size < le64toh(f->header->arena_offset)) - new_size = le64toh(f->header->arena_offset); + if (new_size < le64toh(f->header->header_size)) + new_size = le64toh(f->header->header_size); if (new_size <= old_size) return 0; @@ -232,13 +240,14 @@ static int journal_file_allocate(JournalFile *f, uint64_t offset, uint64_t size) /* Note that the glibc fallocate() fallback is very inefficient, hence we try to minimize the allocation area as we can. */ - if (posix_fallocate(f->fd, old_size, new_size - old_size) < 0) - return -errno; + r = posix_fallocate(f->fd, old_size, new_size - old_size); + if (r != 0) + return -r; if (fstat(f->fd, &f->last_stat) < 0) return -errno; - f->header->arena_size = htole64(new_size - le64toh(f->header->arena_offset)); + f->header->arena_size = htole64(new_size - le64toh(f->header->header_size)); return 0; } @@ -452,7 +461,7 @@ static int journal_file_append_object(JournalFile *f, int type, uint64_t size, O p = le64toh(f->header->tail_object_offset); if (p == 0) - p = le64toh(f->header->arena_offset); + p = le64toh(f->header->header_size); else { r = journal_file_move_to_object(f, -1, p, &tail); if (r < 0) @@ -588,7 +597,7 @@ static int journal_file_link_data(JournalFile *f, Object *o, uint64_t offset, ui o->data.n_entries = 0; h = hash % (le64toh(f->header->data_hash_table_size) / sizeof(HashItem)); - p = le64toh(f->data_hash_table[h].head_hash_offset); + p = le64toh(f->data_hash_table[h].tail_hash_offset); if (p == 0) { /* Only entry in the hash table is easy */ f->data_hash_table[h].head_hash_offset = htole64(offset); @@ -1266,7 +1275,11 @@ static int generic_array_bisect_plus_one(JournalFile *f, r = test_object(f, extra, needle); if (r < 0) return r; - else if (r == TEST_FOUND) { + + if (r == TEST_FOUND) + r = direction == DIRECTION_DOWN ? TEST_RIGHT : TEST_LEFT; + + if (r == TEST_RIGHT) { Object *o; r = journal_file_move_to_object(f, OBJECT_ENTRY, extra, &o); @@ -1283,12 +1296,11 @@ static int generic_array_bisect_plus_one(JournalFile *f, *idx = 0; return 1; - } else if (r == TEST_RIGHT) - return 0; + } r = generic_array_bisect(f, first, n-1, needle, test_object, direction, ret, offset, idx); - if (r > 0) + if (r > 0 && idx) (*idx) ++; return r; @@ -1391,11 +1403,11 @@ int journal_file_move_to_entry_by_monotonic( Object **ret, uint64_t *offset) { - char t[8+32+1] = "_BOOT_ID="; + char t[9+32+1] = "_BOOT_ID="; Object *o; int r; - sd_id128_to_string(boot_id, t + 8); + sd_id128_to_string(boot_id, t + 9); r = journal_file_find_data_object(f, t, strlen(t), &o, NULL); if (r < 0) @@ -1599,8 +1611,10 @@ int journal_file_move_to_entry_by_seqnum_for_data( Object *d; int r; + assert(f); + r = journal_file_move_to_object(f, OBJECT_DATA, data_offset, &d); - if (r <= 0) + if (r < 0) return r; return generic_array_bisect_plus_one(f, @@ -1623,8 +1637,10 @@ int journal_file_move_to_entry_by_realtime_for_data( Object *d; int r; + assert(f); + r = journal_file_move_to_object(f, OBJECT_DATA, data_offset, &d); - if (r <= 0) + if (r < 0) return r; return generic_array_bisect_plus_one(f, @@ -1660,7 +1676,7 @@ void journal_file_dump(JournalFile *f) { (unsigned long) le64toh(f->header->n_objects), (unsigned long) le64toh(f->header->n_entries)); - p = le64toh(f->header->arena_offset); + p = le64toh(f->header->header_size); while (p != 0) { r = journal_file_move_to_object(f, -1, p, &o); if (r < 0) @@ -1694,6 +1710,10 @@ void journal_file_dump(JournalFile *f) { case OBJECT_ENTRY_ARRAY: printf("Type: OBJECT_ENTRY_ARRAY\n"); break; + + case OBJECT_SIGNATURE: + printf("Type: OBJECT_SIGNATURE\n"); + break; } if (o->object.flags & OBJECT_COMPRESSED) @@ -1977,7 +1997,7 @@ int journal_directory_vacuum(const char *directory, uint64_t max_use, uint64_t m size_t q; struct stat st; char *p; - unsigned long long seqnum, realtime; + unsigned long long seqnum = 0, realtime; sd_id128_t seqnum_id; bool have_seqnum; @@ -2272,3 +2292,74 @@ void journal_default_metrics(JournalMetrics *m, int fd) { format_bytes(c, sizeof(c), m->min_size), format_bytes(d, sizeof(d), m->keep_free)); } + +int journal_file_get_cutoff_realtime_usec(JournalFile *f, usec_t *from, usec_t *to) { + Object *o; + int r; + + assert(f); + assert(from || to); + + if (from) { + r = journal_file_next_entry(f, NULL, 0, DIRECTION_DOWN, &o, NULL); + if (r <= 0) + return r; + + *from = le64toh(o->entry.realtime); + } + + if (to) { + r = journal_file_next_entry(f, NULL, 0, DIRECTION_UP, &o, NULL); + if (r <= 0) + return r; + + *to = le64toh(o->entry.realtime); + } + + return 1; +} + +int journal_file_get_cutoff_monotonic_usec(JournalFile *f, sd_id128_t boot_id, usec_t *from, usec_t *to) { + char t[9+32+1] = "_BOOT_ID="; + Object *o; + uint64_t p; + int r; + + assert(f); + assert(from || to); + + sd_id128_to_string(boot_id, t + 9); + + r = journal_file_find_data_object(f, t, strlen(t), &o, &p); + if (r <= 0) + return r; + + if (le64toh(o->data.n_entries) <= 0) + return 0; + + if (from) { + r = journal_file_move_to_object(f, OBJECT_ENTRY, le64toh(o->data.entry_offset), &o); + if (r < 0) + return r; + + *from = le64toh(o->entry.monotonic); + } + + if (to) { + r = journal_file_move_to_object(f, OBJECT_DATA, p, &o); + if (r < 0) + return r; + + r = generic_array_get_plus_one(f, + le64toh(o->data.entry_offset), + le64toh(o->data.entry_array_offset), + le64toh(o->data.n_entries)-1, + &o, NULL); + if (r <= 0) + return r; + + *to = le64toh(o->entry.monotonic); + } + + return 1; +}