glusterfs

Форк
0
441 строка · 11.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 "glusterfs/statedump.h"
12
#include "glusterfs/stack.h"
13
#include "glusterfs/libglusterfs-messages.h"
14

15
call_frame_t *
16
create_frame(xlator_t *xl, call_pool_t *pool)
17
{
18
    call_stack_t *stack = NULL;
19
    call_frame_t *frame = NULL;
20
    static uint64_t unique = 0;
21

22
    if (!xl || !pool) {
23
        return NULL;
24
    }
25

26
    stack = mem_get0(pool->stack_mem_pool);
27
    if (!stack)
28
        return NULL;
29

30
    INIT_LIST_HEAD(&stack->myframes);
31

32
    frame = mem_get0(pool->frame_mem_pool);
33
    if (!frame) {
34
        mem_put(stack);
35
        return NULL;
36
    }
37

38
    frame->root = stack;
39
    frame->this = xl;
40
    LOCK_INIT(&frame->lock);
41
    INIT_LIST_HEAD(&frame->frames);
42
    list_add(&frame->frames, &stack->myframes);
43

44
    stack->pool = pool;
45
    stack->ctx = xl->ctx;
46

47
    if (frame->root->ctx->measure_latency) {
48
        timespec_now(&stack->tv);
49
        memcpy(&frame->begin, &stack->tv, sizeof(stack->tv));
50
    }
51

52
    LOCK(&pool->lock);
53
    {
54
        list_add(&stack->all_frames, &pool->all_frames);
55
        pool->cnt++;
56
        stack->unique = unique++;
57
    }
58
    UNLOCK(&pool->lock);
59
    GF_ATOMIC_INC(pool->total_count);
60

61
    LOCK_INIT(&stack->stack_lock);
62

63
    return frame;
64
}
65

66
void
67
call_stack_set_groups(call_stack_t *stack, int ngrps, gid_t **groupbuf_p)
68
{
69
    /* We take the ownership of the passed group buffer. */
70

71
    if (ngrps <= SMALL_GROUP_COUNT) {
72
        memcpy(stack->groups_small, *groupbuf_p, sizeof(gid_t) * ngrps);
73
        stack->groups = stack->groups_small;
74
        GF_FREE(*groupbuf_p);
75
    } else {
76
        stack->groups_large = *groupbuf_p;
77
        stack->groups = stack->groups_large;
78
    }
79

80
    stack->ngrps = ngrps;
81
    /* Set a canary. */
82
    *groupbuf_p = (void *)0xdeadf00d;
83
}
84

85
static void
86
gf_proc_dump_call_frame(call_frame_t *call_frame, const char *key_buf, ...)
87
{
88
    char prefix[GF_DUMP_MAX_BUF_LEN];
89
    va_list ap;
90
    call_frame_t my_frame = {
91
        0,
92
    };
93

94
    int ret = -1;
95
    char timestr[GF_TIMESTR_SIZE] = {
96
        0,
97
    };
98
    int len;
99

100
    if (!call_frame)
101
        return;
102

103
    GF_ASSERT(key_buf);
104

105
    va_start(ap, key_buf);
106
    vsnprintf(prefix, GF_DUMP_MAX_BUF_LEN, key_buf, ap);
107
    va_end(ap);
108

109
    ret = TRY_LOCK(&call_frame->lock);
110
    if (ret)
111
        goto out;
112

113
    memcpy(&my_frame, call_frame, sizeof(my_frame));
114
    UNLOCK(&call_frame->lock);
115

116
    if (my_frame.root->ctx->measure_latency) {
117
        len = gf_time_fmt_FT(timestr, sizeof(timestr), my_frame.begin.tv_sec);
118
        snprintf(timestr + len, sizeof(timestr) - len, ".%" GF_PRI_SNSECONDS,
119
                 my_frame.begin.tv_nsec);
120
        gf_proc_dump_write("frame-creation-time", "%s", timestr);
121
        gf_proc_dump_write(
122
            "timings", "%ld.%" GF_PRI_SNSECONDS " -> %ld.%" GF_PRI_SNSECONDS,
123
            my_frame.begin.tv_sec, my_frame.begin.tv_nsec, my_frame.end.tv_sec,
124
            my_frame.end.tv_nsec);
125
    }
126

127
    gf_proc_dump_write("frame", "%p", call_frame);
128
    gf_proc_dump_write("translator", "%s", my_frame.this->name);
129
    gf_proc_dump_write("complete", "%d", my_frame.complete);
130

131
    if (my_frame.parent)
132
        gf_proc_dump_write("parent", "%s", my_frame.parent->this->name);
133

134
    if (my_frame.wind_from)
135
        gf_proc_dump_write("wind_from", "%s", my_frame.wind_from);
136

137
    if (my_frame.wind_to)
138
        gf_proc_dump_write("wind_to", "%s", my_frame.wind_to);
139

140
    if (my_frame.unwind_from)
141
        gf_proc_dump_write("unwind_from", "%s", my_frame.unwind_from);
142

143
    if (my_frame.unwind_to)
144
        gf_proc_dump_write("unwind_to", "%s", my_frame.unwind_to);
145

146
    return;
147
out:
148
    if (ret) {
149
        gf_proc_dump_write("Unable to dump the frame information",
150
                           "(Lock acquisition failed)");
151
        return;
152
    }
153
}
154

