diff options
author | Kaushal M <kaushal@redhat.com> | 2012-02-27 12:41:24 +0530 |
---|---|---|
committer | Vijay Bellur <vijay@gluster.com> | 2012-03-14 02:27:42 -0700 |
commit | a476aba5b0368c3bc649db319ee748ae410144d9 (patch) | |
tree | ac6ea7e9ac361f3516ae2a2867f3c2d5aa86e047 | |
parent | fcb5ebde1e84da871a7f43df9ecbce7d1d1de435 (diff) |
cli, glusterd, nfs: "volume status|profile|top" for nfs servers
Enables usage of volume monitoring operations "volume status", "volume top" and
"volume profile" for nfs servers. These operations can be performed on
nfs-servers by passing "nfs" as an option in cli. The output is similar to the
normal brick outputs for these commands.
The new syntaxes for the changed commands are as below,
#gluster volume profile <VOLNAME> {start|info|stop} [nfs]
#gluster volume top <VOLNAME> {[open|read|write|opendir|readdir [nfs]]
|[read-perf|write-perf [nfs|{bs <size> count <count>}]]}
[brick <brick>] [list-cnt <count>]
#gluster volume status [all | <VOLNAME> [nfs|<BRICK>]]
[detail|clients|mem|inode|fd|callpool]
Change-Id: Ia6eb50c60aecacf9b413d3ea993f4cdd90ec0e07
BUG: 795267
Signed-off-by: Kaushal M <kaushal@redhat.com>
Reviewed-on: http://review.gluster.com/2820
Tested-by: Gluster Build System <jenkins@build.gluster.com>
Reviewed-by: Krishnan Parthasarathi <kp@gluster.com>
-rw-r--r-- | cli/src/cli-cmd-parser.c | 56 | ||||
-rw-r--r-- | cli/src/cli-cmd-volume.c | 8 | ||||
-rw-r--r-- | cli/src/cli-rpc-ops.c | 85 | ||||
-rw-r--r-- | glusterfsd/src/glusterfsd-mgmt.c | 247 | ||||
-rw-r--r-- | rpc/rpc-lib/src/protocol-common.h | 2 | ||||
-rw-r--r-- | rpc/xdr/src/cli1-xdr.h | 1 | ||||
-rw-r--r-- | rpc/xdr/src/cli1-xdr.x | 3 | ||||
-rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-handler.c | 15 | ||||
-rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-op-sm.c | 354 | ||||
-rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-op-sm.h | 10 | ||||
-rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-rpc-ops.c | 38 | ||||
-rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-utils.c | 188 | ||||
-rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-utils.h | 20 | ||||
-rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-volume-ops.c | 2 | ||||
-rw-r--r-- | xlators/mgmt/glusterd/src/glusterd.c | 5 | ||||
-rw-r--r-- | xlators/mgmt/glusterd/src/glusterd.h | 6 | ||||
-rw-r--r-- | xlators/nfs/server/src/nfs.c | 89 |
17 files changed, 975 insertions, 154 deletions
diff --git a/cli/src/cli-cmd-parser.c b/cli/src/cli-cmd-parser.c index 24310cac56c..0f13928bbfc 100644 --- a/cli/src/cli-cmd-parser.c +++ b/cli/src/cli-cmd-parser.c @@ -1648,7 +1648,7 @@ cli_cmd_volume_profile_parse (const char **words, int wordcount, if (!dict) goto out; - if (wordcount != 4) + if (wordcount < 4 || wordcount >5) goto out; volname = (char *)words[2]; @@ -1670,7 +1670,19 @@ cli_cmd_volume_profile_parse (const char **words, int wordcount, op = GF_CLI_STATS_INFO; } else GF_ASSERT (!"opword mismatch"); + ret = dict_set_int32 (dict, "op", (int32_t)op); + if (ret) + goto out; + + if (wordcount == 5) { + if (!strcmp (words[4], "nfs")) { + ret = dict_set_int32 (dict, "nfs", _gf_true); + if (ret) + goto out; + } + } + *options = dict; out: if (ret && dict) @@ -1694,6 +1706,7 @@ cli_cmd_volume_top_parse (const char **words, int wordcount, int perf = 0; uint32_t blk_size = 0; uint32_t count = 0; + gf_boolean_t nfs = _gf_false; char *delimiter = NULL; char *opwords[] = { "open", "read", "write", "opendir", "readdir", "read-perf", "write-perf", @@ -1748,7 +1761,17 @@ cli_cmd_volume_top_parse (const char **words, int wordcount, if (ret) goto out; - for (index = 4; index < wordcount; index+=2) { + if ((wordcount > 4) && !strcmp (words[4], "nfs")) { + nfs = _gf_true; + ret = dict_set_int32 (dict, "nfs", nfs); + if (ret) + goto out; + index = 5; + } else { + index = 4; + } + + for (; index < wordcount; index+=2) { key = (char *) words[index]; value = (char *) words[index+1]; @@ -1781,7 +1804,7 @@ cli_cmd_volume_top_parse (const char **words, int wordcount, ret = -1; goto out; } - } else if (perf && !strcmp (key, "bs")) { + } else if (perf && !nfs && !strcmp (key, "bs")) { ret = gf_is_str_int (value); if (!ret) blk_size = atoi (value); @@ -1795,7 +1818,7 @@ cli_cmd_volume_top_parse (const char **words, int wordcount, goto out; } ret = dict_set_uint32 (dict, "blk-size", blk_size); - } else if (perf && !strcmp (key, "count")) { + } else if (perf && !nfs && !strcmp (key, "count")) { ret = gf_is_str_int (value); if (!ret) count = atoi(value); @@ -1931,9 +1954,13 @@ cli_cmd_volume_status_parse (const char **words, int wordcount, goto out; if (cmd == GF_CLI_STATUS_NONE) { - cmd = GF_CLI_STATUS_BRICK; - ret = dict_set_str (dict, "brick", - (char *)words[3]); + if (!strcmp (words[3], "nfs")) { + cmd |= GF_CLI_STATUS_NFS; + } else { + cmd = GF_CLI_STATUS_BRICK; + ret = dict_set_str (dict, "brick", + (char *)words[3]); + } } else { cmd |= GF_CLI_STATUS_VOL; @@ -1945,7 +1972,7 @@ cli_cmd_volume_status_parse (const char **words, int wordcount, case 5: if (!strcmp (words[2], "all")) { - cli_out ("Cannot specify brick for \"all\""); + cli_out ("Cannot specify brick/nfs for \"all\""); ret = -1; goto out; } @@ -1958,13 +1985,22 @@ cli_cmd_volume_status_parse (const char **words, int wordcount, goto out; } - cmd |= GF_CLI_STATUS_BRICK; ret = dict_set_str (dict, "volname", (char *)words[2]); if (ret) goto out; - ret = dict_set_str (dict, "brick", (char *)words[3]); + if (!strcmp (words[3], "nfs")) { + if (cmd == GF_CLI_STATUS_FD) { + cli_out ("FD status not available for NFS"); + ret = -1; + goto out; + } + cmd |= GF_CLI_STATUS_NFS; + } else { + cmd |= GF_CLI_STATUS_BRICK; + ret = dict_set_str (dict, "brick", (char *)words[3]); + } break; default: diff --git a/cli/src/cli-cmd-volume.c b/cli/src/cli-cmd-volume.c index 6b9c0b03f41..9546831ab7c 100644 --- a/cli/src/cli-cmd-volume.c +++ b/cli/src/cli-cmd-volume.c @@ -1804,7 +1804,7 @@ struct cli_cmd volume_cmds[] = { cli_cmd_check_gsync_exists_cbk}, #endif - { "volume profile <VOLNAME> {start|info|stop}", + { "volume profile <VOLNAME> {start|info|stop} [nfs]", cli_cmd_volume_profile_cbk, "volume profile operations"}, @@ -1812,13 +1812,13 @@ struct cli_cmd volume_cmds[] = { cli_cmd_quota_cbk, "quota translator specific operations"}, - { "volume top <VOLNAME> {[open|read|write|opendir|readdir] " - "|[read-perf|write-perf bs <size> count <count>]} " + { "volume top <VOLNAME> {[open|read|write|opendir|readdir [nfs]] " + "|[read-perf|write-perf [nfs|{bs <size> count <count>}]]} " " [brick <brick>] [list-cnt <count>]", cli_cmd_volume_top_cbk, "volume top operations"}, - { "volume status [all | <VOLNAME> [<BRICK>]]" + { "volume status [all | <VOLNAME> [nfs|<BRICK>]]" " [detail|clients|mem|inode|fd|callpool]", cli_cmd_volume_status_cbk, "display status of all or specified volume(s)/brick"}, diff --git a/cli/src/cli-rpc-ops.c b/cli/src/cli-rpc-ops.c index 20688b09687..dbef04a99f8 100644 --- a/cli/src/cli-rpc-ops.c +++ b/cli/src/cli-rpc-ops.c @@ -3506,7 +3506,6 @@ cmd_profile_volume_brick_out (dict_t *dict, int count, int interval) uint64_t sec = 0; uint64_t r_count = 0; uint64_t w_count = 0; - char *brick = NULL; uint64_t rb_counts[32] = {0}; uint64_t wb_counts[32] = {0}; cli_profile_info_t profile_info[GF_FOP_MAXVALUE] = {{0}}; @@ -3519,9 +3518,6 @@ cmd_profile_volume_brick_out (dict_t *dict, int count, int interval) int ret = 0; double total_percentage_latency = 0; - memset (key, 0, sizeof (key)); - snprintf (key, sizeof (key), "%d-brick", count); - ret = dict_get_str (dict, key, &brick); for (i = 0; i < 32; i++) { memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "%d-%d-read-%d", count, @@ -3584,7 +3580,6 @@ cmd_profile_volume_brick_out (dict_t *dict, int count, int interval) ret = dict_get_uint64 (dict, key, &w_count); if (ret == 0) { - cli_out ("Brick: %s", brick); } if (interval == -1) @@ -3681,6 +3676,9 @@ gf_cli3_1_profile_volume_cbk (struct rpc_req *req, struct iovec *iov, int i = 1; int32_t brick_count = 0; char *volname = NULL; + char *brick = NULL; + char str[1024] = {0,}; + if (-1 == req->rpc_status) { goto out; } @@ -3775,6 +3773,23 @@ gf_cli3_1_profile_volume_cbk (struct rpc_req *req, struct iovec *iov, } while (i <= brick_count) { + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%d-brick", i); + ret = dict_get_str (dict, key, &brick); + if (ret) { + gf_log ("cli", GF_LOG_ERROR, "Couldn't get brick name"); + goto out; + } + + ret = dict_get_str_boolean (dict, "nfs", _gf_false); + if (ret) + snprintf (str, sizeof (str), "NFS Server : %s", brick); + else + snprintf (str, sizeof (str), "Brick: %s", brick); + cli_out (str); + memset (str, '-', strlen (str)); + cli_out (str); + snprintf (key, sizeof (key), "%d-cumulative", i); ret = dict_get_int32 (dict, key, &interval); if (ret == 0) { @@ -3935,7 +3950,12 @@ gf_cli3_1_top_volume_cbk (struct rpc_req *req, struct iovec *iov, ret = dict_get_str (dict, brick, &bricks); if (ret) goto out; - cli_out ("Brick: %s", bricks); + ret = dict_get_str_boolean (dict, "nfs", _gf_false); + if (ret) + cli_out ("NFS Server : %s", bricks); + else + cli_out ("Brick: %s", bricks); + snprintf(key, sizeof (key), "%d-members", i); ret = dict_get_int32 (dict, key, &members); @@ -4237,7 +4257,7 @@ out: } void -cli_print_volume_status_mem (dict_t *dict) +cli_print_volume_status_mem (dict_t *dict, gf_boolean_t nfs) { int ret = -1; char *volname = NULL; @@ -4273,7 +4293,10 @@ cli_print_volume_status_mem (dict_t *dict) ret = dict_get_str (dict, key, &path); if (ret) goto out; - cli_out ("Brick : %s:%s", hostname, path); + if (nfs) + cli_out ("%s : %s", hostname, path); + else + cli_out ("Brick : %s:%s", hostname, path); memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "brick%d.status", i); @@ -4368,7 +4391,7 @@ out: } void -cli_print_volume_status_clients (dict_t *dict) +cli_print_volume_status_clients (dict_t *dict, gf_boolean_t nfs) { int ret = -1; char *volname = NULL; @@ -4408,7 +4431,11 @@ cli_print_volume_status_clients (dict_t *dict) ret = dict_get_str (dict, key, &path); if (ret) goto out; - cli_out ("Brick : %s:%s", hostname, path); + + if (nfs) + cli_out ("%s : %s", hostname, path); + else + cli_out ("Brick : %s:%s", hostname, path); memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "brick%d.status", i); @@ -4609,7 +4636,7 @@ out: } void -cli_print_volume_status_inode (dict_t *dict) +cli_print_volume_status_inode (dict_t *dict, gf_boolean_t nfs) { int ret = -1; char *volname = NULL; @@ -4646,7 +4673,10 @@ cli_print_volume_status_inode (dict_t *dict) ret = dict_get_str (dict, key, &path); if (ret) goto out; - cli_out ("Brick : %s:%s", hostname, path); + if (nfs) + cli_out ("%s : %s", hostname, path); + else + cli_out ("Brick : %s:%s", hostname, path); memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "brick%d.status", i); @@ -4762,7 +4792,7 @@ out: } void -cli_print_volume_status_fd (dict_t *dict) +cli_print_volume_status_fd (dict_t *dict, gf_boolean_t nfs) { int ret = -1; char *volname = NULL; @@ -4799,7 +4829,11 @@ cli_print_volume_status_fd (dict_t *dict) ret = dict_get_str (dict, key, &path); if (ret) goto out; - cli_out ("Brick : %s:%s", hostname, path); + + if (nfs) + cli_out ("%s : %s", hostname, path); + else + cli_out ("Brick : %s:%s", hostname, path); memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "brick%d.status", i); @@ -4976,7 +5010,7 @@ cli_print_volume_status_call_stack (dict_t *dict, char *prefix) } void -cli_print_volume_status_callpool (dict_t *dict) +cli_print_volume_status_callpool (dict_t *dict, gf_boolean_t nfs) { int ret = -1; char *volname = NULL; @@ -5013,7 +5047,11 @@ cli_print_volume_status_callpool (dict_t *dict) ret = dict_get_str (dict, key, &path); if (ret) goto out; - cli_out ("Brick : %s:%s", hostname, path); + + if (nfs) + cli_out ("%s : %s", hostname, path); + else + cli_out ("Brick : %s:%s", hostname, path); memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "brick%d.status", i); @@ -5058,6 +5096,7 @@ gf_cli3_1_status_cbk (struct rpc_req *req, struct iovec *iov, int i = 0; int pid = -1; uint32_t cmd = 0; + gf_boolean_t nfs = _gf_false; char key[1024] = {0,}; char *hostname = NULL; char *path = NULL; @@ -5101,6 +5140,10 @@ gf_cli3_1_status_cbk (struct rpc_req *req, struct iovec *iov, ret = 0; goto out; } + + if (cmd & GF_CLI_STATUS_NFS) + nfs = _gf_true; + ret = dict_get_int32 (dict, "count", &count); if (ret) goto out; @@ -5125,23 +5168,23 @@ gf_cli3_1_status_cbk (struct rpc_req *req, struct iovec *iov, switch (cmd & GF_CLI_STATUS_MASK) { case GF_CLI_STATUS_MEM: - cli_print_volume_status_mem (dict); + cli_print_volume_status_mem (dict, nfs); goto cont; break; case GF_CLI_STATUS_CLIENTS: - cli_print_volume_status_clients (dict); + cli_print_volume_status_clients (dict, nfs); goto cont; break; case GF_CLI_STATUS_INODE: - cli_print_volume_status_inode (dict); + cli_print_volume_status_inode (dict, nfs); goto cont; break; case GF_CLI_STATUS_FD: - cli_print_volume_status_fd (dict); + cli_print_volume_status_fd (dict, nfs); goto cont; break; case GF_CLI_STATUS_CALLPOOL: - cli_print_volume_status_callpool (dict); + cli_print_volume_status_callpool (dict, nfs); goto cont; break; default: diff --git a/glusterfsd/src/glusterfsd-mgmt.c b/glusterfsd/src/glusterfsd-mgmt.c index 57c664920ee..e45297d50d9 100644 --- a/glusterfsd/src/glusterfsd-mgmt.c +++ b/glusterfsd/src/glusterfsd-mgmt.c @@ -832,7 +832,7 @@ glusterfs_handle_brick_status (rpcsvc_request_t *req) dict_t *output = NULL; char *volname = NULL; char *xname = NULL; - int32_t cmd = 0; + uint32_t cmd = 0; char *msg = NULL; GF_ASSERT (req); @@ -854,7 +854,7 @@ glusterfs_handle_brick_status (rpcsvc_request_t *req) goto out; } - ret = dict_get_int32 (dict, "cmd", &cmd); + ret = dict_get_uint32 (dict, "cmd", &cmd); if (ret) { gf_log (this->name, GF_LOG_ERROR, "Couldn't get status op"); goto out; @@ -959,6 +959,240 @@ glusterfs_command_done (int ret, call_frame_t *sync_frame, void *data) } int +glusterfs_handle_nfs_status (rpcsvc_request_t *req) +{ + int ret = -1; + gd1_mgmt_brick_op_req nfs_req = {0,}; + gd1_mgmt_brick_op_rsp rsp = {0,}; + glusterfs_ctx_t *ctx = NULL; + glusterfs_graph_t *active = NULL; + xlator_t *any = NULL; + xlator_t *nfs = NULL; + xlator_t *subvol = NULL; + dict_t *dict = NULL; + dict_t *output = NULL; + char *volname = NULL; + uint32_t cmd = 0; + char *msg = NULL; + + GF_ASSERT (req); + + if (!xdr_to_generic (req->msg[0], &nfs_req, + (xdrproc_t)xdr_gd1_mgmt_brick_op_req)) { + req->rpc_err = GARBAGE_ARGS; + goto out; + } + + dict = dict_new (); + ret = dict_unserialize (nfs_req.input.input_val, + nfs_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_uint32 (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; + + nfs = xlator_search_by_name (any, "nfs-server"); + if (!nfs) { + ret = -1; + gf_log (THIS->name, GF_LOG_ERROR, "nfs-server xlator is not" + " loaded"); + goto out; + } + + subvol = xlator_search_by_name (nfs, volname); + if (!subvol) { + ret = -1; + gf_log (THIS->name, GF_LOG_ERROR, "%s xlator is not loaded", + volname); + 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 = dict_set_str (output, "volname", volname); + if (ret) { + gf_log (THIS->name, GF_LOG_ERROR, + "Error setting volname to dict"); + goto out; + } + ret = nfs->dumpops->priv_to_dict (nfs, output); + break; + + case GF_CLI_STATUS_INODE: + ret = 0; + inode_table_dump_to_dict (subvol->itable, "conn0", + output); + ret = dict_set_int32 (output, "conncount", 1); + break; + + case GF_CLI_STATUS_FD: + // cannot find fd-tables in nfs-server graph + // TODO: finish once found + 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"); + gf_log (THIS->name, GF_LOG_ERROR, "%s", msg); + 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 (nfs_req.input.input_val) + free (nfs_req.input.input_val); + if (msg) + GF_FREE (msg); + if (rsp.output.output_val) + GF_FREE (rsp.output.output_val); + + gf_log (THIS->name, GF_LOG_DEBUG, "Returning %d", ret); + return ret; +} + +int +glusterfs_handle_nfs_profile (rpcsvc_request_t *req) +{ + int ret = -1; + gd1_mgmt_brick_op_req nfs_req = {0,}; + gd1_mgmt_brick_op_rsp rsp = {0,}; + dict_t *dict = NULL; + glusterfs_ctx_t *ctx = NULL; + glusterfs_graph_t *active = NULL; + xlator_t *any = NULL; + xlator_t *nfs = NULL; + xlator_t *subvol = NULL; + char *volname = NULL; + dict_t *output = NULL; + + GF_ASSERT (req); + + if (!xdr_to_generic (req->msg[0], &nfs_req, + (xdrproc_t)xdr_gd1_mgmt_brick_op_req)) { + req->rpc_err = GARBAGE_ARGS; + goto out; + } + + dict = dict_new (); + ret = dict_unserialize (nfs_req.input.input_val, + nfs_req.input.input_len, &dict); + if (ret < 0) { + gf_log (THIS->name, GF_LOG_ERROR, "Failed to " + "unserialize req-buffer to dict"); + 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; + + // is this needed? + // are problems possible by searching for subvol directly from "any"? + nfs = xlator_search_by_name (any, "nfs-server"); + if (!nfs) { + ret = -1; + gf_log (THIS->name, GF_LOG_ERROR, "xlator nfs-server is " + "not loaded"); + goto out; + } + + subvol = xlator_search_by_name (nfs, volname); + if (!subvol) { + ret = -1; + gf_log (THIS->name, GF_LOG_ERROR, "xlator %s is no loaded", + volname); + goto out; + } + + output = dict_new (); + ret = subvol->notify (subvol, GF_EVENT_TRANSLATOR_INFO, dict, output); + + rsp.op_ret = ret; + rsp.op_errno = 0; + 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 ouput dict to rsp"); + goto out; + } + + ret = glusterfs_submit_reply (req, &rsp, NULL, 0, NULL, + (xdrproc_t)xdr_gd1_mgmt_brick_op_rsp); + +out: + if (nfs_req.input.input_val) + free (nfs_req.input.input_val); + if (dict) + dict_unref (dict); + if (output) + dict_unref (output); + if (rsp.output.output_val) + free (rsp.output.output_val); + + gf_log (THIS->name, GF_LOG_DEBUG, "Returning %d", ret); + return ret; +} + +int glusterfs_handle_rpc_msg (rpcsvc_request_t *req) { int ret = -1; @@ -987,6 +1221,11 @@ glusterfs_handle_rpc_msg (rpcsvc_request_t *req) case GLUSTERD_BRICK_XLATOR_DEFRAG: ret = glusterfs_handle_defrag (req); break; + case GLUSTERD_NFS_PROFILE: + ret = glusterfs_handle_nfs_profile (req); + break; + case GLUSTERD_NFS_STATUS: + ret = glusterfs_handle_nfs_status (req); default: break; } @@ -1044,7 +1283,9 @@ rpcsvc_actor_t glusterfs_actors[] = { [GLUSTERD_BRICK_XLATOR_INFO] = { "TRANSLATOR INFO", GLUSTERD_BRICK_XLATOR_INFO, glusterfs_handle_rpc_msg, NULL, NULL, 0}, [GLUSTERD_BRICK_XLATOR_OP] = { "TRANSLATOR OP", GLUSTERD_BRICK_XLATOR_OP, glusterfs_handle_rpc_msg, NULL, NULL, 0}, [GLUSTERD_BRICK_STATUS] = {"STATUS", GLUSTERD_BRICK_STATUS, glusterfs_handle_rpc_msg, NULL, NULL, 0}, - [GLUSTERD_BRICK_XLATOR_DEFRAG] = { "TRANSLATOR DEFRAG", GLUSTERD_BRICK_XLATOR_DEFRAG, glusterfs_handle_rpc_msg, NULL, NULL, 0} + [GLUSTERD_BRICK_XLATOR_DEFRAG] = { "TRANSLATOR DEFRAG", GLUSTERD_BRICK_XLATOR_DEFRAG, glusterfs_handle_rpc_msg, NULL, NULL, 0}, + [GLUSTERD_NFS_PROFILE] = {"NFS PROFILE", GLUSTERD_NFS_PROFILE, glusterfs_handle_rpc_msg, NULL, NULL, 0}, + [GLUSTERD_NFS_STATUS] = {"NFS STATUS", GLUSTERD_NFS_STATUS, glusterfs_handle_rpc_msg, NULL, NULL, 0} }; struct rpcsvc_program glusterfs_mop_prog = { diff --git a/rpc/rpc-lib/src/protocol-common.h b/rpc/rpc-lib/src/protocol-common.h index cd7adde4e19..0191c50aa62 100644 --- a/rpc/rpc-lib/src/protocol-common.h +++ b/rpc/rpc-lib/src/protocol-common.h @@ -186,6 +186,8 @@ enum glusterd_brick_procnum { GLUSTERD_BRICK_STATUS, GLUSTERD_BRICK_OP, GLUSTERD_BRICK_XLATOR_DEFRAG, + GLUSTERD_NFS_PROFILE, + GLUSTERD_NFS_STATUS, GLUSTERD_BRICK_MAXVALUE, }; diff --git a/rpc/xdr/src/cli1-xdr.h b/rpc/xdr/src/cli1-xdr.h index 903b6ff724f..979c2250f35 100644 --- a/rpc/xdr/src/cli1-xdr.h +++ b/rpc/xdr/src/cli1-xdr.h @@ -166,6 +166,7 @@ enum gf_cli_status_type { GF_CLI_STATUS_VOL = 0x100, GF_CLI_STATUS_ALL = 0x200, GF_CLI_STATUS_BRICK = 0x400, + GF_CLI_STATUS_NFS = 0x800, }; 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 f45712ce0c1..72d2dbef448 100644 --- a/rpc/xdr/src/cli1-xdr.x +++ b/rpc/xdr/src/cli1-xdr.x @@ -110,7 +110,8 @@ enum gf_cli_status_type { 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*/ + GF_CLI_STATUS_BRICK = 0x400, /*010000000000*/ + GF_CLI_STATUS_NFS = 0x800 /*100000000000*/ }; struct gf_cli_req { diff --git a/xlators/mgmt/glusterd/src/glusterd-handler.c b/xlators/mgmt/glusterd/src/glusterd-handler.c index 4f9822db132..86bc0d7b1c6 100644 --- a/xlators/mgmt/glusterd/src/glusterd-handler.c +++ b/xlators/mgmt/glusterd/src/glusterd-handler.c @@ -2755,12 +2755,13 @@ glusterd_brick_rpc_notify (struct rpc_clnt *rpc, void *mydata, } int -glusterd_shd_rpc_notify (struct rpc_clnt *rpc, void *mydata, - rpc_clnt_event_t event, - void *data) +glusterd_nodesvc_rpc_notify (struct rpc_clnt *rpc, void *mydata, + rpc_clnt_event_t event, + void *data) { xlator_t *this = NULL; glusterd_conf_t *conf = NULL; + char *server = NULL; int ret = 0; this = THIS; @@ -2768,17 +2769,21 @@ glusterd_shd_rpc_notify (struct rpc_clnt *rpc, void *mydata, conf = this->private; GF_ASSERT (conf); + server = mydata; + if (!server) + return 0; + switch (event) { case RPC_CLNT_CONNECT: gf_log (this->name, GF_LOG_DEBUG, "got RPC_CLNT_CONNECT"); - (void) glusterd_shd_set_running (_gf_true); + (void) glusterd_nodesvc_set_running (server, _gf_true); ret = default_notify (this, GF_EVENT_CHILD_UP, NULL); break; case RPC_CLNT_DISCONNECT: gf_log (this->name, GF_LOG_DEBUG, "got RPC_CLNT_DISCONNECT"); - (void) glusterd_shd_set_running (_gf_false); + (void) glusterd_nodesvc_set_running (server, _gf_false); break; default: diff --git a/xlators/mgmt/glusterd/src/glusterd-op-sm.c b/xlators/mgmt/glusterd/src/glusterd-op-sm.c index bda5e61e4fb..46c02bff711 100644 --- a/xlators/mgmt/glusterd/src/glusterd-op-sm.c +++ b/xlators/mgmt/glusterd/src/glusterd-op-sm.c @@ -245,6 +245,59 @@ out: return ret; } +int +glusterd_nfs_op_build_payload (glusterd_op_t op, gd1_mgmt_brick_op_req **req, + dict_t *dict) +{ + int ret = -1; + gd1_mgmt_brick_op_req *brick_req = NULL; + + GF_ASSERT (op < GD_OP_MAX); + GF_ASSERT (op > GD_OP_NONE); + GF_ASSERT (req); + + switch (op) { + case GD_OP_PROFILE_VOLUME: + brick_req = GF_CALLOC (1, sizeof (*brick_req), + gf_gld_mt_mop_brick_req_t); + if (!brick_req) + goto out; + + brick_req->op = GLUSTERD_NFS_PROFILE; + 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) + goto out; + + brick_req->op = GLUSTERD_NFS_STATUS; + brick_req->name = ""; + + break; + + default: + goto out; + } + + ret = dict_allocate_and_serialize (dict, &brick_req->input.input_val, + (size_t*)&brick_req->input.input_len); + + if (ret) + goto out; + + *req = brick_req; + ret = 0; + +out: + if (ret && brick_req) + GF_FREE (brick_req); + gf_log (THIS->name, GF_LOG_DEBUG, "Returning %d", ret); + return ret; +} static int glusterd_op_stage_set_volume (dict_t *dict, char **op_errstr) @@ -1337,7 +1390,13 @@ glusterd_op_status_volume (dict_t *dict, char **op_errstr, goto out; } - if ((cmd & GF_CLI_STATUS_BRICK) != 0) { + if ((cmd & GF_CLI_STATUS_NFS) != 0) { + ret = glusterd_add_node_to_dict ("nfs", rsp_dict, 0); + if (ret) + goto out; + brick_count = 1; + + } else if ((cmd & GF_CLI_STATUS_BRICK) != 0) { ret = dict_get_str (dict, "brick", &brick); if (ret) goto out; @@ -1356,9 +1415,8 @@ glusterd_op_status_volume (dict_t *dict, char **op_errstr, 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); + brick_count = 1; - goto out; } else { list_for_each_entry (brickinfo, &volinfo->bricks, brick_list) { brick_index++; @@ -1387,6 +1445,51 @@ out: } static int +glusterd_op_volume_dict_uuid_to_hostname (dict_t *dict, const char *key_fmt, + int idx_min, int idx_max) +{ + int ret = -1; + int i = 0; + char key[1024]; + char *uuid_str = NULL; + uuid_t uuid = {0,}; + char *hostname = NULL; + + GF_ASSERT (dict); + GF_ASSERT (key_fmt); + + for (i = idx_min; i < idx_max; i++) { + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), key_fmt, i); + ret = dict_get_str (dict, key, &uuid_str); + if (ret) + goto out; + + ret = uuid_parse (uuid_str, uuid); + /* if parsing fails don't error out + * let the original value be retained + */ + if (ret) + continue; + + hostname = glusterd_uuid_to_hostname (uuid); + if (hostname) { + ret = dict_set_dynstr (dict, key, hostname); + if (ret) { + gf_log (THIS->name, GF_LOG_ERROR, + "Error setting hostname to dict"); + GF_FREE (hostname); + goto out; + } + } + } + +out: + gf_log (THIS->name, GF_LOG_DEBUG, "Returning %d", ret); + return ret; +} + +static int glusterd_op_ac_none (glusterd_op_sm_event_t *event, void *ctx) { int ret = 0; @@ -1977,10 +2080,12 @@ out: static int glusterd_op_ac_rcvd_commit_op_acc (glusterd_op_sm_event_t *event, void *ctx) { - dict_t *dict = NULL; + dict_t *op_ctx = NULL; int ret = 0; gf_boolean_t commit_ack_inject = _gf_true; glusterd_op_t op = GD_OP_NONE; + int count = 0; + uint32_t cmd = GF_CLI_STATUS_NONE; op = glusterd_op_get_op (); GF_ASSERT (event); @@ -1992,15 +2097,15 @@ glusterd_op_ac_rcvd_commit_op_acc (glusterd_op_sm_event_t *event, void *ctx) goto out; if (op == GD_OP_REPLACE_BRICK) { - dict = glusterd_op_get_ctx (); - if (!dict) { + op_ctx = glusterd_op_get_ctx (); + if (!op_ctx) { gf_log (THIS->name, GF_LOG_CRITICAL, "Operation " "context is not present."); ret = -1; goto out; } - ret = glusterd_op_start_rb_timer (dict); + ret = glusterd_op_start_rb_timer (op_ctx); if (ret) { gf_log (THIS->name, GF_LOG_ERROR, "Couldn't start " "replace-brick operation."); @@ -2011,6 +2116,77 @@ glusterd_op_ac_rcvd_commit_op_acc (glusterd_op_sm_event_t *event, void *ctx) goto out; } + if (op == GD_OP_STATUS_VOLUME) { + op_ctx = glusterd_op_get_ctx(); + if (!op_ctx) { + gf_log (THIS->name, GF_LOG_CRITICAL, "Operation " + "context is not present."); + ret = -1; + goto out; + } + + ret = dict_get_uint32 (op_ctx, "cmd", &cmd); + if (ret) { + gf_log (THIS->name, GF_LOG_ERROR, + "Failed to get status cmd"); + goto out; + } + if (!(cmd & GF_CLI_STATUS_NFS)) { + ret = 0; + goto out; + } + + ret = dict_get_int32 (op_ctx, "count", &count); + if (ret) { + gf_log (THIS->name, GF_LOG_ERROR, + "Failed to get brick count"); + goto out; + } + + ret = glusterd_op_volume_dict_uuid_to_hostname (op_ctx, + "brick%d.path", + 0, count); + if (ret) { + gf_log (THIS->name, GF_LOG_ERROR, + "Failed uuid to hostname conversion"); + ret = 0; + } + + } + + if (op == GD_OP_PROFILE_VOLUME) { + op_ctx = glusterd_op_get_ctx(); + if (!op_ctx) { + gf_log (THIS->name, GF_LOG_CRITICAL, "Operation " + "context is not present."); + ret = -1; + goto out; + } + + ret = dict_get_str_boolean (op_ctx, "nfs", _gf_false); + if (!ret) { + ret = 0; + goto out; + } + + ret = dict_get_int32 (op_ctx, "count", &count); + if (ret) { + gf_log (THIS->name, GF_LOG_ERROR, + "Failed to get brick count"); + goto out; + } + + ret = glusterd_op_volume_dict_uuid_to_hostname (op_ctx, + "%d-brick", + 1, (count + 1)); + if (ret) { + gf_log (THIS->name, GF_LOG_ERROR, + "Failed uuid to hostname conversion"); + ret = 0; + } + + } + out: if (commit_ack_inject) { if (ret) @@ -2534,21 +2710,29 @@ _profile_volume_add_brick_rsp (dict_t *this, char *key, data_t *value, } int -glusterd_profile_volume_brick_rsp (glusterd_brickinfo_t *brickinfo, +glusterd_profile_volume_brick_rsp (void *pending_entry, dict_t *rsp_dict, dict_t *op_ctx, - char **op_errstr) + char **op_errstr, gd_node_type type) { - int ret = 0; - glusterd_pr_brick_rsp_conv_t rsp_ctx = {0}; - int32_t count = 0; - char brick[PATH_MAX+1024] = {0}; - char key[256] = {0}; - char *full_brick = NULL; + int ret = 0; + glusterd_pr_brick_rsp_conv_t rsp_ctx = {0}; + int32_t count = 0; + char brick[PATH_MAX+1024] = {0}; + char key[256] = {0}; + char *full_brick = NULL; + glusterd_brickinfo_t *brickinfo = NULL; + xlator_t *this = NULL; + glusterd_conf_t *priv = NULL; GF_ASSERT (rsp_dict); GF_ASSERT (op_ctx); GF_ASSERT (op_errstr); - GF_ASSERT (brickinfo); + GF_ASSERT (pending_entry); + + this = THIS; + GF_ASSERT (this); + priv = this->private; + GF_ASSERT (priv); ret = dict_get_int32 (op_ctx, "count", &count); if (ret) { @@ -2557,8 +2741,13 @@ glusterd_profile_volume_brick_rsp (glusterd_brickinfo_t *brickinfo, count++; } snprintf (key, sizeof (key), "%d-brick", count); - snprintf (brick, sizeof (brick), "%s:%s", brickinfo->hostname, - brickinfo->path); + if (type == GD_NODE_BRICK) { + brickinfo = pending_entry; + snprintf (brick, sizeof (brick), "%s:%s", brickinfo->hostname, + brickinfo->path); + } else if (type == GD_NODE_NFS) { + snprintf (brick, sizeof (brick), "%s", uuid_utoa (priv->uuid)); + } full_brick = gf_strdup (brick); GF_ASSERT (full_brick); ret = dict_set_dynstr (op_ctx, key, full_brick); @@ -2571,22 +2760,6 @@ 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; -} - //input-key: <replica-id>:<child-id>-* //output-key: <brick-id>-* void @@ -2675,9 +2848,24 @@ out: 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, +glusterd_status_volume_brick_rsp (dict_t *rsp_dict, dict_t *op_ctx, char **op_errstr) { int ret = 0; @@ -2688,7 +2876,6 @@ glusterd_status_volume_brick_rsp (glusterd_brickinfo_t *brickinfo, 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) { @@ -2704,6 +2891,7 @@ glusterd_status_volume_brick_rsp (glusterd_brickinfo_t *brickinfo, 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; @@ -2789,23 +2977,21 @@ out: int32_t glusterd_handle_node_rsp (glusterd_req_ctx_t *req_ctx, void *pending_entry, glusterd_op_t op, dict_t *rsp_dict, dict_t *op_ctx, - char **op_errstr) + char **op_errstr, gd_node_type type) { int ret = 0; - glusterd_brickinfo_t *brickinfo = NULL; GF_ASSERT (op_errstr); switch (op) { case GD_OP_PROFILE_VOLUME: - brickinfo = pending_entry; - ret = glusterd_profile_volume_brick_rsp (brickinfo, rsp_dict, - op_ctx, op_errstr); + ret = glusterd_profile_volume_brick_rsp (pending_entry, + rsp_dict, op_ctx, + op_errstr, type); break; case GD_OP_STATUS_VOLUME: - brickinfo = pending_entry; - ret = glusterd_status_volume_brick_rsp (brickinfo, rsp_dict, - op_ctx, op_errstr); + ret = glusterd_status_volume_brick_rsp (rsp_dict, op_ctx, + op_errstr); break; case GD_OP_DEFRAG_BRICK_VOLUME: @@ -2987,6 +3173,30 @@ glusterd_bricks_select_profile_volume (dict_t *dict, char **op_errstr) goto out; break; case GF_CLI_STATS_INFO: + ret = dict_get_str_boolean (dict, "nfs", _gf_false); + if (ret) { + if (!glusterd_nodesvc_is_running ("nfs")) { + ret = -1; + gf_log (this->name, GF_LOG_ERROR, "NFS server" + " is not running"); + 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 = priv->nfs; + pending_node->type = GD_NODE_NFS; + list_add_tail (&pending_node->list, + &opinfo.pending_bricks); + pending_node = NULL; + + ret = 0; + goto out; + + } list_for_each_entry (brickinfo, &volinfo->bricks, brick_list) { if (glusterd_is_brick_started (brickinfo)) { pending_node = GF_CALLOC (1, sizeof (*pending_node), @@ -3006,6 +3216,30 @@ glusterd_bricks_select_profile_volume (dict_t *dict, char **op_errstr) break; case GF_CLI_STATS_TOP: + ret = dict_get_str_boolean (dict, "nfs", _gf_false); + if (ret) { + if (!glusterd_nodesvc_is_running ("nfs")) { + ret = -1; + gf_log (this->name, GF_LOG_ERROR, "NFS server" + " is not running"); + 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 = priv->nfs; + pending_node->type = GD_NODE_NFS; + list_add_tail (&pending_node->list, + &opinfo.pending_bricks); + pending_node = NULL; + + ret = 0; + goto out; + + } ret = dict_get_str (dict, "brick", &brick); if (!ret) { ret = glusterd_volume_brickinfo_get_by_brick (brick, volinfo, @@ -3308,7 +3542,7 @@ glusterd_bricks_select_status_volume (dict_t *dict, char **op_errstr) ret = dict_get_int32 (dict, "cmd", &cmd); if (ret) { - gf_log (THIS->name, GF_LOG_ERROR, "Unable to get status type"); + gf_log (this->name, GF_LOG_ERROR, "Unable to get status type"); goto out; } @@ -3321,13 +3555,14 @@ glusterd_bricks_select_status_volume (dict_t *dict, char **op_errstr) case GF_CLI_STATUS_INODE: case GF_CLI_STATUS_FD: case GF_CLI_STATUS_CALLPOOL: + case GF_CLI_STATUS_NFS: break; default: goto out; } ret = dict_get_str (dict, "volname", &volname); if (ret) { - gf_log (THIS->name, GF_LOG_ERROR, "Unable to get volname"); + gf_log (this->name, GF_LOG_ERROR, "Unable to get volname"); goto out; } ret = glusterd_volinfo_find (volname, &volinfo); @@ -3338,7 +3573,7 @@ glusterd_bricks_select_status_volume (dict_t *dict, char **op_errstr) if ( (cmd & GF_CLI_STATUS_BRICK) != 0) { ret = dict_get_str (dict, "brick", &brickname); if (ret) { - gf_log (THIS->name, GF_LOG_ERROR, + gf_log (this->name, GF_LOG_ERROR, "Unable to get brick"); goto out; } @@ -3365,6 +3600,25 @@ glusterd_bricks_select_status_volume (dict_t *dict, char **op_errstr) list_add_tail (&pending_node->list, &opinfo.pending_bricks); ret = 0; + } else if ((cmd & GF_CLI_STATUS_NFS) != 0) { + if (!glusterd_nodesvc_is_running ("nfs")) { + ret = -1; + gf_log (this->name, GF_LOG_ERROR, + "NFS server is not running"); + 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 = priv->nfs; + pending_node->type = GD_NODE_NFS; + 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++; @@ -3444,6 +3698,7 @@ glusterd_op_ac_rcvd_brick_op_acc (glusterd_op_sm_event_t *event, void *ctx) glusterd_op_brick_rsp_ctx_t *ev_ctx = NULL; char *op_errstr = NULL; glusterd_op_t op = GD_OP_NONE; + gd_node_type type = GD_NODE_NONE; dict_t *op_ctx = NULL; glusterd_req_ctx_t *req_ctx = NULL; void *pending_entry = NULL; @@ -3458,6 +3713,7 @@ glusterd_op_ac_rcvd_brick_op_acc (glusterd_op_sm_event_t *event, void *ctx) op = req_ctx->op; op_ctx = glusterd_op_get_ctx (); pending_entry = ev_ctx->pending_node->node; + type = ev_ctx->pending_node->type; ret = glusterd_remove_pending_entry (&opinfo.pending_bricks, pending_entry); @@ -3471,7 +3727,7 @@ glusterd_op_ac_rcvd_brick_op_acc (glusterd_op_sm_event_t *event, void *ctx) opinfo.brick_pending_count--; glusterd_handle_node_rsp (req_ctx, pending_entry, op, ev_ctx->rsp_dict, - op_ctx, &op_errstr); + op_ctx, &op_errstr, type); if (opinfo.brick_pending_count > 0) goto out; diff --git a/xlators/mgmt/glusterd/src/glusterd-op-sm.h b/xlators/mgmt/glusterd/src/glusterd-op-sm.h index b4df8201769..cc2eacffd35 100644 --- a/xlators/mgmt/glusterd/src/glusterd-op-sm.h +++ b/xlators/mgmt/glusterd/src/glusterd-op-sm.h @@ -162,6 +162,7 @@ typedef struct glusterd_heal_rsp_conv_ { typedef struct glusterd_status_rsp_conv_ { int count; dict_t *dict; + gf_boolean_t nfs; } glusterd_status_rsp_conv_t; typedef struct glusterd_gsync_status_temp { @@ -238,10 +239,13 @@ glusterd_op_bricks_select (glusterd_op_t op, dict_t *dict, char **op_errstr); int glusterd_brick_op_build_payload (glusterd_op_t op, glusterd_brickinfo_t *brickinfo, gd1_mgmt_brick_op_req **req, dict_t *dict); +int +glusterd_nfs_op_build_payload (glusterd_op_t op, gd1_mgmt_brick_op_req **req, + dict_t *dict); int32_t -glusterd_handle_brick_rsp (glusterd_brickinfo_t *brickinfo, - glusterd_op_t op, dict_t *rsp_dict, dict_t *ctx_dict, - char **op_errstr); +glusterd_handle_brick_rsp (void *pending_entry, glusterd_op_t op, + dict_t *rsp_dict, dict_t *ctx_dict, char **op_errstr, + gd_node_type type); int32_t glusterd_op_init_ctx (glusterd_op_t op); int32_t diff --git a/xlators/mgmt/glusterd/src/glusterd-rpc-ops.c b/xlators/mgmt/glusterd/src/glusterd-rpc-ops.c index 648ab418d15..ef7a6a64807 100644 --- a/xlators/mgmt/glusterd/src/glusterd-rpc-ops.c +++ b/xlators/mgmt/glusterd/src/glusterd-rpc-ops.c @@ -1011,16 +1011,25 @@ glusterd_volume_status_add_peer_rsp (dict_t *this, char *key, data_t *value, { glusterd_status_rsp_conv_t *rsp_ctx = NULL; data_t *new_value = NULL; + char brick_key[1024] = {0,}; + char new_key[1024] = {0,}; int32_t ret = 0; - if (strcmp (key, "count") == 0) + if (!strcmp (key, "count") || !strcmp (key, "cmd")) return; rsp_ctx = data; new_value = data_copy (value); GF_ASSERT (new_value); - ret = dict_set (rsp_ctx->dict, key, new_value); + if (rsp_ctx->nfs) { + sscanf (key, "brick%*d.%s", brick_key); + snprintf (new_key, sizeof (new_key), "brick%d.%s", + rsp_ctx->count, brick_key); + } else + strncpy (new_key, key, sizeof (new_key)); + + ret = dict_set (rsp_ctx->dict, new_key, new_value); if (ret) gf_log ("", GF_LOG_ERROR, "Unable to set key: %s in dict", key); @@ -1035,6 +1044,7 @@ glusterd_volume_status_use_rsp_dict (dict_t *rsp_dict) glusterd_status_rsp_conv_t rsp_ctx = {0}; int32_t brick_count = 0; int32_t count = 0; + int32_t cmd = 0; dict_t *ctx_dict = NULL; glusterd_op_t op = GD_OP_NONE; @@ -1046,6 +1056,10 @@ glusterd_volume_status_use_rsp_dict (dict_t *rsp_dict) goto out; } + ret = dict_get_int32 (rsp_dict, "cmd", &cmd); + if (ret) + goto out; + op = glusterd_op_get_op (); GF_ASSERT (GD_OP_STATUS_VOLUME == op); ctx_dict = glusterd_op_get_ctx (op); @@ -1053,6 +1067,11 @@ glusterd_volume_status_use_rsp_dict (dict_t *rsp_dict) ret = dict_get_int32 (ctx_dict, "count", &count); rsp_ctx.count = count; rsp_ctx.dict = ctx_dict; + if (cmd & GF_CLI_STATUS_NFS) + rsp_ctx.nfs = _gf_true; + else + rsp_ctx.nfs = _gf_false; + dict_foreach (rsp_dict, glusterd_volume_status_add_peer_rsp, &rsp_ctx); ret = dict_set_int32 (ctx_dict, "count", count + brick_count); @@ -1833,10 +1852,17 @@ glusterd3_1_brick_op (call_frame_t *frame, xlator_t *this, if (!dummy_frame) continue; - ret = glusterd_brick_op_build_payload (req_ctx->op, - pending_node->node, - (gd1_mgmt_brick_op_req **)&req, - req_ctx->dict); + if (pending_node->type == GD_NODE_BRICK) + ret = glusterd_brick_op_build_payload + (req_ctx->op, pending_node->node, + (gd1_mgmt_brick_op_req **)&req, + req_ctx->dict); + else if (pending_node->type == GD_NODE_NFS) + ret = glusterd_nfs_op_build_payload + (req_ctx->op, + (gd1_mgmt_brick_op_req **)&req, + req_ctx->dict); + if (ret) goto out; diff --git a/xlators/mgmt/glusterd/src/glusterd-utils.c b/xlators/mgmt/glusterd/src/glusterd-utils.c index 58a8945325d..64b7ba9ad1b 100644 --- a/xlators/mgmt/glusterd/src/glusterd-utils.c +++ b/xlators/mgmt/glusterd/src/glusterd-utils.c @@ -2536,32 +2536,45 @@ glusterd_get_nodesvc_volfile (char *server, char *workdir, } void -glusterd_shd_set_running (gf_boolean_t status) +glusterd_nodesvc_set_running (char *server, gf_boolean_t status) { glusterd_conf_t *priv = NULL; + GF_ASSERT (server); priv = THIS->private; GF_ASSERT (priv); GF_ASSERT (priv->shd); + GF_ASSERT (priv->nfs); - priv->shd->running = status; + if (!strcmp("glustershd", server)) + priv->shd->running = status; + else if (!strcmp ("nfs", server)) + priv->nfs->running = status; } gf_boolean_t -glusterd_shd_is_running () +glusterd_nodesvc_is_running (char *server) { glusterd_conf_t *conf = NULL; + gf_boolean_t running = _gf_false; + GF_ASSERT (server); conf = THIS->private; GF_ASSERT (conf); GF_ASSERT (conf->shd); + GF_ASSERT (conf->nfs); + + if (!strcmp (server, "glustershd")) + running = conf->shd->running; + else if (!strcmp (server, "nfs")) + running = conf->nfs->running; - return conf->shd->running; + return running; } int32_t -glusterd_shd_set_socket_filepath (char *rundir, uuid_t uuid, - char *socketpath, int len) +glusterd_nodesvc_set_socket_filepath (char *rundir, uuid_t uuid, + char *socketpath, int len) { char sockfilepath[PATH_MAX] = {0,}; char md5_str[PATH_MAX] = {0,}; @@ -2582,6 +2595,8 @@ glusterd_pending_node_get_rpc (glusterd_pending_node_t *pending_node) glusterd_brickinfo_t *brickinfo = NULL; nodesrv_t *shd = NULL; glusterd_volinfo_t *volinfo = NULL; + nodesrv_t *nfs = NULL; + GF_VALIDATE_OR_GOTO (THIS->name, pending_node, out); GF_VALIDATE_OR_GOTO (THIS->name, pending_node->node, out); @@ -2598,6 +2613,10 @@ glusterd_pending_node_get_rpc (glusterd_pending_node_t *pending_node) if (volinfo->defrag) rpc = volinfo->defrag->rpc; + } else if (pending_node->type == GD_NODE_NFS) { + nfs = pending_node->node; + rpc = nfs->rpc; + } else { GF_ASSERT (0); } @@ -2607,19 +2626,27 @@ out: } struct rpc_clnt* -glusterd_shd_get_rpc (void) +glusterd_nodesvc_get_rpc (char *server) { glusterd_conf_t *priv = NULL; + struct rpc_clnt *rpc = NULL; + GF_ASSERT (server); priv = THIS->private; GF_ASSERT (priv); GF_ASSERT (priv->shd); + GF_ASSERT (priv->nfs); + + if (!strcmp (server, "glustershd")) + rpc = priv->shd->rpc; + else if (!strcmp (server, "nfs")) + rpc = priv->nfs->rpc; - return priv->shd->rpc; + return rpc; } int32_t -glusterd_shd_set_rpc (struct rpc_clnt *rpc) +glusterd_nodesvc_set_rpc (char *server, struct rpc_clnt *rpc) { int ret = 0; xlator_t *this = NULL; @@ -2630,14 +2657,18 @@ glusterd_shd_set_rpc (struct rpc_clnt *rpc) priv = this->private; GF_ASSERT (priv); GF_ASSERT (priv->shd); + GF_ASSERT (priv->nfs); - priv->shd->rpc = rpc; + if (!strcmp ("glustershd", server)) + priv->shd->rpc = rpc; + else if (!strcmp ("nfs", server)) + priv->nfs->rpc = rpc; return ret; } int32_t -glusterd_shd_connect (char *socketpath) { +glusterd_nodesvc_connect (char *server, char *socketpath) { int ret = 0; dict_t *options = NULL; struct rpc_clnt *rpc = NULL; @@ -2646,17 +2677,17 @@ glusterd_shd_connect (char *socketpath) { if (ret) goto out; ret = glusterd_rpc_create (&rpc, options, - glusterd_shd_rpc_notify, - NULL); + glusterd_nodesvc_rpc_notify, + server); if (ret) goto out; - (void) glusterd_shd_set_rpc (rpc); + (void) glusterd_nodesvc_set_rpc (server, rpc); out: return ret; } int32_t -glusterd_nodesvc_start (char *server, gf_boolean_t pmap_signin) +glusterd_nodesvc_start (char *server) { int32_t ret = -1; xlator_t *this = NULL; @@ -2666,7 +2697,7 @@ glusterd_nodesvc_start (char *server, gf_boolean_t pmap_signin) char logfile[PATH_MAX] = {0,}; char volfile[PATH_MAX] = {0,}; char rundir[PATH_MAX] = {0,}; - char shd_sockfpath[PATH_MAX] = {0,}; + char sockfpath[PATH_MAX] = {0,}; char volfileid[256] = {0}; #ifdef DEBUG char valgrind_logfile[PATH_MAX] = {0}; @@ -2702,16 +2733,11 @@ glusterd_nodesvc_start (char *server, gf_boolean_t pmap_signin) server); snprintf (volfileid, sizeof (volfileid), "gluster/%s", server); - if (!strcmp (server, "glustershd")) { - glusterd_shd_set_socket_filepath (rundir, - priv->uuid, - shd_sockfpath, - sizeof (shd_sockfpath)); - } + glusterd_nodesvc_set_socket_filepath (rundir, priv->uuid, + sockfpath, sizeof (sockfpath)); runinit (&runner); - //TODO: kp:change the assumption that shd is the one which signs in - // use runner_add_args? + #ifdef DEBUG if (priv->valgrind) { snprintf (valgrind_logfile, PATH_MAX, @@ -2725,27 +2751,19 @@ glusterd_nodesvc_start (char *server, gf_boolean_t pmap_signin) } #endif - if (pmap_signin) { - runner_add_args (&runner, SBIN_DIR"/glusterfs", - "-s", "localhost", - "--volfile-id", volfileid, - "-p", pidfile, - "-l", logfile, - "-S", shd_sockfpath, NULL); - } else { - runner_add_args (&runner, SBIN_DIR"/glusterfs", - "-f", volfile, - "-p", pidfile, - "-l", logfile, NULL); - } + runner_add_args (&runner, SBIN_DIR"/glusterfs", + "-s", "localhost", + "--volfile-id", volfileid, + "-p", pidfile, + "-l", logfile, + "-S", sockfpath, NULL); runner_log (&runner, "", GF_LOG_DEBUG, "Starting the nfs/glustershd services"); ret = runner_run (&runner); if (ret == 0) { - if (pmap_signin) - glusterd_shd_connect (shd_sockfpath); + glusterd_nodesvc_connect (server, sockfpath); } out: return ret; @@ -2754,13 +2772,13 @@ out: int glusterd_nfs_server_start () { - return glusterd_nodesvc_start ("nfs", _gf_false); + return glusterd_nodesvc_start ("nfs"); } int glusterd_shd_start () { - return glusterd_nodesvc_start ("glustershd", _gf_true); + return glusterd_nodesvc_start ("glustershd"); } gf_boolean_t @@ -2833,6 +2851,65 @@ glusterd_shd_stop () return glusterd_nodesvc_stop ("glustershd", SIGTERM); } +/* Only NFS server for now */ +int +glusterd_add_node_to_dict (char *server, dict_t *dict, int count) +{ + int ret = -1; + glusterd_conf_t *priv = THIS->private; + char pidfile[PATH_MAX] = {0,}; + gf_boolean_t running = _gf_false; + int pid = -1; + char key[1024] = {0,}; + + glusterd_get_nodesvc_pidfile (server, priv->workdir, pidfile, + sizeof (pidfile)); + running = glusterd_is_service_running (pidfile, &pid); + + /* For nfs servers setting + * brick<n>.hostname = "NFS server" + * brick<n>.path = uuid + * brick<n>.port = 0 + * + * This might be confusing, but cli display's the name of + * the brick as hostname+path, so this will make more sense + * when output. + */ + snprintf (key, sizeof (key), "brick%d.hostname", count); + ret = dict_set_str (dict, key, "NFS Server"); + if (ret) + goto out; + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "brick%d.path", count); + ret = dict_set_dynstr (dict, key, gf_strdup (uuid_utoa (priv->uuid))); + if (ret) + goto out; + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "brick%d.port", count); + ret = dict_set_int32 (dict, key, 0); + if (ret) + goto out; + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "brick%d.pid", count); + ret = dict_set_int32 (dict, key, pid); + if (ret) + goto out; + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "brick%d.status", count); + ret = dict_set_int32 (dict, key, running); + if (ret) + goto out; + + +out: + gf_log (THIS->name, GF_LOG_DEBUG, "Returning %d", ret); + return ret; +} + int glusterd_remote_hostname_get (rpcsvc_request_t *req, char *remote_host, int len) { @@ -5030,3 +5107,32 @@ glusterd_restart_rebalance (glusterd_conf_t *conf) } return ret; } + +/* Return hostname for given uuid if it exists + * else return NULL + */ +char * +glusterd_uuid_to_hostname (uuid_t uuid) +{ + char *hostname = NULL; + glusterd_conf_t *priv = NULL; + glusterd_peerinfo_t *entry = NULL; + + priv = THIS->private; + GF_ASSERT (priv); + + if (!uuid_compare (priv->uuid, uuid)) { + hostname = gf_strdup ("localhost"); + } + if (!list_empty (&priv->peers)) { + list_for_each_entry (entry, &priv->peers, uuid_list) { + if (!uuid_compare (entry->uuid, uuid)) { + hostname = gf_strdup (entry->hostname); + break; + } + } + } + + return hostname; +} + diff --git a/xlators/mgmt/glusterd/src/glusterd-utils.h b/xlators/mgmt/glusterd/src/glusterd-utils.h index de6185753a1..7b5a387c275 100644 --- a/xlators/mgmt/glusterd/src/glusterd-utils.h +++ b/xlators/mgmt/glusterd/src/glusterd-utils.h @@ -193,26 +193,26 @@ int32_t glusterd_shd_stop (); int32_t -glusterd_shd_set_socket_filepath (char *rundir, uuid_t uuid, - char *socketpath, int len); +glusterd_nodesvc_set_socket_filepath (char *rundir, uuid_t uuid, + char *socketpath, int len); struct rpc_clnt* glusterd_pending_node_get_rpc (glusterd_pending_node_t *pending_node); struct rpc_clnt* -glusterd_shd_get_rpc (void); +glusterd_nodesvc_get_rpc (char *server); int32_t -glusterd_shd_set_rpc (struct rpc_clnt *rpc); +glusterd_nodesvc_set_rpc (char *server, struct rpc_clnt *rpc); int32_t -glusterd_shd_connect (char *socketpath); +glusterd_nodesvc_connect (char *server, char *socketpath); void -glusterd_shd_set_running (gf_boolean_t status); +glusterd_nodesvc_set_running (char *server, gf_boolean_t status); gf_boolean_t -glusterd_shd_is_running (); +glusterd_nodesvc_is_running (char *server); int glusterd_remote_hostname_get (rpcsvc_request_t *req, @@ -413,4 +413,10 @@ glusterd_restart_rebalance (glusterd_conf_t *conf); int32_t glusterd_add_bricks_hname_path_to_dict (dict_t *dict); + +int +glusterd_add_node_to_dict (char *server, dict_t *dict, int count); + +char * +glusterd_uuid_to_hostname (uuid_t uuid); #endif diff --git a/xlators/mgmt/glusterd/src/glusterd-volume-ops.c b/xlators/mgmt/glusterd/src/glusterd-volume-ops.c index 2d06ad834bf..ef338658b97 100644 --- a/xlators/mgmt/glusterd/src/glusterd-volume-ops.c +++ b/xlators/mgmt/glusterd/src/glusterd-volume-ops.c @@ -1060,7 +1060,7 @@ glusterd_op_stage_heal_volume (dict_t *dict, char **op_errstr) goto out; } - if (!glusterd_shd_is_running ()) { + if (!glusterd_nodesvc_is_running ("glustershd")) { ret = -1; snprintf (msg, sizeof (msg), "Self-heal daemon is not " "running. Check self-heal daemon log file."); diff --git a/xlators/mgmt/glusterd/src/glusterd.c b/xlators/mgmt/glusterd/src/glusterd.c index 0f807ca57bc..3ffd7b8ebc5 100644 --- a/xlators/mgmt/glusterd/src/glusterd.c +++ b/xlators/mgmt/glusterd/src/glusterd.c @@ -928,6 +928,9 @@ init (xlator_t *this) conf->shd = GF_CALLOC (1, sizeof (nodesrv_t), gf_gld_mt_nodesrv_t); GF_VALIDATE_OR_GOTO(this->name, conf->shd, out); + conf->nfs = GF_CALLOC (1, sizeof (nodesrv_t), + gf_gld_mt_nodesrv_t); + GF_VALIDATE_OR_GOTO(this->name, conf->nfs, out); INIT_LIST_HEAD (&conf->peers); INIT_LIST_HEAD (&conf->volumes); @@ -964,7 +967,7 @@ init (xlator_t *this) } #endif this->private = conf; - (void) glusterd_shd_set_running (_gf_false); + (void) glusterd_nodesvc_set_running ("glustershd", _gf_false); /* this->ctx->top = this;*/ ret = glusterd_uuid_init (first_time); diff --git a/xlators/mgmt/glusterd/src/glusterd.h b/xlators/mgmt/glusterd/src/glusterd.h index e8193bba24f..7a6ee653f0f 100644 --- a/xlators/mgmt/glusterd/src/glusterd.h +++ b/xlators/mgmt/glusterd/src/glusterd.h @@ -111,6 +111,7 @@ typedef struct { char workdir[PATH_MAX]; rpcsvc_t *rpc; nodesrv_t *shd; + nodesrv_t *nfs; struct pmap_registry *pmap; struct list_head volumes; struct list_head xprt_list; @@ -250,6 +251,7 @@ typedef enum gd_node_type_ { GD_NODE_BRICK, GD_NODE_SHD, GD_NODE_REBALANCE, + GD_NODE_NFS, } gd_node_type; typedef struct glusterd_pending_node_ { @@ -559,8 +561,8 @@ glusterd_brick_rpc_notify (struct rpc_clnt *rpc, void *mydata, rpc_clnt_event_t event, void *data); int -glusterd_shd_rpc_notify (struct rpc_clnt *rpc, void *mydata, - rpc_clnt_event_t event, void *data); +glusterd_nodesvc_rpc_notify (struct rpc_clnt *rpc, void *mydata, + rpc_clnt_event_t event, void *data); int glusterd_rpc_create (struct rpc_clnt **rpc, dict_t *options, diff --git a/xlators/nfs/server/src/nfs.c b/xlators/nfs/server/src/nfs.c index ba68486bd32..9a44c009a3e 100644 --- a/xlators/nfs/server/src/nfs.c +++ b/xlators/nfs/server/src/nfs.c @@ -827,12 +827,101 @@ nfs_forget (xlator_t *this, inode_t *inode) return 0; } +gf_boolean_t +_nfs_export_is_for_vol (char *exname, char *volname) +{ + gf_boolean_t ret = _gf_false; + char *tmp = NULL; + + tmp = exname; + if (tmp[0] == '/') + tmp++; + + if (!strcmp (tmp, volname)) + ret = _gf_true; + + return ret; +} + +int +nfs_priv_to_dict (xlator_t *this, dict_t *dict) +{ + int ret = -1; + struct nfs_state *priv = NULL; + struct mountentry *mentry = NULL; + char *volname = NULL; + char key[1024] = {0,}; + int count = 0; + + GF_VALIDATE_OR_GOTO (THIS->name, this, out); + GF_VALIDATE_OR_GOTO (THIS->name, dict, out); + + priv = this->private; + GF_ASSERT (priv); + + ret = dict_get_str (dict, "volname", &volname); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, "Could not get volname"); + goto out; + } + + list_for_each_entry (mentry, &priv->mstate->mountlist, mlist) { + if (!_nfs_export_is_for_vol (mentry->exname, volname)) + continue; + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "client%d.hostname", count); + ret = dict_set_str (dict, key, mentry->hostname); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, + "Error writing hostname to dict"); + goto out; + } + + /* No connection data available yet in nfs server. + * Hence, setting to 0 to prevent cli failing + */ + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "client%d.bytesread", count); + ret = dict_set_uint64 (dict, key, 0); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, + "Error writing bytes read to dict"); + goto out; + } + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "client%d.byteswrite", count); + ret = dict_set_uint64 (dict, key, 0); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, + "Error writing bytes write to dict"); + goto out; + } + + count++; + } + + ret = dict_set_int32 (dict, "clientcount", count); + if (ret) + gf_log (this->name, GF_LOG_ERROR, + "Error writing client count to dict"); + +out: + gf_log (THIS->name, GF_LOG_DEBUG, "Returning %d", ret); + return ret; +} + struct xlator_cbks cbks = { .forget = nfs_forget, }; struct xlator_fops fops = { }; +struct xlator_dumpops dumpops = { + .priv_to_dict = nfs_priv_to_dict, +}; + /* TODO: If needed, per-volume options below can be extended to be export + * specific also because after export-dir is introduced, a volume is not + * neccessarily an export whereas different subdirectories within that volume |