Mercurial > dovecot > core-2.2
changeset 1381:8ef24a824568 HEAD
mmap(MAP_FIXED) may return ENOMEM as well as EINVAL if address+length
isn't valid. Also some other cleanups.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Wed, 23 Apr 2003 17:31:40 +0300 |
parents | 7dff693ab2b2 |
children | c4d519a6395d |
files | src/lib/mmap-anon.c |
diffstat | 1 files changed, 37 insertions(+), 22 deletions(-) [+] |
line wrap: on
line diff
--- a/src/lib/mmap-anon.c Wed Apr 23 17:11:17 2003 +0300 +++ b/src/lib/mmap-anon.c Wed Apr 23 17:31:40 2003 +0300 @@ -28,17 +28,23 @@ #include <fcntl.h> -#if !defined(MAP_ANONYMOUS) && defined(MAP_ANON) -# define MAP_ANONYMOUS MAP_ANON +#ifndef MAP_ANONYMOUS +# ifdef MAP_ANON +# define MAP_ANONYMOUS MAP_ANON +# else +# define MAP_ANONYMOUS 0 +# endif #endif #ifndef HAVE_LINUX_MREMAP +#include "fd-close-on-exec.h" + #include <stdlib.h> #include <sys/mman.h> -/* MMAP_BASE_MOVE may be negative as well */ -#if SSIZE_T_MAX >= LLONG_MAX +/* MMAP_BASE_MOVE may be set to negative as well */ +#if SSIZE_T_MAX > 2147483647L /* 64bit or more */ # define MMAP_BASE_MOVE (1024ULL*1024ULL*1024ULL*128ULL) /* 128GB */ #else @@ -60,12 +66,21 @@ static int header_size = 0; static void *movable_mmap_base = NULL; static void *mmap_top_limit, *mmap_heap_bottom, *mmap_heap_top; +static int zero_fd = -1; static void movable_mmap_init(void) { ssize_t abs_base_move; char x; +#if MAP_ANONYMOUS == 0 + /* mmap()ing /dev/zero should be the same with some platforms */ + zero_fd = open("/dev/zero", O_RDWR); + if (zero_fd == -1) + i_fatal("Can't open /dev/zero for creating anonymous mmap"); + fd_close_on_exec(zero_fd, TRUE); +#endif + abs_base_move = MMAP_BASE_MOVE; if (abs_base_move < 0) abs_base_move = -abs_base_move; @@ -87,22 +102,10 @@ { void *base; -#ifdef MAP_ANONYMOUS - base = mmap(address, length, PROT_READ | PROT_WRITE, - MAP_FIXED | MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); -#else - int fd; - - /* mmap()ing /dev/zero should be the same with some platforms */ - fd = open("/dev/zero", O_RDWR); - if (fd == -1) - i_fatal("Can't open /dev/zero for creating anonymous mmap"); + i_assert(address != NULL); base = mmap(address, length, PROT_READ | PROT_WRITE, - MAP_FIXED | MAP_PRIVATE, fd, 0); - - (void)close(fd); -#endif + MAP_FIXED | MAP_ANONYMOUS | MAP_PRIVATE, zero_fd, 0); if (base != MAP_FAILED && base != address) { /* shouldn't happen with MAP_FIXED, but who knows.. */ @@ -118,8 +121,9 @@ void *mmap_anon(size_t length) { struct movable_header *hdr; - void *next_mmap_base; + void *next_mmap_base, *base; ssize_t offset; + unsigned int count; int ret; if (header_size == 0) @@ -135,7 +139,7 @@ PAGE_ALIGN((size_t)((char *)mmap_anon - (char *)NULL)); } - offset = MMAP_BASE_MOVE; + offset = MMAP_BASE_MOVE; count = 0; for (;;) { next_mmap_base = (char *) movable_mmap_base + offset; if ((char *) next_mmap_base < (char *) movable_mmap_base) { @@ -176,8 +180,19 @@ if (ret == 0) break; - if (ret < 0 && errno != EINVAL) + if (errno != EINVAL && errno != ENOMEM) return MAP_FAILED; + + if (++count == 100) { + /* enough tries, try non-fixed mmap() */ + base = mmap(NULL, length, PROT_READ | PROT_WRITE, + MAP_ANONYMOUS | MAP_PRIVATE, zero_fd, 0); + if (base == MAP_FAILED) + return MAP_FAILED; + + movable_mmap_base = base; + break; + } } /* initialize the header */ @@ -200,7 +215,7 @@ } if (anon_mmap_fixed(grow_base, new_size - hdr->size) < 0) { - if (errno == EINVAL) { + if (errno == EINVAL || errno == ENOMEM) { /* can't grow, wanted address space is already in use */ return 0; }