[dovecot-cvs] dovecot/src/lib mmap-anon.c,1.10,1.11
cras at procontrol.fi
cras at procontrol.fi
Wed Apr 23 18:31:42 EEST 2003
Update of /home/cvs/dovecot/src/lib
In directory danu:/tmp/cvs-serv14998
Modified Files:
mmap-anon.c
Log Message:
mmap(MAP_FIXED) may return ENOMEM as well as EINVAL if address+length
isn't valid. Also some other cleanups.
Index: mmap-anon.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib/mmap-anon.c,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -d -r1.10 -r1.11
--- mmap-anon.c 29 Dec 2002 19:33:04 -0000 1.10
+++ mmap-anon.c 23 Apr 2003 14:31:40 -0000 1.11
@@ -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;
}
More information about the dovecot-cvs
mailing list