]>
Commit | Line | Data |
---|---|---|
b34b9563 | 1 | /* |
e5b9b344 BB |
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/>. | |
b34b9563 | 23 | */ |
e5b9b344 BB |
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 | */ | |
b34b9563 BB |
43 | #define VMEM_ALLOC 0x01 |
44 | #define VMEM_FREE 0x02 | |
e5b9b344 BB |
45 | |
46 | #ifndef VMALLOC_TOTAL | |
b34b9563 | 47 | #define VMALLOC_TOTAL (VMALLOC_END - VMALLOC_START) |
e5b9b344 BB |
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 | ||
b34b9563 | 81 | return (ptr); |
e5b9b344 BB |
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 | ||
b34b9563 | 93 | return (ptr); |
e5b9b344 BB |
94 | } |
95 | ||
96 | #ifdef DEBUG_KMEM | |
97 | ||
98 | /* | |
99 | * Memory accounting functions to be used only when DEBUG_KMEM is set. | |
100 | */ | |
b34b9563 | 101 | #ifdef HAVE_ATOMIC64_T |
e5b9b344 | 102 | |
b34b9563 BB |
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) | |
e5b9b344 BB |
107 | |
108 | extern atomic64_t vmem_alloc_used; | |
109 | extern unsigned long long vmem_alloc_max; | |
110 | ||
b34b9563 | 111 | #else /* HAVE_ATOMIC64_T */ |
e5b9b344 | 112 | |
b34b9563 BB |
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) | |
e5b9b344 BB |
117 | |
118 | extern atomic_t vmem_alloc_used; | |
119 | extern unsigned long long vmem_alloc_max; | |
120 | ||
b34b9563 | 121 | #endif /* HAVE_ATOMIC64_T */ |
e5b9b344 | 122 | |
b34b9563 | 123 | #ifdef DEBUG_KMEM_TRACKING |
e5b9b344 BB |
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 | */ | |
b34b9563 BB |
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)) | |
e5b9b344 BB |
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 | ||
b34b9563 | 146 | #else /* DEBUG_KMEM_TRACKING */ |
e5b9b344 BB |
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 | */ | |
b34b9563 BB |
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)) | |
e5b9b344 BB |
161 | |
162 | extern void *vmem_alloc_debug(size_t, int, const char *, int); | |
163 | extern void vmem_free_debug(const void *, size_t); | |
164 | ||
b34b9563 | 165 | #endif /* DEBUG_KMEM_TRACKING */ |
e5b9b344 BB |
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 | */ | |
b34b9563 BB |
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)) | |
e5b9b344 BB |
177 | |
178 | #endif /* DEBUG_KMEM */ | |
179 | ||
180 | int spl_vmem_init(void); | |
181 | void spl_vmem_fini(void); | |
182 | ||
183 | #endif /* _SPL_VMEM_H */ |