extern void *vcalloc_noprof(size_t n, size_t size) __alloc_size(1, 2);
 #define vcalloc(...)           alloc_hooks(vcalloc_noprof(__VA_ARGS__))
 
+void * __must_check vrealloc_noprof(const void *p, size_t size, gfp_t flags)
+               __realloc_size(2);
+#define vrealloc(...)          alloc_hooks(vrealloc_noprof(__VA_ARGS__))
+
 extern void vfree(const void *addr);
 extern void vfree_atomic(const void *addr);
 
 
 }
 EXPORT_SYMBOL(__vmalloc_noprof);
 
+void *vrealloc_noprof(const void *p, size_t size, gfp_t flags)
+{
+       return krealloc_noprof(p, size, (flags | __GFP_COMP) & ~__GFP_HIGHMEM);
+}
+
 void *__vmalloc_node_range_noprof(unsigned long size, unsigned long align,
                unsigned long start, unsigned long end, gfp_t gfp_mask,
                pgprot_t prot, unsigned long vm_flags, int node,
 
 }
 EXPORT_SYMBOL(vzalloc_node_noprof);
 
+/**
+ * vrealloc - reallocate virtually contiguous memory; contents remain unchanged
+ * @p: object to reallocate memory for
+ * @size: the size to reallocate
+ * @flags: the flags for the page level allocator
+ *
+ * If @p is %NULL, vrealloc() behaves exactly like vmalloc(). If @size is 0 and
+ * @p is not a %NULL pointer, the object pointed to is freed.
+ *
+ * If __GFP_ZERO logic is requested, callers must ensure that, starting with the
+ * initial memory allocation, every subsequent call to this API for the same
+ * memory allocation is flagged with __GFP_ZERO. Otherwise, it is possible that
+ * __GFP_ZERO is not fully honored by this API.
+ *
+ * In any case, the contents of the object pointed to are preserved up to the
+ * lesser of the new and old sizes.
+ *
+ * This function must not be called concurrently with itself or vfree() for the
+ * same memory allocation.
+ *
+ * Return: pointer to the allocated memory; %NULL if @size is zero or in case of
+ *         failure
+ */
+void *vrealloc_noprof(const void *p, size_t size, gfp_t flags)
+{
+       size_t old_size = 0;
+       void *n;
+
+       if (!size) {
+               vfree(p);
+               return NULL;
+       }
+
+       if (p) {
+               struct vm_struct *vm;
+
+               vm = find_vm_area(p);
+               if (unlikely(!vm)) {
+                       WARN(1, "Trying to vrealloc() nonexistent vm area (%p)\n", p);
+                       return NULL;
+               }
+
+               old_size = get_vm_area_size(vm);
+       }
+
+       /*
+        * TODO: Shrink the vm_area, i.e. unmap and free unused pages. What
+        * would be a good heuristic for when to shrink the vm_area?
+        */
+       if (size <= old_size) {
+               /* Zero out spare memory. */
+               if (want_init_on_alloc(flags))
+                       memset((void *)p + size, 0, old_size - size);
+
+               return (void *)p;
+       }
+
+       /* TODO: Grow the vm_area, i.e. allocate and map additional pages. */
+       n = __vmalloc_noprof(size, flags);
+       if (!n)
+               return NULL;
+
+       if (p) {
+               memcpy(n, p, old_size);
+               vfree(p);
+       }
+
+       return n;
+}
+
 #if defined(CONFIG_64BIT) && defined(CONFIG_ZONE_DMA32)
 #define GFP_VMALLOC32 (GFP_DMA32 | GFP_KERNEL)
 #elif defined(CONFIG_64BIT) && defined(CONFIG_ZONE_DMA)