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:
committed by
Zbigniew Jędrzejewski-Szmek
parent
0d94d1e628
commit
be7cdd8ec9
+17
-11
@@ -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;
|
||||
|
||||
@@ -75,6 +75,7 @@ typedef enum OfflineState {
|
||||
|
||||
typedef struct JournalFile {
|
||||
int fd;
|
||||
MMapFileDescriptor *cache_fd;
|
||||
|
||||
mode_t mode;
|
||||
|
||||
|
||||
@@ -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
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user