]> git.proxmox.com Git - mirror_spl.git/blob - include/sys/vmem.h
f59ac5e8b2803c073fc863455c3500fe63446a14
[mirror_spl.git] / include / sys / vmem.h
1 /*
2 * Copyright (C) 2007-2010 Lawrence Livermore National Security, LLC.
3 * Copyright (C) 2007 The Regents of the University of California.
4 * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
5 * Written by Brian Behlendorf <behlendorf1@llnl.gov>.
6 * UCRL-CODE-235197
7 *
8 * This file is part of the SPL, Solaris Porting Layer.
9 * For details, see <http://zfsonlinux.org/>.
10 *
11 * The SPL is free software; you can redistribute it and/or modify it
12 * under the terms of the GNU General Public License as published by the
13 * Free Software Foundation; either version 2 of the License, or (at your
14 * option) any later version.
15 *
16 * The SPL is distributed in the hope that it will be useful, but WITHOUT
17 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19 * for more details.
20 *
21 * You should have received a copy of the GNU General Public License along
22 * with the SPL. If not, see <http://www.gnu.org/licenses/>.
23 */
24
25 #ifndef _SPL_VMEM_H
26 #define _SPL_VMEM_H
27
28 #include <sys/kmem.h>
29 #include <linux/sched.h>
30 #include <linux/vmalloc.h>
31
32 typedef struct vmem { } vmem_t;
33
34 extern vmem_t *heap_arena;
35 extern vmem_t *zio_alloc_arena;
36 extern vmem_t *zio_arena;
37
38 extern size_t vmem_size(vmem_t *vmp, int typemask);
39
40 /*
41 * Memory allocation interfaces
42 */
43 #define VMEM_ALLOC 0x01
44 #define VMEM_FREE 0x02
45
46 #ifndef VMALLOC_TOTAL
47 #define VMALLOC_TOTAL (VMALLOC_END - VMALLOC_START)
48 #endif
49
50 static inline void *
51 vmalloc_nofail(size_t size, gfp_t flags)
52 {
53 void *ptr;
54
55 /*
56 * Retry failed __vmalloc() allocations once every second. The
57 * rational for the delay is that the likely failure modes are:
58 *
59 * 1) The system has completely exhausted memory, in which case
60 * delaying 1 second for the memory reclaim to run is reasonable
61 * to avoid thrashing the system.
62 * 2) The system has memory but has exhausted the small virtual
63 * address space available on 32-bit systems. Retrying the
64 * allocation immediately will only result in spinning on the
65 * virtual address space lock. It is better delay a second and
66 * hope that another process will free some of the address space.
67 * But the bottom line is there is not much we can actually do
68 * since we can never safely return a failure and honor the
69 * Solaris semantics.
70 */
71 while (1) {
72 ptr = __vmalloc(size, flags | __GFP_HIGHMEM, PAGE_KERNEL);
73 if (unlikely((ptr == NULL) && (flags & __GFP_WAIT))) {
74 set_current_state(TASK_INTERRUPTIBLE);
75 schedule_timeout(HZ);
76 } else {
77 break;
78 }
79 }
80
81 return (ptr);
82 }
83
84 static inline void *
85 vzalloc_nofail(size_t size, gfp_t flags)
86 {
87 void *ptr;
88
89 ptr = vmalloc_nofail(size, flags);
90 if (ptr)
91 memset(ptr, 0, (size));
92
93 return (ptr);
94 }
95
96 #ifdef DEBUG_KMEM
97
98 /*
99 * Memory accounting functions to be used only when DEBUG_KMEM is set.
100 */
101 #ifdef HAVE_ATOMIC64_T
102
103 #define vmem_alloc_used_add(size) atomic64_add(size, &vmem_alloc_used)
104 #define vmem_alloc_used_sub(size) atomic64_sub(size, &vmem_alloc_used)
105 #define vmem_alloc_used_read() atomic64_read(&vmem_alloc_used)
106 #define vmem_alloc_used_set(size) atomic64_set(&vmem_alloc_used, size)
107
108 extern atomic64_t vmem_alloc_used;
109 extern unsigned long long vmem_alloc_max;
110
111 #else /* HAVE_ATOMIC64_T */
112
113 #define vmem_alloc_used_add(size) atomic_add(size, &vmem_alloc_used)
114 #define vmem_alloc_used_sub(size) atomic_sub(size, &vmem_alloc_used)
115 #define vmem_alloc_used_read() atomic_read(&vmem_alloc_used)
116 #define vmem_alloc_used_set(size) atomic_set(&vmem_alloc_used, size)
117
118 extern atomic_t vmem_alloc_used;
119 extern unsigned long long vmem_alloc_max;
120
121 #endif /* HAVE_ATOMIC64_T */
122
123 #ifdef DEBUG_KMEM_TRACKING
124 /*
125 * DEBUG_KMEM && DEBUG_KMEM_TRACKING
126 *
127 * The maximum level of memory debugging. All memory will be accounted
128 * for and each allocation will be explicitly tracked. Any allocation
129 * which is leaked will be reported on module unload and the exact location
130 * where that memory was allocation will be reported. This level of memory
131 * tracking will have a significant impact on performance and should only
132 * be enabled for debugging. This feature may be enabled by passing
133 * --enable-debug-kmem-tracking to configure.
134 */
135 #define vmem_alloc(sz, fl) vmem_alloc_track((sz), (fl), \
136 __FUNCTION__, __LINE__)
137 #define vmem_zalloc(sz, fl) vmem_alloc_track((sz), (fl)|__GFP_ZERO,\
138 __FUNCTION__, __LINE__)
139 #define vmem_free(ptr, sz) vmem_free_track((ptr), (sz))
140
141 extern void *kmem_alloc_track(size_t, int, const char *, int, int, int);
142 extern void kmem_free_track(const void *, size_t);
143 extern void *vmem_alloc_track(size_t, int, const char *, int);
144 extern void vmem_free_track(const void *, size_t);
145
146 #else /* DEBUG_KMEM_TRACKING */
147 /*
148 * DEBUG_KMEM && !DEBUG_KMEM_TRACKING
149 *
150 * The default build will set DEBUG_KEM. This provides basic memory
151 * accounting with little to no impact on performance. When the module
152 * is unloaded in any memory was leaked the total number of leaked bytes
153 * will be reported on the console. To disable this basic accounting
154 * pass the --disable-debug-kmem option to configure.
155 */
156 #define vmem_alloc(sz, fl) vmem_alloc_debug((sz), (fl), \
157 __FUNCTION__, __LINE__)
158 #define vmem_zalloc(sz, fl) vmem_alloc_debug((sz), (fl)|__GFP_ZERO,\
159 __FUNCTION__, __LINE__)
160 #define vmem_free(ptr, sz) vmem_free_debug((ptr), (sz))
161
162 extern void *vmem_alloc_debug(size_t, int, const char *, int);
163 extern void vmem_free_debug(const void *, size_t);
164
165 #endif /* DEBUG_KMEM_TRACKING */
166 #else /* DEBUG_KMEM */
167 /*
168 * !DEBUG_KMEM && !DEBUG_KMEM_TRACKING
169 *
170 * All debugging is disabled. There will be no overhead even for
171 * minimal memory accounting. To enable basic accounting pass the
172 * --enable-debug-kmem option to configure.
173 */
174 #define vmem_alloc(sz, fl) vmalloc_nofail((sz), (fl))
175 #define vmem_zalloc(sz, fl) vzalloc_nofail((sz), (fl))
176 #define vmem_free(ptr, sz) ((void)(sz), vfree(ptr))
177
178 #endif /* DEBUG_KMEM */
179
180 int spl_vmem_init(void);
181 void spl_vmem_fini(void);
182
183 #endif /* _SPL_VMEM_H */