]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
journal: explicitly add fds to mmap-cache (#6307)
authorVito Caputo <vcaputo@gnugeneration.com>
Mon, 10 Jul 2017 23:24:56 +0000 (16:24 -0700)
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Mon, 10 Jul 2017 23:24:56 +0000 (19:24 -0400)
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.

src/journal/journal-file.c
src/journal/journal-file.h
src/journal/journal-verify.c
src/journal/mmap-cache.c
src/journal/mmap-cache.h
src/journal/test-mmap-cache.c

index 243d5198d9fa1396ae746b5927f521c8484a082f..4ff38de2e6a9a94d386fee007593bf93c9468ae1 100644 (file)
@@ -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;
index 564e1a8179b8c2bf2bbf049070d8fab0644b9b1d..df457c9a81de1370f957a5b79cdf62513e79c619 100644 (file)
@@ -75,6 +75,7 @@ typedef enum OfflineState {
 
 typedef struct JournalFile {
         int fd;
+        MMapFileDescriptor *cache_fd;
 
         mode_t mode;
 
index 9e4d8a28a545e2f22f171a57e3e164b8994db594..9feb5b5ae6974d5cddee030f7082176d3ce42dd9 100644 (file)
@@ -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;
 }
index d91247b52449988c91bc74507b218f03b1e9cf41..5dfda73c56a7d7d7f3503c23c31631e7eea3f1e0 100644 (file)
@@ -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);
 }
index 199d944647938199167b1209317032047680f968..7b332185636c401418cc8f43b872479828020ecf 100644 (file)
@@ -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);
index 0ad49aeb5fd5322a6294275d94b212c5b9a3728e..c51b069f8bd200eb90703c0d2c6ad1d4908e528c 100644 (file)
@@ -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);