LCOV - code coverage report
Current view: top level - journal - mmap-cache.c (source / functions) Hit Total Coverage
Test: systemd test coverage Lines: 257 321 80.1 %
Date: 2015-07-29 18:47:03 Functions: 23 25 92.0 %

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

Generated by: LCOV version 1.11