glusterfs
1083 строки · 28.5 Кб
1/*
2Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com>
3This file is part of GlusterFS.
4
5This file is licensed to you under your choice of the GNU Lesser
6General Public License, version 3 or any later version (LGPLv3 or
7later), or the GNU General Public License, version 2 (GPLv2), in all
8cases as published by the Free Software Foundation.
9*/
10
11#include <stdarg.h>12#include "glusterfs/logging.h"13#include "glusterfs/statedump.h"14#include "glusterfs/syscall.h"15
16#ifdef HAVE_MALLOC_H17#include <malloc.h>18#endif /* MALLOC_H */19
20/* We don't want gf_log in this function because it may cause
21'deadlock' with statedump. This is because statedump happens
22inside a signal handler and cannot afford to block on a lock.*/
23#ifdef gf_log24#undef gf_log25#endif26
27#define GF_PROC_DUMP_SET_OPTION(opt, val) opt = val28
29#define GF_CHECK_DUMP_OPTION_ENABLED(option_dump, var, label) \30do { \31if (option_dump == _gf_true) { \32var = _gf_false; \33goto label; \34} \35} while (0);36
37#define GF_PROC_DUMP_IS_OPTION_ENABLED(opt) \38(dump_options.dump_##opt == _gf_true)39
40#define GF_PROC_DUMP_IS_XL_OPTION_ENABLED(opt) \41(dump_options.xl_options.dump_##opt == _gf_true)42
43extern xlator_t global_xlator;44
45static pthread_mutex_t gf_proc_dump_mutex;46static int gf_dump_fd = -1;47gf_dump_options_t dump_options;48
49static strfd_t *gf_dump_strfd = NULL;50
51static void52gf_proc_dump_lock(void)53{
54pthread_mutex_lock(&gf_proc_dump_mutex);55}
56
57static void58gf_proc_dump_unlock(void)59{
60pthread_mutex_unlock(&gf_proc_dump_mutex);61}
62
63static int64gf_proc_dump_open(char *tmpname)65{
66int dump_fd = -1;67
68mode_t mask = umask(S_IRWXG | S_IRWXO);69dump_fd = mkstemp(tmpname);70umask(mask);71if (dump_fd < 0)72return -1;73
74gf_dump_fd = dump_fd;75return 0;76}
77
78static void79gf_proc_dump_close(void)80{
81sys_close(gf_dump_fd);82gf_dump_fd = -1;83}
84
85static int86gf_proc_dump_set_path(char *dump_options_file)87{
88int ret = -1;89FILE *fp = NULL;90char buf[256];91char *key = NULL, *value = NULL;92char *saveptr = NULL;93
94fp = fopen(dump_options_file, "r");95if (!fp)96goto out;97
98ret = fscanf(fp, "%255s", buf);99
100while (ret != EOF) {101key = strtok_r(buf, "=", &saveptr);102if (!key) {103ret = fscanf(fp, "%255s", buf);104continue;105}106
107value = strtok_r(NULL, "=", &saveptr);108
109if (!value) {110ret = fscanf(fp, "%255s", buf);111continue;112}113if (!strcmp(key, "path")) {114dump_options.dump_path = gf_strdup(value);115break;116}117}118
119out:120if (fp)121fclose(fp);122return ret;123}
124
125static int126gf_proc_dump_add_section_fd(char *key, va_list ap)127{
128char buf[GF_DUMP_MAX_BUF_LEN];129int len;130
131GF_ASSERT(key);132
133len = snprintf(buf, GF_DUMP_MAX_BUF_LEN, "\n[");134len += vsnprintf(buf + len, GF_DUMP_MAX_BUF_LEN - len, key, ap);135len += snprintf(buf + len, GF_DUMP_MAX_BUF_LEN - len, "]\n");136return sys_write(gf_dump_fd, buf, len);137}
138
139static int140gf_proc_dump_add_section_strfd(char *key, va_list ap)141{
142int ret = 0;143
144ret += strprintf(gf_dump_strfd, "[");145ret += strvprintf(gf_dump_strfd, key, ap);146ret += strprintf(gf_dump_strfd, "]\n");147
148return ret;149}
150
151int
152gf_proc_dump_add_section(char *key, ...)153{
154va_list ap;155int ret = 0;156
157va_start(ap, key);158if (gf_dump_strfd)159ret = gf_proc_dump_add_section_strfd(key, ap);160else161ret = gf_proc_dump_add_section_fd(key, ap);162va_end(ap);163
164return ret;165}
166
167static int168gf_proc_dump_write_fd(char *key, char *value, va_list ap)169{
170char buf[GF_DUMP_MAX_BUF_LEN];171int len = 0;172
173GF_ASSERT(key);174
175len = snprintf(buf, GF_DUMP_MAX_BUF_LEN, "%s=", key);176len += vsnprintf(buf + len, GF_DUMP_MAX_BUF_LEN - len, value, ap);177
178len += snprintf(buf + len, GF_DUMP_MAX_BUF_LEN - len, "\n");179return sys_write(gf_dump_fd, buf, len);180}
181
182static int183gf_proc_dump_write_strfd(char *key, char *value, va_list ap)184{
185int ret = 0;186
187ret += strprintf(gf_dump_strfd, "%s = ", key);188ret += strvprintf(gf_dump_strfd, value, ap);189ret += strprintf(gf_dump_strfd, "\n");190
191return ret;192}
193
194int
195gf_proc_dump_write(char *key, char *value, ...)196{
197int ret = 0;198va_list ap;199
200va_start(ap, value);201if (gf_dump_strfd)202ret = gf_proc_dump_write_strfd(key, value, ap);203else204ret = gf_proc_dump_write_fd(key, value, ap);205va_end(ap);206
207return ret;208}
209
210void
211gf_latency_statedump_and_reset(char *key, gf_latency_t *lat)212{
213/* Doesn't make sense to continue if there are no fops214came in the given interval */
215if (!lat || !lat->count)216return;217gf_proc_dump_write(key,218"AVG:%lf CNT:%" PRIu64 " TOTAL:%" PRIu64 " MIN:%" PRIu64219" MAX:%" PRIu64,220(((double)lat->total) / lat->count), lat->count,221lat->total, lat->min, lat->max);222gf_latency_reset(lat);223}
224
225void
226gf_proc_dump_xl_latency_info(xlator_t *xl)227{
228char key_prefix[GF_DUMP_MAX_BUF_LEN];229char key[GF_DUMP_MAX_BUF_LEN];230int i;231
232snprintf(key_prefix, GF_DUMP_MAX_BUF_LEN, "%s.latency", xl->name);233gf_proc_dump_add_section("%s", key_prefix);234
235for (i = 0; i < GF_FOP_MAXVALUE; i++) {236gf_proc_dump_build_key(key, key_prefix, "%s", (char *)gf_fop_list[i]);237
238gf_latency_t *lat = &xl->stats[i].latencies;239
240gf_latency_statedump_and_reset(key, lat);241}242}
243
244static void245gf_proc_dump_xlator_mem_info(xlator_t *xl)246{
247int i = 0;248
249if (!xl)250return;251
252if (!xl->mem_acct)253return;254
255gf_proc_dump_add_section("%s.%s - Memory usage", xl->type, xl->name);256gf_proc_dump_write("num_types", "%d", xl->mem_acct->num_types);257
258for (i = 0; i < xl->mem_acct->num_types; i++) {259if (!GF_ATOMIC_GET(xl->mem_acct->rec[i].num_allocs))260continue;261
262gf_proc_dump_add_section("%s.%s - usage-type %s memusage", xl->type,263xl->name, xl->mem_acct->rec[i].typestr);264#ifdef DEBUG265gf_proc_dump_write("size", "%" PRIu64, xl->mem_acct->rec[i].size);266#endif267gf_proc_dump_write("num_allocs", "%" PRIu64,268GF_ATOMIC_GET(xl->mem_acct->rec[i].num_allocs));269#ifdef DEBUG270gf_proc_dump_write("max_size", "%" PRIu64,271xl->mem_acct->rec[i].max_size);272gf_proc_dump_write("max_num_allocs", "%u",273xl->mem_acct->rec[i].max_num_allocs);274#endif275}276
277return;278}
279
280static void281gf_proc_dump_xlator_mem_info_only_in_use(xlator_t *xl)282{
283int i = 0;284
285if (!xl)286return;287
288if (!xl->mem_acct)289return;290
291gf_proc_dump_add_section("%s.%s - Memory usage", xl->type, xl->name);292gf_proc_dump_write("num_types", "%d", xl->mem_acct->num_types);293
294for (i = 0; i < xl->mem_acct->num_types; i++) {295if (!GF_ATOMIC_GET(xl->mem_acct->rec[i].num_allocs))296continue;297
298gf_proc_dump_add_section("%s.%s - usage-type %d", xl->type, xl->name,299i);300#ifdef DEBUG301gf_proc_dump_write("size", "%" PRIu64, xl->mem_acct->rec[i].size);302gf_proc_dump_write("max_size", "%" PRIu64,303xl->mem_acct->rec[i].max_size);304#endif305gf_proc_dump_write("num_allocs", "%" PRIu64,306GF_ATOMIC_GET(xl->mem_acct->rec[i].num_allocs));307#ifdef DEBUG308gf_proc_dump_write("max_num_allocs", "%u",309xl->mem_acct->rec[i].max_num_allocs);310#endif311}312
313return;314}
315
316/* Currently this dumps only mallinfo. More can be built on here. */
317
318#if defined(HAVE_MALLINFO2)319
320typedef struct mallinfo2 gf_mallinfo_t;321
322static inline void323gf_mallinfo(gf_mallinfo_t *info)324{
325memset(info, 0, sizeof(gf_mallinfo_t));326*info = mallinfo2();327}
328
329#define M_FMT "%zd"330
331#elif defined(HAVE_MALLINFO)332
333typedef struct mallinfo gf_mallinfo_t;334
335static inline void336gf_mallinfo(gf_mallinfo_t *info)337{
338memset(info, 0, sizeof(gf_mallinfo_t));339*info = mallinfo();340}
341
342#define M_FMT "%d"343
344#endif /* HAVE_MALLINFO2 */345
346void
347gf_proc_dump_mem_info(void)348{
349#if defined(HAVE_MALLINFO2) || defined(HAVE_MALLINFO)350gf_mallinfo_t info;351
352gf_mallinfo(&info);353gf_proc_dump_add_section("mallinfo");354gf_proc_dump_write("mallinfo_arena", M_FMT, info.arena);355gf_proc_dump_write("mallinfo_ordblks", M_FMT, info.ordblks);356gf_proc_dump_write("mallinfo_smblks", M_FMT, info.smblks);357gf_proc_dump_write("mallinfo_hblks", M_FMT, info.hblks);358gf_proc_dump_write("mallinfo_hblkhd", M_FMT, info.hblkhd);359gf_proc_dump_write("mallinfo_usmblks", M_FMT, info.usmblks);360gf_proc_dump_write("mallinfo_fsmblks", M_FMT, info.fsmblks);361gf_proc_dump_write("mallinfo_uordblks", M_FMT, info.uordblks);362gf_proc_dump_write("mallinfo_fordblks", M_FMT, info.fordblks);363gf_proc_dump_write("mallinfo_keepcost", M_FMT, info.keepcost);364#endif /* MALLINFO2 || MALLINFO */365gf_proc_dump_xlator_mem_info(&global_xlator);366}
367
368void
369gf_proc_dump_mem_info_to_dict(dict_t *dict)370{
371if (!dict)372return;373#if defined(HAVE_MALLINFO2) || defined(HAVE_MALLINFO)374gf_mallinfo_t info;375int ret = -1;376
377gf_mallinfo(&info);378
379ret = dict_set_uint64(dict, "mallinfo.arena", info.arena);380if (ret)381return;382
383ret = dict_set_uint64(dict, "mallinfo.ordblks", info.ordblks);384if (ret)385return;386
387ret = dict_set_uint64(dict, "mallinfo.smblks", info.smblks);388if (ret)389return;390
391ret = dict_set_uint64(dict, "mallinfo.hblks", info.hblks);392if (ret)393return;394
395ret = dict_set_uint64(dict, "mallinfo.hblkhd", info.hblkhd);396if (ret)397return;398
399ret = dict_set_uint64(dict, "mallinfo.usmblks", info.usmblks);400if (ret)401return;402
403ret = dict_set_uint64(dict, "mallinfo.fsmblks", info.fsmblks);404if (ret)405return;406
407ret = dict_set_uint64(dict, "mallinfo.uordblks", info.uordblks);408if (ret)409return;410
411ret = dict_set_uint64(dict, "mallinfo.fordblks", info.fordblks);412if (ret)413return;414
415ret = dict_set_uint64(dict, "mallinfo.keepcost", info.keepcost);416if (ret)417return;418#endif /* HAVE_MALLINFO2 || HAVE_MALLINFO */419}
420
421void
422gf_proc_dump_mempool_info(glusterfs_ctx_t *ctx)423{
424#ifdef GF_DISABLE_MEMPOOL425gf_proc_dump_write("built with --disable-mempool", " so no memory pools");426#else427struct mem_pool *pool = NULL;428
429gf_proc_dump_add_section("mempool");430
431LOCK(&ctx->lock);432{433list_for_each_entry(pool, &ctx->mempool_list, owner)434{435int64_t active = GF_ATOMIC_GET(pool->active);436
437gf_proc_dump_write("-----", "-----");438gf_proc_dump_write("pool-name", "%s", pool->name);439gf_proc_dump_write("xlator-name", "%s", pool->xl_name);440gf_proc_dump_write("active-count", "%" GF_PRI_ATOMIC, active);441gf_proc_dump_write("sizeof-type", "%lu", pool->sizeof_type);442gf_proc_dump_write("padded-sizeof", "%d",4431 << pool->pool->power_of_two);444gf_proc_dump_write("size", "%" PRId64,445(1 << pool->pool->power_of_two) * active);446gf_proc_dump_write("shared-pool", "%p", pool->pool);447}448}449UNLOCK(&ctx->lock);450#endif /* GF_DISABLE_MEMPOOL */451}
452
453void
454gf_proc_dump_mempool_info_to_dict(glusterfs_ctx_t *ctx, dict_t *dict)455{
456#ifndef GF_DISABLE_MEMPOOL457struct mem_pool *pool = NULL;458char key[GF_DUMP_MAX_BUF_LEN] = {4590,460};461int count = 0;462int ret = -1;463
464if (!ctx || !dict)465return;466
467LOCK(&ctx->lock);468{469list_for_each_entry(pool, &ctx->mempool_list, owner)470{471int64_t active = GF_ATOMIC_GET(pool->active);472
473snprintf(key, sizeof(key), "pool%d.name", count);474ret = dict_set_str(dict, key, pool->name);475if (ret)476goto out;477
478snprintf(key, sizeof(key), "pool%d.active-count", count);479ret = dict_set_uint64(dict, key, active);480if (ret)481goto out;482
483snprintf(key, sizeof(key), "pool%d.sizeof-type", count);484ret = dict_set_uint64(dict, key, pool->sizeof_type);485if (ret)486goto out;487
488snprintf(key, sizeof(key), "pool%d.padded-sizeof", count);489ret = dict_set_uint64(dict, key, 1 << pool->pool->power_of_two);490if (ret)491goto out;492
493snprintf(key, sizeof(key), "pool%d.size", count);494ret = dict_set_uint64(dict, key,495(1 << pool->pool->power_of_two) * active);496if (ret)497goto out;498
499snprintf(key, sizeof(key), "pool%d.shared-pool", count);500ret = dict_set_static_ptr(dict, key, pool->pool);501if (ret)502goto out;503}504}505out:506UNLOCK(&ctx->lock);507#endif /* !GF_DISABLE_MEMPOOL */508}
509
510void
511gf_proc_dump_latency_info(xlator_t *xl);512
513void
514gf_proc_dump_dict_info(glusterfs_ctx_t *ctx)515{
516int64_t total_dicts = 0;517int64_t total_pairs = 0;518
519total_dicts = GF_ATOMIC_GET(ctx->stats.total_dicts_used);520total_pairs = GF_ATOMIC_GET(ctx->stats.total_pairs_used);521
522gf_proc_dump_write("max-pairs-per-dict", "%" GF_PRI_ATOMIC,523GF_ATOMIC_GET(ctx->stats.max_dict_pairs));524gf_proc_dump_write("total-pairs-used", "%" PRId64, total_pairs);525gf_proc_dump_write("total-dicts-used", "%" PRId64, total_dicts);526gf_proc_dump_write("average-pairs-per-dict", "%" PRId64,527(total_pairs / total_dicts));528}
529
530static void531gf_proc_dump_single_xlator_info(xlator_t *trav)532{
533glusterfs_ctx_t *ctx = trav->ctx;534char itable_key[1024] = {5350,536};537
538if (trav->cleanup_starting)539return;540
541if (ctx->measure_latency)542gf_proc_dump_xl_latency_info(trav);543
544gf_proc_dump_xlator_mem_info(trav);545
546if (GF_PROC_DUMP_IS_XL_OPTION_ENABLED(inode) && (trav->itable)) {547snprintf(itable_key, sizeof(itable_key), "%d.%s.itable", ctx->graph_id,548trav->name);549}550
551if (!trav->dumpops) {552return;553}554
555if (trav->dumpops->priv && GF_PROC_DUMP_IS_XL_OPTION_ENABLED(priv))556trav->dumpops->priv(trav);557
558if (GF_PROC_DUMP_IS_XL_OPTION_ENABLED(inode) && (trav->dumpops->inode))559trav->dumpops->inode(trav);560if (trav->dumpops->fd && GF_PROC_DUMP_IS_XL_OPTION_ENABLED(fd))561trav->dumpops->fd(trav);562
563if (trav->dumpops->history && GF_PROC_DUMP_IS_XL_OPTION_ENABLED(history))564trav->dumpops->history(trav);565}
566
567static void568gf_proc_dump_per_xlator_info(xlator_t *top)569{
570xlator_t *trav = top;571
572while (trav && !trav->cleanup_starting) {573gf_proc_dump_single_xlator_info(trav);574trav = trav->next;575}576}
577
578static void579gf_proc_dump_xlator_info(xlator_t *top, gf_boolean_t brick_mux)580{
581xlator_t *trav = NULL;582xlator_list_t **trav_p = NULL;583
584if (!top)585return;586
587trav = top;588gf_proc_dump_per_xlator_info(trav);589
590if (brick_mux) {591trav_p = &top->children;592while (*trav_p) {593trav = (*trav_p)->xlator;594gf_proc_dump_per_xlator_info(trav);595trav_p = &(*trav_p)->next;596}597}598
599return;600}
601
602static void603gf_proc_dump_oldgraph_xlator_info(xlator_t *top)604{
605xlator_t *trav = NULL;606
607if (!top)608return;609
610trav = top;611while (trav) {612gf_proc_dump_xlator_mem_info_only_in_use(trav);613
614if (GF_PROC_DUMP_IS_XL_OPTION_ENABLED(inode) && (trav->itable)) {615/*TODO: dump inode table info if necessary by616printing the graph id (taken by glusterfs_cbtx_t)
617in the key
618*/
619}620
621if (!trav->dumpops) {622trav = trav->next;623continue;624}625
626if (GF_PROC_DUMP_IS_XL_OPTION_ENABLED(inode) && (trav->dumpops->inode))627trav->dumpops->inode(trav);628
629if (trav->dumpops->fd && GF_PROC_DUMP_IS_XL_OPTION_ENABLED(fd))630trav->dumpops->fd(trav);631
632trav = trav->next;633}634
635return;636}
637
638static int639gf_proc_dump_enable_all_options(void)640{
641GF_PROC_DUMP_SET_OPTION(dump_options.dump_mem, _gf_true);642GF_PROC_DUMP_SET_OPTION(dump_options.dump_iobuf, _gf_true);643GF_PROC_DUMP_SET_OPTION(dump_options.dump_callpool, _gf_true);644GF_PROC_DUMP_SET_OPTION(dump_options.xl_options.dump_priv, _gf_true);645GF_PROC_DUMP_SET_OPTION(dump_options.xl_options.dump_inode, _gf_true);646GF_PROC_DUMP_SET_OPTION(dump_options.xl_options.dump_fd, _gf_true);647GF_PROC_DUMP_SET_OPTION(dump_options.xl_options.dump_inodectx, _gf_true);648GF_PROC_DUMP_SET_OPTION(dump_options.xl_options.dump_fdctx, _gf_true);649GF_PROC_DUMP_SET_OPTION(dump_options.xl_options.dump_history, _gf_true);650
651return 0;652}
653
654gf_boolean_t
655is_gf_proc_dump_all_disabled(void)656{
657gf_boolean_t all_disabled = _gf_true;658
659GF_CHECK_DUMP_OPTION_ENABLED(dump_options.dump_mem, all_disabled, out);660GF_CHECK_DUMP_OPTION_ENABLED(dump_options.dump_iobuf, all_disabled, out);661GF_CHECK_DUMP_OPTION_ENABLED(dump_options.dump_callpool, all_disabled, out);662GF_CHECK_DUMP_OPTION_ENABLED(dump_options.xl_options.dump_priv,663all_disabled, out);664GF_CHECK_DUMP_OPTION_ENABLED(dump_options.xl_options.dump_inode,665all_disabled, out);666GF_CHECK_DUMP_OPTION_ENABLED(dump_options.xl_options.dump_fd, all_disabled,667out);668GF_CHECK_DUMP_OPTION_ENABLED(dump_options.xl_options.dump_inodectx,669all_disabled, out);670GF_CHECK_DUMP_OPTION_ENABLED(dump_options.xl_options.dump_fdctx,671all_disabled, out);672GF_CHECK_DUMP_OPTION_ENABLED(dump_options.xl_options.dump_history,673all_disabled, out);674
675out:676return all_disabled;677}
678
679/* These options are dumped by default if glusterdump.options
680file exists and it is emtpty
681*/
682static int683gf_proc_dump_enable_default_options(void)684{
685GF_PROC_DUMP_SET_OPTION(dump_options.dump_mem, _gf_true);686GF_PROC_DUMP_SET_OPTION(dump_options.dump_callpool, _gf_true);687
688return 0;689}
690
691static int692gf_proc_dump_disable_all_options(void)693{
694GF_PROC_DUMP_SET_OPTION(dump_options.dump_mem, _gf_false);695GF_PROC_DUMP_SET_OPTION(dump_options.dump_iobuf, _gf_false);696GF_PROC_DUMP_SET_OPTION(dump_options.dump_callpool, _gf_false);697GF_PROC_DUMP_SET_OPTION(dump_options.xl_options.dump_priv, _gf_false);698GF_PROC_DUMP_SET_OPTION(dump_options.xl_options.dump_inode, _gf_false);699GF_PROC_DUMP_SET_OPTION(dump_options.xl_options.dump_fd, _gf_false);700GF_PROC_DUMP_SET_OPTION(dump_options.xl_options.dump_inodectx, _gf_false);701GF_PROC_DUMP_SET_OPTION(dump_options.xl_options.dump_fdctx, _gf_false);702GF_PROC_DUMP_SET_OPTION(dump_options.xl_options.dump_history, _gf_false);703return 0;704}
705
706static int707gf_proc_dump_parse_set_option(char *key, char *value)708{
709gf_boolean_t *opt_key = NULL;710gf_boolean_t opt_value = _gf_false;711char buf[GF_DUMP_MAX_BUF_LEN];712int ret = -1;713int len;714
715if (!strcasecmp(key, "all")) {716(void)gf_proc_dump_enable_all_options();717return 0;718} else if (!strcasecmp(key, "mem")) {719opt_key = &dump_options.dump_mem;720} else if (!strcasecmp(key, "iobuf")) {721opt_key = &dump_options.dump_iobuf;722} else if (!strcasecmp(key, "callpool")) {723opt_key = &dump_options.dump_callpool;724} else if (!strcasecmp(key, "priv")) {725opt_key = &dump_options.xl_options.dump_priv;726} else if (!strcasecmp(key, "fd")) {727opt_key = &dump_options.xl_options.dump_fd;728} else if (!strcasecmp(key, "inode")) {729opt_key = &dump_options.xl_options.dump_inode;730} else if (!strcasecmp(key, "inodectx")) {731opt_key = &dump_options.xl_options.dump_inodectx;732} else if (!strcasecmp(key, "fdctx")) {733opt_key = &dump_options.xl_options.dump_fdctx;734} else if (!strcasecmp(key, "history")) {735opt_key = &dump_options.xl_options.dump_history;736}737
738if (!opt_key) {739// None of dump options match the key, return back740len = snprintf(buf, sizeof(buf),741"[Warning]:None of the options "742"matched key : %s\n",743key);744if (len < 0)745ret = -1;746else {747ret = sys_write(gf_dump_fd, buf, len);748if (ret >= 0)749ret = -1;750}751goto out;752}753
754opt_value = (strncasecmp(value, "yes", 3) ? _gf_false : _gf_true);755
756GF_PROC_DUMP_SET_OPTION(*opt_key, opt_value);757
758ret = 0;759out:760return ret;761}
762
763static int764gf_proc_dump_options_init(void)765{
766int ret = -1;767FILE *fp = NULL;768char buf[256];769char *key = NULL, *value = NULL;770char *saveptr = NULL;771char dump_option_file[PATH_MAX];772
773/* glusterd will create a file glusterdump.<pid>.options and774sets the statedump options for the process and the file is removed
775after the statedump is taken. Direct issue of SIGUSR1 does not have
776mechanism for considering the statedump options. So to have a way
777of configuring the statedump of all the glusterfs processes through
778both cli command and SIGUSR1, glusterdump.options file is searched
779and the options mentioned in it are given the higher priority.
780*/
781snprintf(dump_option_file, sizeof(dump_option_file),782DEFAULT_VAR_RUN_DIRECTORY "/glusterdump.options");783fp = fopen(dump_option_file, "r");784if (!fp) {785snprintf(dump_option_file, sizeof(dump_option_file),786DEFAULT_VAR_RUN_DIRECTORY "/glusterdump.%d.options", getpid());787
788fp = fopen(dump_option_file, "r");789
790if (!fp) {791// ENOENT, return success792(void)gf_proc_dump_enable_all_options();793return 0;794}795}796
797(void)gf_proc_dump_disable_all_options();798
799// swallow the errors if setting statedump file path is failed.800(void)gf_proc_dump_set_path(dump_option_file);801
802ret = fscanf(fp, "%255s", buf);803
804while (ret != EOF) {805key = strtok_r(buf, "=", &saveptr);806if (!key) {807ret = fscanf(fp, "%255s", buf);808continue;809}810
811value = strtok_r(NULL, "=", &saveptr);812
813if (!value) {814ret = fscanf(fp, "%255s", buf);815continue;816}817
818gf_proc_dump_parse_set_option(key, value);819}820
821if (is_gf_proc_dump_all_disabled())822(void)gf_proc_dump_enable_default_options();823
824if (fp)825fclose(fp);826
827return 0;828}
829
830void
831gf_proc_dump_info(int signum, glusterfs_ctx_t *ctx)832{
833int i = 0;834int ret = -1;835glusterfs_graph_t *trav = NULL;836char brick_name[PATH_MAX] = {8370,838};839char timestr[GF_TIMESTR_SIZE] = {8400,841};842char sign_string[512] = {8430,844};845char tmp_dump_name[PATH_MAX] = {8460,847};848char path[PATH_MAX] = {8490,850};851struct timeval tv = {8520,853};854gf_boolean_t is_brick_mux = _gf_false;855xlator_t *top = NULL;856xlator_list_t **trav_p = NULL;857int brick_count = 0;858int len = 0;859
860gf_msg_trace("dump", 0, "received statedump request (sig:USR1)");861
862if (!ctx)863goto out;864
865/*866* Multiplexed daemons can change the active graph when attach/detach
867* is called. So this has to be protected with the cleanup lock.
868*/
869if (mgmt_is_multiplexed_daemon(ctx->cmd_args.process_name))870pthread_mutex_lock(&ctx->cleanup_lock);871gf_proc_dump_lock();872
873if (!mgmt_is_multiplexed_daemon(ctx->cmd_args.process_name) &&874(ctx && ctx->active)) {875top = ctx->active->first;876for (trav_p = &top->children; *trav_p; trav_p = &(*trav_p)->next) {877brick_count++;878}879
880if (brick_count > 1)881is_brick_mux = _gf_true;882}883
884if (ctx->cmd_args.brick_name) {885GF_REMOVE_SLASH_FROM_PATH(ctx->cmd_args.brick_name, brick_name);886} else887snprintf(brick_name, sizeof(brick_name), "glusterdump");888
889ret = gf_proc_dump_options_init();890if (ret < 0)891goto out;892
893ret = snprintf(894path, sizeof(path), "%s/%s.%d.dump.%" PRIu64,895((dump_options.dump_path != NULL)896? dump_options.dump_path897: ((ctx->statedump_path != NULL) ? ctx->statedump_path898: DEFAULT_VAR_RUN_DIRECTORY)),899brick_name, getpid(), (uint64_t)gf_time());900if ((ret < 0) || (ret >= sizeof(path))) {901goto out;902}903
904snprintf(905tmp_dump_name, PATH_MAX, "%s/dumpXXXXXX",906((dump_options.dump_path != NULL)907? dump_options.dump_path908: ((ctx->statedump_path != NULL) ? ctx->statedump_path909: DEFAULT_VAR_RUN_DIRECTORY)));910
911ret = gf_proc_dump_open(tmp_dump_name);912if (ret < 0)913goto out;914
915// continue even though gettimeofday() has failed916ret = gettimeofday(&tv, NULL);917if (0 == ret) {918gf_time_fmt_tv_FT(timestr, sizeof timestr, &tv, &ctx->log);919len = snprintf(sign_string, sizeof(sign_string),920"DUMP-START-TIME: %s\n", timestr);921
922// swallow the errors of write for start and end marker923(void)sys_write(gf_dump_fd, sign_string, len);924}925gf_proc_dump_mempool_info(ctx);926
927if (GF_PROC_DUMP_IS_OPTION_ENABLED(iobuf))928iobuf_stats_dump(ctx->iobuf_pool);929if (GF_PROC_DUMP_IS_OPTION_ENABLED(callpool))930gf_proc_dump_pending_frames(ctx->pool);931
932/* dictionary stats */933gf_proc_dump_add_section("dict");934gf_proc_dump_dict_info(ctx);935
936if (ctx->root) {937gf_proc_dump_add_section("fuse");938gf_proc_dump_single_xlator_info(ctx->root);939}940
941if (ctx->active) {942gf_proc_dump_add_section("active graph - %d", ctx->graph_id);943gf_proc_dump_xlator_info(ctx->active->top, is_brick_mux);944}945
946i = 0;947list_for_each_entry(trav, &ctx->graphs, list)948{949if (trav == ctx->active)950continue;951
952gf_proc_dump_add_section("oldgraph[%d]", i);953
954gf_proc_dump_oldgraph_xlator_info(trav->top);955i++;956}957
958ret = gettimeofday(&tv, NULL);959if (0 == ret) {960gf_time_fmt_tv_FT(timestr, sizeof timestr, &tv, &ctx->log);961len = snprintf(sign_string, sizeof(sign_string), "\nDUMP-END-TIME: %s",962timestr);963(void)sys_write(gf_dump_fd, sign_string, len);964}965
966if (gf_dump_fd != -1)967gf_proc_dump_close();968sys_rename(tmp_dump_name, path);969out:970GF_FREE(dump_options.dump_path);971dump_options.dump_path = NULL;972if (ctx) {973gf_proc_dump_unlock();974if (mgmt_is_multiplexed_daemon(ctx->cmd_args.process_name))975pthread_mutex_unlock(&ctx->cleanup_lock);976}977
978return;979}
980
981void
982gf_proc_dump_fini(void)983{
984pthread_mutex_destroy(&gf_proc_dump_mutex);985}
986
987void
988gf_proc_dump_init(void)989{
990pthread_mutex_init(&gf_proc_dump_mutex, NULL);991
992return;993}
994
995void
996gf_proc_dump_cleanup(void)997{
998pthread_mutex_destroy(&gf_proc_dump_mutex);999}
1000
1001void
1002gf_proc_dump_xlator_private(xlator_t *this, strfd_t *strfd)1003{
1004gf_proc_dump_lock();1005{1006gf_dump_strfd = strfd;1007
1008if (this->dumpops && this->dumpops->priv)1009this->dumpops->priv(this);1010
1011gf_dump_strfd = NULL;1012}1013gf_proc_dump_unlock();1014}
1015
1016void
1017gf_proc_dump_mallinfo(strfd_t *strfd)1018{
1019gf_proc_dump_lock();1020{1021gf_dump_strfd = strfd;1022
1023gf_proc_dump_mem_info();1024
1025gf_dump_strfd = NULL;1026}1027gf_proc_dump_unlock();1028}
1029
1030void
1031gf_proc_dump_xlator_history(xlator_t *this, strfd_t *strfd)1032{
1033gf_proc_dump_lock();1034{1035gf_dump_strfd = strfd;1036
1037if (this->dumpops && this->dumpops->history)1038this->dumpops->history(this);1039
1040gf_dump_strfd = NULL;1041}1042gf_proc_dump_unlock();1043}
1044
1045void
1046gf_proc_dump_xlator_itable(xlator_t *this, strfd_t *strfd)1047{
1048gf_proc_dump_lock();1049{1050gf_dump_strfd = strfd;1051
1052gf_dump_strfd = NULL;1053}1054gf_proc_dump_unlock();1055}
1056
1057void
1058gf_proc_dump_xlator_meminfo(xlator_t *this, strfd_t *strfd)1059{
1060gf_proc_dump_lock();1061{1062gf_dump_strfd = strfd;1063
1064gf_proc_dump_xlator_mem_info(this);1065
1066gf_dump_strfd = NULL;1067}1068gf_proc_dump_unlock();1069}
1070
1071void
1072gf_proc_dump_xlator_profile(xlator_t *this, strfd_t *strfd)1073{
1074gf_proc_dump_lock();1075{1076gf_dump_strfd = strfd;1077
1078gf_proc_dump_xl_latency_info(this);1079
1080gf_dump_strfd = NULL;1081}1082gf_proc_dump_unlock();1083}
1084