1 /* SPDX-License-Identifier: GPL-2.0-only */ 2 /* 3 * Copyright 2023 Red Hat 4 */ 5 6 #ifndef VDO_MEMORY_ALLOC_H 7 #define VDO_MEMORY_ALLOC_H 8 9 #include <linux/cache.h> 10 #include <linux/io.h> /* for PAGE_SIZE */ 11 #include <linux/overflow.h> 12 13 #include "permassert.h" 14 #include "thread-registry.h" 15 16 /* Custom memory allocation function that tracks memory usage */ 17 int __must_check vdo_allocate_memory(size_t size, size_t align, const char *what, void *ptr); 18 19 /* 20 * Allocate one or more elements of the indicated type, logging an error if the allocation fails. 21 * The memory will be zeroed. 22 * 23 * @COUNT: The number of objects to allocate 24 * @WHAT: What is being allocated (for error logging) 25 * @PTR: A pointer to hold the allocated memory 26 * 27 * Return: VDO_SUCCESS or an error code 28 */ 29 #define vdo_allocate(COUNT, WHAT, PTR) \ 30 vdo_allocate_memory(size_mul((COUNT), sizeof(typeof(**(PTR)))), \ 31 __alignof__(typeof(**(PTR))), WHAT, PTR) 32 33 /* 34 * Allocate a structure with a flexible array member, with a specified number of elements, logging 35 * an error if the allocation fails. The memory will be zeroed. 36 * 37 * @COUNT: The number of objects to allocate 38 * @FIELD: The flexible array field at the end of the structure 39 * @WHAT: What is being allocated (for error logging) 40 * @PTR: A pointer to hold the allocated memory 41 * 42 * Return: VDO_SUCCESS or an error code 43 */ 44 #define vdo_allocate_extended(COUNT, FIELD, WHAT, PTR) \ 45 vdo_allocate_memory(struct_size(*(PTR), FIELD, (COUNT)), \ 46 __alignof__(typeof(**(PTR))), \ 47 WHAT, \ 48 (PTR)) 49 50 /* 51 * Allocate memory starting on a cache line boundary, logging an error if the allocation fails. The 52 * memory will be zeroed. 53 * 54 * @size: The number of bytes to allocate 55 * @what: What is being allocated (for error logging) 56 * @ptr: A pointer to hold the allocated memory 57 * 58 * Return: VDO_SUCCESS or an error code 59 */ 60 static inline int __must_check vdo_allocate_cache_aligned(size_t size, const char *what, void *ptr) 61 { 62 return vdo_allocate_memory(size, L1_CACHE_BYTES, what, ptr); 63 } 64 65 /* 66 * Allocate one element of the indicated type immediately, failing if the required memory is not 67 * immediately available. 68 * 69 * @size: The number of bytes to allocate 70 * @what: What is being allocated (for error logging) 71 * 72 * Return: pointer to the memory, or NULL if the memory is not available. 73 */ 74 void *__must_check vdo_allocate_memory_nowait(size_t size, const char *what); 75 76 int __must_check vdo_reallocate_memory(void *ptr, size_t old_size, size_t size, 77 const char *what, void *new_ptr); 78 79 int __must_check vdo_duplicate_string(const char *string, const char *what, 80 char **new_string); 81 82 /* Free memory allocated with vdo_allocate(). */ 83 void vdo_free(void *ptr); 84 85 static inline void *__vdo_forget(void **ptr_ptr) 86 { 87 void *ptr = *ptr_ptr; 88 89 *ptr_ptr = NULL; 90 return ptr; 91 } 92 93 /* 94 * Null out a pointer and return a copy to it. This macro should be used when passing a pointer to 95 * a function for which it is not safe to access the pointer once the function returns. 96 */ 97 #define vdo_forget(ptr) __vdo_forget((void **) &(ptr)) 98 99 void vdo_memory_init(void); 100 101 void vdo_memory_exit(void); 102 103 void vdo_register_allocating_thread(struct registered_thread *new_thread, 104 const bool *flag_ptr); 105 106 void vdo_unregister_allocating_thread(void); 107 108 void vdo_get_memory_stats(u64 *bytes_used, u64 *peak_bytes_used); 109 110 void vdo_report_memory_usage(void); 111 112 #endif /* VDO_MEMORY_ALLOC_H */ 113