summaryrefslogtreecommitdiffstats
path: root/tests/basic/afr
diff options
context:
space:
mode:
authorPranith Kumar K <pkarampu@redhat.com>2014-06-12 20:38:34 +0530
committerVijay Bellur <vbellur@redhat.com>2014-06-14 04:10:06 -0700
commit12b7797bfb143890ad4ca085332ec2f5e1ed08b8 (patch)
tree36fc239722c1df779e7a4efc43f64063bcd39ffd /tests/basic/afr
parent7aa3630b1f5e07227e9cd167cbd717bd7932ae78 (diff)
Fix resolution issues across fuse/server/afr
Problems with fuse/server: Fuse loc touch up sets loc->name even when pargfid is not known. Server lookup does (pargfid, name) based lookup when name is set ignoring the gfid. Because of this server resolver finds that the lookup came on (null-pargfid, name) and fails the lookup with EINVAL. Fix: Don't set loc->name in loc_touchup if the pargfid is not known. Did the same even for server-resolver Problem with afr: Lets say there is a directory hierarchy a/b/c/d on the mount and the user is cd'ed into the directory. Bring down one of the bricks of replica and remove all directories/files to simulate disk replacement on that brick. Now this brick is brought back up. Creates on the cd'ed directory fail with ESTALE. Basically before sending a create of 'f' inside 'd', fuse sends a lookup to make sure the file is not present. On one of the bricks 'd' is present and 'f' is not so it sends ENOENT as response. On the new brick 'd' itself is not present. So it sends ESTALE. In afr ESTALE is considered to be special errno on witnessing which lookup has to fail. And ESTALE is given more priority than ENOENT. Due to these reasons lookup fails with ESTALE rather than ENOENT. Since lookup didn't fail with ENOENT, 'create' can't be issued so the command is failed with ESTALE. Solution: Afr needs to consider ESTALE errno normally and ENOENT needs to be given more priority so that operations like create can proceed even when only one of the brick is up and running. Whenever client xlator identifies that gfid-changed, it sets that information in lookup xdata. Afr uses this information to fail the lookup with ESTALE so that top xlator can send fresh lookup. Change-Id: Ica6ce01baef08620154050a635e6f97d51029ef6 BUG: 1106408 Signed-off-by: Pranith Kumar K <pkarampu@redhat.com> Reviewed-on: http://review.gluster.org/8015 Tested-by: Gluster Build System <jenkins@build.gluster.com> Reviewed-by: Vijay Bellur <vbellur@redhat.com>
Diffstat (limited to 'tests/basic/afr')
-rw-r--r--tests/basic/afr/resolve.t49
1 files changed, 49 insertions, 0 deletions
diff --git a/tests/basic/afr/resolve.t b/tests/basic/afr/resolve.t
new file mode 100644
index 00000000000..7dd432996f6
--- /dev/null
+++ b/tests/basic/afr/resolve.t
@@ -0,0 +1,49 @@
+#!/bin/bash
+
+. $(dirname $0)/../../include.rc
+. $(dirname $0)/../../volume.rc
+
+#Check that operations succeed after changing the disk of the brick while
+#a brick is down
+cleanup;
+
+TEST glusterd
+TEST pidof glusterd
+TEST $CLI volume create $V0 replica 2 $H0:$B0/${V0}{0,1}
+TEST $CLI volume set $V0 cluster.self-heal-daemon off
+TEST $CLI volume start $V0
+TEST glusterfs --volfile-id=/$V0 --volfile-server=$H0 $M0
+TEST glusterfs --volfile-id=/$V0 --volfile-server=$H0 $M1
+TEST cd $M0
+TEST mkdir -p a/b/c/d/e
+TEST cd a/b/c/d/e
+echo abc > g
+
+#Simulate disk replacement
+TEST kill_brick $V0 $H0 $B0/${V0}0
+rm -rf $B0/${V0}0/.glusterfs $B0/${V0}0/a
+
+TEST $CLI volume start $V0 force
+EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" afr_child_up_status $V0 0
+#Test that the lookup returns ENOENT instead of ESTALE
+#If lookup returns ESTALE this command will fail with ESTALE
+TEST touch f
+
+#Test that ESTALE is ignored when there is a good copy
+EXPECT abc cat g
+
+#Simulate file changing only one mount
+#create the file on first mount
+echo ghi > $M0/b
+
+#re-create the file on other mount while one of the bricks is down.
+TEST kill_brick $V0 $H0 $B0/${V0}0
+TEST rm -f $M1/b
+echo jkl > $M1/b
+#Clear the extended attributes on the directory to create a scenario where
+#gfid-mismatch happened. This should result in EIO
+TEST setfattr -x trusted.afr.$V0-client-0 $B0/${V0}1
+TEST $CLI volume start $V0 force
+EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" afr_child_up_status $V0 0
+TEST ! cat $M0/b
+cleanup
/src/glusterd.h1
-rw-r--r--xlators/protocol/server/src/server.c139
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|<VOLNAME>] [brick] [detail]",
+ { "volume status [all|{<VOLNAME> [<BRICKNAME>] "
+ "[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;
@@ -736,6 +737,138 @@ out:
}
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)
{
int ret = -1;
@@ -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
@@ -235,6 +235,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)
{
struct mem_pool *pool = NULL;
@@ -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;
@@ -2869,6 +2947,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)
{
int ret = 0;
@@ -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
@@ -164,6 +164,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)
{
server_conf_t *conf = NULL;
@@ -218,6 +250,53 @@ out:
}
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)
{
server_conf_t *conf = NULL;
@@ -250,6 +329,57 @@ out:
}
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)
{
server_conf_t *conf = NULL;
@@ -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,
};