xref: /freebsd/sys/compat/linuxkpi/common/include/linux/slab.h (revision ce930365d16356e873acd9a732ae863445b7b4e6)
18d59ecb2SHans Petter Selasky /*-
28d59ecb2SHans Petter Selasky  * Copyright (c) 2010 Isilon Systems, Inc.
38d59ecb2SHans Petter Selasky  * Copyright (c) 2010 iX Systems, Inc.
48d59ecb2SHans Petter Selasky  * Copyright (c) 2010 Panasas, Inc.
514c5024dSHans Petter Selasky  * Copyright (c) 2013-2017 Mellanox Technologies, Ltd.
68d59ecb2SHans Petter Selasky  * All rights reserved.
78d59ecb2SHans Petter Selasky  *
88d59ecb2SHans Petter Selasky  * Redistribution and use in source and binary forms, with or without
98d59ecb2SHans Petter Selasky  * modification, are permitted provided that the following conditions
108d59ecb2SHans Petter Selasky  * are met:
118d59ecb2SHans Petter Selasky  * 1. Redistributions of source code must retain the above copyright
128d59ecb2SHans Petter Selasky  *    notice unmodified, this list of conditions, and the following
138d59ecb2SHans Petter Selasky  *    disclaimer.
148d59ecb2SHans Petter Selasky  * 2. Redistributions in binary form must reproduce the above copyright
158d59ecb2SHans Petter Selasky  *    notice, this list of conditions and the following disclaimer in the
168d59ecb2SHans Petter Selasky  *    documentation and/or other materials provided with the distribution.
178d59ecb2SHans Petter Selasky  *
188d59ecb2SHans Petter Selasky  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
198d59ecb2SHans Petter Selasky  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
208d59ecb2SHans Petter Selasky  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
218d59ecb2SHans Petter Selasky  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
228d59ecb2SHans Petter Selasky  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
238d59ecb2SHans Petter Selasky  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
248d59ecb2SHans Petter Selasky  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
258d59ecb2SHans Petter Selasky  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
268d59ecb2SHans Petter Selasky  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
278d59ecb2SHans Petter Selasky  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
288d59ecb2SHans Petter Selasky  *
298d59ecb2SHans Petter Selasky  * $FreeBSD$
308d59ecb2SHans Petter Selasky  */
318d59ecb2SHans Petter Selasky #ifndef	_LINUX_SLAB_H_
328d59ecb2SHans Petter Selasky #define	_LINUX_SLAB_H_
338d59ecb2SHans Petter Selasky 
348d59ecb2SHans Petter Selasky #include <sys/param.h>
358d59ecb2SHans Petter Selasky #include <sys/systm.h>
368d59ecb2SHans Petter Selasky #include <sys/malloc.h>
370a475c59SHans Petter Selasky #include <sys/limits.h>
388d59ecb2SHans Petter Selasky #include <vm/uma.h>
398d59ecb2SHans Petter Selasky 
408d59ecb2SHans Petter Selasky #include <linux/types.h>
418d59ecb2SHans Petter Selasky #include <linux/gfp.h>
428d59ecb2SHans Petter Selasky 
438d59ecb2SHans Petter Selasky MALLOC_DECLARE(M_KMALLOC);
448d59ecb2SHans Petter Selasky 
4514c5024dSHans Petter Selasky #define	kvmalloc(size)			kmalloc(size, 0)
4614c5024dSHans Petter Selasky #define	kzalloc(size, flags)		kmalloc(size, (flags) | __GFP_ZERO)
4714c5024dSHans Petter Selasky #define	kzalloc_node(size, flags, node)	kmalloc(size, (flags) | __GFP_ZERO)
48510ebed7SHans Petter Selasky #define	kfree_const(ptr)		kfree(ptr)
4914c5024dSHans Petter Selasky #define	vzalloc(size)			__vmalloc(size, GFP_KERNEL | __GFP_NOWARN | __GFP_ZERO, 0)
508d59ecb2SHans Petter Selasky #define	vfree(arg)			kfree(arg)
518d59ecb2SHans Petter Selasky #define	kvfree(arg)			kfree(arg)
5214c5024dSHans Petter Selasky #define	vmalloc_node(size, node)        __vmalloc(size, GFP_KERNEL, 0)
5314c5024dSHans Petter Selasky #define	vmalloc_user(size)              __vmalloc(size, GFP_KERNEL | __GFP_ZERO, 0)
5414c5024dSHans Petter Selasky #define	vmalloc(size)                   __vmalloc(size, GFP_KERNEL, 0)
5514c5024dSHans Petter Selasky #define	__kmalloc(...)			kmalloc(__VA_ARGS__)
5614c5024dSHans Petter Selasky #define	kmalloc_node(chunk, flags, n)	kmalloc(chunk, flags)
577fdce5c4SHans Petter Selasky 
587fdce5c4SHans Petter Selasky /*
597fdce5c4SHans Petter Selasky  * Prefix some functions with linux_ to avoid namespace conflict
607fdce5c4SHans Petter Selasky  * with the OpenSolaris code in the kernel.
617fdce5c4SHans Petter Selasky  */
627fdce5c4SHans Petter Selasky #define	kmem_cache		linux_kmem_cache
637fdce5c4SHans Petter Selasky #define	kmem_cache_create(...)	linux_kmem_cache_create(__VA_ARGS__)
647fdce5c4SHans Petter Selasky #define	kmem_cache_alloc(...)	linux_kmem_cache_alloc(__VA_ARGS__)
657fdce5c4SHans Petter Selasky #define	kmem_cache_free(...) 	linux_kmem_cache_free(__VA_ARGS__)
667fdce5c4SHans Petter Selasky #define	kmem_cache_destroy(...) linux_kmem_cache_destroy(__VA_ARGS__)
677fdce5c4SHans Petter Selasky 
6878d74419SHans Petter Selasky #define	KMEM_CACHE(__struct, flags)					\
6978d74419SHans Petter Selasky 	linux_kmem_cache_create(#__struct, sizeof(struct __struct),	\
7078d74419SHans Petter Selasky 	__alignof(struct __struct), (flags), NULL)
7178d74419SHans Petter Selasky 
7214c5024dSHans Petter Selasky typedef void linux_kmem_ctor_t (void *);
7314c5024dSHans Petter Selasky 
747fdce5c4SHans Petter Selasky struct linux_kmem_cache {
758d59ecb2SHans Petter Selasky 	uma_zone_t cache_zone;
7614c5024dSHans Petter Selasky 	linux_kmem_ctor_t *cache_ctor;
7714c5024dSHans Petter Selasky 	unsigned cache_flags;
7814c5024dSHans Petter Selasky 	unsigned cache_size;
798d59ecb2SHans Petter Selasky };
808d59ecb2SHans Petter Selasky 
8114c5024dSHans Petter Selasky #define	SLAB_HWCACHE_ALIGN	(1 << 0)
82782a90d1SHans Petter Selasky #define	SLAB_TYPESAFE_BY_RCU    (1 << 1)
8314c5024dSHans Petter Selasky #define	SLAB_RECLAIM_ACCOUNT	(1 << 2)
848d59ecb2SHans Petter Selasky 
85*ce930365SHans Petter Selasky #define	SLAB_DESTROY_BY_RCU \
86*ce930365SHans Petter Selasky 	SLAB_TYPESAFE_BY_RCU
87*ce930365SHans Petter Selasky 
8814c5024dSHans Petter Selasky static inline gfp_t
8914c5024dSHans Petter Selasky linux_check_m_flags(gfp_t flags)
908d59ecb2SHans Petter Selasky {
9114c5024dSHans Petter Selasky 	const gfp_t m = M_NOWAIT | M_WAITOK;
928d59ecb2SHans Petter Selasky 
9314c5024dSHans Petter Selasky 	/* make sure either M_NOWAIT or M_WAITOK is set */
9414c5024dSHans Petter Selasky 	if ((flags & m) == 0)
9514c5024dSHans Petter Selasky 		flags |= M_NOWAIT;
9614c5024dSHans Petter Selasky 	else if ((flags & m) == m)
9714c5024dSHans Petter Selasky 		flags &= ~M_WAITOK;
988d59ecb2SHans Petter Selasky 
9914c5024dSHans Petter Selasky 	/* mask away LinuxKPI specific flags */
10014c5024dSHans Petter Selasky 	return (flags & GFP_NATIVE_MASK);
1018d59ecb2SHans Petter Selasky }
1028d59ecb2SHans Petter Selasky 
1038d59ecb2SHans Petter Selasky static inline void *
10414c5024dSHans Petter Selasky kmalloc(size_t size, gfp_t flags)
1058d59ecb2SHans Petter Selasky {
10614c5024dSHans Petter Selasky 	return (malloc(size, M_KMALLOC, linux_check_m_flags(flags)));
10714c5024dSHans Petter Selasky }
10814c5024dSHans Petter Selasky 
10914c5024dSHans Petter Selasky static inline void *
110e70c77caSKristof Provost kcalloc(size_t n, size_t size, gfp_t flags)
111e70c77caSKristof Provost {
112e70c77caSKristof Provost 	flags |= __GFP_ZERO;
113e70c77caSKristof Provost 	return (mallocarray(n, size, M_KMALLOC, linux_check_m_flags(flags)));
114e70c77caSKristof Provost }
115e70c77caSKristof Provost 
116e70c77caSKristof Provost static inline void *
11714c5024dSHans Petter Selasky __vmalloc(size_t size, gfp_t flags, int other)
11814c5024dSHans Petter Selasky {
11914c5024dSHans Petter Selasky 	return (malloc(size, M_KMALLOC, linux_check_m_flags(flags)));
12014c5024dSHans Petter Selasky }
12114c5024dSHans Petter Selasky 
12214c5024dSHans Petter Selasky static inline void *
1230a475c59SHans Petter Selasky vmalloc_32(size_t size)
1240a475c59SHans Petter Selasky {
1250a475c59SHans Petter Selasky 	return (contigmalloc(size, M_KMALLOC, M_WAITOK, 0, UINT_MAX, 1, 1));
1260a475c59SHans Petter Selasky }
1270a475c59SHans Petter Selasky 
1280a475c59SHans Petter Selasky static inline void *
12914c5024dSHans Petter Selasky kmalloc_array(size_t n, size_t size, gfp_t flags)
13014c5024dSHans Petter Selasky {
131ed595433SPedro F. Giffuni 	return (mallocarray(n, size, M_KMALLOC, linux_check_m_flags(flags)));
13214c5024dSHans Petter Selasky }
13314c5024dSHans Petter Selasky 
13414c5024dSHans Petter Selasky static inline void *
13514c5024dSHans Petter Selasky krealloc(void *ptr, size_t size, gfp_t flags)
13614c5024dSHans Petter Selasky {
13714c5024dSHans Petter Selasky 	return (realloc(ptr, size, M_KMALLOC, linux_check_m_flags(flags)));
1388d59ecb2SHans Petter Selasky }
1398d59ecb2SHans Petter Selasky 
1408d59ecb2SHans Petter Selasky static inline void
14114c5024dSHans Petter Selasky kfree(const void *ptr)
1428d59ecb2SHans Petter Selasky {
14314c5024dSHans Petter Selasky 	free(__DECONST(void *, ptr), M_KMALLOC);
14414c5024dSHans Petter Selasky }
14514c5024dSHans Petter Selasky 
14614c5024dSHans Petter Selasky extern struct linux_kmem_cache *linux_kmem_cache_create(const char *name,
14714c5024dSHans Petter Selasky     size_t size, size_t align, unsigned flags, linux_kmem_ctor_t *ctor);
14814c5024dSHans Petter Selasky 
14914c5024dSHans Petter Selasky static inline void *
15014c5024dSHans Petter Selasky linux_kmem_cache_alloc(struct linux_kmem_cache *c, gfp_t flags)
15114c5024dSHans Petter Selasky {
15214c5024dSHans Petter Selasky 	return (uma_zalloc_arg(c->cache_zone, c,
15314c5024dSHans Petter Selasky 	    linux_check_m_flags(flags)));
15414c5024dSHans Petter Selasky }
15514c5024dSHans Petter Selasky 
15614c5024dSHans Petter Selasky static inline void *
15714c5024dSHans Petter Selasky kmem_cache_zalloc(struct linux_kmem_cache *c, gfp_t flags)
15814c5024dSHans Petter Selasky {
15914c5024dSHans Petter Selasky 	return (uma_zalloc_arg(c->cache_zone, c,
16014c5024dSHans Petter Selasky 	    linux_check_m_flags(flags | M_ZERO)));
16114c5024dSHans Petter Selasky }
16214c5024dSHans Petter Selasky 
16314c5024dSHans Petter Selasky extern void linux_kmem_cache_free_rcu(struct linux_kmem_cache *, void *);
16414c5024dSHans Petter Selasky 
16514c5024dSHans Petter Selasky static inline void
16614c5024dSHans Petter Selasky linux_kmem_cache_free(struct linux_kmem_cache *c, void *m)
16714c5024dSHans Petter Selasky {
168782a90d1SHans Petter Selasky 	if (unlikely(c->cache_flags & SLAB_TYPESAFE_BY_RCU))
16914c5024dSHans Petter Selasky 		linux_kmem_cache_free_rcu(c, m);
17014c5024dSHans Petter Selasky 	else
1718d59ecb2SHans Petter Selasky 		uma_zfree(c->cache_zone, m);
1728d59ecb2SHans Petter Selasky }
1738d59ecb2SHans Petter Selasky 
17414c5024dSHans Petter Selasky extern void linux_kmem_cache_destroy(struct linux_kmem_cache *);
1758d59ecb2SHans Petter Selasky 
1768d59ecb2SHans Petter Selasky #endif					/* _LINUX_SLAB_H_ */
177