]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-index: mail_cache_map() API cleanup
authorTimo Sirainen <tss@iki.fi>
Thu, 18 Oct 2012 02:10:29 +0000 (05:10 +0300)
committerTimo Sirainen <tss@iki.fi>
Thu, 18 Oct 2012 02:10:29 +0000 (05:10 +0300)
src/lib-index/mail-cache-compress.c
src/lib-index/mail-cache-fields.c
src/lib-index/mail-cache-lookup.c
src/lib-index/mail-cache-private.h
src/lib-index/mail-cache-transaction.c
src/lib-index/mail-cache.c

index e9baaa77fd40ef7cd606a9fc357eb45848bb46b6..cc8ec9cb606b08be02ed87f2062f495e9f02a89d 100644 (file)
@@ -353,6 +353,7 @@ static int mail_cache_compress_locked(struct mail_cache *cache,
        uint32_t file_seq, old_offset;
        ARRAY_TYPE(uint32_t) ext_offsets;
        const uint32_t *offsets;
+       const void *data;
        unsigned int i, count;
        int fd, ret;
 
@@ -440,7 +441,7 @@ static int mail_cache_compress_locked(struct mail_cache *cache,
        if (cache->file_cache != NULL)
                file_cache_set_fd(cache->file_cache, cache->fd);
 
-       if (mail_cache_map(cache, 0, 0) < 0)
+       if (mail_cache_map(cache, 0, 0, &data) < 0)
                return -1;
        if (mail_cache_header_fields_read(cache) < 0)
                return -1;
index 99f47db5de2ce7cd94f9b0fd95da3400f8aea0d3..6b0944aa7facb2f67f4a126c97694c21598feef9 100644 (file)
@@ -198,11 +198,14 @@ mail_cache_register_get_list(struct mail_cache *cache, pool_t pool,
        return list;
 }
 
-static int mail_cache_header_fields_get_offset(struct mail_cache *cache,
-                                              uint32_t *offset_r, bool map)
+static int
+mail_cache_header_fields_get_offset(struct mail_cache *cache,
+                                   uint32_t *offset_r,
+                                   const struct mail_cache_header_fields **field_hdr_r)
 {
        const struct mail_cache_header_fields *field_hdr;
        struct mail_cache_header_fields tmp_field_hdr;
+       const void *data;
        uint32_t offset = 0, next_offset;
        unsigned int next_count = 0;
        bool invalidate = FALSE;
@@ -210,6 +213,8 @@ static int mail_cache_header_fields_get_offset(struct mail_cache *cache,
 
        if (MAIL_CACHE_IS_UNUSABLE(cache)) {
                *offset_r = 0;
+               if (field_hdr_r != NULL)
+                       *field_hdr_r = NULL;
                return 0;
        }
 
@@ -228,16 +233,16 @@ static int mail_cache_header_fields_get_offset(struct mail_cache *cache,
                invalidate = TRUE;
 
                if (cache->mmap_base != NULL) {
-                       if (mail_cache_map(cache, offset,
-                                          sizeof(*field_hdr)) < 0)
-                               return -1;
-                       if (offset >= cache->mmap_length) {
+                       ret = mail_cache_map(cache, offset, sizeof(*field_hdr),
+                                            &data);
+                       if (ret <= 0) {
+                               if (ret < 0)
+                                       return -1;
                                mail_cache_set_corrupted(cache,
                                        "header field next_offset points outside file");
                                return -1;
                        }
-
-                       field_hdr = CONST_PTR_OFFSET(cache->data, offset);
+                       field_hdr = data;
                } else {
                        /* if we need to follow multiple offsets to get to
                           the last one, it's faster to just pread() the file
@@ -270,7 +275,7 @@ static int mail_cache_header_fields_get_offset(struct mail_cache *cache,
        if (next_count > MAIL_CACHE_HEADER_FIELD_CONTINUE_COUNT)
                cache->need_compress_file_seq = cache->hdr->file_seq;
 
-       if (map) {
+       if (field_hdr_r != NULL) {
                if (cache->file_cache != NULL && invalidate) {
                        /* if this isn't the first header in file and we hadn't
                           read this before, we can't trust that the cached
@@ -278,17 +283,23 @@ static int mail_cache_header_fields_get_offset(struct mail_cache *cache,
                        file_cache_invalidate(cache->file_cache, offset,
                                              field_hdr->size);
                }
-               if (mail_cache_map(cache, offset, field_hdr->size) < 0)
+               ret = mail_cache_map(cache, offset, field_hdr->size, &data);
+               if (ret < 0)
                        return -1;
+               if (ret == 0) {
+                       mail_cache_set_corrupted(cache,
+                               "header field size outside file");
+                       return -1;
+               }
+               *field_hdr_r = data;
        }
-
        *offset_r = offset;
        return 0;
 }
 
 int mail_cache_header_fields_read(struct mail_cache *cache)
 {
-       const struct mail_cache_header_fields *field_hdr = NULL;
+       const struct mail_cache_header_fields *field_hdr;
        struct mail_cache_field field;
        const uint32_t *last_used, *sizes;
        const uint8_t *types, *decisions;
@@ -299,7 +310,7 @@ int mail_cache_header_fields_read(struct mail_cache *cache)
        time_t max_drop_time;
        uint32_t offset, i;
 
-       if (mail_cache_header_fields_get_offset(cache, &offset, TRUE) < 0)
+       if (mail_cache_header_fields_get_offset(cache, &offset, &field_hdr) < 0)
                return -1;
 
        if (offset == 0) {
@@ -307,13 +318,6 @@ int mail_cache_header_fields_read(struct mail_cache *cache)
                return 0;
        }
 
-       field_hdr = CONST_PTR_OFFSET(cache->data, offset);
-       if (offset + field_hdr->size > cache->mmap_length) {
-               mail_cache_set_corrupted(cache,
-                                        "field header points outside file");
-               return -1;
-       }
-
        /* check the fixed size of the header. name[] has to be checked
           separately */
        if (field_hdr->size < sizeof(*field_hdr) +
@@ -322,9 +326,7 @@ int mail_cache_header_fields_read(struct mail_cache *cache)
                return -1;
        }
 
-       field_hdr = CONST_PTR_OFFSET(cache->data, offset);
        new_fields_count = field_hdr->fields_count;
-
        if (new_fields_count != 0) {
                cache->file_field_map =
                        i_realloc(cache->file_field_map,
index 937159f2b8c388fcd36ac30362999a6153f3a312..783a3d126c485dc415e09edcf4e2830cf0d05d43 100644 (file)
@@ -14,6 +14,7 @@ int mail_cache_get_record(struct mail_cache *cache, uint32_t offset,
                          const struct mail_cache_record **rec_r)
 {
        const struct mail_cache_record *rec;
+       const void *data;
 
        i_assert(offset != 0);
 
@@ -24,14 +25,15 @@ int mail_cache_get_record(struct mail_cache *cache, uint32_t offset,
        }
 
        /* we don't know yet how large the record is, so just guess */
-       if (mail_cache_map(cache, offset, sizeof(*rec) + CACHE_PREFETCH) < 0)
+       if (mail_cache_map(cache, offset, sizeof(*rec) + CACHE_PREFETCH,
+                          &data) < 0)
                return -1;
 
        if (offset + sizeof(*rec) > cache->mmap_length) {
                mail_cache_set_corrupted(cache, "record points outside file");
                return -1;
        }
-       rec = CACHE_RECORD(cache, offset);
+       rec = data;
 
        if (rec->size < sizeof(*rec)) {
                mail_cache_set_corrupted(cache, "invalid record size");
@@ -39,9 +41,9 @@ int mail_cache_get_record(struct mail_cache *cache, uint32_t offset,
        }
        if (rec->size > CACHE_PREFETCH) {
                /* larger than we guessed. map the rest of the record. */
-               if (mail_cache_map(cache, offset, rec->size) < 0)
+               if (mail_cache_map(cache, offset, rec->size, &data) < 0)
                        return -1;
-               rec = CACHE_RECORD(cache, offset);
+               rec = data;
        }
 
        if (rec->size > cache->mmap_length ||
index d5bfc8caa542fb93b025d1b7b7b24401b206016a..0f7e442fe1486eb10cc9ebe60289e57962240c08 100644 (file)
@@ -256,7 +256,8 @@ void mail_cache_lookup_iter_init(struct mail_cache_view *view, uint32_t seq,
 int mail_cache_lookup_iter_next(struct mail_cache_lookup_iterate_ctx *ctx,
                                struct mail_cache_iterate_field *field_r);
 
-int mail_cache_map(struct mail_cache *cache, size_t offset, size_t size);
+int mail_cache_map(struct mail_cache *cache, size_t offset, size_t size,
+                  const void **data_r);
 void mail_cache_file_close(struct mail_cache *cache);
 int mail_cache_reopen(struct mail_cache *cache);
 
index 22465fdfc33bcfb048555d45ebf3d0fcf4cfd560..620bd800a305331e0e3737e877c7a521a9ffcf09 100644 (file)
@@ -1091,6 +1091,8 @@ int mail_cache_link(struct mail_cache *cache, uint32_t old_offset,
                    uint32_t new_offset)
 {
        const struct mail_cache_record *rec;
+       const void *data;
+       int ret;
 
        i_assert(cache->locked);
 
@@ -1107,15 +1109,16 @@ int mail_cache_link(struct mail_cache *cache, uint32_t old_offset,
           records at the same time. we'd rather not lose those additions, so
           force the linking order to be new_offset -> old_offset if it isn't
           already. */
-       if (mail_cache_map(cache, new_offset, sizeof(*rec)) < 0)
-               return -1;
-       if (new_offset + sizeof(*rec) > cache->mmap_length) {
-               mail_cache_set_corrupted(cache,
-                       "Cache record offset %u points outside file",
-                       new_offset);
+       ret = mail_cache_map(cache, new_offset, sizeof(*rec), &data);
+       if (ret <= 0) {
+               if (ret == 0) {
+                       mail_cache_set_corrupted(cache,
+                               "Cache record offset %u points outside file",
+                               new_offset);
+               }
                return -1;
        }
-       rec = CACHE_RECORD(cache, new_offset);
+       rec = data;
        if (rec->prev_offset == old_offset) {
                /* link is already correct */
                return 0;
index a7db0ad45e8db32908890e07bad5ad93a082ad1f..70814a4ff98c98149fed4ca9b48ec173a1162ab5 100644 (file)
@@ -145,6 +145,7 @@ int mail_cache_reopen(struct mail_cache *cache)
 {
        struct mail_index_view *view;
        const struct mail_index_ext *ext;
+       const void *data;
 
        i_assert(!cache->locked);
 
@@ -167,7 +168,7 @@ int mail_cache_reopen(struct mail_cache *cache)
 
        mail_cache_init_file_cache(cache);
 
-       if (mail_cache_map(cache, 0, 0) < 0)
+       if (mail_cache_map(cache, 0, 0, &data) < 0)
                return -1;
 
        if (mail_cache_header_fields_read(cache) < 0)
@@ -265,8 +266,10 @@ static bool mail_cache_verify_header(struct mail_cache *cache)
        return TRUE;
 }
 
-int mail_cache_map(struct mail_cache *cache, size_t offset, size_t size)
+int mail_cache_map(struct mail_cache *cache, size_t offset, size_t size,
+                  const void **data_r)
 {
+       const void *data;
        ssize_t ret;
 
        cache->remap_counter++;
@@ -309,13 +312,22 @@ int mail_cache_map(struct mail_cache *cache, size_t offset, size_t size)
                cache->hdr = &cache->hdr_ro_copy;
                if (offset == 0)
                        mail_cache_update_need_compress(cache);
-               return 0;
+
+               data = file_cache_get_map(cache->file_cache,
+                                         &cache->mmap_length);
+               if (offset > cache->mmap_length) {
+                       *data_r = NULL;
+                       return 0;
+               }
+               *data_r = CONST_PTR_OFFSET(data, offset);
+               return offset + size > cache->mmap_length ? 0 : 1;
        }
 
        if (offset < cache->mmap_length &&
            size <= cache->mmap_length - offset) {
                /* already mapped */
-               return 0;
+               *data_r = CONST_PTR_OFFSET(cache->mmap_base, offset);
+               return 1;
        }
 
        if (cache->mmap_base != NULL) {
@@ -355,11 +367,18 @@ int mail_cache_map(struct mail_cache *cache, size_t offset, size_t size)
        cache->hdr = cache->data;
        if (offset == 0)
                mail_cache_update_need_compress(cache);
-       return 0;
+       if (offset > cache->mmap_length) {
+               *data_r = NULL;
+               return 0;
+       }
+       *data_r = CONST_PTR_OFFSET(cache->mmap_base, offset);
+       return offset + size > cache->mmap_length ? 0 : 1;
 }
 
 static int mail_cache_try_open(struct mail_cache *cache)
 {
+       const void *data;
+
        cache->opened = TRUE;
 
        if (MAIL_INDEX_IS_IN_MEMORY(cache->index))
@@ -379,9 +398,9 @@ static int mail_cache_try_open(struct mail_cache *cache)
 
        mail_cache_init_file_cache(cache);
 
-       if (mail_cache_map(cache, 0, sizeof(struct mail_cache_header)) < 0)
+       if (mail_cache_map(cache, 0, sizeof(struct mail_cache_header),
+                          &data) < 0)
                return -1;
-
        return 1;
 }
 
@@ -550,6 +569,7 @@ mail_cache_lock_full(struct mail_cache *cache, bool require_same_reset_id,
                     bool nonblock)
 {
        const struct mail_index_ext *ext;
+       const void *data;
        struct mail_index_view *iview;
        uint32_t reset_id;
        int i, ret;
@@ -613,7 +633,7 @@ mail_cache_lock_full(struct mail_cache *cache, bool require_same_reset_id,
                        file_cache_invalidate(cache->file_cache, 0,
                                              sizeof(struct mail_cache_header));
                }
-               if (mail_cache_map(cache, 0, 0) == 0)
+               if (mail_cache_map(cache, 0, 0, &data) == 0)
                        cache->hdr_copy = *cache->hdr;
                else {
                        (void)mail_cache_unlock(cache);