glusterfs

Форк
0
/
statedump.c 
1083 строки · 28.5 Кб
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/logging.h"
13
#include "glusterfs/statedump.h"
14
#include "glusterfs/syscall.h"
15

16
#ifdef HAVE_MALLOC_H
17
#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
22
   inside a signal handler and cannot afford to block on a lock.*/
23
#ifdef gf_log
24
#undef gf_log
25
#endif
26

27
#define GF_PROC_DUMP_SET_OPTION(opt, val) opt = val
28

29
#define GF_CHECK_DUMP_OPTION_ENABLED(option_dump, var, label)                  \
30
    do {                                                                       \
31
        if (option_dump == _gf_true) {                                         \
32
            var = _gf_false;                                                   \
33
            goto 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

43
extern xlator_t global_xlator;
44

45
static pthread_mutex_t gf_proc_dump_mutex;
46
static int gf_dump_fd = -1;
47
gf_dump_options_t dump_options;
48

49
static strfd_t *gf_dump_strfd = NULL;
50

51
static void
52
gf_proc_dump_lock(void)
53
{
54
    pthread_mutex_lock(&gf_proc_dump_mutex);
55
}
56

57
static void
58
gf_proc_dump_unlock(void)
59
{
60
    pthread_mutex_unlock(&gf_proc_dump_mutex);
61
}
62

63
static int
64
gf_proc_dump_open(char *tmpname)
65
{
66
    int dump_fd = -1;
67

68
    mode_t mask = umask(S_IRWXG | S_IRWXO);
69
    dump_fd = mkstemp(tmpname);
70
    umask(mask);
71
    if (dump_fd < 0)
72
        return -1;
73

74
    gf_dump_fd = dump_fd;
75
    return 0;
76
}
77

78
static void
79
gf_proc_dump_close(void)
80
{
81
    sys_close(gf_dump_fd);
82
    gf_dump_fd = -1;
83
}
84

85
static int
86
gf_proc_dump_set_path(char *dump_options_file)
87
{
88
    int ret = -1;
89
    FILE *fp = NULL;
90
    char buf[256];
91
    char *key = NULL, *value = NULL;
92
    char *saveptr = NULL;
93

94
    fp = fopen(dump_options_file, "r");
95
    if (!fp)
96
        goto out;
97

98
    ret = fscanf(fp, "%255s", buf);
99

100
    while (ret != EOF) {
101
        key = strtok_r(buf, "=", &saveptr);
102
        if (!key) {
103
            ret = fscanf(fp, "%255s", buf);
104
            continue;
105
        }
106

107
        value = strtok_r(NULL, "=", &saveptr);
108

109
        if (!value) {
110
            ret = fscanf(fp, "%255s", buf);
111
            continue;
112
        }
113
        if (!strcmp(key, "path")) {
114
            dump_options.dump_path = gf_strdup(value);
115
            break;
116
        }
117
    }
118

119
out:
120
    if (fp)
121
        fclose(fp);
122
    return ret;
123
}
124

125
static int
126
gf_proc_dump_add_section_fd(char *key, va_list ap)
127
{
128
    char buf[GF_DUMP_MAX_BUF_LEN];
129
    int len;
130

131
    GF_ASSERT(key);
132

133
    len = snprintf(buf, GF_DUMP_MAX_BUF_LEN, "\n[");
134
    len += vsnprintf(buf + len, GF_DUMP_MAX_BUF_LEN - len, key, ap);
135
    len += snprintf(buf + len, GF_DUMP_MAX_BUF_LEN - len, "]\n");
136
    return sys_write(gf_dump_fd, buf, len);
137
}
138

139
static int
140
gf_proc_dump_add_section_strfd(char *key, va_list ap)
141
{
142
    int ret = 0;
143

144
    ret += strprintf(gf_dump_strfd, "[");
145
    ret += strvprintf(gf_dump_strfd, key, ap);
146
    ret += strprintf(gf_dump_strfd, "]\n");
147

148
    return ret;
149
}
150

151
int
152
gf_proc_dump_add_section(char *key, ...)
153
{
154
    va_list ap;
155
    int ret = 0;
156

157
    va_start(ap, key);
158
    if (gf_dump_strfd)
159
        ret = gf_proc_dump_add_section_strfd(key, ap);
160
    else
161
        ret = gf_proc_dump_add_section_fd(key, ap);
162
    va_end(ap);
163

164
    return ret;
165
}
166

167
static int
168
gf_proc_dump_write_fd(char *key, char *value, va_list ap)
169
{
170
    char buf[GF_DUMP_MAX_BUF_LEN];
171
    int len = 0;
172

173
    GF_ASSERT(key);
174

175
    len = snprintf(buf, GF_DUMP_MAX_BUF_LEN, "%s=", key);
176
    len += vsnprintf(buf + len, GF_DUMP_MAX_BUF_LEN - len, value, ap);
177

178
    len += snprintf(buf + len, GF_DUMP_MAX_BUF_LEN - len, "\n");
179
    return sys_write(gf_dump_fd, buf, len);
180
}
181

182
static int
183
gf_proc_dump_write_strfd(char *key, char *value, va_list ap)
184
{
185
    int ret = 0;
186

187
    ret += strprintf(gf_dump_strfd, "%s = ", key);
188
    ret += strvprintf(gf_dump_strfd, value, ap);
189
    ret += strprintf(gf_dump_strfd, "\n");
190

191
    return ret;
192
}
193

194
int
195
gf_proc_dump_write(char *key, char *value, ...)
196
{
197
    int ret = 0;
198
    va_list ap;
199

200
    va_start(ap, value);
201
    if (gf_dump_strfd)
202
        ret = gf_proc_dump_write_strfd(key, value, ap);
203
    else
204
        ret = gf_proc_dump_write_fd(key, value, ap);
205
    va_end(ap);
206

207
    return ret;
208
}
209

210
void
211
gf_latency_statedump_and_reset(char *key, gf_latency_t *lat)
212
{
213
    /* Doesn't make sense to continue if there are no fops
214
       came in the given interval */
215
    if (!lat || !lat->count)
216
        return;
217
    gf_proc_dump_write(key,
218
                       "AVG:%lf CNT:%" PRIu64 " TOTAL:%" PRIu64 " MIN:%" PRIu64
219
                       " MAX:%" PRIu64,
220
                       (((double)lat->total) / lat->count), lat->count,
221
                       lat->total, lat->min, lat->max);
222
    gf_latency_reset(lat);
223
}
224

225
void
226
gf_proc_dump_xl_latency_info(xlator_t *xl)
227
{
228
    char key_prefix[GF_DUMP_MAX_BUF_LEN];
229
    char key[GF_DUMP_MAX_BUF_LEN];
230
    int i;
231

232
    snprintf(key_prefix, GF_DUMP_MAX_BUF_LEN, "%s.latency", xl->name);
233
    gf_proc_dump_add_section("%s", key_prefix);
234

235
    for (i = 0; i < GF_FOP_MAXVALUE; i++) {
236
        gf_proc_dump_build_key(key, key_prefix, "%s", (char *)gf_fop_list[i]);
237

238
        gf_latency_t *lat = &xl->stats[i].latencies;
239

240
        gf_latency_statedump_and_reset(key, lat);
241
    }
242
}
243

244
static void
245
gf_proc_dump_xlator_mem_info(xlator_t *xl)
246
{
247
    int i = 0;
248

249
    if (!xl)
250
        return;
251

252
    if (!xl->mem_acct)
253
        return;
254

255
    gf_proc_dump_add_section("%s.%s - Memory usage", xl->type, xl->name);
256
    gf_proc_dump_write("num_types", "%d", xl->mem_acct->num_types);
257

258
    for (i = 0; i < xl->mem_acct->num_types; i++) {
259
        if (!GF_ATOMIC_GET(xl->mem_acct->rec[i].num_allocs))
260
            continue;
261

262
        gf_proc_dump_add_section("%s.%s - usage-type %s memusage", xl->type,
263
                                 xl->name, xl->mem_acct->rec[i].typestr);
264
#ifdef DEBUG
265
        gf_proc_dump_write("size", "%" PRIu64, xl->mem_acct->rec[i].size);
266
#endif
267
        gf_proc_dump_write("num_allocs", "%" PRIu64,
268
                           GF_ATOMIC_GET(xl->mem_acct->rec[i].num_allocs));
269
#ifdef DEBUG
270
        gf_proc_dump_write("max_size", "%" PRIu64,
271
                           xl->mem_acct->rec[i].max_size);
272
        gf_proc_dump_write("max_num_allocs", "%u",
273
                           xl->mem_acct->rec[i].max_num_allocs);
274
#endif
275
    }
276

277
    return;
278
}
279

280
static void
281
gf_proc_dump_xlator_mem_info_only_in_use(xlator_t *xl)
282
{
283
    int i = 0;
284

285
    if (!xl)
286
        return;
287

288
    if (!xl->mem_acct)
289
        return;
290

291
    gf_proc_dump_add_section("%s.%s - Memory usage", xl->type, xl->name);
292
    gf_proc_dump_write("num_types", "%d", xl->mem_acct->num_types);
293

294
    for (i = 0; i < xl->mem_acct->num_types; i++) {
295
        if (!GF_ATOMIC_GET(xl->mem_acct->rec[i].num_allocs))
296
            continue;
297

298
        gf_proc_dump_add_section("%s.%s - usage-type %d", xl->type, xl->name,
299
                                 i);
300
#ifdef DEBUG
301
        gf_proc_dump_write("size", "%" PRIu64, xl->mem_acct->rec[i].size);
302
        gf_proc_dump_write("max_size", "%" PRIu64,
303
                           xl->mem_acct->rec[i].max_size);
304
#endif
305
        gf_proc_dump_write("num_allocs", "%" PRIu64,
306
                           GF_ATOMIC_GET(xl->mem_acct->rec[i].num_allocs));
307
#ifdef DEBUG
308
        gf_proc_dump_write("max_num_allocs", "%u",
309
                           xl->mem_acct->rec[i].max_num_allocs);
310
#endif
311
    }
312

313
    return;
314
}
315

316
/* Currently this dumps only mallinfo. More can be built on here. */
317

318
#if defined(HAVE_MALLINFO2)
319

320
typedef struct mallinfo2 gf_mallinfo_t;
321

322
static inline void
323
gf_mallinfo(gf_mallinfo_t *info)
324
{
325
    memset(info, 0, sizeof(gf_mallinfo_t));
326
    *info = mallinfo2();
327
}
328

329
#define M_FMT "%zd"
330

331
#elif defined(HAVE_MALLINFO)
332

333
typedef struct mallinfo gf_mallinfo_t;
334

335
static inline void
336
gf_mallinfo(gf_mallinfo_t *info)
337
{
338
    memset(info, 0, sizeof(gf_mallinfo_t));
339
    *info = mallinfo();
340
}
341

342
#define M_FMT "%d"
343

344
#endif /* HAVE_MALLINFO2 */
345

346
void
347
gf_proc_dump_mem_info(void)
348
{
349
#if defined(HAVE_MALLINFO2) || defined(HAVE_MALLINFO)
350
    gf_mallinfo_t info;
351

352
    gf_mallinfo(&info);
353
    gf_proc_dump_add_section("mallinfo");
354
    gf_proc_dump_write("mallinfo_arena", M_FMT, info.arena);
355
    gf_proc_dump_write("mallinfo_ordblks", M_FMT, info.ordblks);
356
    gf_proc_dump_write("mallinfo_smblks", M_FMT, info.smblks);
357
    gf_proc_dump_write("mallinfo_hblks", M_FMT, info.hblks);
358
    gf_proc_dump_write("mallinfo_hblkhd", M_FMT, info.hblkhd);
359
    gf_proc_dump_write("mallinfo_usmblks", M_FMT, info.usmblks);
360
    gf_proc_dump_write("mallinfo_fsmblks", M_FMT, info.fsmblks);
361
    gf_proc_dump_write("mallinfo_uordblks", M_FMT, info.uordblks);
362
    gf_proc_dump_write("mallinfo_fordblks", M_FMT, info.fordblks);
363
    gf_proc_dump_write("mallinfo_keepcost", M_FMT, info.keepcost);
364
#endif /* MALLINFO2 || MALLINFO */
365
    gf_proc_dump_xlator_mem_info(&global_xlator);
366
}
367

368
void
369
gf_proc_dump_mem_info_to_dict(dict_t *dict)
370
{
371
    if (!dict)
372
        return;
373
#if defined(HAVE_MALLINFO2) || defined(HAVE_MALLINFO)
374
    gf_mallinfo_t info;
375
    int ret = -1;
376

377
    gf_mallinfo(&info);
378

379
    ret = dict_set_uint64(dict, "mallinfo.arena", info.arena);
380
    if (ret)
381
        return;
382

383
    ret = dict_set_uint64(dict, "mallinfo.ordblks", info.ordblks);
384
    if (ret)
385
        return;
386

387
    ret = dict_set_uint64(dict, "mallinfo.smblks", info.smblks);
388
    if (ret)
389
        return;
390

391
    ret = dict_set_uint64(dict, "mallinfo.hblks", info.hblks);
392
    if (ret)
393
        return;
394

395
    ret = dict_set_uint64(dict, "mallinfo.hblkhd", info.hblkhd);
396
    if (ret)
397
        return;
398

399
    ret = dict_set_uint64(dict, "mallinfo.usmblks", info.usmblks);
400
    if (ret)
401
        return;
402

403
    ret = dict_set_uint64(dict, "mallinfo.fsmblks", info.fsmblks);
404
    if (ret)
405
        return;
406

407
    ret = dict_set_uint64(dict, "mallinfo.uordblks", info.uordblks);
408
    if (ret)
409
        return;
410

411
    ret = dict_set_uint64(dict, "mallinfo.fordblks", info.fordblks);
412
    if (ret)
413
        return;
414

415
    ret = dict_set_uint64(dict, "mallinfo.keepcost", info.keepcost);
416
    if (ret)
417
        return;
418
#endif /* HAVE_MALLINFO2 || HAVE_MALLINFO */
419
}
420

421
void
422
gf_proc_dump_mempool_info(glusterfs_ctx_t *ctx)
423
{
424
#ifdef GF_DISABLE_MEMPOOL
425
    gf_proc_dump_write("built with --disable-mempool", " so no memory pools");
426
#else
427
    struct mem_pool *pool = NULL;
428

429
    gf_proc_dump_add_section("mempool");
430

431
    LOCK(&ctx->lock);
432
    {
433
        list_for_each_entry(pool, &ctx->mempool_list, owner)
434
        {
435
            int64_t active = GF_ATOMIC_GET(pool->active);
436

437
            gf_proc_dump_write("-----", "-----");
438
            gf_proc_dump_write("pool-name", "%s", pool->name);
439
            gf_proc_dump_write("xlator-name", "%s", pool->xl_name);
440
            gf_proc_dump_write("active-count", "%" GF_PRI_ATOMIC, active);
441
            gf_proc_dump_write("sizeof-type", "%lu", pool->sizeof_type);
442
            gf_proc_dump_write("padded-sizeof", "%d",
443
                               1 << pool->pool->power_of_two);
444
            gf_proc_dump_write("size", "%" PRId64,
445
                               (1 << pool->pool->power_of_two) * active);
446
            gf_proc_dump_write("shared-pool", "%p", pool->pool);
447
        }
448
    }
449
    UNLOCK(&ctx->lock);
450
#endif /* GF_DISABLE_MEMPOOL */
451
}
452

453
void
454
gf_proc_dump_mempool_info_to_dict(glusterfs_ctx_t *ctx, dict_t *dict)
455
{
456
#ifndef GF_DISABLE_MEMPOOL
457
    struct mem_pool *pool = NULL;
458
    char key[GF_DUMP_MAX_BUF_LEN] = {
459
        0,
460
    };
461
    int count = 0;
462
    int ret = -1;
463

464
    if (!ctx || !dict)
465
        return;
466

467
    LOCK(&ctx->lock);
468
    {
469
        list_for_each_entry(pool, &ctx->mempool_list, owner)
470
        {
471
            int64_t active = GF_ATOMIC_GET(pool->active);
472

473
            snprintf(key, sizeof(key), "pool%d.name", count);
474
            ret = dict_set_str(dict, key, pool->name);
475
            if (ret)
476
                goto out;
477

478
            snprintf(key, sizeof(key), "pool%d.active-count", count);
479
            ret = dict_set_uint64(dict, key, active);
480
            if (ret)
481
                goto out;
482

483
            snprintf(key, sizeof(key), "pool%d.sizeof-type", count);
484
            ret = dict_set_uint64(dict, key, pool->sizeof_type);
485
            if (ret)
486
                goto out;
487

488
            snprintf(key, sizeof(key), "pool%d.padded-sizeof", count);
489
            ret = dict_set_uint64(dict, key, 1 << pool->pool->power_of_two);
490
            if (ret)
491
                goto out;
492

493
            snprintf(key, sizeof(key), "pool%d.size", count);
494
            ret = dict_set_uint64(dict, key,
495
                                  (1 << pool->pool->power_of_two) * active);
496
            if (ret)
497
                goto out;
498

499
            snprintf(key, sizeof(key), "pool%d.shared-pool", count);
500
            ret = dict_set_static_ptr(dict, key, pool->pool);
501
            if (ret)
502
                goto out;
503
        }
504
    }
505
out:
506
    UNLOCK(&ctx->lock);
507
#endif /* !GF_DISABLE_MEMPOOL */
508
}
509

510
void
511
gf_proc_dump_latency_info(xlator_t *xl);
512

513
void
514
gf_proc_dump_dict_info(glusterfs_ctx_t *ctx)
515
{
516
    int64_t total_dicts = 0;
517
    int64_t total_pairs = 0;
518

519
    total_dicts = GF_ATOMIC_GET(ctx->stats.total_dicts_used);
520
    total_pairs = GF_ATOMIC_GET(ctx->stats.total_pairs_used);
521

522
    gf_proc_dump_write("max-pairs-per-dict", "%" GF_PRI_ATOMIC,
523
                       GF_ATOMIC_GET(ctx->stats.max_dict_pairs));
524
    gf_proc_dump_write("total-pairs-used", "%" PRId64, total_pairs);
525
    gf_proc_dump_write("total-dicts-used", "%" PRId64, total_dicts);
526
    gf_proc_dump_write("average-pairs-per-dict", "%" PRId64,
527
                       (total_pairs / total_dicts));
528
}
529

530
static void
531
gf_proc_dump_single_xlator_info(xlator_t *trav)
532
{
533
    glusterfs_ctx_t *ctx = trav->ctx;
534
    char itable_key[1024] = {
535
        0,
536
    };
537

538
    if (trav->cleanup_starting)
539
        return;
540

541
    if (ctx->measure_latency)
542
        gf_proc_dump_xl_latency_info(trav);
543

544
    gf_proc_dump_xlator_mem_info(trav);
545

546
    if (GF_PROC_DUMP_IS_XL_OPTION_ENABLED(inode) && (trav->itable)) {
547
        snprintf(itable_key, sizeof(itable_key), "%d.%s.itable", ctx->graph_id,
548
                 trav->name);
549
    }
550

551
    if (!trav->dumpops) {
552
        return;
553
    }
554

555
    if (trav->dumpops->priv && GF_PROC_DUMP_IS_XL_OPTION_ENABLED(priv))
556
        trav->dumpops->priv(trav);
557

558
    if (GF_PROC_DUMP_IS_XL_OPTION_ENABLED(inode) && (trav->dumpops->inode))
559
        trav->dumpops->inode(trav);
560
    if (trav->dumpops->fd && GF_PROC_DUMP_IS_XL_OPTION_ENABLED(fd))
561
        trav->dumpops->fd(trav);
562

563
    if (trav->dumpops->history && GF_PROC_DUMP_IS_XL_OPTION_ENABLED(history))
564
        trav->dumpops->history(trav);
565
}
566

567
static void
568
gf_proc_dump_per_xlator_info(xlator_t *top)
569
{
570
    xlator_t *trav = top;
571

572
    while (trav && !trav->cleanup_starting) {
573
        gf_proc_dump_single_xlator_info(trav);
574
        trav = trav->next;
575
    }
576
}
577

578
static void
579
gf_proc_dump_xlator_info(xlator_t *top, gf_boolean_t brick_mux)
580
{
581
    xlator_t *trav = NULL;
582
    xlator_list_t **trav_p = NULL;
583

584
    if (!top)
585
        return;
586

587
    trav = top;
588
    gf_proc_dump_per_xlator_info(trav);
589

590
    if (brick_mux) {
591
        trav_p = &top->children;
592
        while (*trav_p) {
593
            trav = (*trav_p)->xlator;
594
            gf_proc_dump_per_xlator_info(trav);
595
            trav_p = &(*trav_p)->next;
596
        }
597
    }
598

599
    return;
600
}
601

602
static void
603
gf_proc_dump_oldgraph_xlator_info(xlator_t *top)
604
{
605
    xlator_t *trav = NULL;
606

607
    if (!top)
608
        return;
609

610
    trav = top;
611
    while (trav) {
612
        gf_proc_dump_xlator_mem_info_only_in_use(trav);
613

614
        if (GF_PROC_DUMP_IS_XL_OPTION_ENABLED(inode) && (trav->itable)) {
615
            /*TODO: dump inode table info if necessary by
616
              printing the graph id (taken by glusterfs_cbtx_t)
617
              in the key
618
            */
619
        }
620

621
        if (!trav->dumpops) {
622
            trav = trav->next;
623
            continue;
624
        }
625

626
        if (GF_PROC_DUMP_IS_XL_OPTION_ENABLED(inode) && (trav->dumpops->inode))
627
            trav->dumpops->inode(trav);
628

629
        if (trav->dumpops->fd && GF_PROC_DUMP_IS_XL_OPTION_ENABLED(fd))
630
            trav->dumpops->fd(trav);
631

632
        trav = trav->next;
633
    }
634

635
    return;
636
}
637

638
static int
639
gf_proc_dump_enable_all_options(void)
640
{
641
    GF_PROC_DUMP_SET_OPTION(dump_options.dump_mem, _gf_true);
642
    GF_PROC_DUMP_SET_OPTION(dump_options.dump_iobuf, _gf_true);
643
    GF_PROC_DUMP_SET_OPTION(dump_options.dump_callpool, _gf_true);
644
    GF_PROC_DUMP_SET_OPTION(dump_options.xl_options.dump_priv, _gf_true);
645
    GF_PROC_DUMP_SET_OPTION(dump_options.xl_options.dump_inode, _gf_true);
646
    GF_PROC_DUMP_SET_OPTION(dump_options.xl_options.dump_fd, _gf_true);
647
    GF_PROC_DUMP_SET_OPTION(dump_options.xl_options.dump_inodectx, _gf_true);
648
    GF_PROC_DUMP_SET_OPTION(dump_options.xl_options.dump_fdctx, _gf_true);
649
    GF_PROC_DUMP_SET_OPTION(dump_options.xl_options.dump_history, _gf_true);
650

651
    return 0;
652
}
653

654
gf_boolean_t
655
is_gf_proc_dump_all_disabled(void)
656
{
657
    gf_boolean_t all_disabled = _gf_true;
658

659
    GF_CHECK_DUMP_OPTION_ENABLED(dump_options.dump_mem, all_disabled, out);
660
    GF_CHECK_DUMP_OPTION_ENABLED(dump_options.dump_iobuf, all_disabled, out);
661
    GF_CHECK_DUMP_OPTION_ENABLED(dump_options.dump_callpool, all_disabled, out);
662
    GF_CHECK_DUMP_OPTION_ENABLED(dump_options.xl_options.dump_priv,
663
                                 all_disabled, out);
664
    GF_CHECK_DUMP_OPTION_ENABLED(dump_options.xl_options.dump_inode,
665
                                 all_disabled, out);
666
    GF_CHECK_DUMP_OPTION_ENABLED(dump_options.xl_options.dump_fd, all_disabled,
667
                                 out);
668
    GF_CHECK_DUMP_OPTION_ENABLED(dump_options.xl_options.dump_inodectx,
669
                                 all_disabled, out);
670
    GF_CHECK_DUMP_OPTION_ENABLED(dump_options.xl_options.dump_fdctx,
671
                                 all_disabled, out);
672
    GF_CHECK_DUMP_OPTION_ENABLED(dump_options.xl_options.dump_history,
673
                                 all_disabled, out);
674

675
out:
676
    return all_disabled;
677
}
678

679
/* These options are dumped by default if glusterdump.options
680
   file exists and it is emtpty
681
*/
682
static int
683
gf_proc_dump_enable_default_options(void)
684
{
685
    GF_PROC_DUMP_SET_OPTION(dump_options.dump_mem, _gf_true);
686
    GF_PROC_DUMP_SET_OPTION(dump_options.dump_callpool, _gf_true);
687

688
    return 0;
689
}
690

691
static int
692
gf_proc_dump_disable_all_options(void)
693
{
694
    GF_PROC_DUMP_SET_OPTION(dump_options.dump_mem, _gf_false);
695
    GF_PROC_DUMP_SET_OPTION(dump_options.dump_iobuf, _gf_false);
696
    GF_PROC_DUMP_SET_OPTION(dump_options.dump_callpool, _gf_false);
697
    GF_PROC_DUMP_SET_OPTION(dump_options.xl_options.dump_priv, _gf_false);
698
    GF_PROC_DUMP_SET_OPTION(dump_options.xl_options.dump_inode, _gf_false);
699
    GF_PROC_DUMP_SET_OPTION(dump_options.xl_options.dump_fd, _gf_false);
700
    GF_PROC_DUMP_SET_OPTION(dump_options.xl_options.dump_inodectx, _gf_false);
701
    GF_PROC_DUMP_SET_OPTION(dump_options.xl_options.dump_fdctx, _gf_false);
702
    GF_PROC_DUMP_SET_OPTION(dump_options.xl_options.dump_history, _gf_false);
703
    return 0;
704
}
705

706
static int
707
gf_proc_dump_parse_set_option(char *key, char *value)
708
{
709
    gf_boolean_t *opt_key = NULL;
710
    gf_boolean_t opt_value = _gf_false;
711
    char buf[GF_DUMP_MAX_BUF_LEN];
712
    int ret = -1;
713
    int len;
714

715
    if (!strcasecmp(key, "all")) {
716
        (void)gf_proc_dump_enable_all_options();
717
        return 0;
718
    } else if (!strcasecmp(key, "mem")) {
719
        opt_key = &dump_options.dump_mem;
720
    } else if (!strcasecmp(key, "iobuf")) {
721
        opt_key = &dump_options.dump_iobuf;
722
    } else if (!strcasecmp(key, "callpool")) {
723
        opt_key = &dump_options.dump_callpool;
724
    } else if (!strcasecmp(key, "priv")) {
725
        opt_key = &dump_options.xl_options.dump_priv;
726
    } else if (!strcasecmp(key, "fd")) {
727
        opt_key = &dump_options.xl_options.dump_fd;
728
    } else if (!strcasecmp(key, "inode")) {
729
        opt_key = &dump_options.xl_options.dump_inode;
730
    } else if (!strcasecmp(key, "inodectx")) {
731
        opt_key = &dump_options.xl_options.dump_inodectx;
732
    } else if (!strcasecmp(key, "fdctx")) {
733
        opt_key = &dump_options.xl_options.dump_fdctx;
734
    } else if (!strcasecmp(key, "history")) {
735
        opt_key = &dump_options.xl_options.dump_history;
736
    }
737

738
    if (!opt_key) {
739
        // None of dump options match the key, return back
740
        len = snprintf(buf, sizeof(buf),
741
                       "[Warning]:None of the options "
742
                       "matched key : %s\n",
743
                       key);
744
        if (len < 0)
745
            ret = -1;
746
        else {
747
            ret = sys_write(gf_dump_fd, buf, len);
748
            if (ret >= 0)
749
                ret = -1;
750
        }
751
        goto out;
752
    }
753

754
    opt_value = (strncasecmp(value, "yes", 3) ? _gf_false : _gf_true);
755

756
    GF_PROC_DUMP_SET_OPTION(*opt_key, opt_value);
757

758
    ret = 0;
759
out:
760
    return ret;
761
}
762

763
static int
764
gf_proc_dump_options_init(void)
765
{
766
    int ret = -1;
767
    FILE *fp = NULL;
768
    char buf[256];
769
    char *key = NULL, *value = NULL;
770
    char *saveptr = NULL;
771
    char dump_option_file[PATH_MAX];
772

773
    /* glusterd will create a file glusterdump.<pid>.options and
774
       sets the statedump options for the process and the file is removed
775
       after the statedump is taken. Direct issue of SIGUSR1 does not have
776
       mechanism for considering the statedump options. So to have a way
777
       of configuring the statedump of all the glusterfs processes through
778
       both cli command and SIGUSR1, glusterdump.options file is searched
779
       and the options mentioned in it are given the higher priority.
780
    */
781
    snprintf(dump_option_file, sizeof(dump_option_file),
782
             DEFAULT_VAR_RUN_DIRECTORY "/glusterdump.options");
783
    fp = fopen(dump_option_file, "r");
784
    if (!fp) {
785
        snprintf(dump_option_file, sizeof(dump_option_file),
786
                 DEFAULT_VAR_RUN_DIRECTORY "/glusterdump.%d.options", getpid());
787

788
        fp = fopen(dump_option_file, "r");
789

790
        if (!fp) {
791
            // ENOENT, return success
792
            (void)gf_proc_dump_enable_all_options();
793
            return 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

802
    ret = fscanf(fp, "%255s", buf);
803

804
    while (ret != EOF) {
805
        key = strtok_r(buf, "=", &saveptr);
806
        if (!key) {
807
            ret = fscanf(fp, "%255s", buf);
808
            continue;
809
        }
810

811
        value = strtok_r(NULL, "=", &saveptr);
812

813
        if (!value) {
814
            ret = fscanf(fp, "%255s", buf);
815
            continue;
816
        }
817

818
        gf_proc_dump_parse_set_option(key, value);
819
    }
820

821
    if (is_gf_proc_dump_all_disabled())
822
        (void)gf_proc_dump_enable_default_options();
823

824
    if (fp)
825
        fclose(fp);
826

827
    return 0;
828
}
829

830
void
831
gf_proc_dump_info(int signum, glusterfs_ctx_t *ctx)
832
{
833
    int i = 0;
834
    int ret = -1;
835
    glusterfs_graph_t *trav = NULL;
836
    char brick_name[PATH_MAX] = {
837
        0,
838
    };
839
    char timestr[GF_TIMESTR_SIZE] = {
840
        0,
841
    };
842
    char sign_string[512] = {
843
        0,
844
    };
845
    char tmp_dump_name[PATH_MAX] = {
846
        0,
847
    };
848
    char path[PATH_MAX] = {
849
        0,
850
    };
851
    struct timeval tv = {
852
        0,
853
    };
854
    gf_boolean_t is_brick_mux = _gf_false;
855
    xlator_t *top = NULL;
856
    xlator_list_t **trav_p = NULL;
857
    int brick_count = 0;
858
    int len = 0;
859

860
    gf_msg_trace("dump", 0, "received statedump request (sig:USR1)");
861

862
    if (!ctx)
863
        goto 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
     */
869
    if (mgmt_is_multiplexed_daemon(ctx->cmd_args.process_name))
870
        pthread_mutex_lock(&ctx->cleanup_lock);
871
    gf_proc_dump_lock();
872

873
    if (!mgmt_is_multiplexed_daemon(ctx->cmd_args.process_name) &&
874
        (ctx && ctx->active)) {
875
        top = ctx->active->first;
876
        for (trav_p = &top->children; *trav_p; trav_p = &(*trav_p)->next) {
877
            brick_count++;
878
        }
879

880
        if (brick_count > 1)
881
            is_brick_mux = _gf_true;
882
    }
883

884
    if (ctx->cmd_args.brick_name) {
885
        GF_REMOVE_SLASH_FROM_PATH(ctx->cmd_args.brick_name, brick_name);
886
    } else
887
        snprintf(brick_name, sizeof(brick_name), "glusterdump");
888

889
    ret = gf_proc_dump_options_init();
890
    if (ret < 0)
891
        goto out;
892

893
    ret = snprintf(
894
        path, sizeof(path), "%s/%s.%d.dump.%" PRIu64,
895
        ((dump_options.dump_path != NULL)
896
             ? dump_options.dump_path
897
             : ((ctx->statedump_path != NULL) ? ctx->statedump_path
898
                                              : DEFAULT_VAR_RUN_DIRECTORY)),
899
        brick_name, getpid(), (uint64_t)gf_time());
900
    if ((ret < 0) || (ret >= sizeof(path))) {
901
        goto out;
902
    }
903

904
    snprintf(
905
        tmp_dump_name, PATH_MAX, "%s/dumpXXXXXX",
906
        ((dump_options.dump_path != NULL)
907
             ? dump_options.dump_path
908
             : ((ctx->statedump_path != NULL) ? ctx->statedump_path
909
                                              : DEFAULT_VAR_RUN_DIRECTORY)));
910

911
    ret = gf_proc_dump_open(tmp_dump_name);
912
    if (ret < 0)
913
        goto out;
914

915
    // continue even though gettimeofday() has failed
916
    ret = gettimeofday(&tv, NULL);
917
    if (0 == ret) {
918
        gf_time_fmt_tv_FT(timestr, sizeof timestr, &tv, &ctx->log);
919
        len = snprintf(sign_string, sizeof(sign_string),
920
                       "DUMP-START-TIME: %s\n", timestr);
921

922
        // swallow the errors of write for start and end marker
923
        (void)sys_write(gf_dump_fd, sign_string, len);
924
    }
925
    gf_proc_dump_mempool_info(ctx);
926

927
    if (GF_PROC_DUMP_IS_OPTION_ENABLED(iobuf))
928
        iobuf_stats_dump(ctx->iobuf_pool);
929
    if (GF_PROC_DUMP_IS_OPTION_ENABLED(callpool))
930
        gf_proc_dump_pending_frames(ctx->pool);
931

932
    /* dictionary stats */
933
    gf_proc_dump_add_section("dict");
934
    gf_proc_dump_dict_info(ctx);
935

936
    if (ctx->root) {
937
        gf_proc_dump_add_section("fuse");
938
        gf_proc_dump_single_xlator_info(ctx->root);
939
    }
940

941
    if (ctx->active) {
942
        gf_proc_dump_add_section("active graph - %d", ctx->graph_id);
943
        gf_proc_dump_xlator_info(ctx->active->top, is_brick_mux);
944
    }
945

946
    i = 0;
947
    list_for_each_entry(trav, &ctx->graphs, list)
948
    {
949
        if (trav == ctx->active)
950
            continue;
951

952
        gf_proc_dump_add_section("oldgraph[%d]", i);
953

954
        gf_proc_dump_oldgraph_xlator_info(trav->top);
955
        i++;
956
    }
957

958
    ret = gettimeofday(&tv, NULL);
959
    if (0 == ret) {
960
        gf_time_fmt_tv_FT(timestr, sizeof timestr, &tv, &ctx->log);
961
        len = snprintf(sign_string, sizeof(sign_string), "\nDUMP-END-TIME: %s",
962
                       timestr);
963
        (void)sys_write(gf_dump_fd, sign_string, len);
964
    }
965

966
    if (gf_dump_fd != -1)
967
        gf_proc_dump_close();
968
    sys_rename(tmp_dump_name, path);
969
out:
970
    GF_FREE(dump_options.dump_path);
971
    dump_options.dump_path = NULL;
972
    if (ctx) {
973
        gf_proc_dump_unlock();
974
        if (mgmt_is_multiplexed_daemon(ctx->cmd_args.process_name))
975
            pthread_mutex_unlock(&ctx->cleanup_lock);
976
    }
977

978
    return;
979
}
980

981
void
982
gf_proc_dump_fini(void)
983
{
984
    pthread_mutex_destroy(&gf_proc_dump_mutex);
985
}
986

987
void
988
gf_proc_dump_init(void)
989
{
990
    pthread_mutex_init(&gf_proc_dump_mutex, NULL);
991

992
    return;
993
}
994

995
void
996
gf_proc_dump_cleanup(void)
997
{
998
    pthread_mutex_destroy(&gf_proc_dump_mutex);
999
}
1000

1001
void
1002
gf_proc_dump_xlator_private(xlator_t *this, strfd_t *strfd)
1003
{
1004
    gf_proc_dump_lock();
1005
    {
1006
        gf_dump_strfd = strfd;
1007

1008
        if (this->dumpops && this->dumpops->priv)
1009
            this->dumpops->priv(this);
1010

1011
        gf_dump_strfd = NULL;
1012
    }
1013
    gf_proc_dump_unlock();
1014
}
1015

1016
void
1017
gf_proc_dump_mallinfo(strfd_t *strfd)
1018
{
1019
    gf_proc_dump_lock();
1020
    {
1021
        gf_dump_strfd = strfd;
1022

1023
        gf_proc_dump_mem_info();
1024

1025
        gf_dump_strfd = NULL;
1026
    }
1027
    gf_proc_dump_unlock();
1028
}
1029

1030
void
1031
gf_proc_dump_xlator_history(xlator_t *this, strfd_t *strfd)
1032
{
1033
    gf_proc_dump_lock();
1034
    {
1035
        gf_dump_strfd = strfd;
1036

1037
        if (this->dumpops && this->dumpops->history)
1038
            this->dumpops->history(this);
1039

1040
        gf_dump_strfd = NULL;
1041
    }
1042
    gf_proc_dump_unlock();
1043
}
1044

1045
void
1046
gf_proc_dump_xlator_itable(xlator_t *this, strfd_t *strfd)
1047
{
1048
    gf_proc_dump_lock();
1049
    {
1050
        gf_dump_strfd = strfd;
1051

1052
        gf_dump_strfd = NULL;
1053
    }
1054
    gf_proc_dump_unlock();
1055
}
1056

1057
void
1058
gf_proc_dump_xlator_meminfo(xlator_t *this, strfd_t *strfd)
1059
{
1060
    gf_proc_dump_lock();
1061
    {
1062
        gf_dump_strfd = strfd;
1063

1064
        gf_proc_dump_xlator_mem_info(this);
1065

1066
        gf_dump_strfd = NULL;
1067
    }
1068
    gf_proc_dump_unlock();
1069
}
1070

1071
void
1072
gf_proc_dump_xlator_profile(xlator_t *this, strfd_t *strfd)
1073
{
1074
    gf_proc_dump_lock();
1075
    {
1076
        gf_dump_strfd = strfd;
1077

1078
        gf_proc_dump_xl_latency_info(this);
1079

1080
        gf_dump_strfd = NULL;
1081
    }
1082
    gf_proc_dump_unlock();
1083
}
1084

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.