mirror of
https://github.com/systemd/systemd.git
synced 2026-08-12 22:17:19 +00:00
mmap-cache: drop Context and boolean flags in Window
No functional change, just refactoring.
This commit is contained in:
@@ -16,14 +16,23 @@
|
||||
#include "sigbus.h"
|
||||
|
||||
typedef struct Window Window;
|
||||
typedef struct Context Context;
|
||||
|
||||
typedef enum WindowFlags {
|
||||
WINDOW_KEEP_ALWAYS = 1u << (MMAP_CACHE_MAX_CONTEXTS + 0),
|
||||
WINDOW_IN_UNUSED = 1u << (MMAP_CACHE_MAX_CONTEXTS + 1),
|
||||
WINDOW_INVALIDATED = 1u << (MMAP_CACHE_MAX_CONTEXTS + 2),
|
||||
|
||||
_WINDOW_USED_MASK = WINDOW_IN_UNUSED - 1, /* The mask contains all bits that indicate the windows
|
||||
* is currently in use. Covers the all the object types
|
||||
* and the additional WINDOW_KEEP_ALWAYS flag. */
|
||||
} WindowFlags;
|
||||
|
||||
#define WINDOW_IS_UNUSED(w) (((w)->flags & _WINDOW_USED_MASK) == 0)
|
||||
|
||||
struct Window {
|
||||
MMapFileDescriptor *fd;
|
||||
|
||||
bool invalidated:1;
|
||||
bool keep_always:1;
|
||||
bool in_unused:1;
|
||||
WindowFlags flags;
|
||||
|
||||
void *ptr;
|
||||
uint64_t offset;
|
||||
@@ -31,21 +40,15 @@ struct Window {
|
||||
|
||||
LIST_FIELDS(Window, windows);
|
||||
LIST_FIELDS(Window, unused);
|
||||
|
||||
LIST_HEAD(Context, contexts);
|
||||
};
|
||||
|
||||
struct Context {
|
||||
Window *window;
|
||||
|
||||
LIST_FIELDS(Context, by_window);
|
||||
};
|
||||
|
||||
struct MMapFileDescriptor {
|
||||
MMapCache *cache;
|
||||
|
||||
int fd;
|
||||
int prot;
|
||||
bool sigbus;
|
||||
|
||||
LIST_HEAD(Window, windows);
|
||||
};
|
||||
|
||||
@@ -62,7 +65,7 @@ struct MMapCache {
|
||||
LIST_HEAD(Window, unused);
|
||||
Window *last_unused;
|
||||
|
||||
Context contexts[MMAP_CACHE_MAX_CONTEXTS];
|
||||
Window *windows_by_context[MMAP_CACHE_MAX_CONTEXTS];
|
||||
};
|
||||
|
||||
#define WINDOWS_MIN 64
|
||||
@@ -96,17 +99,15 @@ static Window* window_unlink(Window *w) {
|
||||
if (w->ptr)
|
||||
munmap(w->ptr, w->size);
|
||||
|
||||
if (w->in_unused) {
|
||||
if (FLAGS_SET(w->flags, WINDOW_IN_UNUSED)) {
|
||||
if (m->last_unused == w)
|
||||
m->last_unused = w->unused_prev;
|
||||
|
||||
LIST_REMOVE(unused, m->unused, w);
|
||||
}
|
||||
|
||||
LIST_FOREACH(by_window, c, w->contexts) {
|
||||
assert(c->window == w);
|
||||
c->window = NULL;
|
||||
}
|
||||
for (unsigned i = 0; i < MMAP_CACHE_MAX_CONTEXTS; i++)
|
||||
if (FLAGS_SET(w->flags, 1u << i))
|
||||
assert_se(TAKE_PTR(m->windows_by_context[i]) == w);
|
||||
|
||||
return LIST_REMOVE(windows, w->fd->windows, w);
|
||||
}
|
||||
@@ -115,14 +116,14 @@ static void window_invalidate(Window *w) {
|
||||
assert(w);
|
||||
assert(w->fd);
|
||||
|
||||
if (w->invalidated)
|
||||
if (FLAGS_SET(w->flags, WINDOW_INVALIDATED))
|
||||
return;
|
||||
|
||||
/* Replace the window with anonymous pages. This is useful when we hit a SIGBUS and want to make sure
|
||||
* the file cannot trigger any further SIGBUS, possibly overrunning the sigbus queue. */
|
||||
|
||||
assert_se(mmap(w->ptr, w->size, w->fd->prot, MAP_PRIVATE|MAP_ANONYMOUS|MAP_FIXED, -1, 0) == w->ptr);
|
||||
w->invalidated = true;
|
||||
w->flags |= WINDOW_INVALIDATED;
|
||||
}
|
||||
|
||||
static Window* window_free(Window *w) {
|
||||
@@ -169,19 +170,20 @@ static Window* window_add(MMapFileDescriptor *f, uint64_t offset, size_t size, v
|
||||
return LIST_PREPEND(windows, f->windows, w);
|
||||
}
|
||||
|
||||
static void context_detach_window(MMapCache *m, Context *c) {
|
||||
static void context_detach_window(MMapCache *m, unsigned c) {
|
||||
Window *w;
|
||||
|
||||
assert(m);
|
||||
assert(c);
|
||||
assert(c < MMAP_CACHE_MAX_CONTEXTS);
|
||||
|
||||
if (!c->window)
|
||||
return;
|
||||
w = TAKE_PTR(m->windows_by_context[c]);
|
||||
if (!w)
|
||||
return; /* Nothing attached. */
|
||||
|
||||
w = TAKE_PTR(c->window);
|
||||
LIST_REMOVE(by_window, w->contexts, c);
|
||||
assert(FLAGS_SET(w->flags, 1u << c));
|
||||
w->flags &= ~(1u << c);
|
||||
|
||||
if (!w->contexts && !w->keep_always) {
|
||||
if (WINDOW_IS_UNUSED(w)) {
|
||||
/* Not used anymore? */
|
||||
#if ENABLE_DEBUG_MMAP_CACHE
|
||||
/* Unmap unused windows immediately to expose use-after-unmap by SIGSEGV. */
|
||||
@@ -190,33 +192,31 @@ static void context_detach_window(MMapCache *m, Context *c) {
|
||||
LIST_PREPEND(unused, m->unused, w);
|
||||
if (!m->last_unused)
|
||||
m->last_unused = w;
|
||||
|
||||
w->in_unused = true;
|
||||
w->flags |= WINDOW_IN_UNUSED;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
static void context_attach_window(MMapCache *m, Context *c, Window *w) {
|
||||
static void context_attach_window(MMapCache *m, unsigned c, Window *w) {
|
||||
assert(m);
|
||||
assert(c);
|
||||
assert(c < MMAP_CACHE_MAX_CONTEXTS);
|
||||
assert(w);
|
||||
|
||||
if (c->window == w)
|
||||
return;
|
||||
if (m->windows_by_context[c] == w)
|
||||
return; /* Already attached. */
|
||||
|
||||
context_detach_window(m, c);
|
||||
|
||||
if (w->in_unused) {
|
||||
if (FLAGS_SET(w->flags, WINDOW_IN_UNUSED)) {
|
||||
/* Used again? */
|
||||
if (m->last_unused == w)
|
||||
m->last_unused = w->unused_prev;
|
||||
LIST_REMOVE(unused, m->unused, w);
|
||||
|
||||
w->in_unused = false;
|
||||
w->flags &= ~WINDOW_IN_UNUSED;
|
||||
}
|
||||
|
||||
c->window = w;
|
||||
LIST_PREPEND(by_window, w->contexts, c);
|
||||
m->windows_by_context[c] = w;
|
||||
w->flags |= (1u << c);
|
||||
}
|
||||
|
||||
static MMapCache* mmap_cache_free(MMapCache *m) {
|
||||
@@ -322,7 +322,7 @@ static int add_mmap(
|
||||
|
||||
int mmap_cache_fd_get(
|
||||
MMapFileDescriptor *f,
|
||||
unsigned context,
|
||||
unsigned c,
|
||||
bool keep_always,
|
||||
uint64_t offset,
|
||||
size_t size,
|
||||
@@ -330,23 +330,20 @@ int mmap_cache_fd_get(
|
||||
void **ret) {
|
||||
|
||||
MMapCache *m = mmap_cache_fd_cache(f);
|
||||
Context *c;
|
||||
Window *w;
|
||||
int r;
|
||||
|
||||
assert(context < MMAP_CACHE_MAX_CONTEXTS);
|
||||
assert(size > 0);
|
||||
assert(c < MMAP_CACHE_MAX_CONTEXTS);
|
||||
assert(ret);
|
||||
|
||||
if (f->sigbus)
|
||||
return -EIO;
|
||||
|
||||
c = &f->cache->contexts[context];
|
||||
|
||||
/* Check whether the current context is the right one already */
|
||||
if (window_matches(c->window, f, offset, size)) {
|
||||
if (window_matches(m->windows_by_context[c], f, offset, size)) {
|
||||
m->n_context_cache_hit++;
|
||||
w = c->window;
|
||||
w = m->windows_by_context[c];
|
||||
goto found;
|
||||
}
|
||||
|
||||
@@ -369,7 +366,9 @@ int mmap_cache_fd_get(
|
||||
return r;
|
||||
|
||||
found:
|
||||
w->keep_always = w->keep_always || keep_always;
|
||||
if (keep_always)
|
||||
w->flags |= WINDOW_KEEP_ALWAYS;
|
||||
|
||||
context_attach_window(m, c, w);
|
||||
*ret = (uint8_t*) w->ptr + (offset - w->offset);
|
||||
return 0;
|
||||
|
||||
Reference in New Issue
Block a user