155
static void
156
gf_proc_dump_call_stack(call_stack_t *call_stack, const char *key_buf, ...)
157
{
158
    char prefix[GF_DUMP_MAX_BUF_LEN];
159
    va_list ap;
160
    call_frame_t *trav;
161
    int32_t i = 1, cnt = 0;
162
    char timestr[GF_TIMESTR_SIZE];
163
    int len;
164

165
    if (!call_stack)
166
        return;
167

168
    GF_ASSERT(key_buf);
169

170
    va_start(ap, key_buf);
171
    vsnprintf(prefix, GF_DUMP_MAX_BUF_LEN, key_buf, ap);
172
    va_end(ap);
173

174
    cnt = call_frames_count(call_stack);
175
    len = gf_time_fmt_FT(timestr, sizeof(timestr), call_stack->tv.tv_sec);
176
    snprintf(timestr + len, sizeof(timestr) - len, ".%" GF_PRI_SNSECONDS,
177
             call_stack->tv.tv_nsec);
178
    gf_proc_dump_write("callstack-creation-time", "%s", timestr);
179

180
    gf_proc_dump_write("stack", "%p", call_stack);
181
    gf_proc_dump_write("uid", "%d", call_stack->uid);
182
    gf_proc_dump_write("gid", "%d", call_stack->gid);
183
    gf_proc_dump_write("pid", "%d", call_stack->pid);
184
    gf_proc_dump_write("unique", "%" PRIu64, call_stack->unique);
185
    gf_proc_dump_write("lk-owner", "%s", lkowner_utoa(&call_stack->lk_owner));
186
    gf_proc_dump_write("ctime", "%" GF_PRI_SECOND ".%" GF_PRI_SNSECONDS,
187
                       call_stack->ctime.tv_sec, call_stack->ctime.tv_nsec);
188

189
    if (call_stack->type == GF_OP_TYPE_FOP)
190
        gf_proc_dump_write("op", "%s", (char *)gf_fop_list[call_stack->op]);
191
    else
192
        gf_proc_dump_write("op", "stack");
193

194
    gf_proc_dump_write("type", "%d", call_stack->type);
195
    gf_proc_dump_write("cnt", "%d", cnt);
196

197
    list_for_each_entry(trav, &call_stack->myframes, frames)
198
    {
199
        gf_proc_dump_add_section("%s.frame.%d", prefix, i);
200
        gf_proc_dump_call_frame(trav, "%s.frame.%d", prefix, i);
201
        i++;
202
    }
203
}
204

