diff options
Diffstat (limited to 'arena.c')
-rw-r--r-- | arena.c | 34 |
1 files changed, 27 insertions, 7 deletions
@@ -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; } |