diff options
author | Simo Sorce <idra@samba.org> | 2011-08-14 18:10:53 -0400 |
---|---|---|
committer | Simo Sorce <idra@samba.org> | 2011-08-14 20:19:02 -0400 |
commit | 039ddef20900322760093a04881007dbb0897b50 (patch) | |
tree | ca79b916a5d2c459bd4e5ff4db664be4024bd55d /lib/util | |
parent | a171938408adde0d787b9ff40a4cebeee66d747a (diff) | |
download | samba-039ddef20900322760093a04881007dbb0897b50.tar.gz samba-039ddef20900322760093a04881007dbb0897b50.tar.bz2 samba-039ddef20900322760093a04881007dbb0897b50.zip |
util: add function to extend anonymous shared memory
Diffstat (limited to 'lib/util')
-rw-r--r-- | lib/util/util.c | 64 | ||||
-rw-r--r-- | lib/util/util.h | 1 |
2 files changed, 65 insertions, 0 deletions
diff --git a/lib/util/util.c b/lib/util/util.c index 2d1d83036d..b700f372c7 100644 --- a/lib/util/util.c +++ b/lib/util/util.c @@ -1073,6 +1073,70 @@ void *anonymous_shared_allocate(size_t orig_bufsz) return ptr; } +void *anonymous_shared_resize(void *ptr, size_t new_size, bool maymove) +{ +#ifdef HAVE_MREMAP + void *buf; + size_t pagesz = getpagesize(); + size_t pagecnt; + size_t bufsz; + struct anonymous_shared_header *hdr; + int flags = 0; + + if (ptr == NULL) { + errno = EINVAL; + return NULL; + } + + hdr = (struct anonymous_shared_header *)ptr; + hdr--; + if (hdr->u.length > (new_size + sizeof(*hdr))) { + errno = EINVAL; + return NULL; + } + + bufsz = new_size + sizeof(*hdr); + + /* round up to full pages */ + pagecnt = bufsz / pagesz; + if (bufsz % pagesz) { + pagecnt += 1; + } + bufsz = pagesz * pagecnt; + + if (new_size >= bufsz) { + /* integer wrap */ + errno = ENOSPC; + return NULL; + } + + if (bufsz <= hdr->u.length) { + return ptr; + } + + if (maymove) { + flags = MREMAP_MAYMOVE; + } + + buf = mremap(hdr, hdr->u.length, bufsz, flags); + + if (buf == MAP_FAILED) { + errno = ENOSPC; + return NULL; + } + + hdr = (struct anonymous_shared_header *)buf; + hdr->u.length = bufsz; + + ptr = (void *)(&hdr[1]); + + return ptr; +#else + errno = ENOSPC; + return NULL; +#endif +} + void anonymous_shared_free(void *ptr) { struct anonymous_shared_header *hdr; diff --git a/lib/util/util.h b/lib/util/util.h index 7f0de26781..0102feaddf 100644 --- a/lib/util/util.h +++ b/lib/util/util.h @@ -852,6 +852,7 @@ bool add_gid_to_array_unique(TALLOC_CTX *mem_ctx, gid_t gid, * Allocate anonymous shared memory of the given size */ void *anonymous_shared_allocate(size_t bufsz); +void *anonymous_shared_resize(void *ptr, size_t new_size, bool maymove); void anonymous_shared_free(void *ptr); /* |