From: Vito Caputo Date: Mon, 10 Jul 2017 23:24:56 +0000 (-0700) Subject: journal: explicitly add fds to mmap-cache (#6307) X-Git-Tag: v234~14 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=be7cdd8ec992b354a98b89e5928aad1b574d01d5;p=thirdparty%2Fsystemd.git journal: explicitly add fds to mmap-cache (#6307) This way we have a MMapFileDescriptor reference external to the cache, and can supply the handle directly to mmap_cache_get(), eliminating hashmap lookups entirely from the hot path. --- diff --git a/src/journal/journal-file.c b/src/journal/journal-file.c index 243d5198d9f..4ff38de2e6a 100644 --- a/src/journal/journal-file.c +++ b/src/journal/journal-file.c @@ -162,7 +162,7 @@ static int journal_file_set_offline_thread_join(JournalFile *f) { f->offline_state = OFFLINE_JOINED; - if (mmap_cache_got_sigbus(f->mmap, f->fd)) + if (mmap_cache_got_sigbus(f->mmap, f->cache_fd)) return -EIO; return 0; @@ -300,7 +300,7 @@ static int journal_file_set_online(JournalFile *f) { } } - if (mmap_cache_got_sigbus(f->mmap, f->fd)) + if (mmap_cache_got_sigbus(f->mmap, f->cache_fd)) return -EIO; switch (f->header->state) { @@ -356,8 +356,8 @@ JournalFile* journal_file_close(JournalFile *f) { journal_file_set_offline(f, true); - if (f->mmap && f->fd >= 0) - mmap_cache_close_fd(f->mmap, f->fd); + if (f->mmap && f->cache_fd) + mmap_cache_free_fd(f->mmap, f->cache_fd); if (f->fd >= 0 && f->defrag_on_close) { @@ -660,7 +660,7 @@ static int journal_file_allocate(JournalFile *f, uint64_t offset, uint64_t size) * for sure, since we always call posix_fallocate() * ourselves */ - if (mmap_cache_got_sigbus(f->mmap, f->fd)) + if (mmap_cache_got_sigbus(f->mmap, f->cache_fd)) return -EIO; old_size = @@ -749,7 +749,7 @@ static int journal_file_move_to(JournalFile *f, ObjectType type, bool keep_alway return -EADDRNOTAVAIL; } - return mmap_cache_get(f->mmap, f->fd, f->prot, type_to_context(type), keep_always, offset, size, &f->last_stat, ret); + return mmap_cache_get(f->mmap, f->cache_fd, f->prot, type_to_context(type), keep_always, offset, size, &f->last_stat, ret); } static uint64_t minimum_header_size(Object *o) { @@ -1857,7 +1857,7 @@ int journal_file_append_entry(JournalFile *f, const dual_timestamp *ts, const st * it is very likely just an effect of a nullified replacement * mapping page */ - if (mmap_cache_got_sigbus(f->mmap, f->fd)) + if (mmap_cache_got_sigbus(f->mmap, f->cache_fd)) r = -EIO; if (f->post_change_timer) @@ -3144,6 +3144,12 @@ int journal_file_open( f->close_fd = true; } + f->cache_fd = mmap_cache_add_fd(f->mmap, f->fd); + if (!f->cache_fd) { + r = -ENOMEM; + goto fail; + } + r = journal_file_fstat(f); if (r < 0) goto fail; @@ -3190,7 +3196,7 @@ int journal_file_open( goto fail; } - r = mmap_cache_get(f->mmap, f->fd, f->prot, CONTEXT_HEADER, true, 0, PAGE_ALIGN(sizeof(Header)), &f->last_stat, &h); + r = mmap_cache_get(f->mmap, f->cache_fd, f->prot, CONTEXT_HEADER, true, 0, PAGE_ALIGN(sizeof(Header)), &f->last_stat, &h); if (r < 0) goto fail; @@ -3247,7 +3253,7 @@ int journal_file_open( #endif } - if (mmap_cache_got_sigbus(f->mmap, f->fd)) { + if (mmap_cache_got_sigbus(f->mmap, f->cache_fd)) { r = -EIO; goto fail; } @@ -3269,7 +3275,7 @@ int journal_file_open( return 0; fail: - if (f->fd >= 0 && mmap_cache_got_sigbus(f->mmap, f->fd)) + if (f->cache_fd && mmap_cache_got_sigbus(f->mmap, f->cache_fd)) r = -EIO; (void) journal_file_close(f); @@ -3482,7 +3488,7 @@ int journal_file_copy_entry(JournalFile *from, JournalFile *to, Object *o, uint6 r = journal_file_append_entry_internal(to, &ts, xor_hash, items, n, seqnum, ret, offset); - if (mmap_cache_got_sigbus(to->mmap, to->fd)) + if (mmap_cache_got_sigbus(to->mmap, to->cache_fd)) return -EIO; return r; diff --git a/src/journal/journal-file.h b/src/journal/journal-file.h index 564e1a8179b..df457c9a81d 100644 --- a/src/journal/journal-file.h +++ b/src/journal/journal-file.h @@ -75,6 +75,7 @@ typedef enum OfflineState { typedef struct JournalFile { int fd; + MMapFileDescriptor *cache_fd; mode_t mode; diff --git a/src/journal/journal-verify.c b/src/journal/journal-verify.c index 9e4d8a28a54..9feb5b5ae69 100644 --- a/src/journal/journal-verify.c +++ b/src/journal/journal-verify.c @@ -377,12 +377,12 @@ static int write_uint64(int fd, uint64_t p) { return 0; } -static int contains_uint64(MMapCache *m, int fd, uint64_t n, uint64_t p) { +static int contains_uint64(MMapCache *m, MMapFileDescriptor *f, uint64_t n, uint64_t p) { uint64_t a, b; int r; assert(m); - assert(fd >= 0); + assert(f); /* Bisection ... */ @@ -392,7 +392,7 @@ static int contains_uint64(MMapCache *m, int fd, uint64_t n, uint64_t p) { c = (a + b) / 2; - r = mmap_cache_get(m, fd, PROT_READ|PROT_WRITE, 0, false, c * sizeof(uint64_t), sizeof(uint64_t), NULL, (void **) &z); + r = mmap_cache_get(m, f, PROT_READ|PROT_WRITE, 0, false, c * sizeof(uint64_t), sizeof(uint64_t), NULL, (void **) &z); if (r < 0) return r; @@ -413,7 +413,7 @@ static int contains_uint64(MMapCache *m, int fd, uint64_t n, uint64_t p) { static int entry_points_to_data( JournalFile *f, - int entry_fd, + MMapFileDescriptor *cache_entry_fd, uint64_t n_entries, uint64_t entry_p, uint64_t data_p) { @@ -424,9 +424,9 @@ static int entry_points_to_data( bool found = false; assert(f); - assert(entry_fd >= 0); + assert(cache_entry_fd); - if (!contains_uint64(f->mmap, entry_fd, n_entries, entry_p)) { + if (!contains_uint64(f->mmap, cache_entry_fd, n_entries, entry_p)) { error(data_p, "Data object references invalid entry at "OFSfmt, entry_p); return -EBADMSG; } @@ -500,16 +500,16 @@ static int entry_points_to_data( static int verify_data( JournalFile *f, Object *o, uint64_t p, - int entry_fd, uint64_t n_entries, - int entry_array_fd, uint64_t n_entry_arrays) { + MMapFileDescriptor *cache_entry_fd, uint64_t n_entries, + MMapFileDescriptor *cache_entry_array_fd, uint64_t n_entry_arrays) { uint64_t i, n, a, last, q; int r; assert(f); assert(o); - assert(entry_fd >= 0); - assert(entry_array_fd >= 0); + assert(cache_entry_fd); + assert(cache_entry_array_fd); n = le64toh(o->data.n_entries); a = le64toh(o->data.entry_array_offset); @@ -527,7 +527,7 @@ static int verify_data( assert(o->data.entry_offset); last = q = le64toh(o->data.entry_offset); - r = entry_points_to_data(f, entry_fd, n_entries, q, p); + r = entry_points_to_data(f, cache_entry_fd, n_entries, q, p); if (r < 0) return r; @@ -540,7 +540,7 @@ static int verify_data( return -EBADMSG; } - if (!contains_uint64(f->mmap, entry_array_fd, n_entry_arrays, a)) { + if (!contains_uint64(f->mmap, cache_entry_array_fd, n_entry_arrays, a)) { error(p, "Invalid array offset "OFSfmt, a); return -EBADMSG; } @@ -565,7 +565,7 @@ static int verify_data( } last = q; - r = entry_points_to_data(f, entry_fd, n_entries, q, p); + r = entry_points_to_data(f, cache_entry_fd, n_entries, q, p); if (r < 0) return r; @@ -583,9 +583,9 @@ static int verify_data( static int verify_hash_table( JournalFile *f, - int data_fd, uint64_t n_data, - int entry_fd, uint64_t n_entries, - int entry_array_fd, uint64_t n_entry_arrays, + MMapFileDescriptor *cache_data_fd, uint64_t n_data, + MMapFileDescriptor *cache_entry_fd, uint64_t n_entries, + MMapFileDescriptor *cache_entry_array_fd, uint64_t n_entry_arrays, usec_t *last_usec, bool show_progress) { @@ -593,9 +593,9 @@ static int verify_hash_table( int r; assert(f); - assert(data_fd >= 0); - assert(entry_fd >= 0); - assert(entry_array_fd >= 0); + assert(cache_data_fd); + assert(cache_entry_fd); + assert(cache_entry_array_fd); assert(last_usec); n = le64toh(f->header->data_hash_table_size) / sizeof(HashItem); @@ -617,7 +617,7 @@ static int verify_hash_table( Object *o; uint64_t next; - if (!contains_uint64(f->mmap, data_fd, n_data, p)) { + if (!contains_uint64(f->mmap, cache_data_fd, n_data, p)) { error(p, "Invalid data object at hash entry %"PRIu64" of %"PRIu64, i, n); return -EBADMSG; } @@ -637,7 +637,7 @@ static int verify_hash_table( return -EBADMSG; } - r = verify_data(f, o, p, entry_fd, n_entries, entry_array_fd, n_entry_arrays); + r = verify_data(f, o, p, cache_entry_fd, n_entries, cache_entry_array_fd, n_entry_arrays); if (r < 0) return r; @@ -689,14 +689,14 @@ static int data_object_in_hash_table(JournalFile *f, uint64_t hash, uint64_t p) static int verify_entry( JournalFile *f, Object *o, uint64_t p, - int data_fd, uint64_t n_data) { + MMapFileDescriptor *cache_data_fd, uint64_t n_data) { uint64_t i, n; int r; assert(f); assert(o); - assert(data_fd >= 0); + assert(cache_data_fd); n = journal_file_entry_n_items(o); for (i = 0; i < n; i++) { @@ -706,7 +706,7 @@ static int verify_entry( q = le64toh(o->entry.items[i].object_offset); h = le64toh(o->entry.items[i].hash); - if (!contains_uint64(f->mmap, data_fd, n_data, q)) { + if (!contains_uint64(f->mmap, cache_data_fd, n_data, q)) { error(p, "Invalid data object of entry"); return -EBADMSG; } @@ -734,9 +734,9 @@ static int verify_entry( static int verify_entry_array( JournalFile *f, - int data_fd, uint64_t n_data, - int entry_fd, uint64_t n_entries, - int entry_array_fd, uint64_t n_entry_arrays, + MMapFileDescriptor *cache_data_fd, uint64_t n_data, + MMapFileDescriptor *cache_entry_fd, uint64_t n_entries, + MMapFileDescriptor *cache_entry_array_fd, uint64_t n_entry_arrays, usec_t *last_usec, bool show_progress) { @@ -744,9 +744,9 @@ static int verify_entry_array( int r; assert(f); - assert(data_fd >= 0); - assert(entry_fd >= 0); - assert(entry_array_fd >= 0); + assert(cache_data_fd); + assert(cache_entry_fd); + assert(cache_entry_array_fd); assert(last_usec); n = le64toh(f->header->n_entries); @@ -763,7 +763,7 @@ static int verify_entry_array( return -EBADMSG; } - if (!contains_uint64(f->mmap, entry_array_fd, n_entry_arrays, a)) { + if (!contains_uint64(f->mmap, cache_entry_array_fd, n_entry_arrays, a)) { error(a, "Invalid array %"PRIu64" of %"PRIu64, i, n); return -EBADMSG; } @@ -789,7 +789,7 @@ static int verify_entry_array( } last = p; - if (!contains_uint64(f->mmap, entry_fd, n_entries, p)) { + if (!contains_uint64(f->mmap, cache_entry_fd, n_entries, p)) { error(a, "Invalid array entry at %"PRIu64" of %"PRIu64, i, n); return -EBADMSG; } @@ -798,7 +798,7 @@ static int verify_entry_array( if (r < 0) return r; - r = verify_entry(f, o, p, data_fd, n_data); + r = verify_entry(f, o, p, cache_data_fd, n_data); if (r < 0) return r; @@ -829,6 +829,7 @@ int journal_file_verify( uint64_t n_weird = 0, n_objects = 0, n_entries = 0, n_data = 0, n_fields = 0, n_data_hash_tables = 0, n_field_hash_tables = 0, n_entry_arrays = 0, n_tags = 0; usec_t last_usec = 0; int data_fd = -1, entry_fd = -1, entry_array_fd = -1; + MMapFileDescriptor *cache_data_fd = NULL, *cache_entry_fd = NULL, *cache_entry_array_fd = NULL; unsigned i; bool found_last = false; const char *tmp_dir = NULL; @@ -876,6 +877,24 @@ int journal_file_verify( goto fail; } + cache_data_fd = mmap_cache_add_fd(f->mmap, data_fd); + if (!cache_data_fd) { + r = log_oom(); + goto fail; + } + + cache_entry_fd = mmap_cache_add_fd(f->mmap, entry_fd); + if (!cache_entry_fd) { + r = log_oom(); + goto fail; + } + + cache_entry_array_fd = mmap_cache_add_fd(f->mmap, entry_array_fd); + if (!cache_entry_array_fd) { + r = log_oom(); + goto fail; + } + if (le32toh(f->header->compatible_flags) & ~HEADER_COMPATIBLE_SUPPORTED) { log_error("Cannot verify file with unknown extensions."); r = -EOPNOTSUPP; @@ -1247,18 +1266,18 @@ int journal_file_verify( * referenced is consistent. */ r = verify_entry_array(f, - data_fd, n_data, - entry_fd, n_entries, - entry_array_fd, n_entry_arrays, + cache_data_fd, n_data, + cache_entry_fd, n_entries, + cache_entry_array_fd, n_entry_arrays, &last_usec, show_progress); if (r < 0) goto fail; r = verify_hash_table(f, - data_fd, n_data, - entry_fd, n_entries, - entry_array_fd, n_entry_arrays, + cache_data_fd, n_data, + cache_entry_fd, n_entries, + cache_entry_array_fd, n_entry_arrays, &last_usec, show_progress); if (r < 0) @@ -1267,9 +1286,9 @@ int journal_file_verify( if (show_progress) flush_progress(); - mmap_cache_close_fd(f->mmap, data_fd); - mmap_cache_close_fd(f->mmap, entry_fd); - mmap_cache_close_fd(f->mmap, entry_array_fd); + mmap_cache_free_fd(f->mmap, cache_data_fd); + mmap_cache_free_fd(f->mmap, cache_entry_fd); + mmap_cache_free_fd(f->mmap, cache_entry_array_fd); safe_close(data_fd); safe_close(entry_fd); @@ -1294,20 +1313,23 @@ fail: (unsigned long long) f->last_stat.st_size, 100 * p / f->last_stat.st_size); - if (data_fd >= 0) { - mmap_cache_close_fd(f->mmap, data_fd); + if (data_fd >= 0) safe_close(data_fd); - } - if (entry_fd >= 0) { - mmap_cache_close_fd(f->mmap, entry_fd); + if (entry_fd >= 0) safe_close(entry_fd); - } - if (entry_array_fd >= 0) { - mmap_cache_close_fd(f->mmap, entry_array_fd); + if (entry_array_fd >= 0) safe_close(entry_array_fd); - } + + if (cache_data_fd) + mmap_cache_free_fd(f->mmap, cache_data_fd); + + if (cache_entry_fd) + mmap_cache_free_fd(f->mmap, cache_entry_fd); + + if (cache_entry_array_fd) + mmap_cache_free_fd(f->mmap, cache_entry_array_fd); return r; } diff --git a/src/journal/mmap-cache.c b/src/journal/mmap-cache.c index d91247b5244..5dfda73c56a 100644 --- a/src/journal/mmap-cache.c +++ b/src/journal/mmap-cache.c @@ -33,7 +33,6 @@ typedef struct Window Window; typedef struct Context Context; -typedef struct FileDescriptor FileDescriptor; struct Window { MMapCache *cache; @@ -47,7 +46,7 @@ struct Window { uint64_t offset; size_t size; - FileDescriptor *fd; + MMapFileDescriptor *fd; LIST_FIELDS(Window, by_fd); LIST_FIELDS(Window, unused); @@ -63,7 +62,7 @@ struct Context { LIST_FIELDS(Context, by_window); }; -struct FileDescriptor { +struct MMapFileDescriptor { MMapCache *cache; int fd; bool sigbus; @@ -158,24 +157,24 @@ static void window_free(Window *w) { free(w); } -_pure_ static bool window_matches(Window *w, int fd, int prot, uint64_t offset, size_t size) { +_pure_ static bool window_matches(Window *w, MMapFileDescriptor *f, int prot, uint64_t offset, size_t size) { assert(w); - assert(fd >= 0); + assert(f); assert(size > 0); return w->fd && - fd == w->fd->fd && + f->fd == w->fd->fd && prot == w->prot && offset >= w->offset && offset + size <= w->offset + w->size; } -static Window *window_add(MMapCache *m, FileDescriptor *fd, int prot, bool keep_always, uint64_t offset, size_t size, void *ptr) { +static Window *window_add(MMapCache *m, MMapFileDescriptor *f, int prot, bool keep_always, uint64_t offset, size_t size, void *ptr) { Window *w; assert(m); - assert(fd); + assert(f); if (!m->last_unused || m->n_windows <= WINDOWS_MIN) { @@ -193,14 +192,14 @@ static Window *window_add(MMapCache *m, FileDescriptor *fd, int prot, bool keep_ } w->cache = m; - w->fd = fd; + w->fd = f; w->prot = prot; w->keep_always = keep_always; w->offset = offset; w->size = size; w->ptr = ptr; - LIST_PREPEND(by_fd, fd->windows, w); + LIST_PREPEND(by_fd, f->windows, w); return w; } @@ -290,49 +289,7 @@ static void context_free(Context *c) { free(c); } -static void fd_free(FileDescriptor *f) { - assert(f); - - while (f->windows) - window_free(f->windows); - - if (f->cache) - assert_se(hashmap_remove(f->cache->fds, FD_TO_PTR(f->fd))); - - free(f); -} - -static FileDescriptor* fd_add(MMapCache *m, int fd) { - FileDescriptor *f; - int r; - - assert(m); - assert(fd >= 0); - - f = hashmap_get(m->fds, FD_TO_PTR(fd)); - if (f) - return f; - - r = hashmap_ensure_allocated(&m->fds, NULL); - if (r < 0) - return NULL; - - f = new0(FileDescriptor, 1); - if (!f) - return NULL; - - f->cache = m; - f->fd = fd; - - r = hashmap_put(m->fds, FD_TO_PTR(fd), f); - if (r < 0) - return mfree(f); - - return f; -} - static void mmap_cache_free(MMapCache *m) { - FileDescriptor *f; int i; assert(m); @@ -341,9 +298,6 @@ static void mmap_cache_free(MMapCache *m) { if (m->contexts[i]) context_free(m->contexts[i]); - while ((f = hashmap_first(m->fds))) - fd_free(f); - hashmap_free(m->fds); while (m->unused) @@ -378,7 +332,7 @@ static int make_room(MMapCache *m) { static int try_context( MMapCache *m, - int fd, + MMapFileDescriptor *f, int prot, unsigned context, bool keep_always, @@ -390,7 +344,7 @@ static int try_context( assert(m); assert(m->n_ref > 0); - assert(fd >= 0); + assert(f); assert(size > 0); assert(ret); @@ -403,7 +357,7 @@ static int try_context( if (!c->window) return 0; - if (!window_matches(c->window, fd, prot, offset, size)) { + if (!window_matches(c->window, f, prot, offset, size)) { /* Drop the reference to the window, since it's unnecessary now */ context_detach_window(c); @@ -421,7 +375,7 @@ static int try_context( static int find_mmap( MMapCache *m, - int fd, + MMapFileDescriptor *f, int prot, unsigned context, bool keep_always, @@ -429,26 +383,19 @@ static int find_mmap( size_t size, void **ret) { - FileDescriptor *f; Window *w; Context *c; assert(m); assert(m->n_ref > 0); - assert(fd >= 0); + assert(f); assert(size > 0); - f = hashmap_get(m->fds, FD_TO_PTR(fd)); - if (!f) - return 0; - - assert(f->fd == fd); - if (f->sigbus) return -EIO; LIST_FOREACH(by_fd, w, f->windows) - if (window_matches(w, fd, prot, offset, size)) + if (window_matches(w, f, prot, offset, size)) break; if (!w) @@ -465,17 +412,17 @@ static int find_mmap( return 1; } -static int mmap_try_harder(MMapCache *m, void *addr, int fd, int prot, int flags, uint64_t offset, size_t size, void **res) { +static int mmap_try_harder(MMapCache *m, void *addr, MMapFileDescriptor *f, int prot, int flags, uint64_t offset, size_t size, void **res) { void *ptr; assert(m); - assert(fd >= 0); + assert(f); assert(res); for (;;) { int r; - ptr = mmap(addr, size, prot, flags, fd, offset); + ptr = mmap(addr, size, prot, flags, f->fd, offset); if (ptr != MAP_FAILED) break; if (errno != ENOMEM) @@ -494,7 +441,7 @@ static int mmap_try_harder(MMapCache *m, void *addr, int fd, int prot, int flags static int add_mmap( MMapCache *m, - int fd, + MMapFileDescriptor *f, int prot, unsigned context, bool keep_always, @@ -505,14 +452,13 @@ static int add_mmap( uint64_t woffset, wsize; Context *c; - FileDescriptor *f; Window *w; void *d; int r; assert(m); assert(m->n_ref > 0); - assert(fd >= 0); + assert(f); assert(size > 0); assert(ret); @@ -545,7 +491,7 @@ static int add_mmap( wsize = PAGE_ALIGN(st->st_size - woffset); } - r = mmap_try_harder(m, NULL, fd, prot, MAP_SHARED, woffset, wsize, &d); + r = mmap_try_harder(m, NULL, f, prot, MAP_SHARED, woffset, wsize, &d); if (r < 0) return r; @@ -553,10 +499,6 @@ static int add_mmap( if (!c) goto outofmem; - f = fd_add(m, fd); - if (!f) - goto outofmem; - w = window_add(m, f, prot, keep_always, woffset, wsize, d); if (!w) goto outofmem; @@ -575,7 +517,7 @@ outofmem: int mmap_cache_get( MMapCache *m, - int fd, + MMapFileDescriptor *f, int prot, unsigned context, bool keep_always, @@ -588,20 +530,20 @@ int mmap_cache_get( assert(m); assert(m->n_ref > 0); - assert(fd >= 0); + assert(f); assert(size > 0); assert(ret); assert(context < MMAP_CACHE_MAX_CONTEXTS); /* Check whether the current context is the right one already */ - r = try_context(m, fd, prot, context, keep_always, offset, size, ret); + r = try_context(m, f, prot, context, keep_always, offset, size, ret); if (r != 0) { m->n_hit++; return r; } /* Search for a matching mmap */ - r = find_mmap(m, fd, prot, context, keep_always, offset, size, ret); + r = find_mmap(m, f, prot, context, keep_always, offset, size, ret); if (r != 0) { m->n_hit++; return r; @@ -610,7 +552,7 @@ int mmap_cache_get( m->n_missed++; /* Create a new mmap */ - return add_mmap(m, fd, prot, context, keep_always, offset, size, st, ret); + return add_mmap(m, f, prot, context, keep_always, offset, size, st, ret); } unsigned mmap_cache_get_hit(MMapCache *m) { @@ -627,7 +569,7 @@ unsigned mmap_cache_get_missed(MMapCache *m) { static void mmap_cache_process_sigbus(MMapCache *m) { bool found = false; - FileDescriptor *f; + MMapFileDescriptor *f; Iterator i; int r; @@ -688,36 +630,59 @@ static void mmap_cache_process_sigbus(MMapCache *m) { } } -bool mmap_cache_got_sigbus(MMapCache *m, int fd) { - FileDescriptor *f; - +bool mmap_cache_got_sigbus(MMapCache *m, MMapFileDescriptor *f) { assert(m); - assert(fd >= 0); + assert(f); mmap_cache_process_sigbus(m); - f = hashmap_get(m->fds, FD_TO_PTR(fd)); - if (!f) - return false; - return f->sigbus; } -void mmap_cache_close_fd(MMapCache *m, int fd) { - FileDescriptor *f; +MMapFileDescriptor* mmap_cache_add_fd(MMapCache *m, int fd) { + MMapFileDescriptor *f; + int r; assert(m); assert(fd >= 0); + f = hashmap_get(m->fds, FD_TO_PTR(fd)); + if (f) + return f; + + r = hashmap_ensure_allocated(&m->fds, NULL); + if (r < 0) + return NULL; + + f = new0(MMapFileDescriptor, 1); + if (!f) + return NULL; + + f->cache = m; + f->fd = fd; + + r = hashmap_put(m->fds, FD_TO_PTR(fd), f); + if (r < 0) + return mfree(f); + + return f; +} + +void mmap_cache_free_fd(MMapCache *m, MMapFileDescriptor *f) { + assert(m); + assert(f); + /* Make sure that any queued SIGBUS are first dispatched, so * that we don't end up with a SIGBUS entry we cannot relate * to any existing memory map */ mmap_cache_process_sigbus(m); - f = hashmap_get(m->fds, FD_TO_PTR(fd)); - if (!f) - return; + while (f->windows) + window_free(f->windows); + + if (f->cache) + assert_se(hashmap_remove(f->cache->fds, FD_TO_PTR(f->fd))); - fd_free(f); + free(f); } diff --git a/src/journal/mmap-cache.h b/src/journal/mmap-cache.h index 199d9446479..7b332185636 100644 --- a/src/journal/mmap-cache.h +++ b/src/journal/mmap-cache.h @@ -26,6 +26,7 @@ #define MMAP_CACHE_MAX_CONTEXTS 9 typedef struct MMapCache MMapCache; +typedef struct MMapFileDescriptor MMapFileDescriptor; MMapCache* mmap_cache_new(void); MMapCache* mmap_cache_ref(MMapCache *m); @@ -33,7 +34,7 @@ MMapCache* mmap_cache_unref(MMapCache *m); int mmap_cache_get( MMapCache *m, - int fd, + MMapFileDescriptor *f, int prot, unsigned context, bool keep_always, @@ -41,9 +42,10 @@ int mmap_cache_get( size_t size, struct stat *st, void **ret); -void mmap_cache_close_fd(MMapCache *m, int fd); +MMapFileDescriptor * mmap_cache_add_fd(MMapCache *m, int fd); +void mmap_cache_free_fd(MMapCache *m, MMapFileDescriptor *f); unsigned mmap_cache_get_hit(MMapCache *m); unsigned mmap_cache_get_missed(MMapCache *m); -bool mmap_cache_got_sigbus(MMapCache *m, int fd); +bool mmap_cache_got_sigbus(MMapCache *m, MMapFileDescriptor *f); diff --git a/src/journal/test-mmap-cache.c b/src/journal/test-mmap-cache.c index 0ad49aeb5fd..c51b069f8bd 100644 --- a/src/journal/test-mmap-cache.c +++ b/src/journal/test-mmap-cache.c @@ -29,6 +29,7 @@ #include "util.h" int main(int argc, char *argv[]) { + MMapFileDescriptor *fx; int x, y, z, r; char px[] = "/tmp/testmmapXXXXXXX", py[] = "/tmp/testmmapYXXXXXX", pz[] = "/tmp/testmmapZXXXXXX"; MMapCache *m; @@ -40,6 +41,8 @@ int main(int argc, char *argv[]) { assert_se(x >= 0); unlink(px); + assert_se(fx = mmap_cache_add_fd(m, x)); + y = mkostemp_safe(py); assert_se(y >= 0); unlink(py); @@ -48,27 +51,28 @@ int main(int argc, char *argv[]) { assert_se(z >= 0); unlink(pz); - r = mmap_cache_get(m, x, PROT_READ, 0, false, 1, 2, NULL, &p); + r = mmap_cache_get(m, fx, PROT_READ, 0, false, 1, 2, NULL, &p); assert_se(r >= 0); - r = mmap_cache_get(m, x, PROT_READ, 0, false, 2, 2, NULL, &q); + r = mmap_cache_get(m, fx, PROT_READ, 0, false, 2, 2, NULL, &q); assert_se(r >= 0); assert_se((uint8_t*) p + 1 == (uint8_t*) q); - r = mmap_cache_get(m, x, PROT_READ, 1, false, 3, 2, NULL, &q); + r = mmap_cache_get(m, fx, PROT_READ, 1, false, 3, 2, NULL, &q); assert_se(r >= 0); assert_se((uint8_t*) p + 2 == (uint8_t*) q); - r = mmap_cache_get(m, x, PROT_READ, 0, false, 16ULL*1024ULL*1024ULL, 2, NULL, &p); + r = mmap_cache_get(m, fx, PROT_READ, 0, false, 16ULL*1024ULL*1024ULL, 2, NULL, &p); assert_se(r >= 0); - r = mmap_cache_get(m, x, PROT_READ, 1, false, 16ULL*1024ULL*1024ULL+1, 2, NULL, &q); + r = mmap_cache_get(m, fx, PROT_READ, 1, false, 16ULL*1024ULL*1024ULL+1, 2, NULL, &q); assert_se(r >= 0); assert_se((uint8_t*) p + 1 == (uint8_t*) q); + mmap_cache_free_fd(m, fx); mmap_cache_unref(m); safe_close(x);