xref: /linux/drivers/md/dm-vdo/memory-alloc.h (revision a5f998094fa344cdd1342164948abb4d7c6101ce)
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  */
vdo_allocate_cache_aligned(size_t size,const char * what,void * ptr)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 
__vdo_forget(void ** ptr_ptr)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