summaryrefslogtreecommitdiff
path: root/libbcachefs/util.h
diff options
context:
space:
mode:
Diffstat (limited to 'libbcachefs/util.h')
-rw-r--r--libbcachefs/util.h33
1 files changed, 19 insertions, 14 deletions
diff --git a/libbcachefs/util.h b/libbcachefs/util.h
index 5f13c824..5669cb8a 100644
--- a/libbcachefs/util.h
+++ b/libbcachefs/util.h
@@ -9,6 +9,7 @@
#include <linux/freezer.h>
#include <linux/kernel.h>
#include <linux/llist.h>
+#include <linux/log2.h>
#include <linux/ratelimit.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
@@ -78,16 +79,22 @@ do { \
(__builtin_types_compatible_p(typeof(_val), _type) || \
__builtin_types_compatible_p(typeof(_val), const _type))
-static inline void *kvmalloc(size_t bytes, gfp_t gfp)
+static inline void kvpfree(void *p, size_t size)
{
- if (bytes <= PAGE_SIZE ||
- !(gfp & GFP_KERNEL))
- return kmalloc(bytes, gfp);
-
- return ((bytes <= KMALLOC_MAX_SIZE)
- ? kmalloc(bytes, gfp|__GFP_NOWARN)
- : NULL) ?:
- vmalloc(bytes);
+ if (size < PAGE_SIZE)
+ kfree(p);
+ else if (is_vmalloc_addr(p))
+ vfree(p);
+ else
+ free_pages((unsigned long) p, get_order(size));
+
+}
+
+static inline void *kvpmalloc(size_t size, gfp_t gfp_mask)
+{
+ return size < PAGE_SIZE ? kmalloc(size, gfp_mask)
+ : (void *) __get_free_pages(gfp_mask, get_order(size))
+ ?: __vmalloc(size, gfp_mask, PAGE_KERNEL);
}
#define DECLARE_HEAP(type, name) \
@@ -98,17 +105,15 @@ static inline void *kvmalloc(size_t bytes, gfp_t gfp)
#define init_heap(heap, _size, gfp) \
({ \
- size_t _bytes; \
(heap)->used = 0; \
(heap)->size = (_size); \
- _bytes = (heap)->size * sizeof(*(heap)->data); \
- (heap)->data = kvmalloc(_bytes, (gfp)); \
- (heap)->data; \
+ (heap)->data = kvpmalloc((heap)->size * sizeof((heap)->data[0]),\
+ (gfp)); \
})
#define free_heap(heap) \
do { \
- kvfree((heap)->data); \
+ kvpfree((heap)->data, (heap)->size * sizeof((heap)->data[0])); \
(heap)->data = NULL; \
} while (0)