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.
This commit is contained in:
Vito Caputo
2017-07-10 19:24:56 -04:00
committed by Zbigniew Jędrzejewski-Szmek
parent 0d94d1e628
commit be7cdd8ec9
6 changed files with 169 additions and 169 deletions
+17 -11
View 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;
+1
View File
@@ -75,6 +75,7 @@ typedef enum OfflineState {
typedef struct JournalFile {
int fd;
MMapFileDescriptor *cache_fd;
mode_t mode;
+73 -51
View 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;
}
+64 -99
View 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);
fd_free(f);
if (f->cache)
assert_se(hashmap_remove(f->cache->fds, FD_TO_PTR(f->fd)));
free(f);
}
+5 -3
View 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);
+9 -5
View 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);