mmap-cache.c revision 8e6d9397b550f5617fc9231e3a275348cda23c89
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering/***
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering This file is part of systemd.
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering Copyright 2012 Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering systemd is free software; you can redistribute it and/or modify it
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering under the terms of the GNU Lesser General Public License as published by
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering the Free Software Foundation; either version 2.1 of the License, or
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering (at your option) any later version.
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering systemd is distributed in the hope that it will be useful, but
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering Lesser General Public License for more details.
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering You should have received a copy of the GNU Lesser General Public License
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering***/
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#include <errno.h>
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#include <stdlib.h>
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#include <sys/mman.h>
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#include <string.h>
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#include "hashmap.h"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#include "list.h"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#include "log.h"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#include "util.h"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#include "macro.h"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#include "mmap-cache.h"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringtypedef struct Window Window;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringtypedef struct Context Context;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringtypedef struct FileDescriptor FileDescriptor;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringstruct Window {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering MMapCache *cache;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering bool keep_always;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering bool in_unused;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering int prot;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering void *ptr;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering uint64_t offset;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering size_t size;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering FileDescriptor *fd;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering LIST_FIELDS(Window, by_fd);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering LIST_FIELDS(Window, unused);
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering LIST_HEAD(Context, contexts);
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering};
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringstruct Context {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering MMapCache *cache;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering unsigned id;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering Window *window;
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering LIST_FIELDS(Context, by_window);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering};
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringstruct FileDescriptor {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering MMapCache *cache;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering int fd;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering LIST_HEAD(Window, windows);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering};
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringstruct MMapCache {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering int n_ref;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering unsigned n_windows;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering Hashmap *fds;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering Hashmap *contexts;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering LIST_HEAD(Window, unused);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering Window *last_unused;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering};
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#define WINDOWS_MIN 64
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#define WINDOW_SIZE (8ULL*1024ULL*1024ULL)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart PoetteringMMapCache* mmap_cache_new(void) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering MMapCache *m;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering m = new0(MMapCache, 1);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (!m)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return NULL;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering m->n_ref = 1;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return m;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering}
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart PoetteringMMapCache* mmap_cache_ref(MMapCache *m) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert(m);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert(m->n_ref > 0);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering m->n_ref ++;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return m;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering}
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringstatic void window_unlink(Window *w) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering Context *c;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert(w);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (w->ptr)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering munmap(w->ptr, w->size);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (w->fd)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering LIST_REMOVE(Window, by_fd, w->fd->windows, w);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (w->in_unused) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (w->cache->last_unused == w)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering w->cache->last_unused = w->unused_prev;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering LIST_REMOVE(Window, unused, w->cache->unused, w);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering }
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering LIST_FOREACH(by_window, c, w->contexts) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert(c->window == w);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering c->window = NULL;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering }
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering}
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringstatic void window_free(Window *w) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert(w);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering window_unlink(w);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering w->cache->n_windows--;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering free(w);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering}
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering_pure_ static bool window_matches(Window *w, int fd, int prot, uint64_t offset, size_t size) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert(w);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert(fd >= 0);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert(size > 0);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering w->fd &&
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering fd == w->fd->fd &&
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering prot == w->prot &&
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering offset >= w->offset &&
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering offset + size <= w->offset + w->size;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering}
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringstatic Window *window_add(MMapCache *m) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering Window *w;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert(m);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (!m->last_unused || m->n_windows <= WINDOWS_MIN) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering /* Allocate a new window */
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering w = new0(Window, 1);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (!w)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return NULL;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering m->n_windows++;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering } else {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering /* Reuse an existing one */
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering w = m->last_unused;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering window_unlink(w);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering zero(*w);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering }
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering w->cache = m;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return w;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering}
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringstatic void context_detach_window(Context *c) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering Window *w;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert(c);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (!c->window)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering w = c->window;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering c->window = NULL;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering LIST_REMOVE(Context, by_window, w->contexts, c);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (!w->contexts && !w->keep_always) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering /* Not used anymore? */
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering LIST_PREPEND(Window, unused, c->cache->unused, w);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (!c->cache->last_unused)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering c->cache->last_unused = w;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering w->in_unused = true;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering }
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering}
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringstatic void context_attach_window(Context *c, Window *w) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert(c);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert(w);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (c->window == w)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering context_detach_window(c);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (w->in_unused) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering /* Used again? */
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering LIST_REMOVE(Window, unused, c->cache->unused, w);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (c->cache->last_unused == w)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering c->cache->last_unused = w->unused_prev;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering w->in_unused = false;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering }
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering c->window = w;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering LIST_PREPEND(Context, by_window, w->contexts, c);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering}
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringstatic Context *context_add(MMapCache *m, unsigned id) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering Context *c;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering int r;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert(m);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering c = hashmap_get(m->contexts, UINT_TO_PTR(id + 1));
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (c)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return c;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering r = hashmap_ensure_allocated(&m->contexts, trivial_hash_func, trivial_compare_func);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (r < 0)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return NULL;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering c = new0(Context, 1);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (!c)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return NULL;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering c->cache = m;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering c->id = id;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering r = hashmap_put(m->contexts, UINT_TO_PTR(id + 1), c);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (r < 0) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering free(c);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return NULL;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering }
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return c;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering}
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringstatic void context_free(Context *c) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert(c);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering context_detach_window(c);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (c->cache)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert_se(hashmap_remove(c->cache->contexts, UINT_TO_PTR(c->id + 1)));
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering free(c);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering}
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringstatic void fd_free(FileDescriptor *f) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert(f);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering while (f->windows)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering window_free(f->windows);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (f->cache)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert_se(hashmap_remove(f->cache->fds, INT_TO_PTR(f->fd + 1)));
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering free(f);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering}
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringstatic FileDescriptor* fd_add(MMapCache *m, int fd) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering FileDescriptor *f;
80343dc19a9bcd703275ad2ad88f43e5310559d6Zbigniew Jędrzejewski-Szmek int r;
80343dc19a9bcd703275ad2ad88f43e5310559d6Zbigniew Jędrzejewski-Szmek
80343dc19a9bcd703275ad2ad88f43e5310559d6Zbigniew Jędrzejewski-Szmek assert(m);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert(fd >= 0);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering f = hashmap_get(m->fds, INT_TO_PTR(fd + 1));
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (f)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return f;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering r = hashmap_ensure_allocated(&m->fds, trivial_hash_func, trivial_compare_func);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (r < 0)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return NULL;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering f = new0(FileDescriptor, 1);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (!f)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return NULL;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering f->cache = m;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering f->fd = fd;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering r = hashmap_put(m->fds, UINT_TO_PTR(fd + 1), f);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (r < 0) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering free(f);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return NULL;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering }
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return f;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering}
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringstatic void mmap_cache_free(MMapCache *m) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering Context *c;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering FileDescriptor *f;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert(m);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering while ((c = hashmap_first(m->contexts)))
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering context_free(c);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering hashmap_free(m->contexts);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering while ((f = hashmap_first(m->fds)))
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering fd_free(f);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
80343dc19a9bcd703275ad2ad88f43e5310559d6Zbigniew Jędrzejewski-Szmek hashmap_free(m->fds);
80343dc19a9bcd703275ad2ad88f43e5310559d6Zbigniew Jędrzejewski-Szmek
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering while (m->unused)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering window_free(m->unused);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering free(m);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering}
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart PoetteringMMapCache* mmap_cache_unref(MMapCache *m) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert(m);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert(m->n_ref > 0);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering m->n_ref --;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (m->n_ref == 0)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering mmap_cache_free(m);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return NULL;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering}
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringstatic int make_room(MMapCache *m) {
80343dc19a9bcd703275ad2ad88f43e5310559d6Zbigniew Jędrzejewski-Szmek assert(m);
80343dc19a9bcd703275ad2ad88f43e5310559d6Zbigniew Jędrzejewski-Szmek
80343dc19a9bcd703275ad2ad88f43e5310559d6Zbigniew Jędrzejewski-Szmek if (!m->last_unused)
80343dc19a9bcd703275ad2ad88f43e5310559d6Zbigniew Jędrzejewski-Szmek return 0;
80343dc19a9bcd703275ad2ad88f43e5310559d6Zbigniew Jędrzejewski-Szmek
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering window_free(m->last_unused);
80343dc19a9bcd703275ad2ad88f43e5310559d6Zbigniew Jędrzejewski-Szmek return 1;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering}
80343dc19a9bcd703275ad2ad88f43e5310559d6Zbigniew Jędrzejewski-Szmek
80343dc19a9bcd703275ad2ad88f43e5310559d6Zbigniew Jędrzejewski-Szmekstatic int try_context(
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering MMapCache *m,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering int fd,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering int prot,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering unsigned context,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering bool keep_always,
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering uint64_t offset,
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering size_t size,
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering void **ret) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering Context *c;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
80343dc19a9bcd703275ad2ad88f43e5310559d6Zbigniew Jędrzejewski-Szmek assert(m);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert(m->n_ref > 0);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert(fd >= 0);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert(size > 0);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert(ret);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
80343dc19a9bcd703275ad2ad88f43e5310559d6Zbigniew Jędrzejewski-Szmek c = hashmap_get(m->contexts, UINT_TO_PTR(context+1));
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (!c)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return 0;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert(c->id == context);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
80343dc19a9bcd703275ad2ad88f43e5310559d6Zbigniew Jędrzejewski-Szmek if (!c->window)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return 0;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (!window_matches(c->window, fd, prot, offset, size)) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering /* Drop the reference to the window, since it's unnecessary now */
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering context_detach_window(c);
80343dc19a9bcd703275ad2ad88f43e5310559d6Zbigniew Jędrzejewski-Szmek return 0;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering }
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering c->window->keep_always = c->window->keep_always || keep_always;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering *ret = (uint8_t*) c->window->ptr + (offset - c->window->offset);
80343dc19a9bcd703275ad2ad88f43e5310559d6Zbigniew Jędrzejewski-Szmek return 1;
80343dc19a9bcd703275ad2ad88f43e5310559d6Zbigniew Jędrzejewski-Szmek}
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringstatic int find_mmap(
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering MMapCache *m,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering int fd,
80343dc19a9bcd703275ad2ad88f43e5310559d6Zbigniew Jędrzejewski-Szmek int prot,
80343dc19a9bcd703275ad2ad88f43e5310559d6Zbigniew Jędrzejewski-Szmek unsigned context,
80343dc19a9bcd703275ad2ad88f43e5310559d6Zbigniew Jędrzejewski-Szmek bool keep_always,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering uint64_t offset,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering size_t size,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering void **ret) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering FileDescriptor *f;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering Window *w;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering Context *c;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert(m);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert(m->n_ref > 0);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert(fd >= 0);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert(size > 0);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert(ret);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering f = hashmap_get(m->fds, INT_TO_PTR(fd + 1));
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (!f)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return 0;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert(f->fd == fd);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering LIST_FOREACH(by_fd, w, f->windows)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (window_matches(w, fd, prot, offset, size))
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering break;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (!w)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return 0;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering c = context_add(m, context);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (!c)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return -ENOMEM;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering context_attach_window(c, w);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering w->keep_always = w->keep_always || keep_always;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering *ret = (uint8_t*) w->ptr + (offset - w->offset);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return 1;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering}
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringstatic int add_mmap(
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering MMapCache *m,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering int fd,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering int prot,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering unsigned context,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering bool keep_always,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering uint64_t offset,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering size_t size,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering struct stat *st,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering void **ret) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering uint64_t woffset, wsize;
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering Context *c;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering FileDescriptor *f;
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering Window *w;
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering void *d;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering int r;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert(m);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert(m->n_ref > 0);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert(fd >= 0);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert(size > 0);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert(ret);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering woffset = offset & ~((uint64_t) page_size() - 1ULL);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering wsize = size + (offset - woffset);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering wsize = PAGE_ALIGN(wsize);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (wsize < WINDOW_SIZE) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering uint64_t delta;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering delta = PAGE_ALIGN((WINDOW_SIZE - wsize) / 2);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (delta > offset)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering woffset = 0;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering else
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering woffset -= delta;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering wsize = WINDOW_SIZE;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering }
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering if (st) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering /* Memory maps that are larger then the files
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering underneath have undefined behavior. Hence, clamp
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering things to the file size if we know it */
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (woffset >= (uint64_t) st->st_size)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return -EADDRNOTAVAIL;
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (woffset + wsize > (uint64_t) st->st_size)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering wsize = PAGE_ALIGN(st->st_size - woffset);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering }
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering for (;;) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering d = mmap(NULL, wsize, prot, MAP_SHARED, fd, woffset);
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering if (d != MAP_FAILED)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering break;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (errno != ENOMEM)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return -errno;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering r = make_room(m);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (r < 0)
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering return r;
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering if (r == 0)
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering return -ENOMEM;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering }
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering c = context_add(m, context);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (!c)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return -ENOMEM;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering f = fd_add(m, fd);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (!f)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return -ENOMEM;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering w = window_add(m);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (!w)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return -ENOMEM;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering w->keep_always = keep_always;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering w->ptr = d;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering w->offset = woffset;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering w->prot = prot;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering w->size = wsize;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering w->fd = f;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering LIST_PREPEND(Window, by_fd, f->windows, w);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering context_detach_window(c);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering c->window = w;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering LIST_PREPEND(Context, by_window, w->contexts, c);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering *ret = (uint8_t*) w->ptr + (offset - w->offset);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return 1;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering}
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringint mmap_cache_get(
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering MMapCache *m,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering int fd,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering int prot,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering unsigned context,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering bool keep_always,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering uint64_t offset,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering size_t size,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering struct stat *st,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering void **ret) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering int r;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert(m);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert(m->n_ref > 0);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert(fd >= 0);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert(size > 0);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert(ret);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering /* Check whether the current context is the right one already */
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering r = try_context(m, fd, prot, context, keep_always, offset, size, ret);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (r != 0)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return r;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering /* Search for a matching mmap */
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering r = find_mmap(m, fd, prot, context, keep_always, offset, size, ret);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (r != 0)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return r;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering /* Create a new mmap */
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return add_mmap(m, fd, prot, context, keep_always, offset, size, st, ret);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering}
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringvoid mmap_cache_close_fd(MMapCache *m, int fd) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering FileDescriptor *f;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert(m);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert(fd >= 0);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering f = hashmap_get(m->fds, INT_TO_PTR(fd + 1));
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (!f)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering fd_free(f);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering}
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringvoid mmap_cache_close_context(MMapCache *m, unsigned context) {
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering Context *c;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering assert(m);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering c = hashmap_get(m->contexts, UINT_TO_PTR(context + 1));
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (!c)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering context_free(c);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering}
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering