aboutsummaryrefslogtreecommitdiffstats
path: root/arena.c
diff options
context:
space:
mode:
Diffstat (limited to 'arena.c')
-rw-r--r--arena.c34
1 files changed, 27 insertions, 7 deletions
diff --git a/arena.c b/arena.c
index 3fdbd7a..c8f0fa5 100644
--- a/arena.c
+++ b/arena.c
@@ -1,7 +1,7 @@
#ident "$Id$"
/* ----------------------------------------------------------------------- *
*
- * Copyright 2000 H. Peter Anvin - All Rights Reserved
+ * Copyright 2000-2001 H. Peter Anvin - All Rights Reserved
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -32,6 +32,8 @@
#include <sys/mman.h>
#include <sys/stat.h>
#include <sched.h>
+#include <sys/time.h>
+#include <sys/resource.h>
#include "objstore.h"
#include "internals.h"
@@ -573,6 +575,7 @@ int objstore_extend(size_t new_size)
int ft;
size_t add_size, old_size;
size_t add_pages, old_pages, new_pages, file_pages;
+ struct rlimit fsizelimit;
old_size = os->arena_len;
@@ -582,7 +585,13 @@ int objstore_extend(size_t new_size)
new_size = (new_size + os->pagesize - 1) & ~(os->pagesize - 1);
add_size = new_size - old_size;
- lock.l_type = F_WRLCK;
+ /* Make sure we won't run afoul of a set resource limit. */
+ if ( getrlimit(RLIMIT_FSIZE, &fsizelimit) == 0 &&
+ fsizelimit.rlim_cur != RLIM_INFINITY &&
+ fsizelimit.rlim_cur < new_size )
+ return -1; /* Would exceed the file limit. */
+
+ lock.l_type = F_WRLCK;
lock.l_whence = SEEK_SET;
lock.l_start = 0;
lock.l_len = 0;
@@ -595,9 +604,8 @@ int objstore_extend(size_t new_size)
else
ft = 0;
- while ( fcntl(os->main_fd, F_SETLKW, &lock) == -1 && errno == EINTR );
if ( ft )
- return -1; /* Failure */
+ goto reset_size; /* Failure */
newp = mmap((char*)os->arena + old_size,
add_size,
@@ -605,7 +613,7 @@ int objstore_extend(size_t new_size)
MAP_PRIVATE|MAP_ANON|MAP_FIXED, 0, 0);
if ( newp == MAP_FAILED )
- return -1; /* Failure */
+ goto reset_size; /* Failure */
/* Since we specified MAP_FIXED, this should be guaranteed */
assert( newp == (char*)os->arena + old_size );
@@ -620,12 +628,15 @@ int objstore_extend(size_t new_size)
infop = realloc(os->pageinfo, new_pages);
if ( !infop ) {
munmap(newp, add_size);
- return -1; /* Failure */
+ goto reset_size;
}
os->arena_len = new_size;
os->pageinfo = infop;
-
+
+ /* No more failure bailouts, unlock */
+ while ( fcntl(os->main_fd, F_SETLKW, &lock) == -1 && errno == EINTR );
+
/* If we extended the file, the new area is known to contain
zero, and can thus be considered "clean"; otherwise we have
to consider it "unread". */
@@ -638,4 +649,13 @@ int objstore_extend(size_t new_size)
}
return 0;
+
+ /* We failed to extend the arena after ftruncate(), this is *usually*
+ due to address space limitations. */
+ reset_size:
+ /* Restore the original file size */
+ ftruncate(os->main_fd, file_size);
+ /* Drop lock */
+ while ( fcntl(os->main_fd, F_SETLKW, &lock) == -1 && errno == EINTR );
+ return -1;
}