diff options
Diffstat (limited to 'lib')
-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); /* |