205
void
206
gf_proc_dump_pending_frames(call_pool_t *call_pool)
207
{
208
    call_stack_t *trav = NULL;
209
    int i = 1;
210
    int ret = -1;
211
    gf_boolean_t section_added = _gf_false;
212

213
    if (!call_pool)
214
        return;
215

216
    ret = TRY_LOCK(&(call_pool->lock));
217
    if (ret)
218
        goto out;
219

220
    gf_proc_dump_add_section("global.callpool");
221
    section_added = _gf_true;
222
    gf_proc_dump_write("callpool_address", "%p", call_pool);
223
    gf_proc_dump_write("callpool.cnt", "%" PRId64, call_pool->cnt);
224

225
    list_for_each_entry(trav, &call_pool->all_frames, all_frames)
226
    {
227
        gf_proc_dump_add_section("global.callpool.stack.%d", i);
228
        gf_proc_dump_call_stack(trav, "global.callpool.stack.%d", i);
229
        i++;
230
    }
231
    UNLOCK(&(call_pool->lock));
232

233
    ret = 0;
234
out:
235
    if (ret) {
236
        if (_gf_false == section_added)
237
            gf_proc_dump_add_section("global.callpool");
238
        gf_proc_dump_write("Unable to dump the callpool",
239
                           "(Lock acquisition failed) %p", call_pool);
240
    }
241
    return;
242
}
243

244
static void
245
gf_proc_dump_call_frame_to_dict(call_frame_t *call_frame, char *prefix,
246
                                dict_t *dict)
247
{
248
    int ret = -1;
249
    char key[128] = {
250
        0,
251
    };
252
    char msg[128] = {
253
        0,
254
    };
255
    call_frame_t tmp_frame = {
256
        0,
257
    };
258

259
    if (!call_frame || !dict)
260
        return;
261

262
    ret = TRY_LOCK(&call_frame->lock);
263
    if (ret)
264
        return;
265
    memcpy(&tmp_frame, call_frame, sizeof(tmp_frame));
266
    UNLOCK(&call_frame->lock);
267

268
    snprintf(key, sizeof(key), "%s.translator", prefix);
269
    ret = dict_set_dynstr(dict, key, gf_strdup(tmp_frame.this->name));
270
    if (ret)
271
        return;
272

273
    snprintf(key, sizeof(key), "%s.complete", prefix);
274
    ret = dict_set_int32(dict, key, tmp_frame.complete);
275
    if (ret)
276
        return;
277

278
    if (tmp_frame.root->ctx->measure_latency) {
279
        snprintf(key, sizeof(key), "%s.timings", prefix);
280
        snprintf(msg, sizeof(msg),
281
                 "%ld.%" GF_PRI_SNSECONDS " -> %ld.%" GF_PRI_SNSECONDS,
282
                 tmp_frame.begin.tv_sec, tmp_frame.begin.tv_nsec,
283
                 tmp_frame.end.tv_sec, tmp_frame.end.tv_nsec);
284
        ret = dict_set_str(dict, key, msg);
285
        if (ret)
286
            return;
287
    }
288

289
    if (tmp_frame.parent) {
290
        snprintf(key, sizeof(key), "%s.parent", prefix);
291
        ret = dict_set_dynstr(dict, key,
292
                              gf_strdup(tmp_frame.parent->this->name));
293
        if (ret)
294
            return;
295
    }
296

297
    if (tmp_frame.wind_from) {
298
        snprintf(key, sizeof(key), "%s.windfrom", prefix);
299
        ret = dict_set_dynstr(dict, key, gf_strdup(tmp_frame.wind_from));
300
        if (ret)
301
            return;
302
    }
303

304
    if (tmp_frame.wind_to) {
305
        snprintf(key, sizeof(key), "%s.windto", prefix);
306
        ret = dict_set_dynstr(dict, key, gf_strdup(tmp_frame.wind_to));
307
        if (ret)
308
            return;
309
    }
310

311
    if (tmp_frame.unwind_from) {
312
        snprintf(key, sizeof(key), "%s.unwindfrom", prefix);
313
        ret = dict_set_dynstr(dict, key, gf_strdup(tmp_frame.unwind_from));
314
        if (ret)
315
            return;
316
    }
317

318
    if (tmp_frame.unwind_to) {
319
        snprintf(key, sizeof(key), "%s.unwind_to", prefix);
320
        ret = dict_set_dynstr(dict, key, gf_strdup(tmp_frame.unwind_to));
321
        if (ret)
322
            return;
323
    }
324

325
    return;
326
}
327

