File: | libglusterfs/src/mem-pool.c |
Location: | line 248, column 14 |
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 | } |