aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJean-Sébastien Pédron <dumbbell@FreeBSD.org>2026-04-14 00:01:26 +0000
committerJean-Sébastien Pédron <dumbbell@FreeBSD.org>2026-04-22 20:46:57 +0000
commitd74fa49d0c0476353af137d22b5ef8711c67b854 (patch)
tree70bb7444b6c0b1cce100cfec582ff86a38a58963
parent0a2f3b8ef16786a44fc88afd8862920df4527a3c (diff)
linuxkpi: Add Linux 6.12 variant of `kvrealloc()`
In Linux 6.12, the API changed to be closer to `krealloc()`: * The function does not take the old size anymore * The function becomes a wrapper around `krealloc()` with a fallback mechanism. Reviewed by: bz Sponsored by: The FreeBSD Foundation Differential Revision: https://reviews.freebsd.org/D56453
-rw-r--r--sys/compat/linuxkpi/common/include/linux/slab.h39
-rw-r--r--sys/compat/linuxkpi/common/src/linux_slab.c38
2 files changed, 61 insertions, 16 deletions
diff --git a/sys/compat/linuxkpi/common/include/linux/slab.h b/sys/compat/linuxkpi/common/include/linux/slab.h
index 8d023eaddadd..b529a6303085 100644
--- a/sys/compat/linuxkpi/common/include/linux/slab.h
+++ b/sys/compat/linuxkpi/common/include/linux/slab.h
@@ -141,6 +141,13 @@ linux_check_m_flags(gfp_t flags)
/*
* Base functions with a native implementation.
*/
+
+static inline size_t
+ksize(const void *ptr)
+{
+ return (malloc_usable_size(ptr));
+}
+
static inline void *
kmalloc(size_t size, gfp_t flags)
{
@@ -264,22 +271,28 @@ kvmalloc_array(size_t n, size_t size, gfp_t flags)
return (kvmalloc(size * n, flags));
}
+void * lkpi_kvrealloc(const void *ptr, size_t oldsize, size_t newsize, gfp_t flags);
+
+#if defined(LINUXKPI_VERSION) && LINUXKPI_VERSION < 61200
static inline void *
kvrealloc(const void *ptr, size_t oldsize, size_t newsize, gfp_t flags)
{
- void *newptr;
-
- if (newsize <= oldsize)
- return (__DECONST(void *, ptr));
+ return (lkpi_kvrealloc(ptr, oldsize, newsize, flags));
+}
+#else
+static inline void *
+kvrealloc(const void *ptr, size_t newsize, gfp_t flags)
+{
+ size_t oldsize;
- newptr = kvmalloc(newsize, flags);
- if (newptr != NULL) {
- memcpy(newptr, ptr, oldsize);
- kvfree(ptr);
- }
+ if (!ZERO_OR_NULL_PTR(ptr))
+ oldsize = ksize(ptr);
+ else
+ oldsize = 0;
- return (newptr);
+ return (lkpi_kvrealloc(ptr, oldsize, newsize, flags));
}
+#endif
/*
* Misc.
@@ -295,12 +308,6 @@ kfree_sensitive(const void *ptr)
}
static inline size_t
-ksize(const void *ptr)
-{
- return (malloc_usable_size(ptr));
-}
-
-static inline size_t
kmalloc_size_roundup(size_t size)
{
if (unlikely(size == 0 || size == SIZE_MAX))
diff --git a/sys/compat/linuxkpi/common/src/linux_slab.c b/sys/compat/linuxkpi/common/src/linux_slab.c
index a387e5c23ad3..9fe51f0f4e10 100644
--- a/sys/compat/linuxkpi/common/src/linux_slab.c
+++ b/sys/compat/linuxkpi/common/src/linux_slab.c
@@ -278,6 +278,44 @@ lkpi_krealloc(const void *ptr, size_t size, gfp_t flags)
return (nptr);
}
+void *
+lkpi_kvrealloc(const void *ptr, size_t oldsize, size_t newsize, gfp_t flags)
+{
+ void *newptr;
+
+ /*
+ * We replicate the behaviour of krealloc() instead of calling it
+ * because we don't need to allocate physically contiguous memory.
+ */
+
+ if (newsize == 0) {
+ kfree(ptr);
+ return (ZERO_SIZE_PTR);
+ }
+
+ if (ptr == NULL) {
+ newptr = kvmalloc(newsize, flags);
+ return (newptr);
+ }
+
+ newptr = realloc(
+ __DECONST(void *, ptr), newsize, M_KMALLOC,
+ linux_check_m_flags(flags));
+
+ if (newptr == NULL) {
+ newptr = kvmalloc(newsize, flags);
+ if (newptr == NULL)
+ return (NULL);
+
+ if (ptr != NULL) {
+ memcpy(newptr, ptr, oldsize);
+ kfree(ptr);
+ }
+ }
+
+ return (newptr);
+}
+
struct lkpi_kmalloc_ctx {
size_t size;
gfp_t flags;