From fcde238921b857679363a95488a5a5af1dc1f243 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 21 Aug 2012 15:33:21 +0200 Subject: [PATCH] journal: be more careful when keeping around mmaps we still need --- src/journal/journal-file.c | 14 +++---- src/journal/journal-verify.c | 5 +-- src/journal/mmap-cache.c | 73 ++++++++++++------------------------ src/journal/mmap-cache.h | 3 +- 4 files changed, 35 insertions(+), 60 deletions(-) diff --git a/src/journal/journal-file.c b/src/journal/journal-file.c index f01f12496..79f759897 100644 --- a/src/journal/journal-file.c +++ b/src/journal/journal-file.c @@ -311,8 +311,6 @@ static int journal_file_allocate(JournalFile *f, uint64_t offset, uint64_t size) if (r != 0) return -r; - mmap_cache_close_fd_range(f->mmap, f->fd, old_size); - if (fstat(f->fd, &f->last_stat) < 0) return -errno; @@ -321,7 +319,7 @@ static int journal_file_allocate(JournalFile *f, uint64_t offset, uint64_t size) return 0; } -static int journal_file_move_to(JournalFile *f, int context, uint64_t offset, uint64_t size, void **ret) { +static int journal_file_move_to(JournalFile *f, int context, bool keep_always, uint64_t offset, uint64_t size, void **ret) { assert(f); assert(ret); @@ -335,7 +333,7 @@ static int journal_file_move_to(JournalFile *f, int context, uint64_t offset, ui return -EADDRNOTAVAIL; } - return mmap_cache_get(f->mmap, f->fd, f->prot, context, offset, size, ret); + return mmap_cache_get(f->mmap, f->fd, f->prot, context, keep_always, offset, size, &f->last_stat, ret); } static uint64_t minimum_header_size(Object *o) { @@ -373,7 +371,7 @@ int journal_file_move_to_object(JournalFile *f, int type, uint64_t offset, Objec /* One context for each type, plus one catch-all for the rest */ context = type > 0 && type < _OBJECT_TYPE_MAX ? type : 0; - r = journal_file_move_to(f, context, offset, sizeof(ObjectHeader), &t); + r = journal_file_move_to(f, context, false, offset, sizeof(ObjectHeader), &t); if (r < 0) return r; @@ -393,7 +391,7 @@ int journal_file_move_to_object(JournalFile *f, int type, uint64_t offset, Objec return -EBADMSG; if (s > sizeof(ObjectHeader)) { - r = journal_file_move_to(f, o->object.type, offset, s, &t); + r = journal_file_move_to(f, o->object.type, false, offset, s, &t); if (r < 0) return r; @@ -457,7 +455,7 @@ int journal_file_append_object(JournalFile *f, int type, uint64_t size, Object * if (r < 0) return r; - r = journal_file_move_to(f, type, p, size, &t); + r = journal_file_move_to(f, type, false, p, size, &t); if (r < 0) return r; @@ -544,6 +542,7 @@ static int journal_file_map_data_hash_table(JournalFile *f) { r = journal_file_move_to(f, OBJECT_DATA_HASH_TABLE, + true, p, s, &t); if (r < 0) @@ -565,6 +564,7 @@ static int journal_file_map_field_hash_table(JournalFile *f) { r = journal_file_move_to(f, OBJECT_FIELD_HASH_TABLE, + true, p, s, &t); if (r < 0) diff --git a/src/journal/journal-verify.c b/src/journal/journal-verify.c index 90739a66c..9156fd5dc 100644 --- a/src/journal/journal-verify.c +++ b/src/journal/journal-verify.c @@ -249,7 +249,7 @@ static int contains_uint64(MMapCache *m, int fd, uint64_t n, uint64_t p) { c = (a + b) / 2; - r = mmap_cache_get(m, fd, PROT_READ|PROT_WRITE, 0, c * sizeof(uint64_t), sizeof(uint64_t), (void **) &z); + r = mmap_cache_get(m, fd, PROT_READ|PROT_WRITE, 0, false, c * sizeof(uint64_t), sizeof(uint64_t), NULL, (void **) &z); if (r < 0) return r; @@ -261,9 +261,8 @@ static int contains_uint64(MMapCache *m, int fd, uint64_t n, uint64_t p) { if (p < *z) b = c; - else { + else a = c; - } } return 0; diff --git a/src/journal/mmap-cache.c b/src/journal/mmap-cache.c index 69efb20ad..2b45e375c 100644 --- a/src/journal/mmap-cache.c +++ b/src/journal/mmap-cache.c @@ -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 behaviour. 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); @@ -581,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; @@ -638,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) { @@ -679,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); } diff --git a/src/journal/mmap-cache.h b/src/journal/mmap-cache.h index aae454435..98a1a731f 100644 --- a/src/journal/mmap-cache.h +++ b/src/journal/mmap-cache.h @@ -29,7 +29,6 @@ MMapCache* mmap_cache_new(void); MMapCache* mmap_cache_ref(MMapCache *m); MMapCache* mmap_cache_unref(MMapCache *m); -int mmap_cache_get(MMapCache *m, int fd, int prot, unsigned context, uint64_t offset, uint64_t size, void **ret); +int mmap_cache_get(MMapCache *m, int fd, int prot, unsigned context, bool keep_always, uint64_t offset, uint64_t size, struct stat *st, void **ret); void mmap_cache_close_fd(MMapCache *m, int fd); -void mmap_cache_close_fd_range(MMapCache *m, int fd, uint64_t range); void mmap_cache_close_context(MMapCache *m, unsigned context); -- 2.30.2