X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Fjournal%2Fsd-journal.c;h=acde84fe2d3138242b08ed1586df7ba1d9af3d5b;hb=f2cc3753ce0e85960f0299855c3b98ba60efa580;hp=672896d57ceb913af96ec91505add9ce37008b68;hpb=7827b1a10f4dfe2c6771b515f28f7ae22e0ae039;p=elogind.git diff --git a/src/journal/sd-journal.c b/src/journal/sd-journal.c index 672896d57..acde84fe2 100644 --- a/src/journal/sd-journal.c +++ b/src/journal/sd-journal.c @@ -357,15 +357,27 @@ _public_ void sd_journal_flush_matches(sd_journal *j) { detach_location(j); } -static int compare_order(JournalFile *af, Object *ao, - JournalFile *bf, Object *bo) { +static int compare_entry_order(JournalFile *af, Object *_ao, + JournalFile *bf, uint64_t bp) { uint64_t a, b; + Object *ao, *bo; + int r; assert(af); - assert(ao); assert(bf); - assert(bo); + assert(_ao); + + /* The mmap cache might invalidate the object from the first + * file if we look at the one from the second file. Hence + * temporarily copy the header of the first one, and look at + * that only. */ + ao = alloca(offsetof(EntryObject, items)); + memcpy(ao, _ao, offsetof(EntryObject, items)); + + r = journal_file_move_to_object(bf, OBJECT_ENTRY, bp, &bo); + if (r < 0) + return strcmp(af->path, bf->path); /* We operate on two different files here, hence we can access * two objects at the same time, which we normally can't. @@ -808,18 +820,17 @@ static int next_beyond_location(sd_journal *j, JournalFile *f, direction_t direc } static int real_journal_next(sd_journal *j, direction_t direction) { - JournalFile *f, *new_current = NULL; + JournalFile *f, *new_file = NULL; + uint64_t new_offset = 0; + Object *o; + uint64_t p; Iterator i; int r; - uint64_t new_offset = 0; - Object *new_entry = NULL; if (!j) return -EINVAL; HASHMAP_FOREACH(f, j->files, i) { - Object *o; - uint64_t p; bool found; r = next_beyond_location(j, f, direction, &o, &p); @@ -829,12 +840,12 @@ static int real_journal_next(sd_journal *j, direction_t direction) { } else if (r == 0) continue; - if (!new_current) + if (!new_file) found = true; else { int k; - k = compare_order(f, o, new_current, new_entry); + k = compare_entry_order(f, o, new_file, new_offset); if (direction == DIRECTION_DOWN) found = k < 0; @@ -843,16 +854,19 @@ static int real_journal_next(sd_journal *j, direction_t direction) { } if (found) { - new_current = f; - new_entry = o; + new_file = f; new_offset = p; } } - if (!new_current) + if (!new_file) return 0; - set_location(j, new_current, new_entry, new_offset); + r = journal_file_move_to_object(new_file, OBJECT_ENTRY, new_offset, &o); + if (r < 0) + return r; + + set_location(j, new_file, o, new_offset); return 1; } @@ -1098,7 +1112,9 @@ static int add_file(sd_journal *j, const char *prefix, const char *filename) { if ((j->flags & SD_JOURNAL_SYSTEM_ONLY) && !(streq(filename, "system.journal") || - (startswith(filename, "system@") && endswith(filename, ".journal")))) + streq(filename, "system.journal~") || + (startswith(filename, "system@") && + (endswith(filename, ".journal") || endswith(filename, ".journal~"))))) return 0; path = strjoin(prefix, "/", filename, NULL); @@ -1116,7 +1132,7 @@ static int add_file(sd_journal *j, const char *prefix, const char *filename) { return 0; } - r = journal_file_open(path, O_RDONLY, 0, NULL, NULL, &f); + r = journal_file_open(path, O_RDONLY, 0, false, false, NULL, j->mmap, NULL, &f); free(path); if (r < 0) { @@ -1233,20 +1249,22 @@ static int add_directory(sd_journal *j, const char *prefix, const char *dirname) m->wd = inotify_add_watch(j->inotify_fd, m->path, IN_CREATE|IN_MOVED_TO|IN_MODIFY|IN_ATTRIB|IN_DELETE| IN_DELETE_SELF|IN_MOVE_SELF|IN_UNMOUNT| - IN_DONT_FOLLOW|IN_ONLYDIR); + IN_ONLYDIR); if (m->wd > 0 && hashmap_put(j->directories_by_wd, INT_TO_PTR(m->wd), m) < 0) inotify_rm_watch(j->inotify_fd, m->wd); } for (;;) { - struct dirent buf, *de; + struct dirent *de; + union dirent_storage buf; - r = readdir_r(d, &buf, &de); + r = readdir_r(d, &buf.de, &de); if (r != 0 || !de) break; - if (dirent_is_file_with_suffix(de, ".journal")) { + if (dirent_is_file_with_suffix(de, ".journal") || + dirent_is_file_with_suffix(de, ".journal~")) { r = add_file(j, m->path, de->d_name); if (r < 0) log_debug("Failed to add file %s/%s: %s", m->path, de->d_name, strerror(-r)); @@ -1310,21 +1328,23 @@ static int add_root_directory(sd_journal *j, const char *p) { m->wd = inotify_add_watch(j->inotify_fd, m->path, IN_CREATE|IN_MOVED_TO|IN_MODIFY|IN_ATTRIB|IN_DELETE| - IN_DONT_FOLLOW|IN_ONLYDIR); + IN_ONLYDIR); if (m->wd > 0 && hashmap_put(j->directories_by_wd, INT_TO_PTR(m->wd), m) < 0) inotify_rm_watch(j->inotify_fd, m->wd); } for (;;) { - struct dirent buf, *de; + struct dirent *de; + union dirent_storage buf; sd_id128_t id; - r = readdir_r(d, &buf, &de); + r = readdir_r(d, &buf.de, &de); if (r != 0 || !de) break; - if (dirent_is_file_with_suffix(de, ".journal")) { + if (dirent_is_file_with_suffix(de, ".journal") || + dirent_is_file_with_suffix(de, ".journal~")) { r = add_file(j, m->path, de->d_name); if (r < 0) log_debug("Failed to add file %s/%s: %s", m->path, de->d_name, strerror(-r)); @@ -1435,6 +1455,15 @@ static sd_journal *journal_new(int flags, const char *path) { return NULL; } + j->mmap = mmap_cache_new(); + if (!j->mmap) { + hashmap_free(j->files); + hashmap_free(j->directories_by_path); + free(j->path); + free(j); + return NULL; + } + return j; } @@ -1523,6 +1552,9 @@ _public_ void sd_journal_close(sd_journal *j) { sd_journal_flush_matches(j); + if (j->mmap) + mmap_cache_unref(j->mmap); + free(j->path); free(j); } @@ -1823,7 +1855,9 @@ static void process_inotify_event(sd_journal *j, struct inotify_event *e) { if (d) { sd_id128_t id; - if (!(e->mask & IN_ISDIR) && e->len > 0 && endswith(e->name, ".journal")) { + if (!(e->mask & IN_ISDIR) && e->len > 0 && + (endswith(e->name, ".journal") || + endswith(e->name, ".journal~"))) { /* Event for a journal file */ @@ -2044,6 +2078,29 @@ void journal_print_header(sd_journal *j) { } } +_public_ int sd_journal_get_usage(sd_journal *j, uint64_t *bytes) { + Iterator i; + JournalFile *f; + uint64_t sum = 0; + + if (!j) + return -EINVAL; + if (!bytes) + return -EINVAL; + + HASHMAP_FOREACH(f, j->files, i) { + struct stat st; + + if (fstat(f->fd, &st) < 0) + return -errno; + + sum += (uint64_t) st.st_blocks * 512ULL; + } + + *bytes = sum; + return 0; +} + /* _public_ int sd_journal_query_unique(sd_journal *j, const char *field) { */ /* if (!j) */ /* return -EINVAL; */