]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib: istream-mmap - Use memarea API
authorTimo Sirainen <timo.sirainen@dovecot.fi>
Fri, 8 Sep 2017 11:59:37 +0000 (14:59 +0300)
committerTimo Sirainen <tss@dovecot.fi>
Wed, 1 Nov 2017 11:45:51 +0000 (13:45 +0200)
src/lib/istream-mmap.c

index 85284c07d37bd1e481f2cc8ef6558c1aa45da9cb..7dd37a4b632608050ec6644adb5d5da5501f3378 100644 (file)
@@ -2,18 +2,23 @@
 
 #include "lib.h"
 #include "ioloop.h"
+#include "memarea.h"
 #include "mmap-util.h"
 #include "istream-private.h"
 
 #include <unistd.h>
 #include <sys/stat.h>
 
+struct mmap_memarea {
+       void *mmap_base;
+       size_t mmap_size;
+};
+
 struct mmap_istream {
        struct istream_private istream;
 
         struct timeval fstat_cache_stamp;
 
-       void *mmap_base;
        off_t mmap_offset;
        uoff_t v_size;
 
@@ -41,14 +46,13 @@ static void i_stream_munmap(struct mmap_istream *mstream)
        struct istream_private *_stream = &mstream->istream;
 
        if (_stream->buffer != NULL) {
-               if (munmap(mstream->mmap_base, _stream->buffer_size) < 0) {
-                       i_error("mmap_istream.munmap(%s) failed: %m",
-                               i_stream_get_name(&_stream->istream));
-               }
-               mstream->mmap_base = NULL;
+               if (_stream->memarea != NULL)
+                       memarea_unref(&_stream->memarea);
                _stream->buffer = NULL;
                _stream->buffer_size = 0;
                mstream->mmap_offset = 0;
+       } else {
+               i_assert(_stream->memarea == NULL);
        }
 }
 
@@ -65,6 +69,12 @@ static size_t mstream_get_mmap_block_size(struct istream_private *stream)
                (mmap_get_page_size() - 1);
 }
 
+static void i_stream_mmap_marea_free(struct mmap_memarea *marea)
+{
+       if (munmap(marea->mmap_base, marea->mmap_size) < 0)
+               i_error("mmap_istream.munmap() failed: %m");
+}
+
 static ssize_t i_stream_mmap_read(struct istream_private *stream)
 {
        struct mmap_istream *mstream = (struct mmap_istream *) stream;
@@ -83,7 +93,7 @@ static ssize_t i_stream_mmap_read(struct istream_private *stream)
        }
 
        aligned_skip = stream->skip & ~mmap_pagemask;
-       if (aligned_skip == 0 && mstream->mmap_base != NULL) {
+       if (aligned_skip == 0 && stream->buffer != NULL) {
                /* didn't skip enough bytes */
                return -2;
        }
@@ -91,12 +101,8 @@ static ssize_t i_stream_mmap_read(struct istream_private *stream)
        stream->skip -= aligned_skip;
        mstream->mmap_offset += aligned_skip;
 
-       if (mstream->mmap_base != NULL) {
-               if (munmap(mstream->mmap_base, stream->buffer_size) < 0) {
-                       i_error("mmap_istream.munmap(%s) failed: %m",
-                               i_stream_get_name(&stream->istream));
-               }
-       }
+       if (stream->memarea != NULL)
+               memarea_unref(&stream->memarea);
 
        top = mstream->v_size - mstream->mmap_offset;
        stream->buffer_size = I_MIN(top, mstream_get_mmap_block_size(stream));
@@ -106,16 +112,14 @@ static ssize_t i_stream_mmap_read(struct istream_private *stream)
 
        if (stream->buffer_size == 0) {
                /* don't bother even trying mmap */
-               mstream->mmap_base = NULL;
                stream->buffer = NULL;
        } else {
-               mstream->mmap_base =
+               void *mmap_base =
                        mmap(NULL, stream->buffer_size, PROT_READ, MAP_PRIVATE,
                             stream->fd, mstream->mmap_offset);
-               if (mstream->mmap_base == MAP_FAILED) {
+               if (mmap_base == MAP_FAILED) {
                        i_assert(errno != 0);
                        stream->istream.stream_errno = errno;
-                       mstream->mmap_base = NULL;
                        stream->buffer = NULL;
                        stream->buffer_size = 0;
                        stream->skip = stream->pos = 0;
@@ -125,14 +129,19 @@ static ssize_t i_stream_mmap_read(struct istream_private *stream)
                                i_stream_get_name(&stream->istream));
                        return -1;
                }
-               stream->buffer = mstream->mmap_base;
-       }
-
-       if (stream->buffer_size > mmap_get_page_size()) {
-               if (madvise(mstream->mmap_base, stream->buffer_size,
-                           MADV_SEQUENTIAL) < 0) {
-                       i_error("mmap_istream.madvise(%s): %m",
-                               i_stream_get_name(&stream->istream));
+               stream->buffer = mmap_base;
+
+               struct mmap_memarea *marea = i_new(struct mmap_memarea, 1);
+               marea->mmap_base = mmap_base;
+               marea->mmap_size = stream->buffer_size;
+               stream->memarea = memarea_init(mmap_base, marea->mmap_size,
+                                              i_stream_mmap_marea_free, marea);
+               if (stream->buffer_size > mmap_get_page_size()) {
+                       if (madvise(mmap_base, stream->buffer_size,
+                                   MADV_SEQUENTIAL) < 0) {
+                               i_error("mmap_istream.madvise(%s): %m",
+                                       i_stream_get_name(&stream->istream));
+                       }
                }
        }