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;
}
}
- 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) {
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) {
* 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 =
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) {
* 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)
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;
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;
#endif
}
- if (mmap_cache_got_sigbus(f->mmap, f->fd)) {
+ if (mmap_cache_got_sigbus(f->mmap, f->cache_fd)) {
r = -EIO;
goto fail;
}
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);
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;
typedef struct JournalFile {
int fd;
+ MMapFileDescriptor *cache_fd;
mode_t mode;
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 ... */
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;
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) {
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;
}
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);
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;
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;
}
}
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;
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) {
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);
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;
}
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;
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++) {
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;
}
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) {
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);
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;
}
}
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;
}
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;
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;
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;
* 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)
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);
(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;
}
typedef struct Window Window;
typedef struct Context Context;
-typedef struct FileDescriptor FileDescriptor;
struct Window {
MMapCache *cache;
uint64_t offset;
size_t size;
- FileDescriptor *fd;
+ MMapFileDescriptor *fd;
LIST_FIELDS(Window, by_fd);
LIST_FIELDS(Window, unused);
LIST_FIELDS(Context, by_window);
};
-struct FileDescriptor {
+struct MMapFileDescriptor {
MMapCache *cache;
int fd;
bool sigbus;
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) {
}
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;
}
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);
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)
static int try_context(
MMapCache *m,
- int fd,
+ MMapFileDescriptor *f,
int prot,
unsigned context,
bool keep_always,
assert(m);
assert(m->n_ref > 0);
- assert(fd >= 0);
+ assert(f);
assert(size > 0);
assert(ret);
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);
static int find_mmap(
MMapCache *m,
- int fd,
+ MMapFileDescriptor *f,
int prot,
unsigned context,
bool keep_always,
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)
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)
static int add_mmap(
MMapCache *m,
- int fd,
+ MMapFileDescriptor *f,
int prot,
unsigned context,
bool keep_always,
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);
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;
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;
int mmap_cache_get(
MMapCache *m,
- int fd,
+ MMapFileDescriptor *f,
int prot,
unsigned context,
bool keep_always,
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;
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) {
static void mmap_cache_process_sigbus(MMapCache *m) {
bool found = false;
- FileDescriptor *f;
+ MMapFileDescriptor *f;
Iterator i;
int r;
}
}
-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);
}
#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);
int mmap_cache_get(
MMapCache *m,
- int fd,
+ MMapFileDescriptor *f,
int prot,
unsigned context,
bool keep_always,
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);
#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;
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);
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);