diff --git a/NEWS b/NEWS index 4ac67e08..942d2c20 100644 --- a/NEWS +++ b/NEWS @@ -15,6 +15,7 @@ NEWS * [autoconf] define HAVE_CRYPT when crypt() is present * [bsd xattr] fix compile break with BSD extended attributes in stat_cache * [mod_cgi] rewrite mmap and generic (post body) send error handling + * [mmap] fix mmap alignment - 1.4.36 - 2015-07-26 * use keep-alive timeout while waiting for HTTP headers; use always the read timeout while waiting for the HTTP body diff --git a/src/mod_cgi.c b/src/mod_cgi.c index d1f4e09b..50bbc485 100644 --- a/src/mod_cgi.c +++ b/src/mod_cgi.c @@ -766,8 +766,8 @@ static int cgi_write_file_chunk_mmap(server *srv, connection *con, int fd, chunk c->file.mmap.start = MAP_FAILED; } - c->file.mmap.offset = offset; - c->file.mmap.length = toSend; + c->file.mmap.offset = mmap_align_offset(offset); + c->file.mmap.length = file_end - c->file.mmap.offset; if (MAP_FAILED == (c->file.mmap.start = mmap(NULL, c->file.mmap.length, PROT_READ, MAP_SHARED, c->file.fd, c->file.mmap.offset))) { log_error_write(srv, __FILE__, __LINE__, "ssbdoo", "mmap failed:", diff --git a/src/network_backends.h b/src/network_backends.h index 2245c749..8233c488 100644 --- a/src/network_backends.h +++ b/src/network_backends.h @@ -91,6 +91,7 @@ static inline int network_writev_mem_chunks(server *srv, connection *con, int fd /* next chunk must be FILE_CHUNK. use temporary buffer (srv->tmp_buf) to read into, then write()/send() it */ int network_write_file_chunk_no_mmap(server *srv, connection *con, int fd, chunkqueue *cq, off_t *p_max_bytes); +off_t mmap_align_offset(off_t start); #if defined(USE_MMAP) /* next chunk must be FILE_CHUNK. send mmap()ed file with write() */ int network_write_file_chunk_mmap(server *srv, connection *con, int fd, chunkqueue *cq, off_t *p_max_bytes); diff --git a/src/network_write_mmap.c b/src/network_write_mmap.c index 9747d619..9ff3ae96 100644 --- a/src/network_write_mmap.c +++ b/src/network_write_mmap.c @@ -1,7 +1,5 @@ #include "network_backends.h" -#if defined(USE_MMAP) - #include "network.h" #include "log.h" #include "sys-mmap.h" @@ -11,6 +9,20 @@ #include #include +#define MMAP_CHUNK_SIZE (512*1024) + +off_t mmap_align_offset(off_t start) { + static long pagesize = 0; + if (0 == pagesize) { + pagesize = sysconf(_SC_PAGESIZE); + force_assert(pagesize < MMAP_CHUNK_SIZE); + } + force_assert(start >= (start % pagesize)); + return start - (start % pagesize); +} + +#if defined(USE_MMAP) + #if 0 /* read mmap()ed data into local buffer */ #define LOCAL_BUFFERING 1 @@ -70,10 +82,10 @@ int network_write_file_chunk_mmap(server *srv, connection *con, int fd, chunkque * 3. use non-blocking IO for file-transfers * */ - c->file.mmap.offset = offset & ~(4095); /* align at 4kb */ + c->file.mmap.offset = mmap_align_offset(offset); - /* all mmap()ed areas are 512kb except the last which might be smaller */ - c->file.mmap.length = 512*1024; + /* all mmap()ed areas are MMAP_CHUNK_SIZE except the last which might be smaller */ + c->file.mmap.length = MMAP_CHUNK_SIZE; if (c->file.mmap.offset > file_end - (off_t)c->file.mmap.length) { c->file.mmap.length = file_end - c->file.mmap.offset; }