| File: | build-scan/../src/journal/mmap-cache.c |
| Warning: | line 180, column 17 Use of memory after it is freed |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
| 1 | /* SPDX-License-Identifier: LGPL-2.1+ */ | |||
| 2 | ||||
| 3 | #include <errno(*__errno_location ()).h> | |||
| 4 | #include <stdlib.h> | |||
| 5 | #include <sys/mman.h> | |||
| 6 | ||||
| 7 | #include "alloc-util.h" | |||
| 8 | #include "fd-util.h" | |||
| 9 | #include "hashmap.h" | |||
| 10 | #include "list.h" | |||
| 11 | #include "log.h" | |||
| 12 | #include "macro.h" | |||
| 13 | #include "mmap-cache.h" | |||
| 14 | #include "sigbus.h" | |||
| 15 | #include "util.h" | |||
| 16 | ||||
| 17 | typedef struct Window Window; | |||
| 18 | typedef struct Context Context; | |||
| 19 | ||||
| 20 | struct Window { | |||
| 21 | MMapCache *cache; | |||
| 22 | ||||
| 23 | bool_Bool invalidated:1; | |||
| 24 | bool_Bool keep_always:1; | |||
| 25 | bool_Bool in_unused:1; | |||
| 26 | ||||
| 27 | int prot; | |||
| 28 | void *ptr; | |||
| 29 | uint64_t offset; | |||
| 30 | size_t size; | |||
| 31 | ||||
| 32 | MMapFileDescriptor *fd; | |||
| 33 | ||||
| 34 | LIST_FIELDS(Window, by_fd)Window *by_fd_next, *by_fd_prev; | |||
| 35 | LIST_FIELDS(Window, unused)Window *unused_next, *unused_prev; | |||
| 36 | ||||
| 37 | LIST_HEAD(Context, contexts)Context *contexts; | |||
| 38 | }; | |||
| 39 | ||||
| 40 | struct Context { | |||
| 41 | MMapCache *cache; | |||
| 42 | unsigned id; | |||
| 43 | Window *window; | |||
| 44 | ||||
| 45 | LIST_FIELDS(Context, by_window)Context *by_window_next, *by_window_prev; | |||
| 46 | }; | |||
| 47 | ||||
| 48 | struct MMapFileDescriptor { | |||
| 49 | MMapCache *cache; | |||
| 50 | int fd; | |||
| 51 | bool_Bool sigbus; | |||
| 52 | LIST_HEAD(Window, windows)Window *windows; | |||
| 53 | }; | |||
| 54 | ||||
| 55 | struct MMapCache { | |||
| 56 | int n_ref; | |||
| 57 | unsigned n_windows; | |||
| 58 | ||||
| 59 | unsigned n_hit, n_missed; | |||
| 60 | ||||
| 61 | Hashmap *fds; | |||
| 62 | Context *contexts[MMAP_CACHE_MAX_CONTEXTS9]; | |||
| 63 | ||||
| 64 | LIST_HEAD(Window, unused)Window *unused; | |||
| 65 | Window *last_unused; | |||
| 66 | }; | |||
| 67 | ||||
| 68 | #define WINDOWS_MIN64 64 | |||
| 69 | ||||
| 70 | #if ENABLE_DEBUG_MMAP_CACHE0 | |||
| 71 | /* Tiny windows increase mmap activity and the chance of exposing unsafe use. */ | |||
| 72 | # define WINDOW_SIZE(8ULL*1024ULL*1024ULL) (page_size()) | |||
| 73 | #else | |||
| 74 | # define WINDOW_SIZE(8ULL*1024ULL*1024ULL) (8ULL*1024ULL*1024ULL) | |||
| 75 | #endif | |||
| 76 | ||||
| 77 | MMapCache* mmap_cache_new(void) { | |||
| 78 | MMapCache *m; | |||
| 79 | ||||
| 80 | m = new0(MMapCache, 1)((MMapCache*) calloc((1), sizeof(MMapCache))); | |||
| 81 | if (!m) | |||
| 82 | return NULL((void*)0); | |||
| 83 | ||||
| 84 | m->n_ref = 1; | |||
| 85 | return m; | |||
| 86 | } | |||
| 87 | ||||
| 88 | MMapCache* mmap_cache_ref(MMapCache *m) { | |||
| 89 | assert(m)do { if ((__builtin_expect(!!(!(m)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("m"), "../src/journal/mmap-cache.c", 89, __PRETTY_FUNCTION__); } while (0); | |||
| 90 | assert(m->n_ref > 0)do { if ((__builtin_expect(!!(!(m->n_ref > 0)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("m->n_ref > 0"), "../src/journal/mmap-cache.c" , 90, __PRETTY_FUNCTION__); } while (0); | |||
| 91 | ||||
| 92 | m->n_ref++; | |||
| 93 | return m; | |||
| 94 | } | |||
| 95 | ||||
| 96 | static void window_unlink(Window *w) { | |||
| 97 | Context *c; | |||
| 98 | ||||
| 99 | assert(w)do { if ((__builtin_expect(!!(!(w)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("w"), "../src/journal/mmap-cache.c", 99, __PRETTY_FUNCTION__); } while (0); | |||
| 100 | ||||
| 101 | if (w->ptr) | |||
| 102 | munmap(w->ptr, w->size); | |||
| 103 | ||||
| 104 | if (w->fd) | |||
| 105 | LIST_REMOVE(by_fd, w->fd->windows, w)do { typeof(*(w->fd->windows)) **_head = &(w->fd ->windows), *_item = (w); do { if ((__builtin_expect(!!(!( _item)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("_item" ), "../src/journal/mmap-cache.c", 105, __PRETTY_FUNCTION__); } while (0); if (_item->by_fd_next) _item->by_fd_next-> by_fd_prev = _item->by_fd_prev; if (_item->by_fd_prev) _item ->by_fd_prev->by_fd_next = _item->by_fd_next; else { do { if ((__builtin_expect(!!(!(*_head == _item)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("*_head == _item"), "../src/journal/mmap-cache.c" , 105, __PRETTY_FUNCTION__); } while (0); *_head = _item-> by_fd_next; } _item->by_fd_next = _item->by_fd_prev = ( (void*)0); } while (0); | |||
| 106 | ||||
| 107 | if (w->in_unused) { | |||
| 108 | if (w->cache->last_unused == w) | |||
| 109 | w->cache->last_unused = w->unused_prev; | |||
| 110 | ||||
| 111 | LIST_REMOVE(unused, w->cache->unused, w)do { typeof(*(w->cache->unused)) **_head = &(w-> cache->unused), *_item = (w); do { if ((__builtin_expect(! !(!(_item)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ( "_item"), "../src/journal/mmap-cache.c", 111, __PRETTY_FUNCTION__ ); } while (0); if (_item->unused_next) _item->unused_next ->unused_prev = _item->unused_prev; if (_item->unused_prev ) _item->unused_prev->unused_next = _item->unused_next ; else { do { if ((__builtin_expect(!!(!(*_head == _item)),0) )) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("*_head == _item" ), "../src/journal/mmap-cache.c", 111, __PRETTY_FUNCTION__); } while (0); *_head = _item->unused_next; } _item->unused_next = _item->unused_prev = ((void*)0); } while (0); | |||
| 112 | } | |||
| 113 | ||||
| 114 | LIST_FOREACH(by_window, c, w->contexts)for ((c) = (w->contexts); (c); (c) = (c)->by_window_next ) { | |||
| 115 | assert(c->window == w)do { if ((__builtin_expect(!!(!(c->window == w)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("c->window == w"), "../src/journal/mmap-cache.c" , 115, __PRETTY_FUNCTION__); } while (0); | |||
| 116 | c->window = NULL((void*)0); | |||
| 117 | } | |||
| 118 | } | |||
| 119 | ||||
| 120 | static void window_invalidate(Window *w) { | |||
| 121 | assert(w)do { if ((__builtin_expect(!!(!(w)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("w"), "../src/journal/mmap-cache.c", 121 , __PRETTY_FUNCTION__); } while (0); | |||
| 122 | ||||
| 123 | if (w->invalidated) | |||
| 124 | return; | |||
| 125 | ||||
| 126 | /* Replace the window with anonymous pages. This is useful | |||
| 127 | * when we hit a SIGBUS and want to make sure the file cannot | |||
| 128 | * trigger any further SIGBUS, possibly overrunning the sigbus | |||
| 129 | * queue. */ | |||
| 130 | ||||
| 131 | assert_se(mmap(w->ptr, w->size, w->prot, MAP_PRIVATE|MAP_ANONYMOUS|MAP_FIXED, -1, 0) == w->ptr)do { if ((__builtin_expect(!!(!(mmap(w->ptr, w->size, w ->prot, 0x02|0x20|0x10, -1, 0) == w->ptr)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("mmap(w->ptr, w->size, w->prot, MAP_PRIVATE|MAP_ANONYMOUS|MAP_FIXED, -1, 0) == w->ptr" ), "../src/journal/mmap-cache.c", 131, __PRETTY_FUNCTION__); } while (0); | |||
| 132 | w->invalidated = true1; | |||
| 133 | } | |||
| 134 | ||||
| 135 | static void window_free(Window *w) { | |||
| 136 | assert(w)do { if ((__builtin_expect(!!(!(w)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("w"), "../src/journal/mmap-cache.c", 136 , __PRETTY_FUNCTION__); } while (0); | |||
| 137 | ||||
| 138 | window_unlink(w); | |||
| 139 | w->cache->n_windows--; | |||
| 140 | free(w); | |||
| 141 | } | |||
| 142 | ||||
| 143 | _pure___attribute__ ((pure)) static inline bool_Bool window_matches(Window *w, int prot, uint64_t offset, size_t size) { | |||
| 144 | assert(w)do { if ((__builtin_expect(!!(!(w)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("w"), "../src/journal/mmap-cache.c", 144 , __PRETTY_FUNCTION__); } while (0); | |||
| 145 | assert(size > 0)do { if ((__builtin_expect(!!(!(size > 0)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("size > 0"), "../src/journal/mmap-cache.c" , 145, __PRETTY_FUNCTION__); } while (0); | |||
| 146 | ||||
| 147 | return | |||
| 148 | prot == w->prot && | |||
| 149 | offset >= w->offset && | |||
| 150 | offset + size <= w->offset + w->size; | |||
| 151 | } | |||
| 152 | ||||
| 153 | _pure___attribute__ ((pure)) static bool_Bool window_matches_fd(Window *w, MMapFileDescriptor *f, int prot, uint64_t offset, size_t size) { | |||
| 154 | assert(w)do { if ((__builtin_expect(!!(!(w)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("w"), "../src/journal/mmap-cache.c", 154 , __PRETTY_FUNCTION__); } while (0); | |||
| 155 | assert(f)do { if ((__builtin_expect(!!(!(f)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("f"), "../src/journal/mmap-cache.c", 155 , __PRETTY_FUNCTION__); } while (0); | |||
| 156 | ||||
| 157 | return | |||
| 158 | w->fd && | |||
| 159 | f->fd == w->fd->fd && | |||
| 160 | window_matches(w, prot, offset, size); | |||
| 161 | } | |||
| 162 | ||||
| 163 | static Window *window_add(MMapCache *m, MMapFileDescriptor *f, int prot, bool_Bool keep_always, uint64_t offset, size_t size, void *ptr) { | |||
| 164 | Window *w; | |||
| 165 | ||||
| 166 | assert(m)do { if ((__builtin_expect(!!(!(m)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("m"), "../src/journal/mmap-cache.c", 166 , __PRETTY_FUNCTION__); } while (0); | |||
| 167 | assert(f)do { if ((__builtin_expect(!!(!(f)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("f"), "../src/journal/mmap-cache.c", 167 , __PRETTY_FUNCTION__); } while (0); | |||
| 168 | ||||
| 169 | if (!m->last_unused
| |||
| 170 | ||||
| 171 | /* Allocate a new window */ | |||
| 172 | w = new0(Window, 1)((Window*) calloc((1), sizeof(Window))); | |||
| 173 | if (!w) | |||
| 174 | return NULL((void*)0); | |||
| 175 | m->n_windows++; | |||
| 176 | } else { | |||
| 177 | ||||
| 178 | /* Reuse an existing one */ | |||
| 179 | w = m->last_unused; | |||
| 180 | window_unlink(w); | |||
| ||||
| 181 | zero(*w)(({ size_t _l_ = (sizeof(*w)); void *_x_ = (&(*w)); _l_ == 0 ? _x_ : memset(_x_, 0, _l_); })); | |||
| 182 | } | |||
| 183 | ||||
| 184 | w->cache = m; | |||
| 185 | w->fd = f; | |||
| 186 | w->prot = prot; | |||
| 187 | w->keep_always = keep_always; | |||
| 188 | w->offset = offset; | |||
| 189 | w->size = size; | |||
| 190 | w->ptr = ptr; | |||
| 191 | ||||
| 192 | LIST_PREPEND(by_fd, f->windows, w)do { typeof(*(f->windows)) **_head = &(f->windows), *_item = (w); do { if ((__builtin_expect(!!(!(_item)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("_item"), "../src/journal/mmap-cache.c", 192, __PRETTY_FUNCTION__); } while (0); if ((_item->by_fd_next = *_head)) _item->by_fd_next->by_fd_prev = _item; _item ->by_fd_prev = ((void*)0); *_head = _item; } while (0); | |||
| 193 | ||||
| 194 | return w; | |||
| 195 | } | |||
| 196 | ||||
| 197 | static void context_detach_window(Context *c) { | |||
| 198 | Window *w; | |||
| 199 | ||||
| 200 | assert(c)do { if ((__builtin_expect(!!(!(c)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("c"), "../src/journal/mmap-cache.c", 200 , __PRETTY_FUNCTION__); } while (0); | |||
| 201 | ||||
| 202 | if (!c->window) | |||
| 203 | return; | |||
| 204 | ||||
| 205 | w = TAKE_PTR(c->window)({ typeof(c->window) _ptr_ = (c->window); (c->window ) = ((void*)0); _ptr_; }); | |||
| 206 | LIST_REMOVE(by_window, w->contexts, c)do { typeof(*(w->contexts)) **_head = &(w->contexts ), *_item = (c); do { if ((__builtin_expect(!!(!(_item)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("_item"), "../src/journal/mmap-cache.c" , 206, __PRETTY_FUNCTION__); } while (0); if (_item->by_window_next ) _item->by_window_next->by_window_prev = _item->by_window_prev ; if (_item->by_window_prev) _item->by_window_prev-> by_window_next = _item->by_window_next; else { do { if ((__builtin_expect (!!(!(*_head == _item)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD , ("*_head == _item"), "../src/journal/mmap-cache.c", 206, __PRETTY_FUNCTION__ ); } while (0); *_head = _item->by_window_next; } _item-> by_window_next = _item->by_window_prev = ((void*)0); } while (0); | |||
| 207 | ||||
| 208 | if (!w->contexts && !w->keep_always) { | |||
| 209 | /* Not used anymore? */ | |||
| 210 | #if ENABLE_DEBUG_MMAP_CACHE0 | |||
| 211 | /* Unmap unused windows immediately to expose use-after-unmap | |||
| 212 | * by SIGSEGV. */ | |||
| 213 | window_free(w); | |||
| 214 | #else | |||
| 215 | LIST_PREPEND(unused, c->cache->unused, w)do { typeof(*(c->cache->unused)) **_head = &(c-> cache->unused), *_item = (w); do { if ((__builtin_expect(! !(!(_item)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ( "_item"), "../src/journal/mmap-cache.c", 215, __PRETTY_FUNCTION__ ); } while (0); if ((_item->unused_next = *_head)) _item-> unused_next->unused_prev = _item; _item->unused_prev = ( (void*)0); *_head = _item; } while (0); | |||
| 216 | if (!c->cache->last_unused) | |||
| 217 | c->cache->last_unused = w; | |||
| 218 | ||||
| 219 | w->in_unused = true1; | |||
| 220 | #endif | |||
| 221 | } | |||
| 222 | } | |||
| 223 | ||||
| 224 | static void context_attach_window(Context *c, Window *w) { | |||
| 225 | assert(c)do { if ((__builtin_expect(!!(!(c)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("c"), "../src/journal/mmap-cache.c", 225 , __PRETTY_FUNCTION__); } while (0); | |||
| 226 | assert(w)do { if ((__builtin_expect(!!(!(w)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("w"), "../src/journal/mmap-cache.c", 226 , __PRETTY_FUNCTION__); } while (0); | |||
| 227 | ||||
| 228 | if (c->window == w) | |||
| 229 | return; | |||
| 230 | ||||
| 231 | context_detach_window(c); | |||
| 232 | ||||
| 233 | if (w->in_unused) { | |||
| 234 | /* Used again? */ | |||
| 235 | LIST_REMOVE(unused, c->cache->unused, w)do { typeof(*(c->cache->unused)) **_head = &(c-> cache->unused), *_item = (w); do { if ((__builtin_expect(! !(!(_item)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ( "_item"), "../src/journal/mmap-cache.c", 235, __PRETTY_FUNCTION__ ); } while (0); if (_item->unused_next) _item->unused_next ->unused_prev = _item->unused_prev; if (_item->unused_prev ) _item->unused_prev->unused_next = _item->unused_next ; else { do { if ((__builtin_expect(!!(!(*_head == _item)),0) )) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("*_head == _item" ), "../src/journal/mmap-cache.c", 235, __PRETTY_FUNCTION__); } while (0); *_head = _item->unused_next; } _item->unused_next = _item->unused_prev = ((void*)0); } while (0); | |||
| 236 | if (c->cache->last_unused == w) | |||
| 237 | c->cache->last_unused = w->unused_prev; | |||
| 238 | ||||
| 239 | w->in_unused = false0; | |||
| 240 | } | |||
| 241 | ||||
| 242 | c->window = w; | |||
| 243 | LIST_PREPEND(by_window, w->contexts, c)do { typeof(*(w->contexts)) **_head = &(w->contexts ), *_item = (c); do { if ((__builtin_expect(!!(!(_item)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("_item"), "../src/journal/mmap-cache.c" , 243, __PRETTY_FUNCTION__); } while (0); if ((_item->by_window_next = *_head)) _item->by_window_next->by_window_prev = _item ; _item->by_window_prev = ((void*)0); *_head = _item; } while (0); | |||
| 244 | } | |||
| 245 | ||||
| 246 | static Context *context_add(MMapCache *m, unsigned id) { | |||
| 247 | Context *c; | |||
| 248 | ||||
| 249 | assert(m)do { if ((__builtin_expect(!!(!(m)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("m"), "../src/journal/mmap-cache.c", 249 , __PRETTY_FUNCTION__); } while (0); | |||
| 250 | ||||
| 251 | c = m->contexts[id]; | |||
| 252 | if (c) | |||
| 253 | return c; | |||
| 254 | ||||
| 255 | c = new0(Context, 1)((Context*) calloc((1), sizeof(Context))); | |||
| 256 | if (!c) | |||
| 257 | return NULL((void*)0); | |||
| 258 | ||||
| 259 | c->cache = m; | |||
| 260 | c->id = id; | |||
| 261 | ||||
| 262 | assert(!m->contexts[id])do { if ((__builtin_expect(!!(!(!m->contexts[id])),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("!m->contexts[id]"), "../src/journal/mmap-cache.c" , 262, __PRETTY_FUNCTION__); } while (0); | |||
| 263 | m->contexts[id] = c; | |||
| 264 | ||||
| 265 | return c; | |||
| 266 | } | |||
| 267 | ||||
| 268 | static void context_free(Context *c) { | |||
| 269 | assert(c)do { if ((__builtin_expect(!!(!(c)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("c"), "../src/journal/mmap-cache.c", 269 , __PRETTY_FUNCTION__); } while (0); | |||
| 270 | ||||
| 271 | context_detach_window(c); | |||
| 272 | ||||
| 273 | if (c->cache) { | |||
| 274 | assert(c->cache->contexts[c->id] == c)do { if ((__builtin_expect(!!(!(c->cache->contexts[c-> id] == c)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("c->cache->contexts[c->id] == c" ), "../src/journal/mmap-cache.c", 274, __PRETTY_FUNCTION__); } while (0); | |||
| 275 | c->cache->contexts[c->id] = NULL((void*)0); | |||
| 276 | } | |||
| 277 | ||||
| 278 | free(c); | |||
| 279 | } | |||
| 280 | ||||
| 281 | static void mmap_cache_free(MMapCache *m) { | |||
| 282 | int i; | |||
| 283 | ||||
| 284 | assert(m)do { if ((__builtin_expect(!!(!(m)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("m"), "../src/journal/mmap-cache.c", 284 , __PRETTY_FUNCTION__); } while (0); | |||
| 285 | ||||
| 286 | for (i = 0; i < MMAP_CACHE_MAX_CONTEXTS9; i++) | |||
| 287 | if (m->contexts[i]) | |||
| 288 | context_free(m->contexts[i]); | |||
| 289 | ||||
| 290 | hashmap_free(m->fds); | |||
| 291 | ||||
| 292 | while (m->unused) | |||
| 293 | window_free(m->unused); | |||
| 294 | ||||
| 295 | free(m); | |||
| 296 | } | |||
| 297 | ||||
| 298 | MMapCache* mmap_cache_unref(MMapCache *m) { | |||
| 299 | ||||
| 300 | if (!m) | |||
| 301 | return NULL((void*)0); | |||
| 302 | ||||
| 303 | assert(m->n_ref > 0)do { if ((__builtin_expect(!!(!(m->n_ref > 0)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("m->n_ref > 0"), "../src/journal/mmap-cache.c" , 303, __PRETTY_FUNCTION__); } while (0); | |||
| 304 | ||||
| 305 | m->n_ref--; | |||
| 306 | if (m->n_ref == 0) | |||
| 307 | mmap_cache_free(m); | |||
| 308 | ||||
| 309 | return NULL((void*)0); | |||
| 310 | } | |||
| 311 | ||||
| 312 | static int make_room(MMapCache *m) { | |||
| 313 | assert(m)do { if ((__builtin_expect(!!(!(m)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("m"), "../src/journal/mmap-cache.c", 313 , __PRETTY_FUNCTION__); } while (0); | |||
| 314 | ||||
| 315 | if (!m->last_unused) | |||
| 316 | return 0; | |||
| 317 | ||||
| 318 | window_free(m->last_unused); | |||
| 319 | return 1; | |||
| 320 | } | |||
| 321 | ||||
| 322 | static int try_context( | |||
| 323 | MMapCache *m, | |||
| 324 | MMapFileDescriptor *f, | |||
| 325 | int prot, | |||
| 326 | unsigned context, | |||
| 327 | bool_Bool keep_always, | |||
| 328 | uint64_t offset, | |||
| 329 | size_t size, | |||
| 330 | void **ret, | |||
| 331 | size_t *ret_size) { | |||
| 332 | ||||
| 333 | Context *c; | |||
| 334 | ||||
| 335 | assert(m)do { if ((__builtin_expect(!!(!(m)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("m"), "../src/journal/mmap-cache.c", 335 , __PRETTY_FUNCTION__); } while (0); | |||
| 336 | assert(m->n_ref > 0)do { if ((__builtin_expect(!!(!(m->n_ref > 0)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("m->n_ref > 0"), "../src/journal/mmap-cache.c" , 336, __PRETTY_FUNCTION__); } while (0); | |||
| 337 | assert(f)do { if ((__builtin_expect(!!(!(f)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("f"), "../src/journal/mmap-cache.c", 337 , __PRETTY_FUNCTION__); } while (0); | |||
| 338 | assert(size > 0)do { if ((__builtin_expect(!!(!(size > 0)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("size > 0"), "../src/journal/mmap-cache.c" , 338, __PRETTY_FUNCTION__); } while (0); | |||
| 339 | assert(ret)do { if ((__builtin_expect(!!(!(ret)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("ret"), "../src/journal/mmap-cache.c", 339 , __PRETTY_FUNCTION__); } while (0); | |||
| 340 | ||||
| 341 | c = m->contexts[context]; | |||
| 342 | if (!c) | |||
| 343 | return 0; | |||
| 344 | ||||
| 345 | assert(c->id == context)do { if ((__builtin_expect(!!(!(c->id == context)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("c->id == context"), "../src/journal/mmap-cache.c" , 345, __PRETTY_FUNCTION__); } while (0); | |||
| 346 | ||||
| 347 | if (!c->window) | |||
| 348 | return 0; | |||
| 349 | ||||
| 350 | if (!window_matches_fd(c->window, f, prot, offset, size)) { | |||
| 351 | ||||
| 352 | /* Drop the reference to the window, since it's unnecessary now */ | |||
| 353 | context_detach_window(c); | |||
| 354 | return 0; | |||
| 355 | } | |||
| 356 | ||||
| 357 | if (c->window->fd->sigbus) | |||
| 358 | return -EIO5; | |||
| 359 | ||||
| 360 | c->window->keep_always = c->window->keep_always || keep_always; | |||
| 361 | ||||
| 362 | *ret = (uint8_t*) c->window->ptr + (offset - c->window->offset); | |||
| 363 | if (ret_size) | |||
| 364 | *ret_size = c->window->size - (offset - c->window->offset); | |||
| 365 | ||||
| 366 | return 1; | |||
| 367 | } | |||
| 368 | ||||
| 369 | static int find_mmap( | |||
| 370 | MMapCache *m, | |||
| 371 | MMapFileDescriptor *f, | |||
| 372 | int prot, | |||
| 373 | unsigned context, | |||
| 374 | bool_Bool keep_always, | |||
| 375 | uint64_t offset, | |||
| 376 | size_t size, | |||
| 377 | void **ret, | |||
| 378 | size_t *ret_size) { | |||
| 379 | ||||
| 380 | Window *w; | |||
| 381 | Context *c; | |||
| 382 | ||||
| 383 | assert(m)do { if ((__builtin_expect(!!(!(m)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("m"), "../src/journal/mmap-cache.c", 383 , __PRETTY_FUNCTION__); } while (0); | |||
| 384 | assert(m->n_ref > 0)do { if ((__builtin_expect(!!(!(m->n_ref > 0)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("m->n_ref > 0"), "../src/journal/mmap-cache.c" , 384, __PRETTY_FUNCTION__); } while (0); | |||
| 385 | assert(f)do { if ((__builtin_expect(!!(!(f)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("f"), "../src/journal/mmap-cache.c", 385 , __PRETTY_FUNCTION__); } while (0); | |||
| 386 | assert(size > 0)do { if ((__builtin_expect(!!(!(size > 0)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("size > 0"), "../src/journal/mmap-cache.c" , 386, __PRETTY_FUNCTION__); } while (0); | |||
| 387 | ||||
| 388 | if (f->sigbus) | |||
| 389 | return -EIO5; | |||
| 390 | ||||
| 391 | LIST_FOREACH(by_fd, w, f->windows)for ((w) = (f->windows); (w); (w) = (w)->by_fd_next) | |||
| 392 | if (window_matches(w, prot, offset, size)) | |||
| 393 | break; | |||
| 394 | ||||
| 395 | if (!w) | |||
| 396 | return 0; | |||
| 397 | ||||
| 398 | c = context_add(m, context); | |||
| 399 | if (!c) | |||
| 400 | return -ENOMEM12; | |||
| 401 | ||||
| 402 | context_attach_window(c, w); | |||
| 403 | w->keep_always = w->keep_always || keep_always; | |||
| 404 | ||||
| 405 | *ret = (uint8_t*) w->ptr + (offset - w->offset); | |||
| 406 | if (ret_size) | |||
| 407 | *ret_size = w->size - (offset - w->offset); | |||
| 408 | ||||
| 409 | return 1; | |||
| 410 | } | |||
| 411 | ||||
| 412 | static int mmap_try_harder(MMapCache *m, void *addr, MMapFileDescriptor *f, int prot, int flags, uint64_t offset, size_t size, void **res) { | |||
| 413 | void *ptr; | |||
| 414 | ||||
| 415 | assert(m)do { if ((__builtin_expect(!!(!(m)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("m"), "../src/journal/mmap-cache.c", 415 , __PRETTY_FUNCTION__); } while (0); | |||
| 416 | assert(f)do { if ((__builtin_expect(!!(!(f)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("f"), "../src/journal/mmap-cache.c", 416 , __PRETTY_FUNCTION__); } while (0); | |||
| 417 | assert(res)do { if ((__builtin_expect(!!(!(res)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("res"), "../src/journal/mmap-cache.c", 417 , __PRETTY_FUNCTION__); } while (0); | |||
| 418 | ||||
| 419 | for (;;) { | |||
| 420 | int r; | |||
| 421 | ||||
| 422 | ptr = mmap(addr, size, prot, flags, f->fd, offset); | |||
| 423 | if (ptr != MAP_FAILED((void *) -1)) | |||
| 424 | break; | |||
| 425 | if (errno(*__errno_location ()) != ENOMEM12) | |||
| 426 | return negative_errno(); | |||
| 427 | ||||
| 428 | r = make_room(m); | |||
| 429 | if (r
| |||
| 430 | return r; | |||
| 431 | if (r
| |||
| 432 | return -ENOMEM12; | |||
| 433 | } | |||
| 434 | ||||
| 435 | *res = ptr; | |||
| 436 | return 0; | |||
| 437 | } | |||
| 438 | ||||
| 439 | static int add_mmap( | |||
| 440 | MMapCache *m, | |||
| 441 | MMapFileDescriptor *f, | |||
| 442 | int prot, | |||
| 443 | unsigned context, | |||
| 444 | bool_Bool keep_always, | |||
| 445 | uint64_t offset, | |||
| 446 | size_t size, | |||
| 447 | struct stat *st, | |||
| 448 | void **ret, | |||
| 449 | size_t *ret_size) { | |||
| 450 | ||||
| 451 | uint64_t woffset, wsize; | |||
| 452 | Context *c; | |||
| 453 | Window *w; | |||
| 454 | void *d; | |||
| 455 | int r; | |||
| 456 | ||||
| 457 | assert(m)do { if ((__builtin_expect(!!(!(m)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("m"), "../src/journal/mmap-cache.c", 457 , __PRETTY_FUNCTION__); } while (0); | |||
| 458 | assert(m->n_ref > 0)do { if ((__builtin_expect(!!(!(m->n_ref > 0)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("m->n_ref > 0"), "../src/journal/mmap-cache.c" , 458, __PRETTY_FUNCTION__); } while (0); | |||
| 459 | assert(f)do { if ((__builtin_expect(!!(!(f)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("f"), "../src/journal/mmap-cache.c", 459 , __PRETTY_FUNCTION__); } while (0); | |||
| 460 | assert(size > 0)do { if ((__builtin_expect(!!(!(size > 0)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("size > 0"), "../src/journal/mmap-cache.c" , 460, __PRETTY_FUNCTION__); } while (0); | |||
| 461 | assert(ret)do { if ((__builtin_expect(!!(!(ret)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("ret"), "../src/journal/mmap-cache.c", 461 , __PRETTY_FUNCTION__); } while (0); | |||
| 462 | ||||
| 463 | woffset = offset & ~((uint64_t) page_size() - 1ULL); | |||
| 464 | wsize = size + (offset - woffset); | |||
| 465 | wsize = PAGE_ALIGN(wsize)ALIGN_TO((wsize), page_size()); | |||
| 466 | ||||
| 467 | if (wsize < WINDOW_SIZE(8ULL*1024ULL*1024ULL)) { | |||
| 468 | uint64_t delta; | |||
| 469 | ||||
| 470 | delta = PAGE_ALIGN((WINDOW_SIZE - wsize) / 2)ALIGN_TO((((8ULL*1024ULL*1024ULL) - wsize) / 2), page_size()); | |||
| 471 | ||||
| 472 | if (delta > offset) | |||
| 473 | woffset = 0; | |||
| 474 | else | |||
| 475 | woffset -= delta; | |||
| 476 | ||||
| 477 | wsize = WINDOW_SIZE(8ULL*1024ULL*1024ULL); | |||
| 478 | } | |||
| 479 | ||||
| 480 | if (st) { | |||
| 481 | /* Memory maps that are larger then the files | |||
| 482 | underneath have undefined behavior. Hence, clamp | |||
| 483 | things to the file size if we know it */ | |||
| 484 | ||||
| 485 | if (woffset >= (uint64_t) st->st_size) | |||
| 486 | return -EADDRNOTAVAIL99; | |||
| 487 | ||||
| 488 | if (woffset + wsize > (uint64_t) st->st_size) | |||
| 489 | wsize = PAGE_ALIGN(st->st_size - woffset)ALIGN_TO((st->st_size - woffset), page_size()); | |||
| 490 | } | |||
| 491 | ||||
| 492 | r = mmap_try_harder(m, NULL((void*)0), f, prot, MAP_SHARED0x01, woffset, wsize, &d); | |||
| 493 | if (r
| |||
| 494 | return r; | |||
| 495 | ||||
| 496 | c = context_add(m, context); | |||
| 497 | if (!c
| |||
| 498 | goto outofmem; | |||
| 499 | ||||
| 500 | w = window_add(m, f, prot, keep_always, woffset, wsize, d); | |||
| 501 | if (!w) | |||
| 502 | goto outofmem; | |||
| 503 | ||||
| 504 | context_attach_window(c, w); | |||
| 505 | ||||
| 506 | *ret = (uint8_t*) w->ptr + (offset - w->offset); | |||
| 507 | if (ret_size) | |||
| 508 | *ret_size = w->size - (offset - w->offset); | |||
| 509 | ||||
| 510 | return 1; | |||
| 511 | ||||
| 512 | outofmem: | |||
| 513 | (void) munmap(d, wsize); | |||
| 514 | return -ENOMEM12; | |||
| 515 | } | |||
| 516 | ||||
| 517 | int mmap_cache_get( | |||
| 518 | MMapCache *m, | |||
| 519 | MMapFileDescriptor *f, | |||
| 520 | int prot, | |||
| 521 | unsigned context, | |||
| 522 | bool_Bool keep_always, | |||
| 523 | uint64_t offset, | |||
| 524 | size_t size, | |||
| 525 | struct stat *st, | |||
| 526 | void **ret, | |||
| 527 | size_t *ret_size) { | |||
| 528 | ||||
| 529 | int r; | |||
| 530 | ||||
| 531 | assert(m)do { if ((__builtin_expect(!!(!(m)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("m"), "../src/journal/mmap-cache.c", 531 , __PRETTY_FUNCTION__); } while (0); | |||
| ||||
| 532 | assert(m->n_ref > 0)do { if ((__builtin_expect(!!(!(m->n_ref > 0)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("m->n_ref > 0"), "../src/journal/mmap-cache.c" , 532, __PRETTY_FUNCTION__); } while (0); | |||
| 533 | assert(f)do { if ((__builtin_expect(!!(!(f)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("f"), "../src/journal/mmap-cache.c", 533 , __PRETTY_FUNCTION__); } while (0); | |||
| 534 | assert(size > 0)do { if ((__builtin_expect(!!(!(size > 0)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("size > 0"), "../src/journal/mmap-cache.c" , 534, __PRETTY_FUNCTION__); } while (0); | |||
| 535 | assert(ret)do { if ((__builtin_expect(!!(!(ret)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("ret"), "../src/journal/mmap-cache.c", 535 , __PRETTY_FUNCTION__); } while (0); | |||
| 536 | assert(context < MMAP_CACHE_MAX_CONTEXTS)do { if ((__builtin_expect(!!(!(context < 9)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("context < MMAP_CACHE_MAX_CONTEXTS"), "../src/journal/mmap-cache.c", 536, __PRETTY_FUNCTION__); } while (0); | |||
| 537 | ||||
| 538 | /* Check whether the current context is the right one already */ | |||
| 539 | r = try_context(m, f, prot, context, keep_always, offset, size, ret, ret_size); | |||
| 540 | if (r
| |||
| 541 | m->n_hit++; | |||
| 542 | return r; | |||
| 543 | } | |||
| 544 | ||||
| 545 | /* Search for a matching mmap */ | |||
| 546 | r = find_mmap(m, f, prot, context, keep_always, offset, size, ret, ret_size); | |||
| 547 | if (r
| |||
| 548 | m->n_hit++; | |||
| 549 | return r; | |||
| 550 | } | |||
| 551 | ||||
| 552 | m->n_missed++; | |||
| 553 | ||||
| 554 | /* Create a new mmap */ | |||
| 555 | return add_mmap(m, f, prot, context, keep_always, offset, size, st, ret, ret_size); | |||
| 556 | } | |||
| 557 | ||||
| 558 | unsigned mmap_cache_get_hit(MMapCache *m) { | |||
| 559 | assert(m)do { if ((__builtin_expect(!!(!(m)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("m"), "../src/journal/mmap-cache.c", 559 , __PRETTY_FUNCTION__); } while (0); | |||
| 560 | ||||
| 561 | return m->n_hit; | |||
| 562 | } | |||
| 563 | ||||
| 564 | unsigned mmap_cache_get_missed(MMapCache *m) { | |||
| 565 | assert(m)do { if ((__builtin_expect(!!(!(m)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("m"), "../src/journal/mmap-cache.c", 565 , __PRETTY_FUNCTION__); } while (0); | |||
| 566 | ||||
| 567 | return m->n_missed; | |||
| 568 | } | |||
| 569 | ||||
| 570 | static void mmap_cache_process_sigbus(MMapCache *m) { | |||
| 571 | bool_Bool found = false0; | |||
| 572 | MMapFileDescriptor *f; | |||
| 573 | Iterator i; | |||
| 574 | int r; | |||
| 575 | ||||
| 576 | assert(m)do { if ((__builtin_expect(!!(!(m)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("m"), "../src/journal/mmap-cache.c", 576 , __PRETTY_FUNCTION__); } while (0); | |||
| 577 | ||||
| 578 | /* Iterate through all triggered pages and mark their files as | |||
| 579 | * invalidated */ | |||
| 580 | for (;;) { | |||
| 581 | bool_Bool ours; | |||
| 582 | void *addr; | |||
| 583 | ||||
| 584 | r = sigbus_pop(&addr); | |||
| 585 | if (_likely_(r == 0)(__builtin_expect(!!(r == 0),1))) | |||
| 586 | break; | |||
| 587 | if (r < 0) { | |||
| 588 | log_error_errno(r, "SIGBUS handling failed: %m")({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/journal/mmap-cache.c", 588, __func__, "SIGBUS handling failed: %m" ) : -abs(_e); }); | |||
| 589 | abort(); | |||
| 590 | } | |||
| 591 | ||||
| 592 | ours = false0; | |||
| 593 | HASHMAP_FOREACH(f, m->fds, i)for ((i) = ((Iterator) { .idx = ((2147483647 *2U +1U) - 1), . next_key = ((void*)0) }); hashmap_iterate((m->fds), &( i), (void**)&(f), ((void*)0)); ) { | |||
| 594 | Window *w; | |||
| 595 | ||||
| 596 | LIST_FOREACH(by_fd, w, f->windows)for ((w) = (f->windows); (w); (w) = (w)->by_fd_next) { | |||
| 597 | if ((uint8_t*) addr >= (uint8_t*) w->ptr && | |||
| 598 | (uint8_t*) addr < (uint8_t*) w->ptr + w->size) { | |||
| 599 | found = ours = f->sigbus = true1; | |||
| 600 | break; | |||
| 601 | } | |||
| 602 | } | |||
| 603 | ||||
| 604 | if (ours) | |||
| 605 | break; | |||
| 606 | } | |||
| 607 | ||||
| 608 | /* Didn't find a matching window, give up */ | |||
| 609 | if (!ours) { | |||
| 610 | log_error("Unknown SIGBUS page, aborting.")({ int _level = (((3))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/journal/mmap-cache.c", 610, __func__, "Unknown SIGBUS page, aborting." ) : -abs(_e); }); | |||
| 611 | abort(); | |||
| 612 | } | |||
| 613 | } | |||
| 614 | ||||
| 615 | /* The list of triggered pages is now empty. Now, let's remap | |||
| 616 | * all windows of the triggered file to anonymous maps, so | |||
| 617 | * that no page of the file in question is triggered again, so | |||
| 618 | * that we can be sure not to hit the queue size limit. */ | |||
| 619 | if (_likely_(!found)(__builtin_expect(!!(!found),1))) | |||
| 620 | return; | |||
| 621 | ||||
| 622 | HASHMAP_FOREACH(f, m->fds, i)for ((i) = ((Iterator) { .idx = ((2147483647 *2U +1U) - 1), . next_key = ((void*)0) }); hashmap_iterate((m->fds), &( i), (void**)&(f), ((void*)0)); ) { | |||
| 623 | Window *w; | |||
| 624 | ||||
| 625 | if (!f->sigbus) | |||
| 626 | continue; | |||
| 627 | ||||
| 628 | LIST_FOREACH(by_fd, w, f->windows)for ((w) = (f->windows); (w); (w) = (w)->by_fd_next) | |||
| 629 | window_invalidate(w); | |||
| 630 | } | |||
| 631 | } | |||
| 632 | ||||
| 633 | bool_Bool mmap_cache_got_sigbus(MMapCache *m, MMapFileDescriptor *f) { | |||
| 634 | assert(m)do { if ((__builtin_expect(!!(!(m)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("m"), "../src/journal/mmap-cache.c", 634 , __PRETTY_FUNCTION__); } while (0); | |||
| 635 | assert(f)do { if ((__builtin_expect(!!(!(f)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("f"), "../src/journal/mmap-cache.c", 635 , __PRETTY_FUNCTION__); } while (0); | |||
| 636 | ||||
| 637 | mmap_cache_process_sigbus(m); | |||
| 638 | ||||
| 639 | return f->sigbus; | |||
| 640 | } | |||
| 641 | ||||
| 642 | MMapFileDescriptor* mmap_cache_add_fd(MMapCache *m, int fd) { | |||
| 643 | MMapFileDescriptor *f; | |||
| 644 | int r; | |||
| 645 | ||||
| 646 | assert(m)do { if ((__builtin_expect(!!(!(m)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("m"), "../src/journal/mmap-cache.c", 646 , __PRETTY_FUNCTION__); } while (0); | |||
| 647 | assert(fd >= 0)do { if ((__builtin_expect(!!(!(fd >= 0)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("fd >= 0"), "../src/journal/mmap-cache.c" , 647, __PRETTY_FUNCTION__); } while (0); | |||
| 648 | ||||
| 649 | f = hashmap_get(m->fds, FD_TO_PTR(fd)((void *) ((intptr_t) ((fd)+1)))); | |||
| 650 | if (f) | |||
| 651 | return f; | |||
| 652 | ||||
| 653 | r = hashmap_ensure_allocated(&m->fds, NULL)internal_hashmap_ensure_allocated(&m->fds, ((void*)0) ); | |||
| 654 | if (r < 0) | |||
| 655 | return NULL((void*)0); | |||
| 656 | ||||
| 657 | f = new0(MMapFileDescriptor, 1)((MMapFileDescriptor*) calloc((1), sizeof(MMapFileDescriptor) )); | |||
| 658 | if (!f) | |||
| 659 | return NULL((void*)0); | |||
| 660 | ||||
| 661 | f->cache = m; | |||
| 662 | f->fd = fd; | |||
| 663 | ||||
| 664 | r = hashmap_put(m->fds, FD_TO_PTR(fd)((void *) ((intptr_t) ((fd)+1))), f); | |||
| 665 | if (r < 0) | |||
| 666 | return mfree(f); | |||
| 667 | ||||
| 668 | return f; | |||
| 669 | } | |||
| 670 | ||||
| 671 | void mmap_cache_free_fd(MMapCache *m, MMapFileDescriptor *f) { | |||
| 672 | assert(m)do { if ((__builtin_expect(!!(!(m)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("m"), "../src/journal/mmap-cache.c", 672 , __PRETTY_FUNCTION__); } while (0); | |||
| 673 | assert(f)do { if ((__builtin_expect(!!(!(f)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("f"), "../src/journal/mmap-cache.c", 673 , __PRETTY_FUNCTION__); } while (0); | |||
| 674 | ||||
| 675 | /* Make sure that any queued SIGBUS are first dispatched, so | |||
| 676 | * that we don't end up with a SIGBUS entry we cannot relate | |||
| 677 | * to any existing memory map */ | |||
| 678 | ||||
| 679 | mmap_cache_process_sigbus(m); | |||
| 680 | ||||
| 681 | while (f->windows) | |||
| 682 | window_free(f->windows); | |||
| 683 | ||||
| 684 | if (f->cache) | |||
| 685 | assert_se(hashmap_remove(f->cache->fds, FD_TO_PTR(f->fd)))do { if ((__builtin_expect(!!(!(hashmap_remove(f->cache-> fds, ((void *) ((intptr_t) ((f->fd)+1)))))),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("hashmap_remove(f->cache->fds, FD_TO_PTR(f->fd))" ), "../src/journal/mmap-cache.c", 685, __PRETTY_FUNCTION__); } while (0); | |||
| 686 | ||||
| 687 | free(f); | |||
| 688 | } |