summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/util/util.c64
-rw-r--r--lib/util/util.h1
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);
/*