/** @file @brief Linux kernel memory management interface wrapper @details Copyright (c) 2017-2018 Acronis International GmbH @author Mikhail Krivtsov ([email protected]) @since $Id: $ */ #pragma once #ifndef BPF_PROGRAM #include <linux/mm.h> // is_vmalloc_addr() #include <linux/slab.h> // kmalloc(), kzalloc(), kfree() #include <linux/vmalloc.h> // vmalloc(), vfree() #include "safe_kobject.h" #define mem_flags(nowait) ((nowait) ? (GFP_ATOMIC) : (GFP_KERNEL)) #define mem_alloc_with_alloc_flags(size, nowait) kmalloc(size, mem_flags(nowait)) #define mem_alloc0_with_alloc_flags(size, nowait) kzalloc(size, mem_flags(nowait)) #define mem_alloc(size) mem_alloc_with_alloc_flags(size, false) #define mem_alloc0(size) mem_alloc0_with_alloc_flags(size, false) #define mem_alloc_nowait(size) mem_alloc_with_alloc_flags(size, true) #define mem_alloc0_nowait(size) mem_alloc0_with_alloc_flags(size, true) #define mem_free(p) kfree(p) static inline void *kvmalloc_compat(size_t size, gfp_t flags) { void *ret; ret = kmalloc(size, flags | __GFP_NOWARN); if (ret) { return ret; } return vmalloc(size); } static inline void kvfree_compat(void *addr) { if (is_vmalloc_addr(addr)) vfree(addr); else kfree(addr); } #define large_mem_alloc(size) kvmalloc_compat(size, GFP_KERNEL) #define large_mem_free(p) kvfree_compat(p) #define vmem_alloc(size) vmalloc(size) #define vmem_free(p) vfree(p) // kmem_cache used to make semantics like 'new' or 'delete' #define KMEM_STRUCT_CACHE_NAME(__struct) g_##__struct##_new_cache #define KMEM_STRUCT_CACHE_DECLARE(__struct) struct kmem_cache* KMEM_STRUCT_CACHE_NAME(__struct) #define KMEM_STRUCT_CACHE_INIT(__struct, flags, ctor) (KMEM_STRUCT_CACHE_NAME(__struct) = kmem_cache_create("fileprotector_" #__struct, sizeof(__struct##_t), __alignof__(__struct##_t), flags, ctor)) #define KMEM_STRUCT_CACHE_DEINIT(__struct) do{ if (KMEM_STRUCT_CACHE_NAME(__struct)) kmem_cache_destroy(KMEM_STRUCT_CACHE_NAME(__struct)); }while(0) #define KMEM_NEW_WITH_ALLOC_FLAGS(__struct, nowait) (__struct##_t*) kmem_cache_alloc(KMEM_STRUCT_CACHE_NAME(__struct), mem_flags(nowait)) #define KMEM_NEW(__struct) (__struct##_t*) KMEM_NEW_WITH_ALLOC_FLAGS(__struct, false) #define KMEM_NEW0_WITH_ALLOC_FLAGS(__struct, nowait) (__struct##_t*) kmem_cache_zalloc(KMEM_STRUCT_CACHE_NAME(__struct), mem_flags(nowait)) #define KMEM_NEW0(__struct) (__struct##_t*) KMEM_NEW0_WITH_ALLOC_FLAGS(__struct, false) #define KMEM_DELETE(__struct, ptr) kmem_cache_free(KMEM_STRUCT_CACHE_NAME(__struct), ptr) extern struct kmem_cache *g_handles_cache; int memory_init(void); void memory_deinit(void); typedef struct memory_metrics_s { safe_kobject_t skobj; atomic64_t total_file_contexts_tables; atomic64_t total_transports; atomic64_t total_transport_events; atomic64_t total_msgs; atomic64_t total_msgs_size; atomic64_t total_sized_msgs; atomic64_t total_sized_msgs_size; } memory_metrics_t; extern memory_metrics_t* g_memory_metrics; #endif