328
static void
329
gf_proc_dump_call_stack_to_dict(call_stack_t *call_stack, char *prefix,
330
                                dict_t *dict)
331
{
332
    int ret = -1;
333
    char key[64] = {
334
        0,
335
    };
336
    call_frame_t *trav = NULL;
337
    int i = 0;
338
    int count = 0;
339

340
    if (!call_stack || !dict)
341
        return;
342

343
    count = call_frames_count(call_stack);
344
    snprintf(key, sizeof(key), "%s.uid", prefix);
345
    ret = dict_set_int32(dict, key, call_stack->uid);
346
    if (ret)
347
        return;
348

349
    snprintf(key, sizeof(key), "%s.gid", prefix);
350
    ret = dict_set_int32(dict, key, call_stack->gid);
351
    if (ret)
352
        return;
353

354
    snprintf(key, sizeof(key), "%s.pid", prefix);
355
    ret = dict_set_int32(dict, key, call_stack->pid);
356
    if (ret)
357
        return;
358

359
    snprintf(key, sizeof(key), "%s.unique", prefix);
360
    ret = dict_set_uint64(dict, key, call_stack->unique);
361
    if (ret)
362
        return;
363

364
    snprintf(key, sizeof(key), "%s.op", prefix);
365
    if (call_stack->type == GF_OP_TYPE_FOP)
366
        ret = dict_set_str(dict, key, (char *)gf_fop_list[call_stack->op]);
367
    else
368
        ret = dict_set_str(dict, key, "other");
369

370
    if (ret)
371
        return;
372

373
    snprintf(key, sizeof(key), "%s.type", prefix);
374
    ret = dict_set_int32(dict, key, call_stack->type);
375
    if (ret)
376
        return;
377

378
    snprintf(key, sizeof(key), "%s.count", prefix);
379
    ret = dict_set_int32(dict, key, count);
380
    if (ret)
381
        return;
382

383
    list_for_each_entry(trav, &call_stack->myframes, frames)
384
    {
385
        snprintf(key, sizeof(key), "%s.frame%d", prefix, i);
386
        gf_proc_dump_call_frame_to_dict(trav, key, dict);
387
        i++;
388
    }
389

390
    return;
391
}
392

393
void
394
gf_proc_dump_pending_frames_to_dict(call_pool_t *call_pool, dict_t *dict)
395
{
396
    int ret = -1;
397
    call_stack_t *trav = NULL;
398
    char key[32] = {
399
        0,
400
    };
401
    int i = 0;
402

403
    if (!call_pool || !dict)
404
        return;
405

406
    ret = TRY_LOCK(&call_pool->lock);
407
    if (ret) {
408
        gf_msg(THIS->name, GF_LOG_WARNING, errno, LG_MSG_LOCK_FAILURE,
409
               "Unable to dump call "
410
               "pool to dict.");
411
        return;
412
    }
413

414
    ret = dict_set_int32(dict, "callpool.count", call_pool->cnt);
415
    if (ret)
416
        goto out;
417

418
    list_for_each_entry(trav, &call_pool->all_frames, all_frames)
419
    {
420
        snprintf(key, sizeof(key), "callpool.stack%d", i);
421
        gf_proc_dump_call_stack_to_dict(trav, key, dict);
422
        i++;
423
    }
424

425
out:
426
    UNLOCK(&call_pool->lock);
427

428
    return;
429
}
430

431
gf_boolean_t
432
__is_fuse_call(call_frame_t *frame)
433
{
434
    gf_boolean_t is_fuse_call = _gf_false;
435
    GF_ASSERT(frame);
436
    GF_ASSERT(frame->root);
437

438
    if (NFS_PID != frame->root->pid)
439
        is_fuse_call = _gf_true;
440
    return is_fuse_call;
441
}
442

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

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

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

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