mmap-cache.c revision 69adae5168da231c6cf319f708860954701b25ed
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering/***
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering This file is part of systemd.
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering Copyright 2012 Lennart Poettering
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering systemd is free software; you can redistribute it and/or modify it
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering under the terms of the GNU Lesser General Public License as published by
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering the Free Software Foundation; either version 2.1 of the License, or
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering (at your option) any later version.
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering systemd is distributed in the hope that it will be useful, but
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering Lesser General Public License for more details.
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering You should have received a copy of the GNU Lesser General Public License
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering***/
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering#include <errno.h>
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering#include <stdlib.h>
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering#include <sys/mman.h>
4871690d9e32608bbd9b18505b5326c2079c9690Allin Cottrell#include <string.h>
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering#include "hashmap.h"
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering#include "list.h"
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering#include "log.h"
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering#include "util.h"
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering#include "macro.h"
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering#include "mmap-cache.h"
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering
afc5dbf37fd2399d37976388d9dd9ab470ecf446Lennart Poetteringtypedef struct Window Window;
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poetteringtypedef struct Context Context;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmektypedef struct FileDescriptor FileDescriptor;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poetteringstruct Window {
0b452006de98294d1690f045f6ea2f7f6630ec3bRonny Chevalier MMapCache *cache;
15a5e95075a7f6007dd97b2a165c8ed16fe683dfLennart Poettering
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering bool keep_always;
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering bool in_unused;
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering int prot;
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering void *ptr;
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering uint64_t offset;
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering size_t size;
3b3154df7e2773332bb814e167187367a0ccae4aLennart Poettering
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering FileDescriptor *fd;
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering
3b97fcbd28f92a1e51887fef5de8844a89bde523Lennart Poettering LIST_FIELDS(Window, by_fd);
5ffa8c818120e35c89becd938d160235c069dd12Zbigniew Jędrzejewski-Szmek LIST_FIELDS(Window, unused);
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering LIST_HEAD(Context, contexts);
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering};
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poetteringstruct Context {
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering MMapCache *cache;
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering unsigned id;
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering Window *window;
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering LIST_FIELDS(Context, by_window);
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering};
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poetteringstruct FileDescriptor {
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering MMapCache *cache;
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering int fd;
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering LIST_HEAD(Window, windows);
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering};
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poetteringstruct MMapCache {
5ffa8c818120e35c89becd938d160235c069dd12Zbigniew Jędrzejewski-Szmek int n_ref;
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering unsigned n_windows;
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering unsigned n_hit, n_missed;
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering Hashmap *fds;
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering Context *contexts[MMAP_CACHE_MAX_CONTEXTS];
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering LIST_HEAD(Window, unused);
5ffa8c818120e35c89becd938d160235c069dd12Zbigniew Jędrzejewski-Szmek Window *last_unused;
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering};
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering#define WINDOWS_MIN 64
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering#ifdef ENABLE_DEBUG_MMAP_CACHE
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering/* Tiny windows increase mmap activity and the chance of exposing unsafe use. */
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering# define WINDOW_SIZE (page_size())
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering#else
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering# define WINDOW_SIZE (8ULL*1024ULL*1024ULL)
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering#endif
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart PoetteringMMapCache* mmap_cache_new(void) {
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering MMapCache *m;
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering m = new0(MMapCache, 1);
56f64d95763a799ba4475daf44d8e9f72a1bd474Michal Schmidt if (!m)
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering return NULL;
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering m->n_ref = 1;
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering return m;
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering}
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart PoetteringMMapCache* mmap_cache_ref(MMapCache *m) {
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering assert(m);
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering assert(m->n_ref > 0);
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering m->n_ref ++;
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering return m;
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering}
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poetteringstatic void window_unlink(Window *w) {
3b3154df7e2773332bb814e167187367a0ccae4aLennart Poettering Context *c;
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering assert(w);
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering if (w->ptr)
e9f600f2fb4b0df55c7a8fb4b4d09f9979997223Lennart Poettering munmap(w->ptr, w->size);
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering if (w->fd)
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering LIST_REMOVE(by_fd, w->fd->windows, w);
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering if (w->in_unused) {
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering if (w->cache->last_unused == w)
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering w->cache->last_unused = w->unused_prev;
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering LIST_REMOVE(unused, w->cache->unused, w);
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering }
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering LIST_FOREACH(by_window, c, w->contexts) {
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering assert(c->window == w);
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering c->window = NULL;
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering }
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering}
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poetteringstatic void window_free(Window *w) {
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering assert(w);
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering window_unlink(w);
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering w->cache->n_windows--;
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering free(w);
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering}
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering_pure_ static bool window_matches(Window *w, int fd, int prot, uint64_t offset, size_t size) {
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering assert(w);
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering assert(fd >= 0);
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering assert(size > 0);
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering return
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering w->fd &&
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering fd == w->fd->fd &&
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering prot == w->prot &&
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering offset >= w->offset &&
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering offset + size <= w->offset + w->size;
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering}
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poetteringstatic Window *window_add(MMapCache *m) {
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering Window *w;
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering
507f22bd0172bff5e5d98145b1419bd472a2c57fZbigniew Jędrzejewski-Szmek assert(m);
b9c488f60050248b35640f28e4d00958702ba1c3Eelco Dolstra
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering if (!m->last_unused || m->n_windows <= WINDOWS_MIN) {
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering /* Allocate a new window */
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering w = new0(Window, 1);
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering if (!w)
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering return NULL;
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering m->n_windows++;
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering } else {
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering /* Reuse an existing one */
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering w = m->last_unused;
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering window_unlink(w);
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering zero(*w);
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering }
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering w->cache = m;
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering return w;
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering}
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering
e9f600f2fb4b0df55c7a8fb4b4d09f9979997223Lennart Poetteringstatic void context_detach_window(Context *c) {
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering Window *w;
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering assert(c);
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering if (!c->window)
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering return;
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering w = c->window;
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering c->window = NULL;
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering LIST_REMOVE(by_window, w->contexts, c);
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering if (!w->contexts && !w->keep_always) {
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering /* Not used anymore? */
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering#ifdef ENABLE_DEBUG_MMAP_CACHE
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering /* Unmap unused windows immediately to expose use-after-unmap
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering * by SIGSEGV. */
dc61b7e45d89a69f0469ab7b3289cdde7fcc55abTorstein Husebø window_free(w);
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering#else
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering LIST_PREPEND(unused, c->cache->unused, w);
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering if (!c->cache->last_unused)
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering c->cache->last_unused = w;
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering w->in_unused = true;
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering#endif
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering }
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering}
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poetteringstatic void context_attach_window(Context *c, Window *w) {
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering assert(c);
527b7a421ff3927d4f3f170b1b143452e88ae1dcLennart Poettering assert(w);
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering if (c->window == w)
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering return;
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering context_detach_window(c);
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering if (w->in_unused) {
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering /* Used again? */
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering LIST_REMOVE(unused, c->cache->unused, w);
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering if (c->cache->last_unused == w)
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering c->cache->last_unused = w->unused_prev;
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering w->in_unused = false;
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering }
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering c->window = w;
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering LIST_PREPEND(by_window, w->contexts, c);
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering}
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poetteringstatic Context *context_add(MMapCache *m, unsigned id) {
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering Context *c;
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering assert(m);
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering c = m->contexts[id];
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering if (c)
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering return c;
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering c = new0(Context, 1);
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering if (!c)
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering return NULL;
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering c->cache = m;
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering c->id = id;
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering assert(!m->contexts[id]);
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering m->contexts[id] = c;
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering return c;
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering}
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poetteringstatic void context_free(Context *c) {
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering assert(c);
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering context_detach_window(c);
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering if (c->cache) {
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering assert(c->cache->contexts[c->id] == c);
4b94f3b8f7693f076e5c85bc2c02cf028192d8deZbigniew Jędrzejewski-Szmek c->cache->contexts[c->id] = NULL;
4b94f3b8f7693f076e5c85bc2c02cf028192d8deZbigniew Jędrzejewski-Szmek }
4b94f3b8f7693f076e5c85bc2c02cf028192d8deZbigniew Jędrzejewski-Szmek
4b94f3b8f7693f076e5c85bc2c02cf028192d8deZbigniew Jędrzejewski-Szmek free(c);
4b94f3b8f7693f076e5c85bc2c02cf028192d8deZbigniew Jędrzejewski-Szmek}
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poetteringstatic void fd_free(FileDescriptor *f) {
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering assert(f);
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering while (f->windows)
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering window_free(f->windows);
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering if (f->cache)
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering assert_se(hashmap_remove(f->cache->fds, INT_TO_PTR(f->fd + 1)));
e9f600f2fb4b0df55c7a8fb4b4d09f9979997223Lennart Poettering
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering free(f);
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering}
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poetteringstatic FileDescriptor* fd_add(MMapCache *m, int fd) {
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering FileDescriptor *f;
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering int r;
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering
36dd072cdf03dcac0fcd2d6b42f261444dc7ac88Michal Sekletar assert(m);
36dd072cdf03dcac0fcd2d6b42f261444dc7ac88Michal Sekletar assert(fd >= 0);
36dd072cdf03dcac0fcd2d6b42f261444dc7ac88Michal Sekletar
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering f = hashmap_get(m->fds, INT_TO_PTR(fd + 1));
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering if (f)
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering return f;
e88baee88fad8bc59d33b55a7a2d640ef9e16cd6Zbigniew Jędrzejewski-Szmek
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering r = hashmap_ensure_allocated(&m->fds, NULL);
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering if (r < 0)
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering return NULL;
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering f = new0(FileDescriptor, 1);
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering if (!f)
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering return NULL;
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering f->cache = m;
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering f->fd = fd;
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering r = hashmap_put(m->fds, UINT_TO_PTR(fd + 1), f);
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering if (r < 0) {
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering free(f);
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering return NULL;
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering }
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering return f;
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering}
527b7a421ff3927d4f3f170b1b143452e88ae1dcLennart Poettering
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poetteringstatic void mmap_cache_free(MMapCache *m) {
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering FileDescriptor *f;
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek int i;
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering assert(m);
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering for (i = 0; i < MMAP_CACHE_MAX_CONTEXTS; i++)
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering if (m->contexts[i])
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering context_free(m->contexts[i]);
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering while ((f = hashmap_first(m->fds)))
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering fd_free(f);
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering hashmap_free(m->fds);
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering while (m->unused)
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering window_free(m->unused);
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering free(m);
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering}
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart PoetteringMMapCache* mmap_cache_unref(MMapCache *m) {
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering assert(m);
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering assert(m->n_ref > 0);
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering m->n_ref --;
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering if (m->n_ref == 0)
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering mmap_cache_free(m);
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering return NULL;
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering}
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poetteringstatic int make_room(MMapCache *m) {
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering assert(m);
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering if (!m->last_unused)
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering return 0;
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering window_free(m->last_unused);
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering return 1;
56f64d95763a799ba4475daf44d8e9f72a1bd474Michal Schmidt}
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poetteringstatic int try_context(
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering MMapCache *m,
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering int fd,
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering int prot,
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering unsigned context,
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering bool keep_always,
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering uint64_t offset,
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering size_t size,
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering void **ret) {
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering Context *c;
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering assert(m);
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering assert(m->n_ref > 0);
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering assert(fd >= 0);
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering assert(size > 0);
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering assert(ret);
2b43f939a4b3ad5aeb2650868b0234ff42ec0045Lennart Poettering
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering c = m->contexts[context];
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering if (!c)
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering return 0;
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering assert(c->id == context);
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering if (!c->window)
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering return 0;
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering if (!window_matches(c->window, fd, prot, offset, size)) {
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering /* Drop the reference to the window, since it's unnecessary now */
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering context_detach_window(c);
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering return 0;
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering }
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering c->window->keep_always |= keep_always;
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering *ret = (uint8_t*) c->window->ptr + (offset - c->window->offset);
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering return 1;
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering}
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poetteringstatic int find_mmap(
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering MMapCache *m,
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering int fd,
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering int prot,
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering unsigned context,
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering bool keep_always,
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering uint64_t offset,
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering size_t size,
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering void **ret) {
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering FileDescriptor *f;
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering Window *w;
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering Context *c;
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering
445ea9be520b9549aee45d0b6427cf48b446987fLennart Poettering assert(m);
445ea9be520b9549aee45d0b6427cf48b446987fLennart Poettering assert(m->n_ref > 0);
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering assert(fd >= 0);
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering assert(size > 0);
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering
151b9b9662a90455262ce575a8a8ae74bf4ff336Lennart Poettering f = hashmap_get(m->fds, INT_TO_PTR(fd + 1));
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering if (!f)
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering return 0;
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering assert(f->fd == fd);
c0f71f469fef3f3a0822e0021085e6d165df2b46Lennart Poettering
c0f71f469fef3f3a0822e0021085e6d165df2b46Lennart Poettering LIST_FOREACH(by_fd, w, f->windows)
c0f71f469fef3f3a0822e0021085e6d165df2b46Lennart Poettering if (window_matches(w, fd, prot, offset, size))
c0f71f469fef3f3a0822e0021085e6d165df2b46Lennart Poettering break;
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering
da927ba997d68401563b927f92e6e40e021a8e5cMichal Schmidt if (!w)
c0f71f469fef3f3a0822e0021085e6d165df2b46Lennart Poettering return 0;
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering c = context_add(m, context);
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering if (!c)
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering return -ENOMEM;
da927ba997d68401563b927f92e6e40e021a8e5cMichal Schmidt
c0f71f469fef3f3a0822e0021085e6d165df2b46Lennart Poettering context_attach_window(c, w);
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering w->keep_always += keep_always;
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering *ret = (uint8_t*) w->ptr + (offset - w->offset);
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering return 1;
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering}
c0f71f469fef3f3a0822e0021085e6d165df2b46Lennart Poettering
c0f71f469fef3f3a0822e0021085e6d165df2b46Lennart Poetteringstatic int add_mmap(
03e334a1c7dc8c20c38902aa039440763acc9b17Lennart Poettering MMapCache *m,
03e334a1c7dc8c20c38902aa039440763acc9b17Lennart Poettering int fd,
c0f71f469fef3f3a0822e0021085e6d165df2b46Lennart Poettering int prot,
c0f71f469fef3f3a0822e0021085e6d165df2b46Lennart Poettering unsigned context,
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering bool keep_always,
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering uint64_t offset,
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering size_t size,
03e334a1c7dc8c20c38902aa039440763acc9b17Lennart Poettering struct stat *st,
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering void **ret) {
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering uint64_t woffset, wsize;
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering Context *c;
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering FileDescriptor *f;
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering Window *w;
b2e6df73aa508cc09b1b536a2fb9f90f152b89faZbigniew Jędrzejewski-Szmek void *d;
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering int r;
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering assert(m);
56f64d95763a799ba4475daf44d8e9f72a1bd474Michal Schmidt assert(m->n_ref > 0);
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering assert(fd >= 0);
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering assert(size > 0);
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering assert(ret);
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering
56f64d95763a799ba4475daf44d8e9f72a1bd474Michal Schmidt woffset = offset & ~((uint64_t) page_size() - 1ULL);
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering wsize = size + (offset - woffset);
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering wsize = PAGE_ALIGN(wsize);
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering if (wsize < WINDOW_SIZE) {
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering uint64_t delta;
56f64d95763a799ba4475daf44d8e9f72a1bd474Michal Schmidt
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering delta = PAGE_ALIGN((WINDOW_SIZE - wsize) / 2);
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering if (delta > offset)
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering woffset = 0;
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering else
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering woffset -= delta;
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering
wsize = WINDOW_SIZE;
}
if (st) {
/* Memory maps that are larger then the files
underneath have undefined behavior. Hence, clamp
things to the file size if we know it */
if (woffset >= (uint64_t) st->st_size)
return -EADDRNOTAVAIL;
if (woffset + wsize > (uint64_t) st->st_size)
wsize = PAGE_ALIGN(st->st_size - woffset);
}
for (;;) {
d = mmap(NULL, wsize, prot, MAP_SHARED, fd, woffset);
if (d != MAP_FAILED)
break;
if (errno != ENOMEM)
return -errno;
r = make_room(m);
if (r < 0)
return r;
if (r == 0)
return -ENOMEM;
}
c = context_add(m, context);
if (!c)
goto outofmem;
f = fd_add(m, fd);
if (!f)
goto outofmem;
w = window_add(m);
if (!w)
goto outofmem;
w->keep_always = keep_always;
w->ptr = d;
w->offset = woffset;
w->prot = prot;
w->size = wsize;
w->fd = f;
LIST_PREPEND(by_fd, f->windows, w);
context_detach_window(c);
c->window = w;
LIST_PREPEND(by_window, w->contexts, c);
*ret = (uint8_t*) w->ptr + (offset - w->offset);
return 1;
outofmem:
munmap(d, wsize);
return -ENOMEM;
}
int mmap_cache_get(
MMapCache *m,
int fd,
int prot,
unsigned context,
bool keep_always,
uint64_t offset,
size_t size,
struct stat *st,
void **ret) {
int r;
assert(m);
assert(m->n_ref > 0);
assert(fd >= 0);
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);
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);
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);
}
void mmap_cache_close_fd(MMapCache *m, int fd) {
FileDescriptor *f;
assert(m);
assert(fd >= 0);
f = hashmap_get(m->fds, INT_TO_PTR(fd + 1));
if (!f)
return;
fd_free(f);
}
unsigned mmap_cache_get_hit(MMapCache *m) {
assert(m);
return m->n_hit;
}
unsigned mmap_cache_get_missed(MMapCache *m) {
assert(m);
return m->n_missed;
}