File: | libglusterfs/src/mem-pool.c |
Location: | line 61, column 9 |
Description: | Dereference of null pointer |
1 | /* | |||||
2 | Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com> | |||||
3 | This file is part of GlusterFS. | |||||
4 | ||||||
5 | This file is licensed to you under your choice of the GNU Lesser | |||||
6 | General Public License, version 3 or any later version (LGPLv3 or | |||||
7 | later), or the GNU General Public License, version 2 (GPLv2), in all | |||||
8 | cases as published by the Free Software Foundation. | |||||
9 | */ | |||||
10 | ||||||
11 | #include "mem-pool.h" | |||||
12 | #include "logging.h" | |||||
13 | #include "xlator.h" | |||||
14 | #include <stdlib.h> | |||||
15 | #include <stdarg.h> | |||||
16 | ||||||
17 | #define GF_MEM_POOL_LIST_BOUNDARY(sizeof(struct list_head)) (sizeof(struct list_head)) | |||||
18 | #define GF_MEM_POOL_PTR(sizeof(struct mem_pool*)) (sizeof(struct mem_pool*)) | |||||
19 | #define GF_MEM_POOL_PAD_BOUNDARY((sizeof(struct list_head)) + (sizeof(struct mem_pool*)) + sizeof (int)) (GF_MEM_POOL_LIST_BOUNDARY(sizeof(struct list_head)) + GF_MEM_POOL_PTR(sizeof(struct mem_pool*)) + sizeof(int)) | |||||
20 | #define mem_pool_chunkhead2ptr(head)((head) + ((sizeof(struct list_head)) + (sizeof(struct mem_pool *)) + sizeof(int))) ((head) + GF_MEM_POOL_PAD_BOUNDARY((sizeof(struct list_head)) + (sizeof(struct mem_pool*)) + sizeof (int))) | |||||
21 | #define mem_pool_ptr2chunkhead(ptr)((ptr) - ((sizeof(struct list_head)) + (sizeof(struct mem_pool *)) + sizeof(int))) ((ptr) - GF_MEM_POOL_PAD_BOUNDARY((sizeof(struct list_head)) + (sizeof(struct mem_pool*)) + sizeof (int))) | |||||
22 | #define is_mem_chunk_in_use(ptr)(*ptr == 1) (*ptr == 1) | |||||
23 | #define mem_pool_from_ptr(ptr)((ptr) + (sizeof(struct list_head))) ((ptr) + GF_MEM_POOL_LIST_BOUNDARY(sizeof(struct list_head))) | |||||
24 | ||||||
25 | #define GF_MEM_HEADER_SIZE(4 + sizeof (size_t) + sizeof (xlator_t *) + 4 + 8) (4 + sizeof (size_t) + sizeof (xlator_t *) + 4 + 8) | |||||
26 | #define GF_MEM_TRAILER_SIZE8 8 | |||||
27 | ||||||
28 | #define GF_MEM_HEADER_MAGIC0xCAFEBABE 0xCAFEBABE | |||||
29 | #define GF_MEM_TRAILER_MAGIC0xBAADF00D 0xBAADF00D | |||||
30 | ||||||
31 | #define GLUSTERFS_ENV_MEM_ACCT_STR"GLUSTERFS_DISABLE_MEM_ACCT" "GLUSTERFS_DISABLE_MEM_ACCT" | |||||
32 | ||||||
33 | void | |||||
34 | gf_mem_acct_enable_set (void *data) | |||||
35 | { | |||||
36 | glusterfs_ctx_t *ctx = NULL((void*)0); | |||||
37 | ||||||
38 | ctx = data; | |||||
39 | ||||||
40 | GF_ASSERT (ctx)do { if (!(ctx)) { do { do { if (0) printf ("Assertion failed: " "ctx"); } while (0); _gf_log_callingfn ("", "mem-pool.c", __FUNCTION__ , 40, GF_LOG_ERROR, "Assertion failed: " "ctx"); } while (0); } } while (0); | |||||
41 | ||||||
42 | ctx->mem_acct_enable = 1; | |||||
43 | ||||||
44 | return; | |||||
45 | } | |||||
46 | ||||||
47 | void | |||||
48 | gf_mem_set_acct_info (xlator_t *xl, char **alloc_ptr, | |||||
49 | size_t size, uint32_t type) | |||||
50 | { | |||||
51 | ||||||
52 | char *ptr = NULL((void*)0); | |||||
53 | ||||||
54 | if (!alloc_ptr) | |||||
55 | return; | |||||
56 | ||||||
57 | ptr = (char *) (*alloc_ptr); | |||||
58 | ||||||
59 | GF_ASSERT (xl != NULL)do { if (!(xl != ((void*)0))) { do { do { if (0) printf ("Assertion failed: " "xl != NULL"); } while (0); _gf_log_callingfn ("", "mem-pool.c" , __FUNCTION__, 59, GF_LOG_ERROR, "Assertion failed: " "xl != NULL" ); } while (0); } } while (0); | |||||
60 | ||||||
61 | GF_ASSERT (xl->mem_acct.rec != NULL)do { if (!(xl->mem_acct.rec != ((void*)0))) { do { do { if (0) printf ("Assertion failed: " "xl->mem_acct.rec != NULL" ); } while (0); _gf_log_callingfn ("", "mem-pool.c", __FUNCTION__ , 61, GF_LOG_ERROR, "Assertion failed: " "xl->mem_acct.rec != NULL" ); } while (0); } } while (0); | |||||
| ||||||
62 | ||||||
63 | GF_ASSERT (type <= xl->mem_acct.num_types)do { if (!(type <= xl->mem_acct.num_types)) { do { do { if (0) printf ("Assertion failed: " "type <= xl->mem_acct.num_types" ); } while (0); _gf_log_callingfn ("", "mem-pool.c", __FUNCTION__ , 63, GF_LOG_ERROR, "Assertion failed: " "type <= xl->mem_acct.num_types" ); } while (0); } } while (0); | |||||
64 | ||||||
65 | LOCK(&xl->mem_acct.rec[type].lock)pthread_spin_lock (&xl->mem_acct.rec[type].lock); | |||||
66 | { | |||||
67 | xl->mem_acct.rec[type].size += size; | |||||
68 | xl->mem_acct.rec[type].num_allocs++; | |||||
69 | xl->mem_acct.rec[type].total_allocs++; | |||||
70 | xl->mem_acct.rec[type].max_size = | |||||
71 | max (xl->mem_acct.rec[type].max_size,((xl->mem_acct.rec[type].max_size)>(xl->mem_acct.rec [type].size)?(xl->mem_acct.rec[type].max_size):(xl->mem_acct .rec[type].size)) | |||||
72 | xl->mem_acct.rec[type].size)((xl->mem_acct.rec[type].max_size)>(xl->mem_acct.rec [type].size)?(xl->mem_acct.rec[type].max_size):(xl->mem_acct .rec[type].size)); | |||||
73 | xl->mem_acct.rec[type].max_num_allocs = | |||||
74 | max (xl->mem_acct.rec[type].max_num_allocs,((xl->mem_acct.rec[type].max_num_allocs)>(xl->mem_acct .rec[type].num_allocs)?(xl->mem_acct.rec[type].max_num_allocs ):(xl->mem_acct.rec[type].num_allocs)) | |||||
75 | xl->mem_acct.rec[type].num_allocs)((xl->mem_acct.rec[type].max_num_allocs)>(xl->mem_acct .rec[type].num_allocs)?(xl->mem_acct.rec[type].max_num_allocs ):(xl->mem_acct.rec[type].num_allocs)); | |||||
76 | } | |||||
77 | UNLOCK(&xl->mem_acct.rec[type].lock)pthread_spin_unlock (&xl->mem_acct.rec[type].lock); | |||||
78 | ||||||
79 | *(uint32_t *)(ptr) = type; | |||||
80 | ptr = ptr + 4; | |||||
81 | memcpy (ptr, &size, sizeof(size_t)); | |||||
82 | ptr += sizeof (size_t); | |||||
83 | memcpy (ptr, &xl, sizeof(xlator_t *)); | |||||
84 | ptr += sizeof (xlator_t *); | |||||
85 | *(uint32_t *)(ptr) = GF_MEM_HEADER_MAGIC0xCAFEBABE; | |||||
86 | ptr = ptr + 4; | |||||
87 | ptr = ptr + 8; //padding | |||||
88 | *(uint32_t *) (ptr + size) = GF_MEM_TRAILER_MAGIC0xBAADF00D; | |||||
89 | ||||||
90 | *alloc_ptr = (void *)ptr; | |||||
91 | return; | |||||
92 | } | |||||
93 | ||||||
94 | ||||||
95 | void * | |||||
96 | __gf_calloc (size_t nmemb, size_t size, uint32_t type) | |||||
97 | { | |||||
98 | size_t tot_size = 0; | |||||
99 | size_t req_size = 0; | |||||
100 | char *ptr = NULL((void*)0); | |||||
101 | xlator_t *xl = NULL((void*)0); | |||||
102 | ||||||
103 | if (!THIS(*__glusterfs_this_location())->ctx->mem_acct_enable) | |||||
104 | return CALLOC (nmemb, size)__gf_default_calloc(nmemb,size); | |||||
105 | ||||||
106 | xl = THIS(*__glusterfs_this_location()); | |||||
107 | ||||||
108 | req_size = nmemb * size; | |||||
109 | tot_size = req_size + GF_MEM_HEADER_SIZE(4 + sizeof (size_t) + sizeof (xlator_t *) + 4 + 8) + GF_MEM_TRAILER_SIZE8; | |||||
110 | ||||||
111 | ptr = calloc (1, tot_size); | |||||
112 | ||||||
113 | if (!ptr) { | |||||
114 | gf_log_nomem ("", GF_LOG_ALERT, tot_size)do { _gf_log_nomem ("", "mem-pool.c", __FUNCTION__, 114, GF_LOG_ALERT , tot_size); } while (0); | |||||
115 | return NULL((void*)0); | |||||
116 | } | |||||
117 | gf_mem_set_acct_info (xl, &ptr, req_size, type); | |||||
118 | ||||||
119 | return (void *)ptr; | |||||
120 | } | |||||
121 | ||||||
122 | void * | |||||
123 | __gf_malloc (size_t size, uint32_t type) | |||||
124 | { | |||||
125 | size_t tot_size = 0; | |||||
126 | char *ptr = NULL((void*)0); | |||||
127 | xlator_t *xl = NULL((void*)0); | |||||
128 | ||||||
129 | if (!THIS(*__glusterfs_this_location())->ctx->mem_acct_enable) | |||||
130 | return MALLOC (size)__gf_default_malloc(size); | |||||
131 | ||||||
132 | xl = THIS(*__glusterfs_this_location()); | |||||
133 | ||||||
134 | tot_size = size + GF_MEM_HEADER_SIZE(4 + sizeof (size_t) + sizeof (xlator_t *) + 4 + 8) + GF_MEM_TRAILER_SIZE8; | |||||
135 | ||||||
136 | ptr = malloc (tot_size); | |||||
137 | if (!ptr) { | |||||
138 | gf_log_nomem ("", GF_LOG_ALERT, tot_size)do { _gf_log_nomem ("", "mem-pool.c", __FUNCTION__, 138, GF_LOG_ALERT , tot_size); } while (0); | |||||
139 | return NULL((void*)0); | |||||
140 | } | |||||
141 | gf_mem_set_acct_info (xl, &ptr, size, type); | |||||
142 | ||||||
143 | return (void *)ptr; | |||||
144 | } | |||||
145 | ||||||
146 | void * | |||||
147 | __gf_realloc (void *ptr, size_t size) | |||||
148 | { | |||||
149 | size_t tot_size = 0; | |||||
150 | char *orig_ptr = NULL((void*)0); | |||||
151 | xlator_t *xl = NULL((void*)0); | |||||
152 | uint32_t type = 0; | |||||
153 | ||||||
154 | if (!THIS(*__glusterfs_this_location())->ctx->mem_acct_enable) | |||||
155 | return REALLOC (ptr, size)__gf_default_realloc(ptr,size); | |||||
156 | ||||||
157 | tot_size = size + GF_MEM_HEADER_SIZE(4 + sizeof (size_t) + sizeof (xlator_t *) + 4 + 8) + GF_MEM_TRAILER_SIZE8; | |||||
158 | ||||||
159 | orig_ptr = (char *)ptr - 8 - 4; | |||||
160 | ||||||
161 | GF_ASSERT (*(uint32_t *)orig_ptr == GF_MEM_HEADER_MAGIC)do { if (!(*(uint32_t *)orig_ptr == 0xCAFEBABE)) { do { do { if (0) printf ("Assertion failed: " "*(uint32_t *)orig_ptr == GF_MEM_HEADER_MAGIC" ); } while (0); _gf_log_callingfn ("", "mem-pool.c", __FUNCTION__ , 161, GF_LOG_ERROR, "Assertion failed: " "*(uint32_t *)orig_ptr == GF_MEM_HEADER_MAGIC" ); } while (0); } } while (0); | |||||
162 | ||||||
163 | orig_ptr = orig_ptr - sizeof(xlator_t *); | |||||
164 | xl = *((xlator_t **)orig_ptr); | |||||
165 | ||||||
166 | orig_ptr = (char *)ptr - GF_MEM_HEADER_SIZE(4 + sizeof (size_t) + sizeof (xlator_t *) + 4 + 8); | |||||
167 | type = *(uint32_t *)orig_ptr; | |||||
168 | ||||||
169 | ptr = realloc (orig_ptr, tot_size); | |||||
170 | if (!ptr) { | |||||
171 | gf_log_nomem ("", GF_LOG_ALERT, tot_size)do { _gf_log_nomem ("", "mem-pool.c", __FUNCTION__, 171, GF_LOG_ALERT , tot_size); } while (0); | |||||
172 | return NULL((void*)0); | |||||
173 | } | |||||
174 | ||||||
175 | gf_mem_set_acct_info (xl, (char **)&ptr, size, type); | |||||
176 | ||||||
177 | return (void *)ptr; | |||||
178 | } | |||||
179 | ||||||
180 | int | |||||
181 | gf_vasprintf (char **string_ptr, const char *format, va_list arg) | |||||
182 | { | |||||
183 | va_list arg_save; | |||||
184 | char *str = NULL((void*)0); | |||||
185 | int size = 0; | |||||
186 | int rv = 0; | |||||
187 | ||||||
188 | if (!string_ptr || !format) | |||||
189 | return -1; | |||||
190 | ||||||
191 | va_copy (arg_save, arg)__builtin_va_copy(arg_save, arg); | |||||
192 | ||||||
193 | size = vsnprintf (NULL((void*)0), 0, format, arg); | |||||
194 | size++; | |||||
195 | str = GF_MALLOC (size, gf_common_mt_asprintf)__gf_malloc (size, gf_common_mt_asprintf); | |||||
196 | if (str == NULL((void*)0)) { | |||||
197 | /* log is done in GF_MALLOC itself */ | |||||
198 | return -1; | |||||
199 | } | |||||
200 | rv = vsnprintf (str, size, format, arg_save); | |||||
201 | ||||||
202 | *string_ptr = str; | |||||
203 | return (rv); | |||||
204 | } | |||||
205 | ||||||
206 | int | |||||
207 | gf_asprintf (char **string_ptr, const char *format, ...) | |||||
208 | { | |||||
209 | va_list arg; | |||||
210 | int rv = 0; | |||||
211 | ||||||
212 | va_start (arg, format)__builtin_va_start(arg, format); | |||||
213 | rv = gf_vasprintf (string_ptr, format, arg); | |||||
214 | va_end (arg)__builtin_va_end(arg); | |||||
215 | ||||||
216 | return rv; | |||||
217 | } | |||||
218 | ||||||
219 | void | |||||
220 | __gf_free (void *free_ptr) | |||||
221 | { | |||||
222 | size_t req_size = 0; | |||||
223 | char *ptr = NULL((void*)0); | |||||
224 | uint32_t type = 0; | |||||
225 | xlator_t *xl = NULL((void*)0); | |||||
226 | ||||||
227 | if (!THIS(*__glusterfs_this_location())->ctx->mem_acct_enable) { | |||||
228 | FREE (free_ptr)if (free_ptr != ((void*)0)) { free ((void *)free_ptr); free_ptr = (void *)0xeeeeeeee; }; | |||||
229 | return; | |||||
230 | } | |||||
231 | ||||||
232 | if (!free_ptr) | |||||
233 | return; | |||||
234 | ||||||
235 | ptr = (char *)free_ptr - 8 - 4; | |||||
236 | ||||||
237 | //Possible corruption, assert here | |||||
238 | GF_ASSERT (GF_MEM_HEADER_MAGIC == *(uint32_t *)ptr)do { if (!(0xCAFEBABE == *(uint32_t *)ptr)) { do { do { if (0 ) printf ("Assertion failed: " "GF_MEM_HEADER_MAGIC == *(uint32_t *)ptr" ); } while (0); _gf_log_callingfn ("", "mem-pool.c", __FUNCTION__ , 238, GF_LOG_ERROR, "Assertion failed: " "GF_MEM_HEADER_MAGIC == *(uint32_t *)ptr" ); } while (0); } } while (0); | |||||
239 | ||||||
240 | *(uint32_t *)ptr = 0; | |||||
241 | ||||||
242 | ptr = ptr - sizeof(xlator_t *); | |||||
243 | memcpy (&xl, ptr, sizeof(xlator_t *)); | |||||
244 | ||||||
245 | //gf_free expects xl to be available | |||||
246 | GF_ASSERT (xl != NULL)do { if (!(xl != ((void*)0))) { do { do { if (0) printf ("Assertion failed: " "xl != NULL"); } while (0); _gf_log_callingfn ("", "mem-pool.c" , __FUNCTION__, 246, GF_LOG_ERROR, "Assertion failed: " "xl != NULL" ); } while (0); } } while (0); | |||||
247 | ||||||
248 | if (!xl->mem_acct.rec) { | |||||
249 | ptr = (char *)free_ptr - GF_MEM_HEADER_SIZE(4 + sizeof (size_t) + sizeof (xlator_t *) + 4 + 8); | |||||
250 | goto free; | |||||
251 | } | |||||
252 | ||||||
253 | ||||||
254 | ptr = ptr - sizeof(size_t); | |||||
255 | memcpy (&req_size, ptr, sizeof (size_t)); | |||||
256 | ptr = ptr - 4; | |||||
257 | type = *(uint32_t *)ptr; | |||||
258 | ||||||
259 | // This points to a memory overrun | |||||
260 | GF_ASSERT (GF_MEM_TRAILER_MAGIC ==do { if (!(0xBAADF00D == *(uint32_t *)((char *)free_ptr + req_size ))) { do { do { if (0) printf ("Assertion failed: " "GF_MEM_TRAILER_MAGIC == *(uint32_t *)((char *)free_ptr + req_size)" ); } while (0); _gf_log_callingfn ("", "mem-pool.c", __FUNCTION__ , 261, GF_LOG_ERROR, "Assertion failed: " "GF_MEM_TRAILER_MAGIC == *(uint32_t *)((char *)free_ptr + req_size)" ); } while (0); } } while (0) | |||||
261 | *(uint32_t *)((char *)free_ptr + req_size))do { if (!(0xBAADF00D == *(uint32_t *)((char *)free_ptr + req_size ))) { do { do { if (0) printf ("Assertion failed: " "GF_MEM_TRAILER_MAGIC == *(uint32_t *)((char *)free_ptr + req_size)" ); } while (0); _gf_log_callingfn ("", "mem-pool.c", __FUNCTION__ , 261, GF_LOG_ERROR, "Assertion failed: " "GF_MEM_TRAILER_MAGIC == *(uint32_t *)((char *)free_ptr + req_size)" ); } while (0); } } while (0); | |||||
262 | ||||||
263 | *(uint32_t *) ((char *)free_ptr + req_size) = 0; | |||||
264 | ||||||
265 | LOCK (&xl->mem_acct.rec[type].lock)pthread_spin_lock (&xl->mem_acct.rec[type].lock); | |||||
266 | { | |||||
267 | xl->mem_acct.rec[type].size -= req_size; | |||||
268 | xl->mem_acct.rec[type].num_allocs--; | |||||
269 | } | |||||
270 | UNLOCK (&xl->mem_acct.rec[type].lock)pthread_spin_unlock (&xl->mem_acct.rec[type].lock); | |||||
271 | free: | |||||
272 | FREE (ptr)if (ptr != ((void*)0)) { free ((void *)ptr); ptr = (void *)0xeeeeeeee ; }; | |||||
273 | } | |||||
274 | ||||||
275 | ||||||
276 | ||||||
277 | struct mem_pool * | |||||
278 | mem_pool_new_fn (unsigned long sizeof_type, | |||||
279 | unsigned long count, char *name) | |||||
280 | { | |||||
281 | struct mem_pool *mem_pool = NULL((void*)0); | |||||
282 | unsigned long padded_sizeof_type = 0; | |||||
283 | void *pool = NULL((void*)0); | |||||
284 | int i = 0; | |||||
285 | int ret = 0; | |||||
286 | struct list_head *list = NULL((void*)0); | |||||
287 | glusterfs_ctx_t *ctx = NULL((void*)0); | |||||
288 | ||||||
289 | if (!sizeof_type || !count) { | |||||
| ||||||
290 | gf_log_callingfn ("mem-pool", GF_LOG_ERROR, "invalid argument")do { do { if (0) printf ("invalid argument"); } while (0); _gf_log_callingfn ("mem-pool", "mem-pool.c", __FUNCTION__, 290, GF_LOG_ERROR, "invalid argument" ); } while (0); | |||||
291 | return NULL((void*)0); | |||||
292 | } | |||||
293 | padded_sizeof_type = sizeof_type + GF_MEM_POOL_PAD_BOUNDARY((sizeof(struct list_head)) + (sizeof(struct mem_pool*)) + sizeof (int)); | |||||
294 | ||||||
295 | mem_pool = GF_CALLOC (sizeof (*mem_pool), 1, gf_common_mt_mem_pool)__gf_calloc (sizeof (*mem_pool), 1, gf_common_mt_mem_pool); | |||||
296 | if (!mem_pool) | |||||
297 | return NULL((void*)0); | |||||
298 | ||||||
299 | ret = gf_asprintf (&mem_pool->name, "%s:%s", THIS(*__glusterfs_this_location())->name, name); | |||||
300 | if (ret < 0) | |||||
301 | return NULL((void*)0); | |||||
302 | ||||||
303 | if (!mem_pool->name) { | |||||
304 | GF_FREE (mem_pool)__gf_free (mem_pool); | |||||
305 | return NULL((void*)0); | |||||
306 | } | |||||
307 | ||||||
308 | LOCK_INIT (&mem_pool->lock)pthread_spin_init (&mem_pool->lock, 0); | |||||
309 | INIT_LIST_HEAD (&mem_pool->list)do { (&mem_pool->list)->next = (&mem_pool->list )->prev = &mem_pool->list; } while (0); | |||||
310 | INIT_LIST_HEAD (&mem_pool->global_list)do { (&mem_pool->global_list)->next = (&mem_pool ->global_list)->prev = &mem_pool->global_list; } while (0); | |||||
311 | ||||||
312 | mem_pool->padded_sizeof_type = padded_sizeof_type; | |||||
313 | mem_pool->cold_count = count; | |||||
314 | mem_pool->real_sizeof_type = sizeof_type; | |||||
315 | ||||||
316 | pool = GF_CALLOC (count, padded_sizeof_type, gf_common_mt_long)__gf_calloc (count, padded_sizeof_type, gf_common_mt_long); | |||||
317 | if (!pool) { | |||||
318 | GF_FREE (mem_pool->name)__gf_free (mem_pool->name); | |||||
319 | GF_FREE (mem_pool)__gf_free (mem_pool); | |||||
320 | return NULL((void*)0); | |||||
321 | } | |||||
322 | ||||||
323 | for (i = 0; i < count; i++) { | |||||
324 | list = pool + (i * (padded_sizeof_type)); | |||||
325 | INIT_LIST_HEAD (list)do { (list)->next = (list)->prev = list; } while (0); | |||||
326 | list_add_tail (list, &mem_pool->list); | |||||
327 | } | |||||
328 | ||||||
329 | mem_pool->pool = pool; | |||||
330 | mem_pool->pool_end = pool + (count * (padded_sizeof_type)); | |||||
331 | ||||||
332 | /* add this pool to the global list */ | |||||
333 | ctx = THIS(*__glusterfs_this_location())->ctx; | |||||
334 | if (!ctx) | |||||
335 | goto out; | |||||
336 | ||||||
337 | list_add (&mem_pool->global_list, &ctx->mempool_list); | |||||
338 | ||||||
339 | out: | |||||
340 | return mem_pool; | |||||
341 | } | |||||
342 | ||||||
343 | void* | |||||
344 | mem_get0 (struct mem_pool *mem_pool) | |||||
345 | { | |||||
346 | void *ptr = NULL((void*)0); | |||||
347 | ||||||
348 | if (!mem_pool) { | |||||
349 | gf_log_callingfn ("mem-pool", GF_LOG_ERROR, "invalid argument")do { do { if (0) printf ("invalid argument"); } while (0); _gf_log_callingfn ("mem-pool", "mem-pool.c", __FUNCTION__, 349, GF_LOG_ERROR, "invalid argument" ); } while (0); | |||||
350 | return NULL((void*)0); | |||||
351 | } | |||||
352 | ||||||
353 | ptr = mem_get(mem_pool); | |||||
354 | ||||||
355 | if (ptr) | |||||
356 | memset(ptr, 0, mem_pool->real_sizeof_type); | |||||
357 | ||||||
358 | return ptr; | |||||
359 | } | |||||
360 | ||||||
361 | void * | |||||
362 | mem_get (struct mem_pool *mem_pool) | |||||
363 | { | |||||
364 | struct list_head *list = NULL((void*)0); | |||||
365 | void *ptr = NULL((void*)0); | |||||
366 | int *in_use = NULL((void*)0); | |||||
367 | struct mem_pool **pool_ptr = NULL((void*)0); | |||||
368 | ||||||
369 | if (!mem_pool) { | |||||
370 | gf_log_callingfn ("mem-pool", GF_LOG_ERROR, "invalid argument")do { do { if (0) printf ("invalid argument"); } while (0); _gf_log_callingfn ("mem-pool", "mem-pool.c", __FUNCTION__, 370, GF_LOG_ERROR, "invalid argument" ); } while (0); | |||||
371 | return NULL((void*)0); | |||||
372 | } | |||||
373 | ||||||
374 | LOCK (&mem_pool->lock)pthread_spin_lock (&mem_pool->lock); | |||||
375 | { | |||||
376 | mem_pool->alloc_count++; | |||||
377 | if (mem_pool->cold_count) { | |||||
378 | list = mem_pool->list.next; | |||||
379 | list_del (list); | |||||
380 | ||||||
381 | mem_pool->hot_count++; | |||||
382 | mem_pool->cold_count--; | |||||
383 | ||||||
384 | if (mem_pool->max_alloc < mem_pool->hot_count) | |||||
385 | mem_pool->max_alloc = mem_pool->hot_count; | |||||
386 | ||||||
387 | ptr = list; | |||||
388 | in_use = (ptr + GF_MEM_POOL_LIST_BOUNDARY(sizeof(struct list_head)) + | |||||
389 | GF_MEM_POOL_PTR(sizeof(struct mem_pool*))); | |||||
390 | *in_use = 1; | |||||
391 | ||||||
392 | goto fwd_addr_out; | |||||
393 | } | |||||
394 | ||||||
395 | /* This is a problem area. If we've run out of | |||||
396 | * chunks in our slab above, we need to allocate | |||||
397 | * enough memory to service this request. | |||||
398 | * The problem is, these individual chunks will fail | |||||
399 | * the first address range check in __is_member. Now, since | |||||
400 | * we're not allocating a full second slab, we wont have | |||||
401 | * enough info perform the range check in __is_member. | |||||
402 | * | |||||
403 | * I am working around this by performing a regular allocation | |||||
404 | * , just the way the caller would've done when not using the | |||||
405 | * mem-pool. That also means, we're not padding the size with | |||||
406 | * the list_head structure because, this will not be added to | |||||
407 | * the list of chunks that belong to the mem-pool allocated | |||||
408 | * initially. | |||||
409 | * | |||||
410 | * This is the best we can do without adding functionality for | |||||
411 | * managing multiple slabs. That does not interest us at present | |||||
412 | * because it is too much work knowing that a better slab | |||||
413 | * allocator is coming RSN. | |||||
414 | */ | |||||
415 | mem_pool->pool_misses++; | |||||
416 | mem_pool->curr_stdalloc++; | |||||
417 | if (mem_pool->max_stdalloc < mem_pool->curr_stdalloc) | |||||
418 | mem_pool->max_stdalloc = mem_pool->curr_stdalloc; | |||||
419 | ptr = GF_CALLOC (1, mem_pool->padded_sizeof_type,__gf_calloc (1, mem_pool->padded_sizeof_type, gf_common_mt_mem_pool ) | |||||
420 | gf_common_mt_mem_pool)__gf_calloc (1, mem_pool->padded_sizeof_type, gf_common_mt_mem_pool ); | |||||
421 | gf_log_callingfn ("mem-pool", GF_LOG_DEBUG, "Mem pool is full. "do { do { if (0) printf ("Mem pool is full. " "Callocing mem" ); } while (0); _gf_log_callingfn ("mem-pool", "mem-pool.c", __FUNCTION__ , 422, GF_LOG_DEBUG, "Mem pool is full. " "Callocing mem"); } while (0) | |||||
422 | "Callocing mem")do { do { if (0) printf ("Mem pool is full. " "Callocing mem" ); } while (0); _gf_log_callingfn ("mem-pool", "mem-pool.c", __FUNCTION__ , 422, GF_LOG_DEBUG, "Mem pool is full. " "Callocing mem"); } while (0); | |||||
423 | ||||||
424 | /* Memory coming from the heap need not be transformed from a | |||||
425 | * chunkhead to a usable pointer since it is not coming from | |||||
426 | * the pool. | |||||
427 | */ | |||||
428 | } | |||||
429 | fwd_addr_out: | |||||
430 | pool_ptr = mem_pool_from_ptr (ptr)((ptr) + (sizeof(struct list_head))); | |||||
431 | *pool_ptr = (struct mem_pool *)mem_pool; | |||||
432 | ptr = mem_pool_chunkhead2ptr (ptr)((ptr) + ((sizeof(struct list_head)) + (sizeof(struct mem_pool *)) + sizeof(int))); | |||||
433 | UNLOCK (&mem_pool->lock)pthread_spin_unlock (&mem_pool->lock); | |||||
434 | ||||||
435 | return ptr; | |||||
436 | } | |||||
437 | ||||||
438 | ||||||
439 | static int | |||||
440 | __is_member (struct mem_pool *pool, void *ptr) | |||||
441 | { | |||||
442 | if (!pool || !ptr) { | |||||
443 | gf_log_callingfn ("mem-pool", GF_LOG_ERROR, "invalid argument")do { do { if (0) printf ("invalid argument"); } while (0); _gf_log_callingfn ("mem-pool", "mem-pool.c", __FUNCTION__, 443, GF_LOG_ERROR, "invalid argument" ); } while (0); | |||||
444 | return -1; | |||||
445 | } | |||||
446 | ||||||
447 | if (ptr < pool->pool || ptr >= pool->pool_end) | |||||
448 | return 0; | |||||
449 | ||||||
450 | if ((mem_pool_ptr2chunkhead (ptr)((ptr) - ((sizeof(struct list_head)) + (sizeof(struct mem_pool *)) + sizeof(int))) - pool->pool) | |||||
451 | % pool->padded_sizeof_type) | |||||
452 | return -1; | |||||
453 | ||||||
454 | return 1; | |||||
455 | } | |||||
456 | ||||||
457 | ||||||
458 | void | |||||
459 | mem_put (void *ptr) | |||||
460 | { | |||||
461 | struct list_head *list = NULL((void*)0); | |||||
462 | int *in_use = NULL((void*)0); | |||||
463 | void *head = NULL((void*)0); | |||||
464 | struct mem_pool **tmp = NULL((void*)0); | |||||
465 | struct mem_pool *pool = NULL((void*)0); | |||||
466 | ||||||
467 | if (!ptr) { | |||||
468 | gf_log_callingfn ("mem-pool", GF_LOG_ERROR, "invalid argument")do { do { if (0) printf ("invalid argument"); } while (0); _gf_log_callingfn ("mem-pool", "mem-pool.c", __FUNCTION__, 468, GF_LOG_ERROR, "invalid argument" ); } while (0); | |||||
469 | return; | |||||
470 | } | |||||
471 | ||||||
472 | list = head = mem_pool_ptr2chunkhead (ptr)((ptr) - ((sizeof(struct list_head)) + (sizeof(struct mem_pool *)) + sizeof(int))); | |||||
473 | tmp = mem_pool_from_ptr (head)((head) + (sizeof(struct list_head))); | |||||
474 | if (!tmp) { | |||||
475 | gf_log_callingfn ("mem-pool", GF_LOG_ERROR,do { do { if (0) printf ("ptr header is corrupted"); } while ( 0); _gf_log_callingfn ("mem-pool", "mem-pool.c", __FUNCTION__ , 476, GF_LOG_ERROR, "ptr header is corrupted"); } while (0) | |||||
476 | "ptr header is corrupted")do { do { if (0) printf ("ptr header is corrupted"); } while ( 0); _gf_log_callingfn ("mem-pool", "mem-pool.c", __FUNCTION__ , 476, GF_LOG_ERROR, "ptr header is corrupted"); } while (0); | |||||
477 | return; | |||||
478 | } | |||||
479 | ||||||
480 | pool = *tmp; | |||||
481 | if (!pool) { | |||||
482 | gf_log_callingfn ("mem-pool", GF_LOG_ERROR,do { do { if (0) printf ("mem-pool ptr is NULL"); } while (0) ; _gf_log_callingfn ("mem-pool", "mem-pool.c", __FUNCTION__, 483 , GF_LOG_ERROR, "mem-pool ptr is NULL"); } while (0) | |||||
483 | "mem-pool ptr is NULL")do { do { if (0) printf ("mem-pool ptr is NULL"); } while (0) ; _gf_log_callingfn ("mem-pool", "mem-pool.c", __FUNCTION__, 483 , GF_LOG_ERROR, "mem-pool ptr is NULL"); } while (0); | |||||
484 | return; | |||||
485 | } | |||||
486 | LOCK (&pool->lock)pthread_spin_lock (&pool->lock); | |||||
487 | { | |||||
488 | ||||||
489 | switch (__is_member (pool, ptr)) | |||||
490 | { | |||||
491 | case 1: | |||||
492 | in_use = (head + GF_MEM_POOL_LIST_BOUNDARY(sizeof(struct list_head)) + | |||||
493 | GF_MEM_POOL_PTR(sizeof(struct mem_pool*))); | |||||
494 | if (!is_mem_chunk_in_use(in_use)(*in_use == 1)) { | |||||
495 | gf_log_callingfn ("mem-pool", GF_LOG_CRITICAL,do { do { if (0) printf ("mem_put called on freed ptr %p of mem " "pool %p", ptr, pool); } while (0); _gf_log_callingfn ("mem-pool" , "mem-pool.c", __FUNCTION__, 497, GF_LOG_CRITICAL, "mem_put called on freed ptr %p of mem " "pool %p", ptr, pool); } while (0) | |||||
496 | "mem_put called on freed ptr %p of mem "do { do { if (0) printf ("mem_put called on freed ptr %p of mem " "pool %p", ptr, pool); } while (0); _gf_log_callingfn ("mem-pool" , "mem-pool.c", __FUNCTION__, 497, GF_LOG_CRITICAL, "mem_put called on freed ptr %p of mem " "pool %p", ptr, pool); } while (0) | |||||
497 | "pool %p", ptr, pool)do { do { if (0) printf ("mem_put called on freed ptr %p of mem " "pool %p", ptr, pool); } while (0); _gf_log_callingfn ("mem-pool" , "mem-pool.c", __FUNCTION__, 497, GF_LOG_CRITICAL, "mem_put called on freed ptr %p of mem " "pool %p", ptr, pool); } while (0); | |||||
498 | break; | |||||
499 | } | |||||
500 | pool->hot_count--; | |||||
501 | pool->cold_count++; | |||||
502 | *in_use = 0; | |||||
503 | list_add (list, &pool->list); | |||||
504 | break; | |||||
505 | case -1: | |||||
506 | /* For some reason, the address given is within | |||||
507 | * the address range of the mem-pool but does not align | |||||
508 | * with the expected start of a chunk that includes | |||||
509 | * the list headers also. Sounds like a problem in | |||||
510 | * layers of clouds up above us. ;) | |||||
511 | */ | |||||
512 | abort (); | |||||
513 | break; | |||||
514 | case 0: | |||||
515 | /* The address is outside the range of the mem-pool. We | |||||
516 | * assume here that this address was allocated at a | |||||
517 | * point when the mem-pool was out of chunks in mem_get | |||||
518 | * or the programmer has made a mistake by calling the | |||||
519 | * wrong de-allocation interface. We do | |||||
520 | * not have enough info to distinguish between the two | |||||
521 | * situations. | |||||
522 | */ | |||||
523 | pool->curr_stdalloc--; | |||||
524 | GF_FREE (list)__gf_free (list); | |||||
525 | break; | |||||
526 | default: | |||||
527 | /* log error */ | |||||
528 | break; | |||||
529 | } | |||||
530 | } | |||||
531 | UNLOCK (&pool->lock)pthread_spin_unlock (&pool->lock); | |||||
532 | } | |||||
533 | ||||||
534 | void | |||||
535 | mem_pool_destroy (struct mem_pool *pool) | |||||
536 | { | |||||
537 | if (!pool) | |||||
538 | return; | |||||
539 | ||||||
540 | gf_log (THIS->name, GF_LOG_INFO, "size=%lu max=%d total=%"PRIu64,do { do { if (0) printf ("size=%lu max=%d total=%""ll" "u", pool ->padded_sizeof_type, pool->max_alloc, pool->alloc_count ); } while (0); _gf_log ((*__glusterfs_this_location())->name , "mem-pool.c", __FUNCTION__, 541, GF_LOG_INFO, "size=%lu max=%d total=%" "ll" "u", pool->padded_sizeof_type, pool->max_alloc, pool ->alloc_count); } while (0) | |||||
541 | pool->padded_sizeof_type, pool->max_alloc, pool->alloc_count)do { do { if (0) printf ("size=%lu max=%d total=%""ll" "u", pool ->padded_sizeof_type, pool->max_alloc, pool->alloc_count ); } while (0); _gf_log ((*__glusterfs_this_location())->name , "mem-pool.c", __FUNCTION__, 541, GF_LOG_INFO, "size=%lu max=%d total=%" "ll" "u", pool->padded_sizeof_type, pool->max_alloc, pool ->alloc_count); } while (0); | |||||
542 | ||||||
543 | list_del (&pool->global_list); | |||||
544 | ||||||
545 | LOCK_DESTROY (&pool->lock)pthread_spin_destroy (&pool->lock); | |||||
546 | GF_FREE (pool->name)__gf_free (pool->name); | |||||
547 | GF_FREE (pool->pool)__gf_free (pool->pool); | |||||
548 | GF_FREE (pool)__gf_free (pool); | |||||
549 | ||||||
550 | return; | |||||
551 | } |