From 623919a78a7faac30d1f0df5793681da2c449e32 Mon Sep 17 00:00:00 2001 From: Kaushal M Date: Sun, 1 Jan 2012 15:59:28 +0530 Subject: cli: Extend "volume status" with statedump info This patch enhances and extends the "volume status" command with information obtained from the statedump of the bricks of volumes. Adds new status types : clients, inode, fd, mem, callpool The new syntax of "volume status" is, #gluster volume status [all|{ [] [misc-details|clients|inode|fd|mem|callpool]}] Change-Id: I8d019718465bbc3de727653a839de7238f45da5c BUG: 765495 Signed-off-by: Kaushal M Reviewed-on: http://review.gluster.com/2637 Tested-by: Gluster Build System Reviewed-by: Krishnan Parthasarathi --- cli/src/cli-cmd-parser.c | 90 ++- cli/src/cli-cmd-volume.c | 3 +- cli/src/cli-rpc-ops.c | 891 ++++++++++++++++++++++++++- glusterfsd/src/glusterfsd-mgmt.c | 139 ++++- libglusterfs/src/fd.c | 92 +++ libglusterfs/src/inode.c | 96 +++ libglusterfs/src/stack.c | 188 ++++++ libglusterfs/src/stack.h | 3 +- libglusterfs/src/statedump.c | 110 ++++ libglusterfs/src/statedump.h | 8 + libglusterfs/src/xlator.h | 27 +- rpc/rpc-lib/src/protocol-common.h | 1 + rpc/xdr/src/cli1-xdr.h | 20 +- rpc/xdr/src/cli1-xdr.x | 20 +- xlators/mgmt/glusterd/src/glusterd-op-sm.c | 233 ++++++- xlators/mgmt/glusterd/src/glusterd-rpc-ops.c | 22 +- xlators/mgmt/glusterd/src/glusterd.h | 1 + xlators/protocol/server/src/server.c | 139 ++++- 18 files changed, 2008 insertions(+), 75 deletions(-) diff --git a/cli/src/cli-cmd-parser.c b/cli/src/cli-cmd-parser.c index acbd960ba..afd668ea2 100644 --- a/cli/src/cli-cmd-parser.c +++ b/cli/src/cli-cmd-parser.c @@ -1795,6 +1795,42 @@ out: return ret; } +gf_boolean_t +cli_cmd_validate_statusop (const char *arg) +{ + char *opwords[] = {"misc-details", "mem", "clients", "fd", "inode", + "callpool", NULL}; + char *w = NULL; + + w = str_getunamb (arg, opwords); + if (!w) { + gf_log ("cli", GF_LOG_ERROR, "Unknown status op %s", + arg); + return _gf_false; + } + return _gf_true; +} + +int +cli_cmd_get_statusop (const char *arg) +{ + int ret = GF_CLI_STATUS_INVAL; + if (!strcmp (arg, "misc-details")) + ret = GF_CLI_STATUS_DETAIL; + else if (!strcmp (arg, "mem")) + ret = GF_CLI_STATUS_MEM; + else if (!strcmp (arg, "clients")) + ret = GF_CLI_STATUS_CLIENTS; + else if (!strcmp (arg, "inode")) + ret = GF_CLI_STATUS_INODE; + else if (!strcmp (arg, "fd")) + ret = GF_CLI_STATUS_FD; + else if (!strcmp (arg, "callpool")) + ret = GF_CLI_STATUS_CALLPOOL; + + return ret; +} + int cli_cmd_volume_status_parse (const char **words, int wordcount, dict_t **options) @@ -1821,12 +1857,6 @@ cli_cmd_volume_status_parse (const char **words, int wordcount, cmd = GF_CLI_STATUS_ALL; ret = 0; - - } else if (!strcmp (words[2], "detail")) { - - cmd = GF_CLI_STATUS_ALL_DETAIL; - ret = 0; - } else { cmd = GF_CLI_STATUS_VOL; ret = dict_set_str (dict, "volname", (char *)words[2]); @@ -1834,34 +1864,50 @@ cli_cmd_volume_status_parse (const char **words, int wordcount, break; case 4: - if (!strcmp (words[2], "all") && - !strcmp (words[3], "detail")) { - - cmd = GF_CLI_STATUS_ALL_DETAIL; - ret = 0; - - } else if (!strcmp (words[3], "detail")) { - cmd = GF_CLI_STATUS_VOL_DETAIL; - ret = dict_set_str (dict, "volname", (char *)words[2]); - + if (!strcmp (words[2], "all")) { + cli_out ("Cannot specify brick/status-type for \"all\""); + ret = -1; + goto out; } else { - - cmd = GF_CLI_STATUS_BRICK; + cmd = GF_CLI_STATUS_VOL; ret = dict_set_str (dict, "volname", (char *)words[2]); if (ret) goto out; + } + + if (cli_cmd_validate_statusop (words[3])) { + ret = cli_cmd_get_statusop (words[3]); + if (GF_CLI_STATUS_INVAL == ret) + goto out; + cmd |= ret; + ret = 0; + } else { + cmd = GF_CLI_STATUS_BRICK; ret = dict_set_str (dict, "brick", (char *)words[3]); } break; case 5: - if (strcmp (words[4], "detail")) + if (!cli_cmd_validate_statusop (words[4])) { + ret = -1; goto out; + } - cmd = GF_CLI_STATUS_BRICK_DETAIL; - ret = dict_set_str (dict, "volname", (char *)words[2]); - if (ret) + cmd = GF_CLI_STATUS_BRICK; + ret = cli_cmd_get_statusop (words[4]); + if (GF_CLI_STATUS_INVAL == ret) + goto out; + cmd |= ret; + + if (!strcmp (words[2], "all")) { + cli_out ("Cannot specify brick/status-type for \"all\""); + ret = -1; goto out; + } else { + ret = dict_set_str (dict, "volname", (char *)words[2]); + if (ret) + goto out; + } ret = dict_set_str (dict, "brick", (char *)words[3]); break; diff --git a/cli/src/cli-cmd-volume.c b/cli/src/cli-cmd-volume.c index a572bdc3f..0168628dd 100644 --- a/cli/src/cli-cmd-volume.c +++ b/cli/src/cli-cmd-volume.c @@ -1740,7 +1740,8 @@ struct cli_cmd volume_cmds[] = { cli_cmd_volume_top_cbk, "volume top operations"}, - { "volume status [all|] [brick] [detail]", + { "volume status [all|{ [] " + "[misc-details|clients|mem|inode|fd|callpool]}]", cli_cmd_volume_status_cbk, "display status of specified volume"}, diff --git a/cli/src/cli-rpc-ops.c b/cli/src/cli-rpc-ops.c index bb6cd0754..6a212919c 100644 --- a/cli/src/cli-rpc-ops.c +++ b/cli/src/cli-rpc-ops.c @@ -3807,6 +3807,869 @@ out: return ret; } +void +cli_print_volume_status_mempool (dict_t *dict, char *prefix) +{ + int ret = -1; + int32_t mempool_count = 0; + char *name = NULL; + int32_t hotcount = 0; + int32_t coldcount = 0; + uint64_t paddedsizeof = 0; + uint64_t alloccount = 0; + int32_t maxalloc = 0; + char key[1024] = {0,}; + int i = 0; + + GF_ASSERT (dict); + GF_ASSERT (prefix); + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.mempool-count",prefix); + ret = dict_get_int32 (dict, key, &mempool_count); + if (ret) + goto out; + + cli_out ("Mempool Stats\n-------------"); + cli_out ("%-30s %9s %9s %12s %10s %8s", "Name", "HotCount","ColdCount", + "PaddedSizeof", "AllocCount", "MaxAlloc"); + cli_out ("%-30s %9s %9s %12s %10s %8s", "----", "--------", "---------", + "------------", "----------", "--------"); + + for (i = 0; i < mempool_count; i++) { + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.pool%d.name", prefix, i); + ret = dict_get_str (dict, key, &name); + if (ret) + goto out; + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.pool%d.hotcount", prefix, i); + ret = dict_get_int32 (dict, key, &hotcount); + if (ret) + goto out; + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.pool%d.coldcount", prefix, i); + ret = dict_get_int32 (dict, key, &coldcount); + if (ret) + goto out; + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.pool%d.paddedsizeof", + prefix, i); + ret = dict_get_uint64 (dict, key, &paddedsizeof); + if (ret) + goto out; + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.pool%d.alloccount", prefix, i); + ret = dict_get_uint64 (dict, key, &alloccount); + if (ret) + goto out; + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.pool%d.max_alloc", prefix, i); + ret = dict_get_int32 (dict, key, &maxalloc); + if (ret) + goto out; + + cli_out ("%-30s %9d %9d %12"PRIu64" %10"PRIu64" %8d", name, + hotcount, coldcount, paddedsizeof, alloccount, + maxalloc); + } + +out: + return; + +} + +void +cli_print_volume_status_mem (dict_t *dict) +{ + int ret = -1; + char *volname = NULL; + char *hostname = NULL; + char *path = NULL; + int online = -1; + char key[1024] = {0,}; + int brick_count = 0; + int val = 0; + int i = 0; + + GF_ASSERT (dict); + + ret = dict_get_str (dict, "volname", &volname); + if (ret) + goto out; + cli_out ("Memory status for volume : %s", volname); + + ret = dict_get_int32 (dict, "count", &brick_count); + if (ret) + goto out; + + for (i = 0; i < brick_count; i++) { + cli_out ("----------------------------------------------"); + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "brick%d.hostname", i); + ret = dict_get_str (dict, key, &hostname); + if (ret) + goto out; + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "brick%d.path", i); + ret = dict_get_str (dict, key, &path); + if (ret) + goto out; + cli_out ("Brick : %s:%s", hostname, path); + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "brick%d.status", i); + ret = dict_get_int32 (dict, key, &online); + if (ret) + goto out; + if (!online) { + cli_out ("Brick is offline"); + continue; + } + + cli_out ("Mallinfo\n--------"); + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "brick%d.mallinfo.arena", i); + ret = dict_get_int32 (dict, key, &val); + if (ret) + goto out; + cli_out ("%-8s : %d","Arena", val); + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "brick%d.mallinfo.ordblks", i); + ret = dict_get_int32 (dict, key, &val); + if(ret) + goto out; + cli_out ("%-8s : %d","Ordblks", val); + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "brick%d.mallinfo.smblks", i); + ret = dict_get_int32 (dict, key, &val); + if(ret) + goto out; + cli_out ("%-8s : %d","Smblks", val); + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "brick%d.mallinfo.hblks", i); + ret = dict_get_int32 (dict, key, &val); + if(ret) + goto out; + cli_out ("%-8s : %d", "Hblks", val); + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "brick%d.mallinfo.hblkhd", i); + ret = dict_get_int32 (dict, key, &val); + if (ret) + goto out; + cli_out ("%-8s : %d", "Hblkhd", val); + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "brick%d.mallinfo.usmblks", i); + ret = dict_get_int32 (dict, key, &val); + if (ret) + goto out; + cli_out ("%-8s : %d", "Usmblks", val); + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "brick%d.mallinfo.fsmblks", i); + ret = dict_get_int32 (dict, key, &val); + if (ret) + goto out; + cli_out ("%-8s : %d", "Fsmblks", val); + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "brick%d.mallinfo.uordblks", i); + ret = dict_get_int32 (dict, key, &val); + if (ret) + goto out; + cli_out ("%-8s : %d", "Uordblks", val); + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "brick%d.mallinfo.fordblks", i); + ret = dict_get_int32 (dict, key, &val); + if (ret) + goto out; + cli_out ("%-8s : %d", "Fordblks", val); + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "brick%d.mallinfo.keepcost", i); + ret = dict_get_int32 (dict, key, &val); + if (ret) + goto out; + cli_out ("%-8s : %d", "Keepcost", val); + + cli_out (" "); + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "brick%d", i); + cli_print_volume_status_mempool (dict, key); + } +out: + cli_out ("----------------------------------------------\n"); + return; +} + +void +cli_print_volume_status_clients (dict_t *dict) +{ + int ret = -1; + char *volname = NULL; + int brick_count = 0; + char *hostname = NULL; + char *path = NULL; + int online = -1; + int client_count = 0; + char *clientname = NULL; + uint64_t bytesread = 0; + uint64_t byteswrite = 0; + char key[1024] = {0,}; + int i = 0; + int j = 0; + + GF_ASSERT (dict); + + ret = dict_get_str (dict, "volname", &volname); + if (ret) + goto out; + cli_out ("Client connections for volume %s", volname); + + ret = dict_get_int32 (dict, "count", &brick_count); + if (ret) + goto out; + + for ( i = 0; i < brick_count; i++) { + cli_out ("----------------------------------------------"); + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "brick%d.hostname", i); + ret = dict_get_str (dict, key, &hostname); + if (ret) + goto out; + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "brick%d.path", i); + ret = dict_get_str (dict, key, &path); + if (ret) + goto out; + cli_out ("Brick : %s:%s", hostname, path); + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "brick%d.status", i); + ret = dict_get_int32 (dict, key, &online); + if (ret) + goto out; + if (!online) { + cli_out ("Brick is offline"); + continue; + } + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "brick%d.clientcount", i); + ret = dict_get_int32 (dict, key, &client_count); + if (ret) + goto out; + + cli_out ("Clients connected : %d", client_count); + cli_out ("%-48s %15s %15s", "Hostname", "BytesRead", + "BytesWritten"); + cli_out ("%-48s %15s %15s", "--------", "---------", + "------------"); + for (j =0; j < client_count; j++) { + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), + "brick%d.client%d.hostname", i, j); + ret = dict_get_str (dict, key, &clientname); + if (ret) + goto out; + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), + "brick%d.client%d.bytesread", i, j); + ret = dict_get_uint64 (dict, key, &bytesread); + if (ret) + goto out; + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), + "brick%d.client%d.byteswrite", i, j); + ret = dict_get_uint64 (dict, key, &byteswrite); + if (ret) + goto out; + + cli_out ("%-48s %15"PRIu64" %15"PRIu64, + clientname, bytesread, byteswrite); + } + } +out: + cli_out ("----------------------------------------------\n"); + return; +} + +void +cli_print_volume_status_inode_entry (dict_t *dict, char *prefix) +{ + int ret = -1; + char key[1024] = {0,}; + char *gfid = NULL; + uint64_t nlookup = 0; + uint32_t ref = 0; + int ia_type = 0; + + GF_ASSERT (dict); + GF_ASSERT (prefix); + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.gfid", prefix); + ret = dict_get_str (dict, key, &gfid); + if (ret) + goto out; + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.nlookup", prefix); + ret = dict_get_uint64 (dict, key, &nlookup); + if (ret) + goto out; + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.ref", prefix); + ret = dict_get_uint32 (dict, key, &ref); + if (ret) + goto out; + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.ia_type", prefix); + ret = dict_get_int32 (dict, key, &ia_type); + if (ret) + goto out; + + cli_out ("%-40s %14"PRIu64" %14"PRIu32" %9d", + gfid, nlookup, ref, ia_type); + +out: + return; + +} + +void +cli_print_volume_status_itables (dict_t *dict, char *prefix) +{ + int ret = -1; + char key[1024] = {0,}; + uint32_t active_size = 0; + uint32_t lru_size = 0; + uint32_t purge_size = 0; + int i =0; + + GF_ASSERT (dict); + GF_ASSERT (prefix); + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.active_size", prefix); + ret = dict_get_uint32 (dict, key, &active_size); + if (ret) + goto out; + if (active_size != 0) { + cli_out ("Active inodes:"); + cli_out ("%-40s %14s %14s %9s", "GFID", "Lookups", "Ref", + "IA type"); + cli_out ("%-40s %14s %14s %9s", "----", "-------", "---", + "-------"); + } + for (i = 0; i < active_size; i++) { + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.active%d", prefix, i); + cli_print_volume_status_inode_entry (dict, key); + } + cli_out (" "); + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.lru_size", prefix); + ret = dict_get_uint32 (dict, key, &lru_size); + if (ret) + goto out; + if (lru_size != 0) { + cli_out ("LRU inodes:"); + cli_out ("%-40s %14s %14s %9s", "GFID", "Lookups", "Ref", + "IA type"); + cli_out ("%-40s %14s %14s %9s", "----", "-------", "---", + "-------"); + } + for (i = 0; i < lru_size; i++) { + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.lru%d", prefix, i); + cli_print_volume_status_inode_entry (dict, key); + } + cli_out (" "); + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.purge_size", prefix); + ret = dict_get_uint32 (dict, key, &purge_size); + if (ret) + goto out; + if (purge_size != 0) { + cli_out ("Purged inodes:"); + cli_out ("%-40s %14s %14s %9s", "GFID", "Lookups", "Ref", + "IA type"); + cli_out ("%-40s %14s %14s %9s", "----", "-------", "---", + "-------"); + } + for (i = 0; i < purge_size; i++) { + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.purge%d", prefix, i); + cli_print_volume_status_inode_entry (dict, key); + } + +out: + return; +} + +void +cli_print_volume_status_inode (dict_t *dict) +{ + int ret = -1; + char *volname = NULL; + int brick_count = 0; + char *hostname = NULL; + char *path = NULL; + int online = -1; + int conn_count = 0; + char key[1024] = {0,}; + int i = 0; + int j = 0; + + GF_ASSERT (dict); + + ret = dict_get_str (dict, "volname", &volname); + if (ret) + goto out; + cli_out ("Inode tables for volume %s", volname); + + ret = dict_get_int32 (dict, "count", &brick_count); + if (ret) + goto out; + + for (i = 0; i < brick_count; i++) { + cli_out ("----------------------------------------------"); + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "brick%d.hostname", i); + ret = dict_get_str (dict, key, &hostname); + if (ret) + goto out; + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "brick%d.path", i); + ret = dict_get_str (dict, key, &path); + if (ret) + goto out; + cli_out ("Brick : %s:%s", hostname, path); + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "brick%d.status", i); + ret = dict_get_int32 (dict, key, &online); + if (ret) + goto out; + if (!online) { + cli_out ("Brick is offline"); + continue; + } + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "brick%d.conncount", i); + ret = dict_get_int32 (dict, key, &conn_count); + if (ret) + goto out; + + for (j = 0; j < conn_count; j++) { + if (conn_count > 1) + cli_out ("Connection %d:", j+1); + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "brick%d.conn%d.itable", + i, j); + cli_print_volume_status_itables (dict, key); + cli_out (" "); + } + } +out: + cli_out ("----------------------------------------------"); + return; +} + +void +cli_print_volume_status_fdtable (dict_t *dict, char *prefix) +{ + int ret = -1; + char key[1024] = {0,}; + int refcount = 0; + uint32_t maxfds = 0; + int firstfree = 0; + int openfds = 0; + int fd_pid = 0; + int fd_refcount = 0; + int fd_flags = 0; + int i = 0; + + GF_ASSERT (dict); + GF_ASSERT (prefix); + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.refcount", prefix); + ret = dict_get_int32 (dict, key, &refcount); + if (ret) + goto out; + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.maxfds", prefix); + ret = dict_get_uint32 (dict, key, &maxfds); + if (ret) + goto out; + + memset (key, 0 ,sizeof (key)); + snprintf (key, sizeof (key), "%s.firstfree", prefix); + ret = dict_get_int32 (dict, key, &firstfree); + if (ret) + goto out; + + cli_out ("RefCount = %d MaxFDs = %d FirstFree = %d", + refcount, maxfds, firstfree); + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.openfds", prefix); + ret = dict_get_int32 (dict, key, &openfds); + if (ret) + goto out; + if (0 == openfds) { + cli_out ("No open fds"); + goto out; + } + + cli_out ("%-19s %-19s %-19s %-19s", "FD Entry", "PID", + "RefCount", "Flags"); + cli_out ("%-19s %-19s %-19s %-19s", "--------", "---", + "--------", "-----"); + + for (i = 0; i < maxfds ; i++) { + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.fdentry%d.pid", prefix, i); + ret = dict_get_int32 (dict, key, &fd_pid); + if (ret) + continue; + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.fdentry%d.refcount", + prefix, i); + ret = dict_get_int32 (dict, key, &fd_refcount); + if (ret) + continue; + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.fdentry%d.flags", prefix, i); + ret = dict_get_int32 (dict, key, &fd_flags); + if (ret) + continue; + + cli_out ("%-19d %-19d %-19d %-19d", i, fd_pid, fd_refcount, + fd_flags); + } + +out: + return; +} + +void +cli_print_volume_status_fd (dict_t *dict) +{ + int ret = -1; + char *volname = NULL; + int brick_count = 0; + char *hostname = NULL; + char *path = NULL; + int online = -1; + int conn_count = 0; + char key[1024] = {0,}; + int i = 0; + int j = 0; + + GF_ASSERT (dict); + + ret = dict_get_str (dict, "volname", &volname); + if (ret) + goto out; + cli_out ("FD tables for volume %s", volname); + + ret = dict_get_int32 (dict, "count", &brick_count); + if (ret) + goto out; + + for (i = 0; i < brick_count; i++) { + cli_out ("----------------------------------------------"); + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "brick%d.hostname", i); + ret = dict_get_str (dict, key, &hostname); + if (ret) + goto out; + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "brick%d.path", i); + ret = dict_get_str (dict, key, &path); + if (ret) + goto out; + cli_out ("Brick : %s:%s", hostname, path); + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "brick%d.status", i); + ret = dict_get_int32 (dict, key, &online); + if (ret) + goto out; + if (!online) { + cli_out ("Brick is offline"); + continue; + } + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "brick%d.conncount", i); + ret = dict_get_int32 (dict, key, &conn_count); + if (ret) + goto out; + + for (j = 0; j < conn_count; j++) { + cli_out ("Connection %d:", j+1); + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "brick%d.conn%d.fdtable", + i, j); + cli_print_volume_status_fdtable (dict, key); + cli_out (" "); + } + } +out: + cli_out ("----------------------------------------------"); + return; +} + +void +cli_print_volume_status_call_frame (dict_t *dict, char *prefix) +{ + int ret = -1; + char key[1024] = {0,}; + int ref_count = 0; + char *translator = 0; + int complete = 0; + char *parent = NULL; + char *wind_from = NULL; + char *wind_to = NULL; + char *unwind_from = NULL; + char *unwind_to = NULL; + + if (!dict || !prefix) + return; + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.refcount", prefix); + ret = dict_get_int32 (dict, key, &ref_count); + if (ret) + return; + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.translator", prefix); + ret = dict_get_str (dict, key, &translator); + if (ret) + return; + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.complete", prefix); + ret = dict_get_int32 (dict, key, &complete); + if (ret) + return; + + cli_out (" Ref Count = %d", ref_count); + cli_out (" Translator = %s", translator); + cli_out (" Completed = %s", (complete ? "Yes" : "No")); + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.parent", prefix); + ret = dict_get_str (dict, key, &parent); + if (!ret) + cli_out (" Parent = %s", parent); + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.windfrom", prefix); + ret = dict_get_str (dict, key, &wind_from); + if (!ret) + cli_out (" Wind From = %s", wind_from); + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.windto", prefix); + ret = dict_get_str (dict, key, &wind_to); + if (!ret) + cli_out (" Wind To = %s", wind_to); + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.unwindfrom", prefix); + ret = dict_get_str (dict, key, &unwind_from); + if (!ret) + cli_out (" Unwind From = %s", unwind_from); + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.unwindto", prefix); + ret = dict_get_str (dict, key, &unwind_to); + if (!ret) + cli_out (" Unwind To = %s", unwind_to); +} + +void +cli_print_volume_status_call_stack (dict_t *dict, char *prefix) +{ + int ret = -1; + char key[1024] = {0,}; + int uid = 0; + int gid = 0; + int pid = 0; + uint64_t unique = 0; + //char *op = NULL; + int count = 0; + int i = 0; + + if (!dict || !prefix) + return; + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.uid", prefix); + ret = dict_get_int32 (dict, key, &uid); + if (ret) + return; + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.gid", prefix); + ret = dict_get_int32 (dict, key, &gid); + if (ret) + return; + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.pid", prefix); + ret = dict_get_int32 (dict, key, &pid); + if (ret) + return; + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.unique", prefix); + ret = dict_get_uint64 (dict, key, &unique); + if (ret) + return; + + /* + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.op", prefix); + ret = dict_get_str (dict, key, &op); + if (ret) + return; + */ + + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.count", prefix); + ret = dict_get_int32 (dict, key, &count); + if (ret) + return; + + cli_out (" UID : %d", uid); + cli_out (" GID : %d", gid); + cli_out (" PID : %d", pid); + cli_out (" Unique : %"PRIu64, unique); + //cli_out ("\tOp : %s", op); + cli_out (" Frames : %d", count); + + for (i = 0; i < count; i++) { + cli_out (" Frame %d", i+1); + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.frame%d", prefix, i); + cli_print_volume_status_call_frame (dict, key); + } + + cli_out (" "); +} + +void +cli_print_volume_status_callpool (dict_t *dict) +{ + int ret = -1; + char *volname = NULL; + int brick_count = 0; + char *hostname = NULL; + char *path = NULL; + int online = -1; + int call_count = 0; + char key[1024] = {0,}; + int i = 0; + int j = 0; + + GF_ASSERT (dict); + + ret = dict_get_str (dict, "volname", &volname); + if (ret) + goto out; + cli_out ("Pending calls for volume %s", volname); + + ret = dict_get_int32 (dict, "count", &brick_count); + if (ret) + goto out; + + for (i = 0; i < brick_count; i++) { + cli_out ("----------------------------------------------"); + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "brick%d.hostname", i); + ret = dict_get_str (dict, key, &hostname); + if (ret) + goto out; + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "brick%d.path", i); + ret = dict_get_str (dict, key, &path); + if (ret) + goto out; + cli_out ("Brick : %s:%s", hostname, path); + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "brick%d.status", i); + ret = dict_get_int32 (dict, key, &online); + if (ret) + goto out; + if (!online) { + cli_out ("Brick is offline"); + continue; + } + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "brick%d.callpool.count", i); + ret = dict_get_int32 (dict, key, &call_count); + if (ret) + goto out; + cli_out ("Pending calls: %d", call_count); + + if (0 == call_count) + continue; + + for (j = 0; j < call_count; j++) { + cli_out ("Call Stack%d", j+1); + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), + "brick%d.callpool.stack%d", i, j); + cli_print_volume_status_call_stack (dict, key); + } + } + +out: + cli_out ("----------------------------------------------"); + return; +} + static int gf_cli3_1_status_cbk (struct rpc_req *req, struct iovec *iov, int count, void *myframe) @@ -3869,6 +4732,31 @@ gf_cli3_1_status_cbk (struct rpc_req *req, struct iovec *iov, status.brick = GF_CALLOC (1, PATH_MAX + 256, gf_common_mt_strdup); + switch (cmd & GF_CLI_STATUS_MASK) { + case GF_CLI_STATUS_MEM: + cli_print_volume_status_mem (dict); + goto cont; + break; + case GF_CLI_STATUS_CLIENTS: + cli_print_volume_status_clients (dict); + goto cont; + break; + case GF_CLI_STATUS_INODE: + cli_print_volume_status_inode (dict); + goto cont; + break; + case GF_CLI_STATUS_FD: + cli_print_volume_status_fd (dict); + goto cont; + break; + case GF_CLI_STATUS_CALLPOOL: + cli_print_volume_status_callpool (dict); + goto cont; + break; + default: + break; + } + ret = dict_get_str (dict, "volname", &volname); if (ret) goto out; @@ -3934,9 +4822,10 @@ gf_cli3_1_status_cbk (struct rpc_req *req, struct iovec *iov, } } +cont: ret = rsp.op_ret; - out: +out: if (status.brick) GF_FREE (status.brick); diff --git a/glusterfsd/src/glusterfsd-mgmt.c b/glusterfsd/src/glusterfsd-mgmt.c index 9e98190ba..558ab1651 100644 --- a/glusterfsd/src/glusterfsd-mgmt.c +++ b/glusterfsd/src/glusterfsd-mgmt.c @@ -45,6 +45,7 @@ #include "glusterfsd-mem-types.h" #include "rpcsvc.h" #include "cli1-xdr.h" +#include "statedump.h" static char is_mgmt_rpc_reconnect; @@ -735,6 +736,138 @@ out: return ret; } +int +glusterfs_handle_brick_status (rpcsvc_request_t *req) +{ + int ret = -1; + gd1_mgmt_brick_op_req brick_req = {0,}; + gd1_mgmt_brick_op_rsp rsp = {0,}; + glusterfs_ctx_t *ctx = NULL; + glusterfs_graph_t *active = NULL; + xlator_t *this = NULL; + xlator_t *any = NULL; + xlator_t *xlator = NULL; + dict_t *dict = NULL; + dict_t *output = NULL; + char *volname = NULL; + char *xname = NULL; + int32_t cmd = 0; + char *msg = NULL; + + GF_ASSERT (req); + this = THIS; + GF_ASSERT (this); + + if (!xdr_to_generic (req->msg[0], &brick_req, + (xdrproc_t)xdr_gd1_mgmt_brick_op_req)) { + req->rpc_err = GARBAGE_ARGS; + goto out; + } + + dict = dict_new (); + ret = dict_unserialize (brick_req.input.input_val, + brick_req.input.input_len, &dict); + if (ret < 0) { + gf_log (this->name, GF_LOG_ERROR, "Failed to unserialize " + "req-buffer to dictionary"); + goto out; + } + + ret = dict_get_int32 (dict, "cmd", &cmd); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, "Couldn't get status op"); + goto out; + } + + ret = dict_get_str (dict, "volname", &volname); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, "Couldn't get volname"); + goto out; + } + + ctx = glusterfs_ctx_get (); + GF_ASSERT (ctx); + active = ctx->active; + any = active->first; + + ret = gf_asprintf (&xname, "%s-server", volname); + if (-1 == ret) { + gf_log (this->name, GF_LOG_ERROR, "Out of memory"); + goto out; + } + + xlator = xlator_search_by_name (any, xname); + if (!xlator) { + gf_log (this->name, GF_LOG_ERROR, "xlator %s is not loaded", + xname); + ret = -1; + goto out; + } + + + output = dict_new (); + switch (cmd & GF_CLI_STATUS_MASK) { + case GF_CLI_STATUS_MEM: + ret = 0; + gf_proc_dump_mem_info_to_dict (output); + gf_proc_dump_mempool_info_to_dict (ctx, output); + break; + + case GF_CLI_STATUS_CLIENTS: + ret = xlator->dumpops->priv_to_dict (xlator, output); + break; + + case GF_CLI_STATUS_INODE: + ret = xlator->dumpops->inode_to_dict (xlator, output); + break; + + case GF_CLI_STATUS_FD: + ret = xlator->dumpops->fd_to_dict (xlator, output); + break; + + case GF_CLI_STATUS_CALLPOOL: + ret = 0; + gf_proc_dump_pending_frames_to_dict (ctx->pool, output); + break; + + default: + ret = -1; + msg = gf_strdup ("Unknown status op"); + break; + } + rsp.op_ret = ret; + rsp.op_errno = 0; + if (ret && msg) + rsp.op_errstr = msg; + else + rsp.op_errstr = ""; + + ret = dict_allocate_and_serialize (output, &rsp.output.output_val, + (size_t *)&rsp.output.output_len); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, + "Failed to serialize output dict to rsp"); + goto out; + } + + ret = glusterfs_submit_reply (req, &rsp, NULL, 0, NULL, + (xdrproc_t)xdr_gd1_mgmt_brick_op_rsp); + +out: + if (dict) + dict_unref (dict); + if (brick_req.input.input_val) + free (brick_req.input.input_val); + if (xname) + GF_FREE (xname); + if (msg) + GF_FREE (msg); + if (rsp.output.output_val) + GF_FREE (rsp.output.output_val); + + return ret; +} + int glusterfs_handle_rpc_msg (rpcsvc_request_t *req) { @@ -751,6 +884,9 @@ glusterfs_handle_rpc_msg (rpcsvc_request_t *req) case GLUSTERD_BRICK_XLATOR_HEAL: ret = glusterfs_handle_translator_heal (req); break; + case GLUSTERD_BRICK_STATUS: + ret = glusterfs_handle_brick_status (req); + break; default: break; } @@ -806,7 +942,8 @@ rpcsvc_actor_t glusterfs_actors[] = { [GLUSTERD_BRICK_NULL] = { "NULL", GLUSTERD_BRICK_NULL, glusterfs_handle_rpc_msg, NULL, NULL, 0}, [GLUSTERD_BRICK_TERMINATE] = { "TERMINATE", GLUSTERD_BRICK_TERMINATE, glusterfs_handle_rpc_msg, NULL, NULL, 0}, [GLUSTERD_BRICK_XLATOR_INFO] = { "TRANSLATOR INFO", GLUSTERD_BRICK_XLATOR_INFO, glusterfs_handle_rpc_msg, NULL, NULL, 0}, - [GLUSTERD_BRICK_XLATOR_HEAL] = { "TRANSLATOR HEAL", GLUSTERD_BRICK_XLATOR_HEAL, glusterfs_handle_rpc_msg, NULL, NULL, 0} + [GLUSTERD_BRICK_XLATOR_HEAL] = { "TRANSLATOR HEAL", GLUSTERD_BRICK_XLATOR_HEAL, glusterfs_handle_rpc_msg, NULL, NULL, 0}, + [GLUSTERD_BRICK_STATUS] = {"STATUS", GLUSTERD_BRICK_STATUS, glusterfs_handle_rpc_msg, NULL, NULL, 0} }; struct rpcsvc_program glusterfs_mop_prog = { diff --git a/libglusterfs/src/fd.c b/libglusterfs/src/fd.c index 50a564ee6..62a70c457 100644 --- a/libglusterfs/src/fd.c +++ b/libglusterfs/src/fd.c @@ -905,3 +905,95 @@ out: return; } + +void +fdentry_dump_to_dict (fdentry_t *fdentry, char *prefix, dict_t *dict, + int *openfds) +{ + char key[GF_DUMP_MAX_BUF_LEN] = {0,}; + int ret = -1; + + if (!fdentry) + return; + if (!dict) + return; + + if (GF_FDENTRY_ALLOCATED != fdentry->next_free) + return; + + if (fdentry->fd) { + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.pid", prefix); + ret = dict_set_int32 (dict, key, fdentry->fd->pid); + if (ret) + return; + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.refcount", prefix); + ret = dict_set_int32 (dict, key, fdentry->fd->refcount); + if (ret) + return; + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.flags", prefix); + ret = dict_set_int32 (dict, key, fdentry->fd->flags); + + (*openfds)++; + } + return; +} + +void +fdtable_dump_to_dict (fdtable_t *fdtable, char *prefix, dict_t *dict) +{ + char key[GF_DUMP_MAX_BUF_LEN] = {0,}; + int i = 0; + int openfds = 0; + int ret = -1; + + if (!fdtable) + return; + if (!dict) + return; + + ret = pthread_mutex_trylock (&fdtable->lock); + if (ret) + goto out; + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.fdtable.refcount", prefix); + ret = dict_set_int32 (dict, key, fdtable->refcount); + if (ret) + goto out; + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.fdtable.maxfds", prefix); + ret = dict_set_uint32 (dict, key, fdtable->max_fds); + if (ret) + goto out; + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.fdtable.firstfree", prefix); + ret = dict_set_int32 (dict, key, fdtable->first_free); + if (ret) + goto out; + + for (i = 0; i < fdtable->max_fds; i++) { + if (GF_FDENTRY_ALLOCATED == + fdtable->fdentries[i].next_free) { + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.fdtable.fdentry%d", + prefix, i); + fdentry_dump_to_dict (&fdtable->fdentries[i], key, + dict, &openfds); + } + } + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.fdtable.openfds", prefix); + ret = dict_set_int32 (dict, key, openfds); + +out: + pthread_mutex_unlock (&fdtable->lock); + return; +} diff --git a/libglusterfs/src/inode.c b/libglusterfs/src/inode.c index c23f0f0e5..4685ec8d2 100644 --- a/libglusterfs/src/inode.c +++ b/libglusterfs/src/inode.c @@ -1637,3 +1637,99 @@ inode_table_dump (inode_table_t *itable, char *prefix) pthread_mutex_unlock(&itable->lock); } + +void +inode_dump_to_dict (inode_t *inode, char *prefix, dict_t *dict) +{ + int ret = -1; + char key[GF_DUMP_MAX_BUF_LEN] = {0,}; + + ret = TRY_LOCK (&inode->lock); + if (ret) + return; + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.gfid", prefix); + ret = dict_set_str (dict, key, gf_strdup (uuid_utoa (inode->gfid))); + if (ret) + goto out; + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.nlookup", prefix); + ret = dict_set_uint64 (dict, key, inode->nlookup); + if (ret) + goto out; + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.ref", prefix); + ret = dict_set_uint32 (dict, key, inode->ref); + if (ret) + goto out; + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.ia_type", prefix); + ret = dict_set_int32 (dict, key, inode->ia_type); + +out: + UNLOCK (&inode->lock); + return; +} + +void +inode_table_dump_to_dict (inode_table_t *itable, char *prefix, dict_t *dict) +{ + char key[GF_DUMP_MAX_BUF_LEN] = {0,}; + int ret = 0; + inode_t *inode = NULL; + int count = 0; + + ret = pthread_mutex_trylock (&itable->lock); + if (ret) + return; + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.itable.active_size", prefix); + ret = dict_set_uint32 (dict, key, itable->active_size); + if (ret) + goto out; + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.itable.lru_size", prefix); + ret = dict_set_uint32 (dict, key, itable->lru_size); + if (ret) + goto out; + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.itable.purge_size", prefix); + ret = dict_set_uint32 (dict, key, itable->purge_size); + if (ret) + goto out; + + list_for_each_entry (inode, &itable->active, list) { + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.itable.active%d", prefix, + count++); + inode_dump_to_dict (inode, key, dict); + } + count = 0; + + list_for_each_entry (inode, &itable->lru, list) { + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.itable.lru%d", prefix, + count++); + inode_dump_to_dict (inode, key, dict); + } + count = 0; + + list_for_each_entry (inode, &itable->purge, list) { + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.itable.purge%d", prefix, + count++); + inode_dump_to_dict (inode, key, dict); + } + +out: + pthread_mutex_unlock (&itable->lock); + + return; +} diff --git a/libglusterfs/src/stack.c b/libglusterfs/src/stack.c index 0f65faa6f..29b44aedf 100644 --- a/libglusterfs/src/stack.c +++ b/libglusterfs/src/stack.c @@ -161,6 +161,194 @@ gf_proc_dump_pending_frames (call_pool_t *call_pool) UNLOCK (&(call_pool->lock)); } +void +gf_proc_dump_call_frame_to_dict (call_frame_t *call_frame, + char *prefix, dict_t *dict) +{ + int ret = -1; + char key[GF_DUMP_MAX_BUF_LEN] = {0,}; + call_frame_t tmp_frame = {0,}; + + if (!call_frame || !dict) + return; + + ret = TRY_LOCK (&call_frame->lock); + if (ret) + return; + memcpy (&tmp_frame, call_frame, sizeof (tmp_frame)); + UNLOCK (&call_frame->lock); + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.refcount", prefix); + ret = dict_set_int32 (dict, key, tmp_frame.ref_count); + if (ret) + return; + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.translator", prefix); + ret = dict_set_str (dict, key, gf_strdup (tmp_frame.this->name)); + if (ret) + return; + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.complete", prefix); + ret = dict_set_int32 (dict, key, tmp_frame.complete); + if (ret) + return; + + if (tmp_frame.parent) { + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.parent", prefix); + ret = dict_set_str (dict, key, + gf_strdup (tmp_frame.parent->this->name)); + if (ret) + return; + } + + if (tmp_frame.wind_from) { + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.windfrom", prefix); + ret = dict_set_str (dict, key, gf_strdup (tmp_frame.wind_from)); + if (ret) + return; + } + + if (tmp_frame.wind_to) { + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.windto", prefix); + ret = dict_set_str (dict, key, gf_strdup (tmp_frame.wind_to)); + if (ret) + return; + } + + if (tmp_frame.unwind_from) { + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.unwindfrom", prefix); + ret = dict_set_str (dict, key, gf_strdup (tmp_frame.unwind_from)); + if (ret) + return; + } + + if (tmp_frame.unwind_to) { + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.unwind_to", prefix); + ret = dict_set_str (dict, key, gf_strdup (tmp_frame.unwind_to)); + } + + return; +} + +void +gf_proc_dump_call_stack_to_dict (call_stack_t *call_stack, + char *prefix, dict_t *dict) +{ + int ret = -1; + char key[GF_DUMP_MAX_BUF_LEN] = {0,}; + call_frame_t *trav = NULL; + int count = 0; + int i = 0; + + if (!call_stack || !dict) + return; + + count = call_frames_count (&call_stack->frames); + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.uid", prefix); + ret = dict_set_int32 (dict, key, call_stack->uid); + if (ret) + return; + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.gid", prefix); + ret = dict_set_int32 (dict, key, call_stack->gid); + if (ret) + return; + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.pid", prefix); + ret = dict_set_int32 (dict, key, call_stack->pid); + if (ret) + return; + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.unique", prefix); + ret = dict_set_uint64 (dict, key, call_stack->unique); + if (ret) + return; + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.op", prefix); + if (call_stack->type == GF_OP_TYPE_FOP) + ret = dict_set_str (dict, key, + gf_fop_list[call_stack->op]); + else if (call_stack->type == GF_OP_TYPE_MGMT) + ret = dict_set_str (dict, key, + gf_mgmt_list[call_stack->op]); + if (ret) + return; + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.type", prefix); + ret = dict_set_int32 (dict, key, call_stack->type); + if (ret) + return; + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.count", prefix); + ret = dict_set_int32 (dict, key, count); + if (ret) + return; + + trav = &call_stack->frames; + for (i = 0; i < count; i++) { + if (trav) { + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.frame%d", + prefix, i); + gf_proc_dump_call_frame_to_dict (trav, key, dict); + trav = trav->next; + } + } + + return; +} + +void +gf_proc_dump_pending_frames_to_dict (call_pool_t *call_pool, dict_t *dict) +{ + int ret = -1; + call_stack_t *trav = NULL; + char key[GF_DUMP_MAX_BUF_LEN] = {0,}; + int i = 0; + + if (!call_pool || !dict) + return; + + ret = TRY_LOCK (&call_pool->lock); + if (ret) { + gf_log (THIS->name, GF_LOG_WARNING, "Unable to dump call pool" + " to dict. errno: %d", errno); + return; + } + + ret = dict_set_int32 (dict, "callpool.count", call_pool->cnt); + if (ret) + goto out; + + list_for_each_entry (trav, &call_pool->all_frames, all_frames) { + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "callpool.stack%d", i); + gf_proc_dump_call_stack_to_dict (trav, key, dict); + i++; + } + +out: + UNLOCK (&call_pool->lock); + + return; +} + gf_boolean_t __is_fuse_call (call_frame_t *frame) { diff --git a/libglusterfs/src/stack.h b/libglusterfs/src/stack.h index a5689e096..c84040576 100644 --- a/libglusterfs/src/stack.h +++ b/libglusterfs/src/stack.h @@ -414,6 +414,7 @@ create_frame (xlator_t *xl, call_pool_t *pool) } void gf_proc_dump_pending_frames(call_pool_t *call_pool); - +void gf_proc_dump_pending_frames_to_dict (call_pool_t *call_pool, + dict_t *dict); gf_boolean_t __is_fuse_call (call_frame_t *frame); #endif /* _STACK_H */ diff --git a/libglusterfs/src/statedump.c b/libglusterfs/src/statedump.c index c744c6c5f..8c6fe9215 100644 --- a/libglusterfs/src/statedump.c +++ b/libglusterfs/src/statedump.c @@ -234,6 +234,61 @@ gf_proc_dump_mem_info () } +void +gf_proc_dump_mem_info_to_dict (dict_t *dict) +{ + if (!dict) + return; +#ifdef HAVE_MALLOC_STATS + struct mallinfo info; + int ret = -1; + + memset (&info, 0, sizeof(struct mallinfo)); + info = mallinfo (); + + ret = dict_set_int32 (dict, "mallinfo.arena", info.arena); + if (ret) + return; + + ret = dict_set_int32 (dict, "mallinfo.ordblks", info.ordblks); + if (ret) + return; + + ret = dict_set_int32 (dict, "mallinfo.smblks", info.smblks); + if (ret) + return; + + ret = dict_set_int32 (dict, "mallinfo.hblks", info.hblks); + if (ret) + return; + + ret = dict_set_int32 (dict, "mallinfo.hblkhd", info.hblkhd); + if (ret) + return; + + ret = dict_set_int32 (dict, "mallinfo.usmblks", info.usmblks); + if (ret) + return; + + ret = dict_set_int32 (dict, "mallinfo.fsmblks", info.fsmblks); + if (ret) + return; + + ret = dict_set_int32 (dict, "mallinfo.uordblks", info.uordblks); + if (ret) + return; + + ret = dict_set_int32 (dict, "mallinfo.fordblks", info.fordblks); + if (ret) + return; + + ret = dict_set_int32 (dict, "mallinfo.keepcost", info.keepcost); + if (ret) + return; +#endif + return; +} + void gf_proc_dump_mempool_info (glusterfs_ctx_t *ctx) { @@ -253,6 +308,61 @@ gf_proc_dump_mempool_info (glusterfs_ctx_t *ctx) } } +void +gf_proc_dump_mempool_info_to_dict (glusterfs_ctx_t *ctx, dict_t *dict) +{ + struct mem_pool *pool = NULL; + char key[GF_DUMP_MAX_BUF_LEN] = {0,}; + int count = 0; + int ret = -1; + + if (!ctx || !dict) + return; + + list_for_each_entry (pool, &ctx->mempool_list, global_list) { + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "pool%d.name", count); + ret = dict_set_str (dict, key, pool->name); + if (ret) + return; + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "pool%d.hotcount", count); + ret = dict_set_int32 (dict, key, pool->hot_count); + if (ret) + return; + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "pool%d.coldcount", count); + ret = dict_set_int32 (dict, key, pool->cold_count); + if (ret) + return; + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "pool%d.paddedsizeof", count); + ret = dict_set_uint64 (dict, key, pool->padded_sizeof_type); + if (ret) + return; + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "pool%d.alloccount", count); + ret = dict_set_uint64 (dict, key, pool->alloc_count); + if (ret) + return; + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "pool%d.max_alloc", count); + ret = dict_set_int32 (dict, key, pool->max_alloc); + if (ret) + return; + + count++; + } + ret = dict_set_int32 (dict, "mempool-count", count); + + return; +} + void gf_proc_dump_latency_info (xlator_t *xl); void diff --git a/libglusterfs/src/statedump.h b/libglusterfs/src/statedump.h index 1c56d6cfa..cdeb5b7fc 100644 --- a/libglusterfs/src/statedump.h +++ b/libglusterfs/src/statedump.h @@ -77,9 +77,17 @@ int gf_proc_dump_write(char *key, char *value,...); void inode_table_dump(inode_table_t *itable, char *prefix); +void inode_table_dump_to_dict (inode_table_t *itable, char *prefix, dict_t *dict); + void fdtable_dump(fdtable_t *fdtable, char *prefix); +void fdtable_dump_to_dict (fdtable_t *fdtable, char *prefix, dict_t *dict); + void inode_dump(inode_t *inode, char *prefix); +void gf_proc_dump_mem_info_to_dict (dict_t *dict); + +void gf_proc_dump_mempool_info_to_dict (glusterfs_ctx_t *ctx, dict_t *dict); + void glusterd_init (int sig); #endif /* STATEDUMP_H */ diff --git a/libglusterfs/src/xlator.h b/libglusterfs/src/xlator.h index bc3d7a6dc..cca2505ab 100644 --- a/libglusterfs/src/xlator.h +++ b/libglusterfs/src/xlator.h @@ -756,12 +756,29 @@ typedef int32_t (*dumpop_inodectx_t) (xlator_t *this, inode_t *ino); typedef int32_t (*dumpop_fdctx_t) (xlator_t *this, fd_t *fd); +typedef int32_t (*dumpop_priv_to_dict_t) (xlator_t *this, dict_t *dict); + +typedef int32_t (*dumpop_inode_to_dict_t) (xlator_t *this, dict_t *dict); + +typedef int32_t (*dumpop_fd_to_dict_t) (xlator_t *this, dict_t *dict); + +typedef int32_t (*dumpop_inodectx_to_dict_t) (xlator_t *this, inode_t *ino, + dict_t *dict); + +typedef int32_t (*dumpop_fdctx_to_dict_t) (xlator_t *this, fd_t *fd, + dict_t *dict); + struct xlator_dumpops { - dumpop_priv_t priv; - dumpop_inode_t inode; - dumpop_fd_t fd; - dumpop_inodectx_t inodectx; - dumpop_fdctx_t fdctx; + dumpop_priv_t priv; + dumpop_inode_t inode; + dumpop_fd_t fd; + dumpop_inodectx_t inodectx; + dumpop_fdctx_t fdctx; + dumpop_priv_to_dict_t priv_to_dict; + dumpop_inode_to_dict_t inode_to_dict; + dumpop_fd_to_dict_t fd_to_dict; + dumpop_inodectx_to_dict_t inodectx_to_dict; + dumpop_fdctx_to_dict_t fdctx_to_dict; }; typedef struct xlator_list { diff --git a/rpc/rpc-lib/src/protocol-common.h b/rpc/rpc-lib/src/protocol-common.h index b35cdf911..971996091 100644 --- a/rpc/rpc-lib/src/protocol-common.h +++ b/rpc/rpc-lib/src/protocol-common.h @@ -180,6 +180,7 @@ enum glusterd_brick_procnum { GLUSTERD_BRICK_TERMINATE, GLUSTERD_BRICK_XLATOR_INFO, GLUSTERD_BRICK_XLATOR_HEAL, + GLUSTERD_BRICK_STATUS, GLUSTERD_BRICK_OP, GLUSTERD_BRICK_MAXVALUE, }; diff --git a/rpc/xdr/src/cli1-xdr.h b/rpc/xdr/src/cli1-xdr.h index d5593977d..ea8ab02b6 100644 --- a/rpc/xdr/src/cli1-xdr.h +++ b/rpc/xdr/src/cli1-xdr.h @@ -161,14 +161,18 @@ enum gf1_cli_top_op { typedef enum gf1_cli_top_op gf1_cli_top_op; enum gf_cli_status_type { - GF_CLI_STATUS_NONE = 0x0000, - GF_CLI_STATUS_VOL = 0x0100, - GF_CLI_STATUS_ALL = 0x0200, - GF_CLI_STATUS_BRICK = 0x0400, - GF_CLI_STATUS_DETAIL = 0x0800, - GF_CLI_STATUS_VOL_DETAIL = 0x0900, - GF_CLI_STATUS_ALL_DETAIL = 0x0A00, - GF_CLI_STATUS_BRICK_DETAIL = 0x0C00, + GF_CLI_STATUS_INVAL = -1, + GF_CLI_STATUS_NONE = 0x000, + GF_CLI_STATUS_MEM = 0x001, + GF_CLI_STATUS_CLIENTS = 0x002, + GF_CLI_STATUS_INODE = 0x004, + GF_CLI_STATUS_FD = 0x008, + GF_CLI_STATUS_CALLPOOL = 0x010, + GF_CLI_STATUS_DETAIL = 0x020, + GF_CLI_STATUS_MASK = 0x0FF, + GF_CLI_STATUS_VOL = 0x100, + GF_CLI_STATUS_ALL = 0x200, + GF_CLI_STATUS_BRICK = 0x400, }; typedef enum gf_cli_status_type gf_cli_status_type; diff --git a/rpc/xdr/src/cli1-xdr.x b/rpc/xdr/src/cli1-xdr.x index 5697310ad..a2edc57eb 100644 --- a/rpc/xdr/src/cli1-xdr.x +++ b/rpc/xdr/src/cli1-xdr.x @@ -106,14 +106,18 @@ enum gf1_cli_top_op { /* The unconventional hex numbers help us perform bit-wise operations which reduces complexity */ enum gf_cli_status_type { - GF_CLI_STATUS_NONE = 0x0000, - GF_CLI_STATUS_VOL = 0x0100, - GF_CLI_STATUS_ALL = 0x0200, - GF_CLI_STATUS_BRICK = 0x0400, - GF_CLI_STATUS_DETAIL = 0x0800, - GF_CLI_STATUS_VOL_DETAIL = 0x0900, - GF_CLI_STATUS_ALL_DETAIL = 0x0A00, - GF_CLI_STATUS_BRICK_DETAIL = 0x0C00 + GF_CLI_STATUS_INVAL = -1, + GF_CLI_STATUS_NONE = 0x000, + GF_CLI_STATUS_MEM = 0x001, /*000000000001*/ + GF_CLI_STATUS_CLIENTS = 0x002, /*000000000010*/ + GF_CLI_STATUS_INODE = 0x004, /*000000000100*/ + GF_CLI_STATUS_FD = 0x008, /*000000001000*/ + GF_CLI_STATUS_CALLPOOL = 0x010, /*000000010000*/ + GF_CLI_STATUS_DETAIL = 0x020, /*000000100000*/ + GF_CLI_STATUS_MASK = 0x0FF, /*000011111111 Used to get the op*/ + GF_CLI_STATUS_VOL = 0x100, /*000100000000*/ + GF_CLI_STATUS_ALL = 0x200, /*001000000000*/ + GF_CLI_STATUS_BRICK = 0x400 /*010000000000*/ }; struct gf_cli_req { diff --git a/xlators/mgmt/glusterd/src/glusterd-op-sm.c b/xlators/mgmt/glusterd/src/glusterd-op-sm.c index d72581910..38d73b1f7 100644 --- a/xlators/mgmt/glusterd/src/glusterd-op-sm.c +++ b/xlators/mgmt/glusterd/src/glusterd-op-sm.c @@ -192,6 +192,18 @@ glusterd_brick_op_build_payload (glusterd_op_t op, glusterd_brickinfo_t *brickin brick_req->name = ""; } break; + case GD_OP_STATUS_VOLUME: + { + brick_req = GF_CALLOC (1, sizeof (*brick_req), + gf_gld_mt_mop_brick_req_t); + if (!brick_req) { + gf_log (THIS->name, GF_LOG_ERROR, "Out of memory"); + goto out; + } + brick_req->op = GLUSTERD_BRICK_STATUS; + brick_req->name = ""; + } + break; default: goto out; break; @@ -562,7 +574,6 @@ glusterd_op_stage_status_volume (dict_t *dict, char **op_errstr) if (ret) { snprintf (msg, sizeof(msg), "Volume %s does not exist", volname); gf_log (THIS->name, GF_LOG_ERROR, "%s", msg); - *op_errstr = gf_strdup(msg); ret = -1; goto out; } @@ -573,8 +584,12 @@ glusterd_op_stage_status_volume (dict_t *dict, char **op_errstr) goto out; ret = glusterd_brickinfo_from_brick (brick, &brickinfo); - if (ret) + if (ret) { + snprintf (msg, sizeof (msg), "%s is not a brick", + brick); + gf_log (THIS->name, GF_LOG_ERROR, "%s", msg); goto out; + } ret = glusterd_volume_brickinfo_get (NULL, brickinfo->hostname, @@ -588,7 +603,6 @@ glusterd_op_stage_status_volume (dict_t *dict, char **op_errstr) " volume %s", brick, volname); gf_log (THIS->name, GF_LOG_ERROR, "%s", msg); - *op_errstr = gf_strdup(msg); ret = -1; goto out; } @@ -597,8 +611,12 @@ glusterd_op_stage_status_volume (dict_t *dict, char **op_errstr) ret = 0; out: - if (ret && !(*op_errstr)) - *op_errstr = gf_strdup ("Validation Failed for Status"); + if (ret) { + if (msg[0] != '\0') + *op_errstr = gf_strdup (msg); + else + *op_errstr = gf_strdup ("Validation Failed for Status"); + } gf_log (THIS->name, GF_LOG_DEBUG, "Returning: %d", ret); return ret; @@ -1242,14 +1260,13 @@ glusterd_op_status_volume (dict_t *dict, char **op_errstr, { int ret = -1; int brick_count = 0; - int32_t brick_index = 0; + int brick_index = -1; uint32_t cmd = 0; char *volname = NULL; char *brick = NULL; xlator_t *this = NULL; glusterd_volinfo_t *volinfo = NULL; glusterd_brickinfo_t *brickinfo = NULL; - glusterd_brickinfo_t *tmpbrickinfo = NULL; glusterd_conf_t *priv = NULL; this = THIS; @@ -1301,36 +1318,41 @@ glusterd_op_status_volume (dict_t *dict, char **op_errstr, ret = dict_get_str (dict, "brick", &brick); if (ret) goto out; - ret = glusterd_brickinfo_from_brick (brick, &tmpbrickinfo); + + ret = glusterd_volume_brickinfo_get_by_brick (brick, + volinfo, + &brickinfo, + GF_PATH_COMPLETE); if (ret) goto out; - if (uuid_is_null (tmpbrickinfo->uuid) && - glusterd_resolve_brick (tmpbrickinfo)) + + if (uuid_compare (brickinfo->uuid, priv->uuid)) goto out; - } - list_for_each_entry (brickinfo, &volinfo->bricks, brick_list) { - if (!uuid_compare (brickinfo->uuid, priv->uuid)) { + glusterd_add_brick_to_dict (volinfo, brickinfo, rsp_dict, 0); + if (cmd & GF_CLI_STATUS_DETAIL) + glusterd_add_brick_detail_to_dict (volinfo, brickinfo, + rsp_dict, 0); + ret = dict_set_int32 (rsp_dict, "count", 1); - if ((cmd & GF_CLI_STATUS_BRICK) != 0 && - (strcmp (tmpbrickinfo->path, - brickinfo->path) || - uuid_compare (tmpbrickinfo->uuid, - brickinfo->uuid))) + goto out; + } else { + list_for_each_entry (brickinfo, &volinfo->bricks, brick_list) { + brick_index++; + if (uuid_compare (brickinfo->uuid, priv->uuid)) continue; glusterd_add_brick_to_dict (volinfo, brickinfo, rsp_dict, brick_index); - if (cmd & GF_CLI_STATUS_DETAIL) + if (cmd & GF_CLI_STATUS_DETAIL) { glusterd_add_brick_detail_to_dict (volinfo, brickinfo, rsp_dict, brick_index); + } brick_count++; } - if (!(cmd & GF_CLI_STATUS_BRICK)) - brick_index++; } ret = dict_set_int32 (rsp_dict, "count", brick_count); @@ -2149,6 +2171,7 @@ glusterd_need_brick_op (glusterd_op_t op) switch (op) { case GD_OP_PROFILE_VOLUME: + case GD_OP_STATUS_VOLUME: ret = _gf_true; break; default: @@ -2503,6 +2526,57 @@ glusterd_profile_volume_brick_rsp (glusterd_brickinfo_t *brickinfo, return ret; } +void +_status_volume_add_brick_rsp (dict_t *this, char *key, data_t *value, + void *data) +{ + char new_key[256] = {0,}; + data_t *new_value = 0; + glusterd_pr_brick_rsp_conv_t *rsp_ctx = NULL; + + rsp_ctx = data; + new_value = data_copy (value); + snprintf (new_key, sizeof (new_key), "brick%d.%s", rsp_ctx->count, key); + dict_set (rsp_ctx->dict, new_key, new_value); + + return; +} + +int +glusterd_status_volume_brick_rsp (glusterd_brickinfo_t *brickinfo, + dict_t *rsp_dict, dict_t *op_ctx, + char **op_errstr) +{ + int ret = 0; + glusterd_pr_brick_rsp_conv_t rsp_ctx = {0}; + int32_t count = 0; + int index = 0; + + GF_ASSERT (rsp_dict); + GF_ASSERT (op_ctx); + GF_ASSERT (op_errstr); + GF_ASSERT (brickinfo); + + ret = dict_get_int32 (op_ctx, "count", &count); + if (ret) { + count = 0; + } else { + count++; + } + ret = dict_get_int32 (rsp_dict, "index", &index); + if (ret) + goto out; + dict_del (rsp_dict, "index"); + + rsp_ctx.count = index; + rsp_ctx.dict = op_ctx; + dict_foreach (rsp_dict, _status_volume_add_brick_rsp, &rsp_ctx); + ret = dict_set_int32 (op_ctx, "count", count); + +out: + return ret; +} + int32_t glusterd_handle_brick_rsp (glusterd_brickinfo_t *brickinfo, glusterd_op_t op, dict_t *rsp_dict, dict_t *op_ctx, @@ -2516,7 +2590,11 @@ glusterd_handle_brick_rsp (glusterd_brickinfo_t *brickinfo, case GD_OP_PROFILE_VOLUME: ret = glusterd_profile_volume_brick_rsp (brickinfo, rsp_dict, op_ctx, op_errstr); - break; + break; + case GD_OP_STATUS_VOLUME: + ret = glusterd_status_volume_brick_rsp (brickinfo, rsp_dict, + op_ctx, op_errstr); + break; default: break; @@ -2868,6 +2946,113 @@ out: } +static int +glusterd_bricks_select_status_volume (dict_t *dict, char **op_errstr) +{ + int ret = -1; + int cmd = 0; + int brick_index = -1; + char *volname = NULL; + char *brickname = NULL; + glusterd_volinfo_t *volinfo = NULL; + glusterd_brickinfo_t *brickinfo = NULL; + glusterd_pending_node_t *pending_node = NULL; + xlator_t *this = NULL; + glusterd_conf_t *priv = NULL; + + GF_ASSERT (dict); + + this = THIS; + GF_ASSERT (this); + priv = this->private; + GF_ASSERT (priv); + + ret = dict_get_int32 (dict, "cmd", &cmd); + if (ret) { + gf_log (THIS->name, GF_LOG_ERROR, "Unable to get status type"); + goto out; + } + + if (cmd & GF_CLI_STATUS_ALL) + goto out; + + switch (cmd & GF_CLI_STATUS_MASK) { + case GF_CLI_STATUS_MEM: + case GF_CLI_STATUS_CLIENTS: + case GF_CLI_STATUS_INODE: + case GF_CLI_STATUS_FD: + case GF_CLI_STATUS_CALLPOOL: + break; + default: + goto out; + } + ret = dict_get_str (dict, "volname", &volname); + if (ret) { + gf_log (THIS->name, GF_LOG_ERROR, "Unable to get volname"); + goto out; + } + ret = glusterd_volinfo_find (volname, &volinfo); + if (ret) { + goto out; + } + + if ( (cmd & GF_CLI_STATUS_BRICK) != 0) { + ret = dict_get_str (dict, "brick", &brickname); + if (ret) { + gf_log (THIS->name, GF_LOG_ERROR, + "Unable to get brick"); + goto out; + } + ret = glusterd_volume_brickinfo_get_by_brick (brickname, + volinfo, + &brickinfo, + GF_PATH_COMPLETE); + if (ret) + goto out; + + if (uuid_compare (brickinfo->uuid, priv->uuid)|| + !glusterd_is_brick_started (brickinfo)) + goto out; + + pending_node = GF_CALLOC (1, sizeof (*pending_node), + gf_gld_mt_pending_node_t); + if (!pending_node) { + ret = -1; + goto out; + } + pending_node->node = brickinfo; + pending_node->type = GD_NODE_BRICK; + pending_node->index = 0; + list_add_tail (&pending_node->list, &opinfo.pending_bricks); + + ret = 0; + } else { + list_for_each_entry (brickinfo, &volinfo->bricks, brick_list) { + brick_index++; + if (uuid_compare (brickinfo->uuid, priv->uuid) || + !glusterd_is_brick_started (brickinfo)) { + continue; + } + pending_node = GF_CALLOC (1, sizeof (*pending_node), + gf_gld_mt_pending_node_t); + if (!pending_node) { + ret = -1; + gf_log (THIS->name ,GF_LOG_ERROR, + "Unable to allocate memory"); + goto out; + } + pending_node->node = brickinfo; + pending_node->type = GD_NODE_BRICK; + pending_node->index = brick_index; + list_add_tail (&pending_node->list, + &opinfo.pending_bricks); + pending_node = NULL; + } + } +out: + return ret; +} + static int glusterd_op_ac_send_brick_op (glusterd_op_sm_event_t *event, void *ctx) { @@ -2990,6 +3175,10 @@ glusterd_op_bricks_select (glusterd_op_t op, dict_t *dict, char **op_errstr) ret = glusterd_bricks_select_heal_volume (dict, op_errstr); break; + case GD_OP_STATUS_VOLUME: + ret = glusterd_bricks_select_status_volume (dict, op_errstr); + break; + default: break; } diff --git a/xlators/mgmt/glusterd/src/glusterd-rpc-ops.c b/xlators/mgmt/glusterd/src/glusterd-rpc-ops.c index a4dd7e25c..21d8ab0ac 100644 --- a/xlators/mgmt/glusterd/src/glusterd-rpc-ops.c +++ b/xlators/mgmt/glusterd/src/glusterd-rpc-ops.c @@ -1038,8 +1038,7 @@ glusterd_volume_status_use_rsp_dict (dict_t *rsp_dict) rsp_ctx.count = count; rsp_ctx.dict = ctx_dict; dict_foreach (rsp_dict, glusterd_volume_status_add_peer_rsp, &rsp_ctx); - dict_del (ctx_dict, "count"); - ret = dict_get_int32 (ctx_dict, "count", &brick_count); + ret = dict_set_int32 (ctx_dict, "count", count + brick_count); out: return ret; @@ -1626,9 +1625,13 @@ glusterd3_1_brick_op_cbk (struct rpc_req *req, struct iovec *iov, call_frame_t *frame = NULL; glusterd_op_brick_rsp_ctx_t *ev_ctx = NULL; dict_t *dict = NULL; + int index = 0; + glusterd_req_ctx_t *req_ctx = NULL; + glusterd_pending_node_t *node = NULL; GF_ASSERT (req); frame = myframe; + req_ctx = frame->local; if (-1 == req->rpc_status) { rsp.op_ret = -1; @@ -1643,7 +1646,7 @@ glusterd3_1_brick_op_cbk (struct rpc_req *req, struct iovec *iov, gf_log ("", GF_LOG_ERROR, "error"); rsp.op_ret = -1; rsp.op_errno = EINVAL; - rsp.op_errstr = strdup ("Unable to decode response"); + rsp.op_errstr = strdup ("Unable to decode brick op response"); event_type = GD_OP_EVENT_RCVD_RJT; goto out; } @@ -1668,6 +1671,19 @@ glusterd3_1_brick_op_cbk (struct rpc_req *req, struct iovec *iov, op_ret = rsp.op_ret; + /* Add index to rsp_dict for GD_OP_STATUS_VOLUME */ + if (GD_OP_STATUS_VOLUME == req_ctx->op) { + node = frame->cookie; + index = node->index; + ret = dict_set_int32 (dict, "index", index); + if (ret) { + gf_log (THIS->name, GF_LOG_ERROR, + "Error setting index on brick status rsp dict"); + rsp.op_ret = -1; + event_type = GD_OP_EVENT_RCVD_RJT; + goto out; + } + } out: ev_ctx = GF_CALLOC (1, sizeof (*ev_ctx), gf_gld_mt_brick_rsp_ctx_t); GF_ASSERT (ev_ctx); diff --git a/xlators/mgmt/glusterd/src/glusterd.h b/xlators/mgmt/glusterd/src/glusterd.h index 6e9619250..44f84d78d 100644 --- a/xlators/mgmt/glusterd/src/glusterd.h +++ b/xlators/mgmt/glusterd/src/glusterd.h @@ -240,6 +240,7 @@ typedef struct glusterd_pending_node_ { struct list_head list; void *node; gd_node_type type; + int32_t index; } glusterd_pending_node_t; enum glusterd_op_ret { diff --git a/xlators/protocol/server/src/server.c b/xlators/protocol/server/src/server.c index d767199d0..60bc517dd 100644 --- a/xlators/protocol/server/src/server.c +++ b/xlators/protocol/server/src/server.c @@ -163,6 +163,38 @@ ret: } /* */ +int +server_fd_to_dict (xlator_t *this, dict_t *dict) +{ + server_conf_t *conf = NULL; + server_connection_t *trav = NULL; + char key[GF_DUMP_MAX_BUF_LEN] = {0,}; + int count = 0; + int ret = -1; + + GF_VALIDATE_OR_GOTO (THIS->name, this, out); + GF_VALIDATE_OR_GOTO (this->name, dict, out); + + conf = this->private; + if (!conf) + return -1; + + ret = pthread_mutex_trylock (&conf->mutex); + if (ret) + return -1; + + list_for_each_entry (trav, &conf->conns, list) { + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "conn%d", count++); + fdtable_dump_to_dict (trav->fdtable, key, dict); + } + pthread_mutex_unlock (&conf->mutex); + + ret = dict_set_int32 (dict, "conncount", count); +out: + return ret; +} + int server_fd (xlator_t *this) { @@ -217,6 +249,53 @@ out: return ret; } +int +server_priv_to_dict (xlator_t *this, dict_t *dict) +{ + server_conf_t *conf = NULL; + rpc_transport_t *xprt = NULL; + peer_info_t *peerinfo = NULL; + char key[32] = {0,}; + int count = 0; + int ret = -1; + + GF_VALIDATE_OR_GOTO (THIS->name, this, out); + GF_VALIDATE_OR_GOTO (THIS->name, dict, out); + + conf = this->private; + if (!conf) + return 0; + //TODO: Dump only specific info to dict + + list_for_each_entry (xprt, &conf->xprt_list, list) { + peerinfo = &xprt->peerinfo; + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "client%d.hostname", count); + ret = dict_set_str (dict, key, peerinfo->identifier); + if (ret) + goto out; + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "client%d.bytesread", count); + ret = dict_set_uint64 (dict, key, xprt->total_bytes_read); + if (ret) + goto out; + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "client%d.byteswrite", count); + ret = dict_set_uint64 (dict, key, xprt->total_bytes_write); + if (ret) + goto out; + + count++; + } + + ret = dict_set_int32 (dict, "clientcount", count); + +out: + return ret; +} + int server_priv (xlator_t *this) { @@ -249,6 +328,57 @@ out: return ret; } +int +server_inode_to_dict (xlator_t *this, dict_t *dict) +{ + server_conf_t *conf = NULL; + server_connection_t *trav = NULL; + char key[32] = {0,}; + int count = 0; + int ret = -1; + xlator_t *prev_bound_xl = NULL; + + GF_VALIDATE_OR_GOTO (THIS->name, this, out); + GF_VALIDATE_OR_GOTO (this->name, dict, out); + + conf = this->private; + if (!conf) + return -1; + + ret = pthread_mutex_trylock (&conf->mutex); + if (ret) + return -1; + + list_for_each_entry (trav, &conf->conns, list) { + if (trav->bound_xl && trav->bound_xl->itable) { + /* Presently every brick contains only one + * bound_xl for all connections. This will lead + * to duplicating of the inode lists, if listing + * is done for every connection. This simple check + * prevents duplication in the present case. If + * need arises the check can be improved. + */ + if (trav->bound_xl == prev_bound_xl) + continue; + prev_bound_xl = trav->bound_xl; + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "conn%d", count); + inode_table_dump_to_dict (trav->bound_xl->itable, + key, dict); + count++; + } + } + pthread_mutex_unlock (&conf->mutex); + + ret = dict_set_int32 (dict, "conncount", count); + +out: + if (prev_bound_xl) + prev_bound_xl = NULL; + return ret; +} + int server_inode (xlator_t *this) { @@ -811,9 +941,12 @@ struct xlator_cbks cbks = { }; struct xlator_dumpops dumpops = { - .priv = server_priv, - .fd = server_fd, - .inode = server_inode, + .priv = server_priv, + .fd = server_fd, + .inode = server_inode, + .priv_to_dict = server_priv_to_dict, + .fd_to_dict = server_fd_to_dict, + .inode_to_dict = server_inode_to_dict, }; -- cgit