chiark / gitweb /
man: fix a bunch of typos in docs
[elogind.git] / src / journal / mmap-cache.c
index 9782139f5a846836ac4fbae199adddf909929ecb..7d6c6c22ba8e550ae7c9d353d95a09bf92ea96f1 100644 (file)
 #include "mmap-cache.h"
 
 #define WINDOW_SIZE (8ULL*1024ULL*1024ULL)
-#define WINDOWS_MAX 32
+
+#define DEFAULT_WINDOWS_MAX 64
+#define DEFAULT_FDS_MAX 32
+#define DEFAULT_CONTEXTS_MAX 32
 
 typedef struct Window {
         int fd;
@@ -236,19 +239,16 @@ static void mmap_cache_free(MMapCache *m) {
         free(m);
 }
 
-MMapCache* mmap_cache_new(unsigned contexts_max, unsigned fds_max) {
+MMapCache* mmap_cache_new(void) {
         MMapCache *m;
 
-        assert(contexts_max > 0);
-        assert(fds_max > 0);
-
         m = new0(MMapCache, 1);
         if (!m)
                 return NULL;
 
-        m->contexts_max = contexts_max;
-        m->fds_max = fds_max;
-        m->windows_max = MAX(m->contexts_max, WINDOWS_MAX);
+        m->contexts_max = DEFAULT_CONTEXTS_MAX;
+        m->fds_max = DEFAULT_FDS_MAX;
+        m->windows_max = DEFAULT_WINDOWS_MAX;
         m->n_ref = 1;
         m->lru_first = (unsigned) -1;
         m->lru_last = (unsigned) -1;
@@ -336,6 +336,7 @@ static int mmap_cache_make_room(MMapCache *m) {
                 Window *v;
 
                 v = m->windows + w;
+                assert(v->n_ref == 0);
 
                 if (v->ptr) {
                         mmap_cache_window_unmap(m, w);
@@ -354,8 +355,10 @@ static int mmap_cache_put(
                 unsigned fd_index,
                 int prot,
                 unsigned context,
+                bool keep_always,
                 uint64_t offset,
                 uint64_t size,
+                struct stat *st,
                 void **ret) {
 
         unsigned w;
@@ -387,6 +390,18 @@ static int mmap_cache_put(
                 wsize = WINDOW_SIZE;
         }
 
+        if (st) {
+                /* Memory maps that are larger then the files
+                   underneath have undefined behavior. Hence, clamp
+                   things to the file size if we know it */
+
+                if (woffset >= (uint64_t) st->st_size)
+                        return -EADDRNOTAVAIL;
+
+                if (woffset + wsize > (uint64_t) st->st_size)
+                        wsize = PAGE_ALIGN(st->st_size - woffset);
+        }
+
         for (;;) {
                 d = mmap(NULL, wsize, prot, MAP_SHARED, fd, woffset);
                 if (d != MAP_FAILED)
@@ -413,8 +428,13 @@ static int mmap_cache_put(
         v->offset = woffset;
         v->size = wsize;
 
-        v->n_ref = 0;
-        mmap_cache_window_add_lru(m, w);
+        if (keep_always)
+                v->n_ref = 1;
+        else {
+                v->n_ref = 0;
+                mmap_cache_window_add_lru(m, w);
+        }
+
         mmap_cache_fd_add(m, fd_index, w);
         mmap_cache_context_set(m, context, w);
 
@@ -465,8 +485,18 @@ static int mmap_cache_get_fd_index(MMapCache *m, int fd, unsigned *fd_index) {
         if (r != 0)
                 return r;
 
-        if (m->n_fds >= m->fds_max)
-                return -E2BIG;
+        if (m->n_fds >= m->fds_max) {
+                unsigned k;
+                FileDescriptor *n;
+
+                k = m->n_fds * 2;
+                n = realloc(m->by_fd, sizeof(FileDescriptor) * k);
+                if (!n)
+                        return -ENOMEM;
+
+                m->fds_max = k;
+                m->by_fd = n;
+        }
 
         j = m->by_fd + m->n_fds ++;
         j->fd = fd;
@@ -571,8 +601,10 @@ int mmap_cache_get(
                 int fd,
                 int prot,
                 unsigned context,
+                bool keep_always,
                 uint64_t offset,
                 uint64_t size,
+                struct stat *st,
                 void **ret) {
 
         unsigned fd_index;
@@ -580,10 +612,33 @@ int mmap_cache_get(
 
         assert(m);
         assert(fd >= 0);
-        assert(context < m->contexts_max);
         assert(size > 0);
         assert(ret);
 
+        if (context >= m->contexts_max) {
+                unsigned k, *n;
+                Window *w;
+
+                /* Increase the number of contexts if necessary, and
+                 * make sure we have twice the number of windows */
+
+                k = context * 2;
+                n = realloc(m->by_context, sizeof(unsigned) * k);
+                if (!n)
+                        return -ENOMEM;
+                memset(n + m->contexts_max, -1, (k - m->contexts_max) * sizeof(unsigned));
+                m->contexts_max = k;
+                m->by_context = n;
+
+                k = MAX(m->windows_max, m->contexts_max*2);
+                w = realloc(m->windows, sizeof(Window) * k);
+                if (!w)
+                        return -ENOMEM;
+
+                m->windows_max = k;
+                m->windows = w;
+        }
+
         /* Maybe the current pointer for this context is already the
          * right one? */
         r = mmap_cache_current(m, fd, context, offset, size, ret);
@@ -605,7 +660,7 @@ int mmap_cache_get(
                 return r;
 
         /* Not found? Then, let's add it */
-        return mmap_cache_put(m, fd, fd_index, prot, context, offset, size, ret);
+        return mmap_cache_put(m, fd, fd_index, prot, context, keep_always, offset, size, st, ret);
 }
 
 void mmap_cache_close_fd(MMapCache *m, int fd) {
@@ -646,51 +701,6 @@ void mmap_cache_close_fd(MMapCache *m, int fd) {
         m->n_fds --;
 }
 
-void mmap_cache_close_fd_range(MMapCache *m, int fd, uint64_t p) {
-        unsigned fd_index, c, w;
-        int r;
-
-        assert(m);
-        assert(fd > 0);
-
-        /* This drops all windows that include space right of the
-         * specified offset. This is useful to ensure that after the
-         * file size is extended we drop our mappings of the end and
-         * create it anew, since otherwise it is undefined whether
-         * mapping will continue to work as intended. */
-
-        r = mmap_cache_peek_fd_index(m, fd, &fd_index);
-        if (r <= 0)
-                return;
-
-        for (c = 0; c < m->contexts_max; c++) {
-                w = m->by_context[c];
-
-                if (w != (unsigned) -1 && m->windows[w].fd == fd)
-                        mmap_cache_context_unset(m, c);
-        }
-
-        w = m->by_fd[fd_index].windows;
-        while (w != (unsigned) -1) {
-                Window *v;
-
-                v = m->windows + w;
-                assert(v->fd == fd);
-                assert(v->by_fd_next == (unsigned) -1 ||
-                       m->windows[v->by_fd_next].fd == fd);
-
-                if (v->offset + v->size > p) {
-
-                        mmap_cache_window_unmap(m, w);
-                        mmap_cache_fd_remove(m, fd_index, w);
-                        v->fd = -1;
-
-                        w = m->by_fd[fd_index].windows;
-                } else
-                        w = v->by_fd_next;
-        }
-}
-
 void mmap_cache_close_context(MMapCache *m, unsigned context) {
         mmap_cache_context_unset(m, context);
 }