File: | libglusterfs/src/statedump.c |
Location: | line 147, column 18 |
Description: | Null pointer passed as an argument to a 'nonnull' parameter |
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 <stdarg.h> | |||||
12 | #include "glusterfs.h" | |||||
13 | #include "logging.h" | |||||
14 | #include "iobuf.h" | |||||
15 | #include "statedump.h" | |||||
16 | #include "stack.h" | |||||
17 | #include "common-utils.h" | |||||
18 | ||||||
19 | #ifdef HAVE_MALLOC_H1 | |||||
20 | #include <malloc.h> | |||||
21 | #endif /* MALLOC_H */ | |||||
22 | ||||||
23 | /* We don't want gf_log in this function because it may cause | |||||
24 | 'deadlock' with statedump. This is because statedump happens | |||||
25 | inside a signal handler and cannot afford to block on a lock.*/ | |||||
26 | #ifdef gf_log | |||||
27 | # undef gf_log | |||||
28 | #endif | |||||
29 | ||||||
30 | #define GF_PROC_DUMP_IS_OPTION_ENABLED(opt)(dump_options.dump_opt == _gf_true) \ | |||||
31 | (dump_options.dump_##opt == _gf_true) | |||||
32 | ||||||
33 | #define GF_PROC_DUMP_IS_XL_OPTION_ENABLED(opt)(dump_options.xl_options.dump_opt == _gf_true) \ | |||||
34 | (dump_options.xl_options.dump_##opt == _gf_true) | |||||
35 | ||||||
36 | extern xlator_t global_xlator; | |||||
37 | ||||||
38 | static pthread_mutex_t gf_proc_dump_mutex; | |||||
39 | static int gf_dump_fd = -1; | |||||
40 | gf_dump_options_t dump_options; | |||||
41 | ||||||
42 | ||||||
43 | static void | |||||
44 | gf_proc_dump_lock (void) | |||||
45 | { | |||||
46 | pthread_mutex_lock (&gf_proc_dump_mutex); | |||||
47 | } | |||||
48 | ||||||
49 | ||||||
50 | static void | |||||
51 | gf_proc_dump_unlock (void) | |||||
52 | { | |||||
53 | pthread_mutex_unlock (&gf_proc_dump_mutex); | |||||
54 | } | |||||
55 | ||||||
56 | static int | |||||
57 | gf_proc_dump_open (char *tmpname) | |||||
58 | { | |||||
59 | int dump_fd = -1; | |||||
60 | ||||||
61 | dump_fd = mkstemp (tmpname); | |||||
62 | if (dump_fd < 0) | |||||
63 | return -1; | |||||
64 | ||||||
65 | gf_dump_fd = dump_fd; | |||||
66 | return 0; | |||||
67 | } | |||||
68 | ||||||
69 | static void | |||||
70 | gf_proc_dump_close (void) | |||||
71 | { | |||||
72 | close (gf_dump_fd); | |||||
73 | gf_dump_fd = -1; | |||||
74 | } | |||||
75 | ||||||
76 | static int | |||||
77 | gf_proc_dump_set_path (char *dump_options_file) | |||||
78 | { | |||||
79 | int ret = -1; | |||||
80 | FILE *fp = NULL((void*)0); | |||||
81 | char buf[256]; | |||||
82 | char *key = NULL((void*)0), *value = NULL((void*)0); | |||||
83 | char *saveptr = NULL((void*)0); | |||||
84 | ||||||
85 | fp = fopen (dump_options_file, "r"); | |||||
86 | if (!fp) | |||||
87 | goto out; | |||||
88 | ||||||
89 | ret = fscanf (fp, "%s", buf); | |||||
90 | ||||||
91 | while (ret != EOF(-1)) { | |||||
92 | key = strtok_r (buf, "=", &saveptr); | |||||
93 | if (!key) { | |||||
94 | ret = fscanf (fp, "%s", buf); | |||||
95 | continue; | |||||
96 | } | |||||
97 | ||||||
98 | value = strtok_r (NULL((void*)0), "=", &saveptr); | |||||
99 | ||||||
100 | if (!value) { | |||||
101 | ret = fscanf (fp, "%s", buf); | |||||
102 | continue; | |||||
103 | } | |||||
104 | if (!strcmp (key, "path")) { | |||||
105 | dump_options.dump_path = gf_strdup (value); | |||||
106 | break; | |||||
107 | } | |||||
108 | } | |||||
109 | ||||||
110 | out: | |||||
111 | if (fp) | |||||
112 | fclose (fp); | |||||
113 | return ret; | |||||
114 | } | |||||
115 | ||||||
116 | int | |||||
117 | gf_proc_dump_add_section (char *key, ...) | |||||
118 | { | |||||
119 | ||||||
120 | char buf[GF_DUMP_MAX_BUF_LEN4096]; | |||||
121 | va_list ap; | |||||
122 | ||||||
123 | GF_ASSERT(key)do { if (!(key)) { do { do { if (0) printf ("Assertion failed: " "key"); } while (0); _gf_log_callingfn ("", "statedump.c", __FUNCTION__ , 123, GF_LOG_ERROR, "Assertion failed: " "key"); } while (0) ; } } while (0); | |||||
124 | ||||||
125 | memset (buf, 0, sizeof(buf)); | |||||
126 | snprintf (buf, GF_DUMP_MAX_BUF_LEN4096, "\n["); | |||||
127 | va_start (ap, key)__builtin_va_start(ap, key); | |||||
128 | vsnprintf (buf + strlen(buf), | |||||
129 | GF_DUMP_MAX_BUF_LEN4096 - strlen (buf), key, ap); | |||||
130 | va_end (ap)__builtin_va_end(ap); | |||||
131 | snprintf (buf + strlen(buf), | |||||
132 | GF_DUMP_MAX_BUF_LEN4096 - strlen (buf), "]\n"); | |||||
133 | return write (gf_dump_fd, buf, strlen (buf)); | |||||
134 | } | |||||
135 | ||||||
136 | ||||||
137 | int | |||||
138 | gf_proc_dump_write (char *key, char *value,...) | |||||
139 | { | |||||
140 | ||||||
141 | char buf[GF_DUMP_MAX_BUF_LEN4096]; | |||||
142 | int offset = 0; | |||||
143 | va_list ap; | |||||
144 | ||||||
145 | GF_ASSERT (key)do { if (!(key)) { do { do { if (0) printf ("Assertion failed: " "key"); } while (0); _gf_log_callingfn ("", "statedump.c", __FUNCTION__ , 145, GF_LOG_ERROR, "Assertion failed: " "key"); } while (0) ; } } while (0); | |||||
| ||||||
146 | ||||||
147 | offset = strlen (key); | |||||
| ||||||
148 | ||||||
149 | memset (buf, 0, GF_DUMP_MAX_BUF_LEN4096); | |||||
150 | snprintf (buf, GF_DUMP_MAX_BUF_LEN4096, "%s", key); | |||||
151 | snprintf (buf + offset, GF_DUMP_MAX_BUF_LEN4096 - offset, "="); | |||||
152 | offset += 1; | |||||
153 | va_start (ap, value)__builtin_va_start(ap, value); | |||||
154 | vsnprintf (buf + offset, GF_DUMP_MAX_BUF_LEN4096 - offset, value, ap); | |||||
155 | va_end (ap)__builtin_va_end(ap); | |||||
156 | ||||||
157 | offset = strlen (buf); | |||||
158 | snprintf (buf + offset, GF_DUMP_MAX_BUF_LEN4096 - offset, "\n"); | |||||
159 | return write (gf_dump_fd, buf, strlen (buf)); | |||||
160 | } | |||||
161 | ||||||
162 | static void | |||||
163 | gf_proc_dump_xlator_mem_info (xlator_t *xl) | |||||
164 | { | |||||
165 | int i = 0; | |||||
166 | struct mem_acct rec = {0,}; | |||||
167 | ||||||
168 | if (!xl) | |||||
169 | return; | |||||
170 | ||||||
171 | if (!xl->mem_acct.rec) | |||||
172 | return; | |||||
173 | ||||||
174 | gf_proc_dump_add_section ("%s.%s - Memory usage", xl->type, xl->name); | |||||
175 | gf_proc_dump_write ("num_types", "%d", xl->mem_acct.num_types); | |||||
176 | ||||||
177 | for (i = 0; i < xl->mem_acct.num_types; i++) { | |||||
178 | if (!(memcmp (&xl->mem_acct.rec[i], &rec, | |||||
179 | sizeof (struct mem_acct)))) | |||||
180 | continue; | |||||
181 | ||||||
182 | gf_proc_dump_add_section ("%s.%s - usage-type %d memusage", | |||||
183 | xl->type, xl->name, i); | |||||
184 | gf_proc_dump_write ("size", "%u", xl->mem_acct.rec[i].size); | |||||
185 | gf_proc_dump_write ("num_allocs", "%u", | |||||
186 | xl->mem_acct.rec[i].num_allocs); | |||||
187 | gf_proc_dump_write ("max_size", "%u", | |||||
188 | xl->mem_acct.rec[i].max_size); | |||||
189 | gf_proc_dump_write ("max_num_allocs", "%u", | |||||
190 | xl->mem_acct.rec[i].max_num_allocs); | |||||
191 | gf_proc_dump_write ("total_allocs", "%u", | |||||
192 | xl->mem_acct.rec[i].total_allocs); | |||||
193 | } | |||||
194 | ||||||
195 | return; | |||||
196 | } | |||||
197 | ||||||
198 | static void | |||||
199 | gf_proc_dump_xlator_mem_info_only_in_use (xlator_t *xl) | |||||
200 | { | |||||
201 | int i = 0; | |||||
202 | ||||||
203 | if (!xl) | |||||
204 | return; | |||||
205 | ||||||
206 | if (!xl->mem_acct.rec) | |||||
207 | return; | |||||
208 | ||||||
209 | gf_proc_dump_add_section ("%s.%s - Memory usage", xl->type, xl->name); | |||||
210 | gf_proc_dump_write ("num_types", "%d", xl->mem_acct.num_types); | |||||
211 | ||||||
212 | for (i = 0; i < xl->mem_acct.num_types; i++) { | |||||
213 | if (!xl->mem_acct.rec[i].size) | |||||
214 | continue; | |||||
215 | ||||||
216 | gf_proc_dump_add_section ("%s.%s - usage-type %d", xl->type, | |||||
217 | xl->name,i); | |||||
218 | ||||||
219 | gf_proc_dump_write ("size", "%u", | |||||
220 | xl->mem_acct.rec[i].size); | |||||
221 | gf_proc_dump_write ("max_size", "%u", | |||||
222 | xl->mem_acct.rec[i].max_size); | |||||
223 | gf_proc_dump_write ("num_allocs", "%u", | |||||
224 | xl->mem_acct.rec[i].num_allocs); | |||||
225 | gf_proc_dump_write ("max_num_allocs", "%u", | |||||
226 | xl->mem_acct.rec[i].max_num_allocs); | |||||
227 | gf_proc_dump_write ("total_allocs", "%u", | |||||
228 | xl->mem_acct.rec[i].total_allocs); | |||||
229 | } | |||||
230 | ||||||
231 | return; | |||||
232 | } | |||||
233 | ||||||
234 | ||||||
235 | ||||||
236 | /* Currently this dumps only mallinfo. More can be built on here */ | |||||
237 | void | |||||
238 | gf_proc_dump_mem_info () | |||||
239 | { | |||||
240 | #ifdef HAVE_MALLOC_STATS1 | |||||
241 | struct mallinfo info; | |||||
242 | ||||||
243 | memset (&info, 0, sizeof (struct mallinfo)); | |||||
244 | info = mallinfo (); | |||||
245 | ||||||
246 | gf_proc_dump_add_section ("mallinfo"); | |||||
247 | gf_proc_dump_write ("mallinfo_arena", "%d", info.arena); | |||||
248 | gf_proc_dump_write ("mallinfo_ordblks", "%d", info.ordblks); | |||||
249 | gf_proc_dump_write ("mallinfo_smblks", "%d", info.smblks); | |||||
250 | gf_proc_dump_write ("mallinfo_hblks", "%d", info.hblks); | |||||
251 | gf_proc_dump_write ("mallinfo_hblkhd", "%d", info.hblkhd); | |||||
252 | gf_proc_dump_write ("mallinfo_usmblks", "%d", info.usmblks); | |||||
253 | gf_proc_dump_write ("mallinfo_fsmblks", "%d", info.fsmblks); | |||||
254 | gf_proc_dump_write ("mallinfo_uordblks", "%d", info.uordblks); | |||||
255 | gf_proc_dump_write ("mallinfo_fordblks", "%d", info.fordblks); | |||||
256 | gf_proc_dump_write ("mallinfo_keepcost", "%d", info.keepcost); | |||||
257 | #endif | |||||
258 | gf_proc_dump_xlator_mem_info(&global_xlator); | |||||
259 | ||||||
260 | } | |||||
261 | ||||||
262 | void | |||||
263 | gf_proc_dump_mem_info_to_dict (dict_t *dict) | |||||
264 | { | |||||
265 | if (!dict) | |||||
266 | return; | |||||
267 | #ifdef HAVE_MALLOC_STATS1 | |||||
268 | struct mallinfo info; | |||||
269 | int ret = -1; | |||||
270 | ||||||
271 | memset (&info, 0, sizeof(struct mallinfo)); | |||||
272 | info = mallinfo (); | |||||
273 | ||||||
274 | ret = dict_set_int32 (dict, "mallinfo.arena", info.arena); | |||||
275 | if (ret) | |||||
276 | return; | |||||
277 | ||||||
278 | ret = dict_set_int32 (dict, "mallinfo.ordblks", info.ordblks); | |||||
279 | if (ret) | |||||
280 | return; | |||||
281 | ||||||
282 | ret = dict_set_int32 (dict, "mallinfo.smblks", info.smblks); | |||||
283 | if (ret) | |||||
284 | return; | |||||
285 | ||||||
286 | ret = dict_set_int32 (dict, "mallinfo.hblks", info.hblks); | |||||
287 | if (ret) | |||||
288 | return; | |||||
289 | ||||||
290 | ret = dict_set_int32 (dict, "mallinfo.hblkhd", info.hblkhd); | |||||
291 | if (ret) | |||||
292 | return; | |||||
293 | ||||||
294 | ret = dict_set_int32 (dict, "mallinfo.usmblks", info.usmblks); | |||||
295 | if (ret) | |||||
296 | return; | |||||
297 | ||||||
298 | ret = dict_set_int32 (dict, "mallinfo.fsmblks", info.fsmblks); | |||||
299 | if (ret) | |||||
300 | return; | |||||
301 | ||||||
302 | ret = dict_set_int32 (dict, "mallinfo.uordblks", info.uordblks); | |||||
303 | if (ret) | |||||
304 | return; | |||||
305 | ||||||
306 | ret = dict_set_int32 (dict, "mallinfo.fordblks", info.fordblks); | |||||
307 | if (ret) | |||||
308 | return; | |||||
309 | ||||||
310 | ret = dict_set_int32 (dict, "mallinfo.keepcost", info.keepcost); | |||||
311 | if (ret) | |||||
312 | return; | |||||
313 | #endif | |||||
314 | return; | |||||
315 | } | |||||
316 | ||||||
317 | void | |||||
318 | gf_proc_dump_mempool_info (glusterfs_ctx_t *ctx) | |||||
319 | { | |||||
320 | struct mem_pool *pool = NULL((void*)0); | |||||
321 | ||||||
322 | gf_proc_dump_add_section ("mempool"); | |||||
323 | ||||||
324 | list_for_each_entry (pool, &ctx->mempool_list, global_list)for (pool = ((typeof(*pool) *)((char *)((&ctx->mempool_list )->next)-(unsigned long)(&((typeof(*pool) *)0)->global_list ))); &pool->global_list != (&ctx->mempool_list) ; pool = ((typeof(*pool) *)((char *)(pool->global_list.next )-(unsigned long)(&((typeof(*pool) *)0)->global_list)) )) { | |||||
325 | gf_proc_dump_write ("-----", "-----"); | |||||
326 | gf_proc_dump_write ("pool-name", "%s", pool->name); | |||||
327 | gf_proc_dump_write ("hot-count", "%d", pool->hot_count); | |||||
328 | gf_proc_dump_write ("cold-count", "%d", pool->cold_count); | |||||
329 | gf_proc_dump_write ("padded_sizeof", "%lu", | |||||
330 | pool->padded_sizeof_type); | |||||
331 | gf_proc_dump_write ("alloc-count", "%"PRIu64"ll" "u", pool->alloc_count); | |||||
332 | gf_proc_dump_write ("max-alloc", "%d", pool->max_alloc); | |||||
333 | ||||||
334 | gf_proc_dump_write ("pool-misses", "%"PRIu64"ll" "u", pool->pool_misses); | |||||
335 | gf_proc_dump_write ("max-stdalloc", "%d", pool->max_stdalloc); | |||||
336 | } | |||||
337 | } | |||||
338 | ||||||
339 | void | |||||
340 | gf_proc_dump_mempool_info_to_dict (glusterfs_ctx_t *ctx, dict_t *dict) | |||||
341 | { | |||||
342 | struct mem_pool *pool = NULL((void*)0); | |||||
343 | char key[GF_DUMP_MAX_BUF_LEN4096] = {0,}; | |||||
344 | int count = 0; | |||||
345 | int ret = -1; | |||||
346 | ||||||
347 | if (!ctx || !dict) | |||||
348 | return; | |||||
349 | ||||||
350 | list_for_each_entry (pool, &ctx->mempool_list, global_list)for (pool = ((typeof(*pool) *)((char *)((&ctx->mempool_list )->next)-(unsigned long)(&((typeof(*pool) *)0)->global_list ))); &pool->global_list != (&ctx->mempool_list) ; pool = ((typeof(*pool) *)((char *)(pool->global_list.next )-(unsigned long)(&((typeof(*pool) *)0)->global_list)) )) { | |||||
351 | memset (key, 0, sizeof (key)); | |||||
352 | snprintf (key, sizeof (key), "pool%d.name", count); | |||||
353 | ret = dict_set_str (dict, key, pool->name); | |||||
354 | if (ret) | |||||
355 | return; | |||||
356 | ||||||
357 | memset (key, 0, sizeof (key)); | |||||
358 | snprintf (key, sizeof (key), "pool%d.hotcount", count); | |||||
359 | ret = dict_set_int32 (dict, key, pool->hot_count); | |||||
360 | if (ret) | |||||
361 | return; | |||||
362 | ||||||
363 | memset (key, 0, sizeof (key)); | |||||
364 | snprintf (key, sizeof (key), "pool%d.coldcount", count); | |||||
365 | ret = dict_set_int32 (dict, key, pool->cold_count); | |||||
366 | if (ret) | |||||
367 | return; | |||||
368 | ||||||
369 | memset (key, 0, sizeof (key)); | |||||
370 | snprintf (key, sizeof (key), "pool%d.paddedsizeof", count); | |||||
371 | ret = dict_set_uint64 (dict, key, pool->padded_sizeof_type); | |||||
372 | if (ret) | |||||
373 | return; | |||||
374 | ||||||
375 | memset (key, 0, sizeof (key)); | |||||
376 | snprintf (key, sizeof (key), "pool%d.alloccount", count); | |||||
377 | ret = dict_set_uint64 (dict, key, pool->alloc_count); | |||||
378 | if (ret) | |||||
379 | return; | |||||
380 | ||||||
381 | memset (key, 0, sizeof (key)); | |||||
382 | snprintf (key, sizeof (key), "pool%d.max_alloc", count); | |||||
383 | ret = dict_set_int32 (dict, key, pool->max_alloc); | |||||
384 | if (ret) | |||||
385 | return; | |||||
386 | ||||||
387 | memset (key, 0, sizeof (key)); | |||||
388 | snprintf (key, sizeof (key), "pool%d.max-stdalloc", count); | |||||
389 | ret = dict_set_int32 (dict, key, pool->max_stdalloc); | |||||
390 | if (ret) | |||||
391 | return; | |||||
392 | ||||||
393 | memset (key, 0, sizeof (key)); | |||||
394 | snprintf (key, sizeof (key), "pool%d.pool-misses", count); | |||||
395 | ret = dict_set_uint64 (dict, key, pool->pool_misses); | |||||
396 | if (ret) | |||||
397 | return; | |||||
398 | count++; | |||||
399 | } | |||||
400 | ret = dict_set_int32 (dict, "mempool-count", count); | |||||
401 | ||||||
402 | return; | |||||
403 | } | |||||
404 | ||||||
405 | void gf_proc_dump_latency_info (xlator_t *xl); | |||||
406 | ||||||
407 | void | |||||
408 | gf_proc_dump_xlator_info (xlator_t *top) | |||||
409 | { | |||||
410 | xlator_t *trav = NULL((void*)0); | |||||
411 | glusterfs_ctx_t *ctx = NULL((void*)0); | |||||
412 | char itable_key[1024] = {0,}; | |||||
413 | ||||||
414 | if (!top) | |||||
415 | return; | |||||
416 | ||||||
417 | ctx = top->ctx; | |||||
418 | ||||||
419 | trav = top; | |||||
420 | while (trav) { | |||||
421 | ||||||
422 | if (ctx->measure_latency) | |||||
423 | gf_proc_dump_latency_info (trav); | |||||
424 | ||||||
425 | gf_proc_dump_xlator_mem_info(trav); | |||||
426 | ||||||
427 | if (GF_PROC_DUMP_IS_XL_OPTION_ENABLED (inode)(dump_options.xl_options.dump_inode == _gf_true) && | |||||
428 | (trav->itable)) { | |||||
429 | snprintf (itable_key, 1024, "%d.%s.itable", | |||||
430 | ctx->graph_id, trav->name); | |||||
431 | } | |||||
432 | ||||||
433 | if (!trav->dumpops) { | |||||
434 | trav = trav->next; | |||||
435 | continue; | |||||
436 | } | |||||
437 | ||||||
438 | if (trav->dumpops->priv && | |||||
439 | GF_PROC_DUMP_IS_XL_OPTION_ENABLED (priv)(dump_options.xl_options.dump_priv == _gf_true)) | |||||
440 | trav->dumpops->priv (trav); | |||||
441 | ||||||
442 | if (GF_PROC_DUMP_IS_XL_OPTION_ENABLED (inode)(dump_options.xl_options.dump_inode == _gf_true) && | |||||
443 | (trav->dumpops->inode)) | |||||
444 | trav->dumpops->inode (trav); | |||||
445 | ||||||
446 | if (trav->dumpops->fd && | |||||
447 | GF_PROC_DUMP_IS_XL_OPTION_ENABLED (fd)(dump_options.xl_options.dump_fd == _gf_true)) | |||||
448 | trav->dumpops->fd (trav); | |||||
449 | ||||||
450 | if (trav->dumpops->history && | |||||
451 | GF_PROC_DUMP_IS_XL_OPTION_ENABLED (history)(dump_options.xl_options.dump_history == _gf_true)) | |||||
452 | trav->dumpops->history (trav); | |||||
453 | ||||||
454 | trav = trav->next; | |||||
455 | } | |||||
456 | ||||||
457 | return; | |||||
458 | } | |||||
459 | ||||||
460 | static void | |||||
461 | gf_proc_dump_oldgraph_xlator_info (xlator_t *top) | |||||
462 | { | |||||
463 | xlator_t *trav = NULL((void*)0); | |||||
464 | ||||||
465 | if (!top) | |||||
466 | return; | |||||
467 | ||||||
468 | trav = top; | |||||
469 | while (trav) { | |||||
470 | gf_proc_dump_xlator_mem_info_only_in_use (trav); | |||||
471 | ||||||
472 | if (GF_PROC_DUMP_IS_XL_OPTION_ENABLED (inode)(dump_options.xl_options.dump_inode == _gf_true) && | |||||
473 | (trav->itable)) { | |||||
474 | /*TODO: dump inode table info if necessary by | |||||
475 | printing the graph id (taken by glusterfs_cbtx_t) | |||||
476 | in the key | |||||
477 | */ | |||||
478 | } | |||||
479 | ||||||
480 | if (!trav->dumpops) { | |||||
481 | trav = trav->next; | |||||
482 | continue; | |||||
483 | } | |||||
484 | ||||||
485 | if (GF_PROC_DUMP_IS_XL_OPTION_ENABLED (inode)(dump_options.xl_options.dump_inode == _gf_true) && | |||||
486 | (trav->dumpops->inode)) | |||||
487 | trav->dumpops->inode (trav); | |||||
488 | ||||||
489 | if (trav->dumpops->fd && | |||||
490 | GF_PROC_DUMP_IS_XL_OPTION_ENABLED (fd)(dump_options.xl_options.dump_fd == _gf_true)) | |||||
491 | trav->dumpops->fd (trav); | |||||
492 | ||||||
493 | trav = trav->next; | |||||
494 | } | |||||
495 | ||||||
496 | return; | |||||
497 | } | |||||
498 | ||||||
499 | static int | |||||
500 | gf_proc_dump_enable_all_options () | |||||
501 | { | |||||
502 | ||||||
503 | GF_PROC_DUMP_SET_OPTION (dump_options.dump_mem, _gf_true)dump_options.dump_mem = _gf_true; | |||||
504 | GF_PROC_DUMP_SET_OPTION (dump_options.dump_iobuf, _gf_true)dump_options.dump_iobuf = _gf_true; | |||||
505 | GF_PROC_DUMP_SET_OPTION (dump_options.dump_callpool, _gf_true)dump_options.dump_callpool = _gf_true; | |||||
506 | GF_PROC_DUMP_SET_OPTION (dump_options.xl_options.dump_priv, _gf_true)dump_options.xl_options.dump_priv = _gf_true; | |||||
507 | GF_PROC_DUMP_SET_OPTION (dump_options.xl_options.dump_inode, _gf_true)dump_options.xl_options.dump_inode = _gf_true; | |||||
508 | GF_PROC_DUMP_SET_OPTION (dump_options.xl_options.dump_fd, _gf_true)dump_options.xl_options.dump_fd = _gf_true; | |||||
509 | GF_PROC_DUMP_SET_OPTION (dump_options.xl_options.dump_inodectx,dump_options.xl_options.dump_inodectx = _gf_true | |||||
510 | _gf_true)dump_options.xl_options.dump_inodectx = _gf_true; | |||||
511 | GF_PROC_DUMP_SET_OPTION (dump_options.xl_options.dump_fdctx, _gf_true)dump_options.xl_options.dump_fdctx = _gf_true; | |||||
512 | GF_PROC_DUMP_SET_OPTION (dump_options.xl_options.dump_history,dump_options.xl_options.dump_history = _gf_true | |||||
513 | _gf_true)dump_options.xl_options.dump_history = _gf_true; | |||||
514 | ||||||
515 | return 0; | |||||
516 | } | |||||
517 | ||||||
518 | gf_boolean_t | |||||
519 | is_gf_proc_dump_all_disabled () | |||||
520 | { | |||||
521 | gf_boolean_t all_disabled = _gf_true; | |||||
522 | ||||||
523 | GF_CHECK_DUMP_OPTION_ENABLED (dump_options.dump_mem, all_disabled, out)do { if (dump_options.dump_mem == _gf_true) { all_disabled = _gf_false ; goto out; } } while (0);; | |||||
524 | GF_CHECK_DUMP_OPTION_ENABLED (dump_options.dump_iobuf, all_disabled, out)do { if (dump_options.dump_iobuf == _gf_true) { all_disabled = _gf_false; goto out; } } while (0);; | |||||
525 | GF_CHECK_DUMP_OPTION_ENABLED (dump_options.dump_callpool, all_disabled,do { if (dump_options.dump_callpool == _gf_true) { all_disabled = _gf_false; goto out; } } while (0); | |||||
526 | out)do { if (dump_options.dump_callpool == _gf_true) { all_disabled = _gf_false; goto out; } } while (0);; | |||||
527 | GF_CHECK_DUMP_OPTION_ENABLED (dump_options.xl_options.dump_priv,do { if (dump_options.xl_options.dump_priv == _gf_true) { all_disabled = _gf_false; goto out; } } while (0); | |||||
528 | all_disabled, out)do { if (dump_options.xl_options.dump_priv == _gf_true) { all_disabled = _gf_false; goto out; } } while (0);; | |||||
529 | GF_CHECK_DUMP_OPTION_ENABLED (dump_options.xl_options.dump_inode,do { if (dump_options.xl_options.dump_inode == _gf_true) { all_disabled = _gf_false; goto out; } } while (0); | |||||
530 | all_disabled, out)do { if (dump_options.xl_options.dump_inode == _gf_true) { all_disabled = _gf_false; goto out; } } while (0);; | |||||
531 | GF_CHECK_DUMP_OPTION_ENABLED (dump_options.xl_options.dump_fd,do { if (dump_options.xl_options.dump_fd == _gf_true) { all_disabled = _gf_false; goto out; } } while (0); | |||||
532 | all_disabled, out)do { if (dump_options.xl_options.dump_fd == _gf_true) { all_disabled = _gf_false; goto out; } } while (0);; | |||||
533 | GF_CHECK_DUMP_OPTION_ENABLED (dump_options.xl_options.dump_inodectx,do { if (dump_options.xl_options.dump_inodectx == _gf_true) { all_disabled = _gf_false; goto out; } } while (0); | |||||
534 | all_disabled, out)do { if (dump_options.xl_options.dump_inodectx == _gf_true) { all_disabled = _gf_false; goto out; } } while (0);; | |||||
535 | GF_CHECK_DUMP_OPTION_ENABLED (dump_options.xl_options.dump_fdctx,do { if (dump_options.xl_options.dump_fdctx == _gf_true) { all_disabled = _gf_false; goto out; } } while (0); | |||||
536 | all_disabled, out)do { if (dump_options.xl_options.dump_fdctx == _gf_true) { all_disabled = _gf_false; goto out; } } while (0);; | |||||
537 | GF_CHECK_DUMP_OPTION_ENABLED (dump_options.xl_options.dump_history,do { if (dump_options.xl_options.dump_history == _gf_true) { all_disabled = _gf_false; goto out; } } while (0); | |||||
538 | all_disabled, out)do { if (dump_options.xl_options.dump_history == _gf_true) { all_disabled = _gf_false; goto out; } } while (0);; | |||||
539 | ||||||
540 | out: | |||||
541 | return all_disabled; | |||||
542 | } | |||||
543 | ||||||
544 | /* These options are dumped by default if glusterdump.options | |||||
545 | file exists and it is emtpty | |||||
546 | */ | |||||
547 | static int | |||||
548 | gf_proc_dump_enable_default_options () | |||||
549 | { | |||||
550 | GF_PROC_DUMP_SET_OPTION (dump_options.dump_mem, _gf_true)dump_options.dump_mem = _gf_true; | |||||
551 | GF_PROC_DUMP_SET_OPTION (dump_options.dump_callpool, _gf_true)dump_options.dump_callpool = _gf_true; | |||||
552 | ||||||
553 | return 0; | |||||
554 | } | |||||
555 | ||||||
556 | static int | |||||
557 | gf_proc_dump_disable_all_options () | |||||
558 | { | |||||
559 | ||||||
560 | GF_PROC_DUMP_SET_OPTION (dump_options.dump_mem, _gf_false)dump_options.dump_mem = _gf_false; | |||||
561 | GF_PROC_DUMP_SET_OPTION (dump_options.dump_iobuf, _gf_false)dump_options.dump_iobuf = _gf_false; | |||||
562 | GF_PROC_DUMP_SET_OPTION (dump_options.dump_callpool, _gf_false)dump_options.dump_callpool = _gf_false; | |||||
563 | GF_PROC_DUMP_SET_OPTION (dump_options.xl_options.dump_priv, _gf_false)dump_options.xl_options.dump_priv = _gf_false; | |||||
564 | GF_PROC_DUMP_SET_OPTION (dump_options.xl_options.dump_inode,dump_options.xl_options.dump_inode = _gf_false | |||||
565 | _gf_false)dump_options.xl_options.dump_inode = _gf_false; | |||||
566 | GF_PROC_DUMP_SET_OPTION (dump_options.xl_options.dump_fd, _gf_false)dump_options.xl_options.dump_fd = _gf_false; | |||||
567 | GF_PROC_DUMP_SET_OPTION (dump_options.xl_options.dump_inodectx,dump_options.xl_options.dump_inodectx = _gf_false | |||||
568 | _gf_false)dump_options.xl_options.dump_inodectx = _gf_false; | |||||
569 | GF_PROC_DUMP_SET_OPTION (dump_options.xl_options.dump_fdctx, _gf_false)dump_options.xl_options.dump_fdctx = _gf_false; | |||||
570 | GF_PROC_DUMP_SET_OPTION (dump_options.xl_options.dump_history,dump_options.xl_options.dump_history = _gf_false | |||||
571 | _gf_false)dump_options.xl_options.dump_history = _gf_false; | |||||
572 | return 0; | |||||
573 | } | |||||
574 | ||||||
575 | static int | |||||
576 | gf_proc_dump_parse_set_option (char *key, char *value) | |||||
577 | { | |||||
578 | gf_boolean_t *opt_key = NULL((void*)0); | |||||
579 | gf_boolean_t opt_value = _gf_false; | |||||
580 | char buf[GF_DUMP_MAX_BUF_LEN4096]; | |||||
581 | int ret = -1; | |||||
582 | ||||||
583 | if (!strcasecmp (key, "all")) { | |||||
584 | (void)gf_proc_dump_enable_all_options (); | |||||
585 | return 0; | |||||
586 | } else if (!strcasecmp (key, "mem")) { | |||||
587 | opt_key = &dump_options.dump_mem; | |||||
588 | } else if (!strcasecmp (key, "iobuf")) { | |||||
589 | opt_key = &dump_options.dump_iobuf; | |||||
590 | } else if (!strcasecmp (key, "callpool")) { | |||||
591 | opt_key = &dump_options.dump_callpool; | |||||
592 | } else if (!strcasecmp (key, "priv")) { | |||||
593 | opt_key = &dump_options.xl_options.dump_priv; | |||||
594 | } else if (!strcasecmp (key, "fd")) { | |||||
595 | opt_key = &dump_options.xl_options.dump_fd; | |||||
596 | } else if (!strcasecmp (key, "inode")) { | |||||
597 | opt_key = &dump_options.xl_options.dump_inode; | |||||
598 | } else if (!strcasecmp (key, "inodectx")) { | |||||
599 | opt_key = &dump_options.xl_options.dump_inodectx; | |||||
600 | } else if (!strcasecmp (key, "fdctx")) { | |||||
601 | opt_key = &dump_options.xl_options.dump_fdctx; | |||||
602 | } else if (!strcasecmp (key, "history")) { | |||||
603 | opt_key = &dump_options.xl_options.dump_history; | |||||
604 | } | |||||
605 | ||||||
606 | if (!opt_key) { | |||||
607 | //None of dump options match the key, return back | |||||
608 | snprintf (buf, sizeof (buf), "[Warning]:None of the options " | |||||
609 | "matched key : %s\n", key); | |||||
610 | ret = write (gf_dump_fd, buf, strlen (buf)); | |||||
611 | ||||||
612 | if (ret >= 0) | |||||
613 | ret = -1; | |||||
614 | goto out; | |||||
615 | ||||||
616 | } | |||||
617 | ||||||
618 | opt_value = (strncasecmp (value, "yes", 3) ? | |||||
619 | _gf_false: _gf_true); | |||||
620 | ||||||
621 | GF_PROC_DUMP_SET_OPTION (*opt_key, opt_value)*opt_key = opt_value; | |||||
622 | ||||||
623 | ret = 0; | |||||
624 | out: | |||||
625 | return ret; | |||||
626 | } | |||||
627 | ||||||
628 | static int | |||||
629 | gf_proc_dump_options_init () | |||||
630 | { | |||||
631 | int ret = -1; | |||||
632 | FILE *fp = NULL((void*)0); | |||||
633 | char buf[256]; | |||||
634 | char *key = NULL((void*)0), *value = NULL((void*)0); | |||||
635 | char *saveptr = NULL((void*)0); | |||||
636 | char dump_option_file[PATH_MAX4096]; | |||||
637 | ||||||
638 | /* glusterd will create a file glusterdump.<pid>.options and | |||||
639 | sets the statedump options for the process and the file is removed | |||||
640 | after the statedump is taken. Direct issue of SIGUSR1 does not have | |||||
641 | mechanism for considering the statedump options. So to have a way | |||||
642 | of configuring the statedump of all the glusterfs processes through | |||||
643 | both cli command and SIGUSR1, glusterdump.options file is searched | |||||
644 | and the options mentioned in it are given the higher priority. | |||||
645 | */ | |||||
646 | snprintf (dump_option_file, sizeof (dump_option_file), | |||||
647 | DEFAULT_VAR_RUN_DIRECTORY"/usr/local/var" "/run/gluster" | |||||
648 | "/glusterdump.options"); | |||||
649 | fp = fopen (dump_option_file, "r"); | |||||
650 | if (!fp) { | |||||
651 | snprintf (dump_option_file, sizeof (dump_option_file), | |||||
652 | DEFAULT_VAR_RUN_DIRECTORY"/usr/local/var" "/run/gluster" | |||||
653 | "/glusterdump.%d.options", getpid ()); | |||||
654 | ||||||
655 | fp = fopen (dump_option_file, "r"); | |||||
656 | ||||||
657 | if (!fp) { | |||||
658 | //ENOENT, return success | |||||
659 | (void) gf_proc_dump_enable_all_options (); | |||||
660 | return 0; | |||||
661 | } | |||||
662 | } | |||||
663 | ||||||
664 | (void) gf_proc_dump_disable_all_options (); | |||||
665 | ||||||
666 | // swallow the errors if setting statedump file path is failed. | |||||
667 | ret = gf_proc_dump_set_path (dump_option_file); | |||||
668 | ||||||
669 | ret = fscanf (fp, "%s", buf); | |||||
670 | ||||||
671 | while (ret != EOF(-1)) { | |||||
672 | key = strtok_r (buf, "=", &saveptr); | |||||
673 | if (!key) { | |||||
674 | ret = fscanf (fp, "%s", buf); | |||||
675 | continue; | |||||
676 | } | |||||
677 | ||||||
678 | value = strtok_r (NULL((void*)0), "=", &saveptr); | |||||
679 | ||||||
680 | if (!value) { | |||||
681 | ret = fscanf (fp, "%s", buf); | |||||
682 | continue; | |||||
683 | } | |||||
684 | ||||||
685 | gf_proc_dump_parse_set_option (key, value); | |||||
686 | } | |||||
687 | ||||||
688 | if (is_gf_proc_dump_all_disabled ()) | |||||
689 | (void) gf_proc_dump_enable_default_options (); | |||||
690 | ||||||
691 | if (fp) | |||||
692 | fclose (fp); | |||||
693 | ||||||
694 | return 0; | |||||
695 | } | |||||
696 | ||||||
697 | void | |||||
698 | gf_proc_dump_info (int signum, glusterfs_ctx_t *ctx) | |||||
699 | { | |||||
700 | int i = 0; | |||||
701 | int ret = -1; | |||||
702 | glusterfs_graph_t *trav = NULL((void*)0); | |||||
703 | char brick_name[PATH_MAX4096] = {0,}; | |||||
704 | char timestr[256] = {0,}; | |||||
705 | char sign_string[512] = {0,}; | |||||
706 | char tmp_dump_name[PATH_MAX4096] = {0,}; | |||||
707 | char path[PATH_MAX4096] = {0,}; | |||||
708 | struct timeval tv = {0,}; | |||||
709 | ||||||
710 | gf_proc_dump_lock (); | |||||
711 | ||||||
712 | if (!ctx) | |||||
713 | goto out; | |||||
714 | ||||||
715 | if (ctx->cmd_args.brick_name) { | |||||
716 | GF_REMOVE_SLASH_FROM_PATH (ctx->cmd_args.brick_name, brick_name)do { int i = 0; for (i = 1; i < strlen (ctx->cmd_args.brick_name ); i++) { brick_name[i-1] = ctx->cmd_args.brick_name[i]; if (brick_name[i-1] == '/') brick_name[i-1] = '-'; } } while (0 ); | |||||
717 | } else | |||||
718 | strncpy (brick_name, "glusterdump", sizeof (brick_name)); | |||||
719 | ||||||
720 | ret = gf_proc_dump_options_init (); | |||||
721 | if (ret < 0) | |||||
722 | goto out; | |||||
723 | ||||||
724 | snprintf (path, sizeof (path), "%s/%s.%d.dump.%"PRIu64"ll" "u", | |||||
725 | ((dump_options.dump_path != NULL((void*)0))?dump_options.dump_path: | |||||
726 | ((ctx->statedump_path != NULL((void*)0))?ctx->statedump_path: | |||||
727 | DEFAULT_VAR_RUN_DIRECTORY"/usr/local/var" "/run/gluster")), brick_name, getpid(), | |||||
728 | (uint64_t) time (NULL((void*)0))); | |||||
729 | ||||||
730 | snprintf (tmp_dump_name, PATH_MAX4096, "%s/dumpXXXXXX", | |||||
731 | ((dump_options.dump_path != NULL((void*)0))?dump_options.dump_path: | |||||
732 | ((ctx->statedump_path != NULL((void*)0))?ctx->statedump_path: | |||||
733 | DEFAULT_VAR_RUN_DIRECTORY"/usr/local/var" "/run/gluster"))); | |||||
734 | ||||||
735 | ret = gf_proc_dump_open (tmp_dump_name); | |||||
736 | if (ret < 0) | |||||
737 | goto out; | |||||
738 | ||||||
739 | //continue even though gettimeofday() has failed | |||||
740 | ret = gettimeofday (&tv, NULL((void*)0)); | |||||
741 | if (0 == ret) { | |||||
742 | gf_time_fmt (timestr, sizeof timestr, tv.tv_sec, gf_timefmt_FT); | |||||
743 | snprintf (timestr + strlen (timestr), | |||||
744 | sizeof timestr - strlen (timestr), | |||||
745 | ".%"GF_PRI_SUSECONDS"06ld", tv.tv_usec); | |||||
746 | } | |||||
747 | ||||||
748 | snprintf (sign_string, sizeof (sign_string), "DUMP-START-TIME: %s\n", | |||||
749 | timestr); | |||||
750 | ||||||
751 | //swallow the errors of write for start and end marker | |||||
752 | ret = write (gf_dump_fd, sign_string, strlen (sign_string)); | |||||
753 | ||||||
754 | memset (sign_string, 0, sizeof (sign_string)); | |||||
755 | memset (timestr, 0, sizeof (timestr)); | |||||
756 | memset (&tv, 0, sizeof (tv)); | |||||
757 | ||||||
758 | if (GF_PROC_DUMP_IS_OPTION_ENABLED (mem)(dump_options.dump_mem == _gf_true)) { | |||||
759 | gf_proc_dump_mem_info (); | |||||
760 | gf_proc_dump_mempool_info (ctx); | |||||
761 | } | |||||
762 | ||||||
763 | if (GF_PROC_DUMP_IS_OPTION_ENABLED (iobuf)(dump_options.dump_iobuf == _gf_true)) | |||||
764 | iobuf_stats_dump (ctx->iobuf_pool); | |||||
765 | if (GF_PROC_DUMP_IS_OPTION_ENABLED (callpool)(dump_options.dump_callpool == _gf_true)) | |||||
766 | gf_proc_dump_pending_frames (ctx->pool); | |||||
767 | ||||||
768 | if (ctx->master) { | |||||
769 | gf_proc_dump_add_section ("fuse"); | |||||
770 | gf_proc_dump_xlator_info (ctx->master); | |||||
771 | } | |||||
772 | ||||||
773 | if (ctx->active) { | |||||
774 | gf_proc_dump_add_section ("active graph - %d", ctx->graph_id); | |||||
775 | gf_proc_dump_xlator_info (ctx->active->top); | |||||
776 | } | |||||
777 | ||||||
778 | i = 0; | |||||
779 | list_for_each_entry (trav, &ctx->graphs, list)for (trav = ((typeof(*trav) *)((char *)((&ctx->graphs) ->next)-(unsigned long)(&((typeof(*trav) *)0)->list ))); &trav->list != (&ctx->graphs); trav = ((typeof (*trav) *)((char *)(trav->list.next)-(unsigned long)(& ((typeof(*trav) *)0)->list)))) { | |||||
780 | if (trav == ctx->active) | |||||
781 | continue; | |||||
782 | ||||||
783 | gf_proc_dump_add_section ("oldgraph[%d]", i); | |||||
784 | ||||||
785 | gf_proc_dump_oldgraph_xlator_info (trav->top); | |||||
786 | i++; | |||||
787 | } | |||||
788 | ||||||
789 | ret = gettimeofday (&tv, NULL((void*)0)); | |||||
790 | if (0 == ret) { | |||||
791 | gf_time_fmt (timestr, sizeof timestr, tv.tv_sec, gf_timefmt_FT); | |||||
792 | snprintf (timestr + strlen (timestr), | |||||
793 | sizeof timestr - strlen (timestr), | |||||
794 | ".%"GF_PRI_SUSECONDS"06ld", tv.tv_usec); | |||||
795 | } | |||||
796 | ||||||
797 | snprintf (sign_string, sizeof (sign_string), "\nDUMP-END-TIME: %s", | |||||
798 | timestr); | |||||
799 | ret = write (gf_dump_fd, sign_string, strlen (sign_string)); | |||||
800 | ||||||
801 | out: | |||||
802 | if (gf_dump_fd != -1) | |||||
803 | gf_proc_dump_close (); | |||||
804 | rename (tmp_dump_name, path); | |||||
805 | GF_FREE (dump_options.dump_path)__gf_free (dump_options.dump_path); | |||||
806 | dump_options.dump_path = NULL((void*)0); | |||||
807 | gf_proc_dump_unlock (); | |||||
808 | ||||||
809 | return; | |||||
810 | } | |||||
811 | ||||||
812 | ||||||
813 | void | |||||
814 | gf_proc_dump_fini (void) | |||||
815 | { | |||||
816 | pthread_mutex_destroy (&gf_proc_dump_mutex); | |||||
817 | } | |||||
818 | ||||||
819 | ||||||
820 | void | |||||
821 | gf_proc_dump_init () | |||||
822 | { | |||||
823 | pthread_mutex_init (&gf_proc_dump_mutex, NULL((void*)0)); | |||||
824 | ||||||
825 | return; | |||||
826 | } | |||||
827 | ||||||
828 | ||||||
829 | void | |||||
830 | gf_proc_dump_cleanup (void) | |||||
831 | { | |||||
832 | pthread_mutex_destroy (&gf_proc_dump_mutex); | |||||
833 | } |