glusterfs
441 строка · 11.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 "glusterfs/statedump.h"12#include "glusterfs/stack.h"13#include "glusterfs/libglusterfs-messages.h"14
15call_frame_t *16create_frame(xlator_t *xl, call_pool_t *pool)17{
18call_stack_t *stack = NULL;19call_frame_t *frame = NULL;20static uint64_t unique = 0;21
22if (!xl || !pool) {23return NULL;24}25
26stack = mem_get0(pool->stack_mem_pool);27if (!stack)28return NULL;29
30INIT_LIST_HEAD(&stack->myframes);31
32frame = mem_get0(pool->frame_mem_pool);33if (!frame) {34mem_put(stack);35return NULL;36}37
38frame->root = stack;39frame->this = xl;40LOCK_INIT(&frame->lock);41INIT_LIST_HEAD(&frame->frames);42list_add(&frame->frames, &stack->myframes);43
44stack->pool = pool;45stack->ctx = xl->ctx;46
47if (frame->root->ctx->measure_latency) {48timespec_now(&stack->tv);49memcpy(&frame->begin, &stack->tv, sizeof(stack->tv));50}51
52LOCK(&pool->lock);53{54list_add(&stack->all_frames, &pool->all_frames);55pool->cnt++;56stack->unique = unique++;57}58UNLOCK(&pool->lock);59GF_ATOMIC_INC(pool->total_count);60
61LOCK_INIT(&stack->stack_lock);62
63return frame;64}
65
66void
67call_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
71if (ngrps <= SMALL_GROUP_COUNT) {72memcpy(stack->groups_small, *groupbuf_p, sizeof(gid_t) * ngrps);73stack->groups = stack->groups_small;74GF_FREE(*groupbuf_p);75} else {76stack->groups_large = *groupbuf_p;77stack->groups = stack->groups_large;78}79
80stack->ngrps = ngrps;81/* Set a canary. */82*groupbuf_p = (void *)0xdeadf00d;83}
84
85static void86gf_proc_dump_call_frame(call_frame_t *call_frame, const char *key_buf, ...)87{
88char prefix[GF_DUMP_MAX_BUF_LEN];89va_list ap;90call_frame_t my_frame = {910,92};93
94int ret = -1;95char timestr[GF_TIMESTR_SIZE] = {960,97};98int len;99
100if (!call_frame)101return;102
103GF_ASSERT(key_buf);104
105va_start(ap, key_buf);106vsnprintf(prefix, GF_DUMP_MAX_BUF_LEN, key_buf, ap);107va_end(ap);108
109ret = TRY_LOCK(&call_frame->lock);110if (ret)111goto out;112
113memcpy(&my_frame, call_frame, sizeof(my_frame));114UNLOCK(&call_frame->lock);115
116if (my_frame.root->ctx->measure_latency) {117len = gf_time_fmt_FT(timestr, sizeof(timestr), my_frame.begin.tv_sec);118snprintf(timestr + len, sizeof(timestr) - len, ".%" GF_PRI_SNSECONDS,119my_frame.begin.tv_nsec);120gf_proc_dump_write("frame-creation-time", "%s", timestr);121gf_proc_dump_write(122"timings", "%ld.%" GF_PRI_SNSECONDS " -> %ld.%" GF_PRI_SNSECONDS,123my_frame.begin.tv_sec, my_frame.begin.tv_nsec, my_frame.end.tv_sec,124my_frame.end.tv_nsec);125}126
127gf_proc_dump_write("frame", "%p", call_frame);128gf_proc_dump_write("translator", "%s", my_frame.this->name);129gf_proc_dump_write("complete", "%d", my_frame.complete);130
131if (my_frame.parent)132gf_proc_dump_write("parent", "%s", my_frame.parent->this->name);133
134if (my_frame.wind_from)135gf_proc_dump_write("wind_from", "%s", my_frame.wind_from);136
137if (my_frame.wind_to)138gf_proc_dump_write("wind_to", "%s", my_frame.wind_to);139
140if (my_frame.unwind_from)141gf_proc_dump_write("unwind_from", "%s", my_frame.unwind_from);142
143if (my_frame.unwind_to)144gf_proc_dump_write("unwind_to", "%s", my_frame.unwind_to);145
146return;147out:148if (ret) {149gf_proc_dump_write("Unable to dump the frame information",150"(Lock acquisition failed)");151return;152}153}
154
155static void156gf_proc_dump_call_stack(call_stack_t *call_stack, const char *key_buf, ...)157{
158char prefix[GF_DUMP_MAX_BUF_LEN];159va_list ap;160call_frame_t *trav;161int32_t i = 1, cnt = 0;162char timestr[GF_TIMESTR_SIZE];163int len;164
165if (!call_stack)166return;167
168GF_ASSERT(key_buf);169
170va_start(ap, key_buf);171vsnprintf(prefix, GF_DUMP_MAX_BUF_LEN, key_buf, ap);172va_end(ap);173
174cnt = call_frames_count(call_stack);175len = gf_time_fmt_FT(timestr, sizeof(timestr), call_stack->tv.tv_sec);176snprintf(timestr + len, sizeof(timestr) - len, ".%" GF_PRI_SNSECONDS,177call_stack->tv.tv_nsec);178gf_proc_dump_write("callstack-creation-time", "%s", timestr);179
180gf_proc_dump_write("stack", "%p", call_stack);181gf_proc_dump_write("uid", "%d", call_stack->uid);182gf_proc_dump_write("gid", "%d", call_stack->gid);183gf_proc_dump_write("pid", "%d", call_stack->pid);184gf_proc_dump_write("unique", "%" PRIu64, call_stack->unique);185gf_proc_dump_write("lk-owner", "%s", lkowner_utoa(&call_stack->lk_owner));186gf_proc_dump_write("ctime", "%" GF_PRI_SECOND ".%" GF_PRI_SNSECONDS,187call_stack->ctime.tv_sec, call_stack->ctime.tv_nsec);188
189if (call_stack->type == GF_OP_TYPE_FOP)190gf_proc_dump_write("op", "%s", (char *)gf_fop_list[call_stack->op]);191else192gf_proc_dump_write("op", "stack");193
194gf_proc_dump_write("type", "%d", call_stack->type);195gf_proc_dump_write("cnt", "%d", cnt);196
197list_for_each_entry(trav, &call_stack->myframes, frames)198{199gf_proc_dump_add_section("%s.frame.%d", prefix, i);200gf_proc_dump_call_frame(trav, "%s.frame.%d", prefix, i);201i++;202}203}
204
205void
206gf_proc_dump_pending_frames(call_pool_t *call_pool)207{
208call_stack_t *trav = NULL;209int i = 1;210int ret = -1;211gf_boolean_t section_added = _gf_false;212
213if (!call_pool)214return;215
216ret = TRY_LOCK(&(call_pool->lock));217if (ret)218goto out;219
220gf_proc_dump_add_section("global.callpool");221section_added = _gf_true;222gf_proc_dump_write("callpool_address", "%p", call_pool);223gf_proc_dump_write("callpool.cnt", "%" PRId64, call_pool->cnt);224
225list_for_each_entry(trav, &call_pool->all_frames, all_frames)226{227gf_proc_dump_add_section("global.callpool.stack.%d", i);228gf_proc_dump_call_stack(trav, "global.callpool.stack.%d", i);229i++;230}231UNLOCK(&(call_pool->lock));232
233ret = 0;234out:235if (ret) {236if (_gf_false == section_added)237gf_proc_dump_add_section("global.callpool");238gf_proc_dump_write("Unable to dump the callpool",239"(Lock acquisition failed) %p", call_pool);240}241return;242}
243
244static void245gf_proc_dump_call_frame_to_dict(call_frame_t *call_frame, char *prefix,246dict_t *dict)247{
248int ret = -1;249char key[128] = {2500,251};252char msg[128] = {2530,254};255call_frame_t tmp_frame = {2560,257};258
259if (!call_frame || !dict)260return;261
262ret = TRY_LOCK(&call_frame->lock);263if (ret)264return;265memcpy(&tmp_frame, call_frame, sizeof(tmp_frame));266UNLOCK(&call_frame->lock);267
268snprintf(key, sizeof(key), "%s.translator", prefix);269ret = dict_set_dynstr(dict, key, gf_strdup(tmp_frame.this->name));270if (ret)271return;272
273snprintf(key, sizeof(key), "%s.complete", prefix);274ret = dict_set_int32(dict, key, tmp_frame.complete);275if (ret)276return;277
278if (tmp_frame.root->ctx->measure_latency) {279snprintf(key, sizeof(key), "%s.timings", prefix);280snprintf(msg, sizeof(msg),281"%ld.%" GF_PRI_SNSECONDS " -> %ld.%" GF_PRI_SNSECONDS,282tmp_frame.begin.tv_sec, tmp_frame.begin.tv_nsec,283tmp_frame.end.tv_sec, tmp_frame.end.tv_nsec);284ret = dict_set_str(dict, key, msg);285if (ret)286return;287}288
289if (tmp_frame.parent) {290snprintf(key, sizeof(key), "%s.parent", prefix);291ret = dict_set_dynstr(dict, key,292gf_strdup(tmp_frame.parent->this->name));293if (ret)294return;295}296
297if (tmp_frame.wind_from) {298snprintf(key, sizeof(key), "%s.windfrom", prefix);299ret = dict_set_dynstr(dict, key, gf_strdup(tmp_frame.wind_from));300if (ret)301return;302}303
304if (tmp_frame.wind_to) {305snprintf(key, sizeof(key), "%s.windto", prefix);306ret = dict_set_dynstr(dict, key, gf_strdup(tmp_frame.wind_to));307if (ret)308return;309}310
311if (tmp_frame.unwind_from) {312snprintf(key, sizeof(key), "%s.unwindfrom", prefix);313ret = dict_set_dynstr(dict, key, gf_strdup(tmp_frame.unwind_from));314if (ret)315return;316}317
318if (tmp_frame.unwind_to) {319snprintf(key, sizeof(key), "%s.unwind_to", prefix);320ret = dict_set_dynstr(dict, key, gf_strdup(tmp_frame.unwind_to));321if (ret)322return;323}324
325return;326}
327
328static void329gf_proc_dump_call_stack_to_dict(call_stack_t *call_stack, char *prefix,330dict_t *dict)331{
332int ret = -1;333char key[64] = {3340,335};336call_frame_t *trav = NULL;337int i = 0;338int count = 0;339
340if (!call_stack || !dict)341return;342
343count = call_frames_count(call_stack);344snprintf(key, sizeof(key), "%s.uid", prefix);345ret = dict_set_int32(dict, key, call_stack->uid);346if (ret)347return;348
349snprintf(key, sizeof(key), "%s.gid", prefix);350ret = dict_set_int32(dict, key, call_stack->gid);351if (ret)352return;353
354snprintf(key, sizeof(key), "%s.pid", prefix);355ret = dict_set_int32(dict, key, call_stack->pid);356if (ret)357return;358
359snprintf(key, sizeof(key), "%s.unique", prefix);360ret = dict_set_uint64(dict, key, call_stack->unique);361if (ret)362return;363
364snprintf(key, sizeof(key), "%s.op", prefix);365if (call_stack->type == GF_OP_TYPE_FOP)366ret = dict_set_str(dict, key, (char *)gf_fop_list[call_stack->op]);367else368ret = dict_set_str(dict, key, "other");369
370if (ret)371return;372
373snprintf(key, sizeof(key), "%s.type", prefix);374ret = dict_set_int32(dict, key, call_stack->type);375if (ret)376return;377
378snprintf(key, sizeof(key), "%s.count", prefix);379ret = dict_set_int32(dict, key, count);380if (ret)381return;382
383list_for_each_entry(trav, &call_stack->myframes, frames)384{385snprintf(key, sizeof(key), "%s.frame%d", prefix, i);386gf_proc_dump_call_frame_to_dict(trav, key, dict);387i++;388}389
390return;391}
392
393void
394gf_proc_dump_pending_frames_to_dict(call_pool_t *call_pool, dict_t *dict)395{
396int ret = -1;397call_stack_t *trav = NULL;398char key[32] = {3990,400};401int i = 0;402
403if (!call_pool || !dict)404return;405
406ret = TRY_LOCK(&call_pool->lock);407if (ret) {408gf_msg(THIS->name, GF_LOG_WARNING, errno, LG_MSG_LOCK_FAILURE,409"Unable to dump call "410"pool to dict.");411return;412}413
414ret = dict_set_int32(dict, "callpool.count", call_pool->cnt);415if (ret)416goto out;417
418list_for_each_entry(trav, &call_pool->all_frames, all_frames)419{420snprintf(key, sizeof(key), "callpool.stack%d", i);421gf_proc_dump_call_stack_to_dict(trav, key, dict);422i++;423}424
425out:426UNLOCK(&call_pool->lock);427
428return;429}
430
431gf_boolean_t
432__is_fuse_call(call_frame_t *frame)433{
434gf_boolean_t is_fuse_call = _gf_false;435GF_ASSERT(frame);436GF_ASSERT(frame->root);437
438if (NFS_PID != frame->root->pid)439is_fuse_call = _gf_true;440return is_fuse_call;441}
442