diff options
-rw-r--r-- | cli/src/cli-cmd-parser.c | 64 | ||||
-rw-r--r-- | cli/src/cli-cmd-volume.c | 60 | ||||
-rw-r--r-- | cli/src/cli-rpc-ops.c | 113 | ||||
-rw-r--r-- | cli/src/cli.h | 3 | ||||
-rw-r--r-- | rpc/rpc-lib/src/protocol-common.h | 1 | ||||
-rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-handler.c | 68 | ||||
-rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-mem-types.h | 3 | ||||
-rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-op-sm.c | 22 | ||||
-rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-rpc-ops.c | 1 | ||||
-rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-utils.c | 20 | ||||
-rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-utils.h | 3 | ||||
-rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-volgen.c | 21 | ||||
-rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-volume-ops.c | 393 | ||||
-rw-r--r-- | xlators/mgmt/glusterd/src/glusterd.h | 5 |
14 files changed, 754 insertions, 23 deletions
diff --git a/cli/src/cli-cmd-parser.c b/cli/src/cli-cmd-parser.c index 090a7246913..b4c86bf1abd 100644 --- a/cli/src/cli-cmd-parser.c +++ b/cli/src/cli-cmd-parser.c @@ -2032,3 +2032,67 @@ out: gf_log ("cli", GF_LOG_ERROR, "Error parsing dumpoptions"); return ret; } + +int +cli_cmd_volume_clrlks_opts_parse (const char **words, int wordcount, + dict_t **options) +{ + int ret = -1; + int i = 0; + dict_t *dict = NULL; + char *kind_opts[4] = {"blocked", "granted", "all", NULL}; + char *types[4] = {"inode", "entry", "posix", NULL}; + char *free_ptr = NULL; + + dict = dict_new (); + if (!dict) + goto out; + + if (strcmp (words[4], "kind")) + goto out; + + for (i = 0; kind_opts[i]; i++) { + if (!strcmp (words[5], kind_opts[i])) { + free_ptr = gf_strdup (words[5]); + ret = dict_set_dynstr (dict, "kind", free_ptr); + if (ret) + goto out; + free_ptr = NULL; + break; + } + } + if (i == 3) + goto out; + + ret = -1; + for (i = 0; types[i]; i++) { + if (!strcmp (words[6], types[i])) { + free_ptr = gf_strdup (words[6]); + ret = dict_set_dynstr (dict, "type", free_ptr); + if (ret) + goto out; + free_ptr = NULL; + break; + } + } + if (i == 3) + goto out; + + if (wordcount == 8) { + free_ptr = gf_strdup (words[7]); + ret = dict_set_dynstr (dict, "opts", free_ptr); + if (ret) + goto out; + free_ptr = NULL; + } + + ret = 0; + *options = dict; +out: + if (ret) { + GF_FREE (free_ptr); + dict_unref (dict); + } + + return ret; +} diff --git a/cli/src/cli-cmd-volume.c b/cli/src/cli-cmd-volume.c index 9c7a43b9f85..41007cb7b2d 100644 --- a/cli/src/cli-cmd-volume.c +++ b/cli/src/cli-cmd-volume.c @@ -1681,6 +1681,60 @@ out: return ret; } +int +cli_cmd_volume_clearlocks_cbk (struct cli_state *state, + struct cli_cmd_word *word, + const char **words, int wordcount) +{ + int ret = -1; + rpc_clnt_procedure_t *proc = NULL; + call_frame_t *frame = NULL; + dict_t *options = NULL; + int sent = 0; + int parse_error = 0; + + frame = create_frame (THIS, THIS->ctx->pool); + if (!frame) + goto out; + + if (wordcount < 7 || wordcount > 8) { + cli_usage_out (word->pattern); + parse_error = 1; + goto out; + } + + ret = cli_cmd_volume_clrlks_opts_parse (words, wordcount, &options); + if (ret) { + parse_error = 1; + gf_log ("cli", GF_LOG_ERROR, "Error parsing " + "clear-locks options"); + cli_out ("Error parsing options"); + cli_usage_out (word->pattern); + } + + ret = dict_set_str (options, "volname", (char *)words[2]); + if (ret) + goto out; + + ret = dict_set_str (options, "path", (char *)words[3]); + if (ret) + goto out; + + proc = &cli_rpc_prog->proctable[GLUSTER_CLI_CLRLOCKS_VOLUME]; + if (proc->fn) { + ret = proc->fn (frame, THIS, options); + } + +out: + if (ret) { + cli_cmd_sent_status_get (&sent); + if ((sent == 0) && (parse_error = 0)) + cli_out ("Volume clear-locks failed"); + } + + return ret; +} + struct cli_cmd volume_cmds[] = { { "volume info [all|<VOLNAME>]", cli_cmd_volume_info_cbk, @@ -1785,6 +1839,12 @@ struct cli_cmd volume_cmds[] = { cli_cmd_volume_list_cbk, "list all volumes in cluster"}, + {"volume clear-locks <VOLNAME> <path> kind {blocked|granted|all}" + "{inode [range]|entry [basename]|posix [range]}", + cli_cmd_volume_clearlocks_cbk, + "Clear locks held on path" + }, + { NULL, NULL, NULL } }; diff --git a/cli/src/cli-rpc-ops.c b/cli/src/cli-rpc-ops.c index 8d22f1b1d58..07a2f9fc7be 100644 --- a/cli/src/cli-rpc-ops.c +++ b/cli/src/cli-rpc-ops.c @@ -5640,6 +5640,118 @@ out: return ret; } +int32_t +gf_cli3_1_clearlocks_volume_cbk (struct rpc_req *req, struct iovec *iov, + int count, void *myframe) +{ + gf_cli_rsp rsp = {0,}; + int ret = -1; + char *lk_summary = NULL; + char *volname = NULL; + dict_t *dict = NULL; + + if (-1 == req->rpc_status) + goto out; + ret = xdr_to_generic (*iov, &rsp, + (xdrproc_t)xdr_gf_cli_rsp); + if (ret < 0) { + + gf_log ("cli", GF_LOG_ERROR, "XDR decoding failed"); + goto out; + } + gf_log ("cli", GF_LOG_DEBUG, "Received response to clear-locks"); + + if (rsp.op_ret) { + cli_out ("Volume clear-locks unsuccessful"); + cli_out ("%s", rsp.op_errstr); + + } else { + if (!rsp.dict.dict_len) { + cli_out ("Possibly no locks cleared"); + ret = 0; + goto out; + } + + dict = dict_new (); + + if (!dict) { + ret = -1; + goto out; + } + + ret = dict_unserialize (rsp.dict.dict_val, + rsp.dict.dict_len, + &dict); + + if (ret) { + gf_log ("cli", GF_LOG_ERROR, + "Unable to serialize response dictionary"); + goto out; + } + + ret = dict_get_str (dict, "volname", &volname); + if (ret) { + gf_log ("cli", GF_LOG_ERROR, "Unable to get volname " + "from dictionary"); + goto out; + } + + ret = dict_get_str (dict, "lk-summary", &lk_summary); + if (ret) { + gf_log ("cli", GF_LOG_ERROR, "Unable to get lock " + "summary from dictionary"); + goto out; + } + cli_out ("Volume clear-locks successful"); + cli_out ("%s", lk_summary); + + } + + ret = rsp.op_ret; + +out: + cli_cmd_broadcast_response (ret); + return ret; +} + +int32_t +gf_cli3_1_clearlocks_volume (call_frame_t *frame, xlator_t *this, + void *data) +{ + gf_cli_req req = {{0,}}; + dict_t *options = NULL; + int ret = -1; + + if (!frame || !this || !data) + goto out; + + options = data; + + ret = dict_allocate_and_serialize (options, + &req.dict.dict_val, + (size_t *)&req.dict.dict_len); + if (ret < 0) { + gf_log ("cli", GF_LOG_ERROR, + "failed to serialize the data"); + + goto out; + } + + ret = cli_cmd_submit (&req, frame, cli_rpc_prog, + GLUSTER_CLI_CLRLOCKS_VOLUME, NULL, + this, gf_cli3_1_clearlocks_volume_cbk, + (xdrproc_t)xdr_gf_cli_req); + +out: + if (options) + dict_destroy (options); + gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); + + if (req.dict.dict_val) + GF_FREE (req.dict.dict_val); + return ret; +} + struct rpc_clnt_procedure gluster_cli_actors[GLUSTER_CLI_MAXVALUE] = { [GLUSTER_CLI_NULL] = {"NULL", NULL }, [GLUSTER_CLI_PROBE] = {"PROBE_QUERY", gf_cli3_1_probe}, @@ -5675,6 +5787,7 @@ struct rpc_clnt_procedure gluster_cli_actors[GLUSTER_CLI_MAXVALUE] = { [GLUSTER_CLI_HEAL_VOLUME] = {"HEAL_VOLUME", gf_cli3_1_heal_volume}, [GLUSTER_CLI_STATEDUMP_VOLUME] = {"STATEDUMP_VOLUME", gf_cli3_1_statedump_volume}, [GLUSTER_CLI_LIST_VOLUME] = {"LIST_VOLUME", gf_cli3_1_list_volume}, + [GLUSTER_CLI_CLRLOCKS_VOLUME] = {"CLEARLOCKS_VOLUME", gf_cli3_1_clearlocks_volume}, }; struct rpc_clnt_program cli_prog = { diff --git a/cli/src/cli.h b/cli/src/cli.h index 0814065a0fd..25b17da4968 100644 --- a/cli/src/cli.h +++ b/cli/src/cli.h @@ -219,6 +219,9 @@ cli_cmd_log_filename_parse (const char **words, int wordcount, dict_t **options) int32_t cli_cmd_volume_statedump_options_parse (const char **words, int wordcount, dict_t **options); +int32_t +cli_cmd_volume_clrlks_opts_parse (const char **words, int wordcount, + dict_t **options); cli_local_t * cli_local_get (); diff --git a/rpc/rpc-lib/src/protocol-common.h b/rpc/rpc-lib/src/protocol-common.h index 08f6194a926..6ef4cb702c3 100644 --- a/rpc/rpc-lib/src/protocol-common.h +++ b/rpc/rpc-lib/src/protocol-common.h @@ -155,6 +155,7 @@ enum gluster_cli_procnum { GLUSTER_CLI_HEAL_VOLUME, GLUSTER_CLI_STATEDUMP_VOLUME, GLUSTER_CLI_LIST_VOLUME, + GLUSTER_CLI_CLRLOCKS_VOLUME, GLUSTER_CLI_MAXVALUE, }; diff --git a/xlators/mgmt/glusterd/src/glusterd-handler.c b/xlators/mgmt/glusterd/src/glusterd-handler.c index 257930720a4..b80164e8d0e 100644 --- a/xlators/mgmt/glusterd/src/glusterd-handler.c +++ b/xlators/mgmt/glusterd/src/glusterd-handler.c @@ -2622,6 +2622,73 @@ out: } int +glusterd_handle_cli_clearlocks_volume (rpcsvc_request_t *req) +{ + int32_t ret = -1; + gf_cli_req cli_req = {{0,}}; + glusterd_op_t cli_op = GD_OP_CLEARLOCKS_VOLUME; + char *volname = NULL; + dict_t *dict = NULL; + + GF_ASSERT (req); + + ret = -1; + if (!xdr_to_generic (req->msg[0], &cli_req, + (xdrproc_t)xdr_gf_cli_req)) { + req->rpc_err = GARBAGE_ARGS; + goto out; + } + + if (cli_req.dict.dict_len) { + dict = dict_new (); + + ret = dict_unserialize (cli_req.dict.dict_val, + cli_req.dict.dict_len, + &dict); + if (ret < 0) { + gf_log (THIS->name, GF_LOG_ERROR, + "failed to unserialize req-buffer to" + " dictionary"); + goto out; + } + + } else { + ret = -1; + gf_log (THIS->name, GF_LOG_ERROR, "Empty cli request."); + goto out; + } + + ret = dict_get_str (dict, "volname", &volname); + if (ret) { + gf_log (THIS->name, GF_LOG_ERROR, "failed to get volname"); + goto out; + } + + gf_log (THIS->name, GF_LOG_INFO, "Received clear-locks volume req " + "for volume %s", volname); + + ret = glusterd_op_begin (req, cli_op, dict); + + gf_cmd_log ("clear-locks", "on volume %s %s", volname, + ((0 == ret) ? "SUCCEEDED" : "FAILED")); + +out: + if (ret && dict) + dict_unref (dict); + + glusterd_friend_sm (); + glusterd_op_sm (); + + if (ret) + ret = glusterd_op_send_cli_response (cli_op, ret, 0, req, + NULL, "operation failed"); + if (cli_req.dict.dict_val) + free (cli_req.dict.dict_val); + + return ret; +} + +int glusterd_brick_rpc_notify (struct rpc_clnt *rpc, void *mydata, rpc_clnt_event_t event, void *data) @@ -2898,6 +2965,7 @@ rpcsvc_actor_t gd_svc_cli_actors[] = { [GLUSTER_CLI_HEAL_VOLUME] = { "HEAL_VOLUME", GLUSTER_CLI_HEAL_VOLUME, glusterd_handle_cli_heal_volume, NULL, NULL, 0}, [GLUSTER_CLI_STATEDUMP_VOLUME] = {"STATEDUMP_VOLUME", GLUSTER_CLI_STATEDUMP_VOLUME, glusterd_handle_cli_statedump_volume, NULL, NULL, 0}, [GLUSTER_CLI_LIST_VOLUME] = {"LIST_VOLUME", GLUSTER_CLI_LIST_VOLUME, glusterd_handle_cli_list_volume, NULL, NULL, 0}, + [GLUSTER_CLI_CLRLOCKS_VOLUME] = {"CLEARLOCKS_VOLUME", GLUSTER_CLI_CLRLOCKS_VOLUME, glusterd_handle_cli_clearlocks_volume, NULL, NULL, 0}, }; struct rpcsvc_program gd_svc_cli_prog = { diff --git a/xlators/mgmt/glusterd/src/glusterd-mem-types.h b/xlators/mgmt/glusterd/src/glusterd-mem-types.h index 196f5f50bd8..3bb446d1a90 100644 --- a/xlators/mgmt/glusterd/src/glusterd-mem-types.h +++ b/xlators/mgmt/glusterd/src/glusterd-mem-types.h @@ -71,7 +71,8 @@ typedef enum gf_gld_mem_types_ { gf_gld_mt_mount_component = gf_common_mt_end + 45, gf_gld_mt_mount_spec = gf_common_mt_end + 46, gf_gld_mt_nodesrv_t = gf_common_mt_end + 47, - gf_gld_mt_end = gf_common_mt_end + 48, + gf_gld_mt_charptr = gf_common_mt_end + 48, + gf_gld_mt_end = gf_common_mt_end + 49, } gf_gld_mem_types_t; #endif diff --git a/xlators/mgmt/glusterd/src/glusterd-op-sm.c b/xlators/mgmt/glusterd/src/glusterd-op-sm.c index d0d280a0923..4a0561d1e6e 100644 --- a/xlators/mgmt/glusterd/src/glusterd-op-sm.c +++ b/xlators/mgmt/glusterd/src/glusterd-op-sm.c @@ -1616,6 +1616,7 @@ glusterd_op_build_payload (dict_t **req) case GD_OP_REBALANCE: case GD_OP_HEAL_VOLUME: case GD_OP_STATEDUMP_VOLUME: + case GD_OP_CLEARLOCKS_VOLUME: { dict_t *dict = ctx; dict_copy (dict, req_dict); @@ -2219,8 +2220,16 @@ glusterd_op_ac_commit_op (glusterd_op_sm_event_t *event, void *ctx) rsp_dict = glusterd_op_init_commit_rsp_dict (req_ctx->op); if (NULL == rsp_dict) return -1; - status = glusterd_op_commit_perform (req_ctx->op, dict, &op_errstr, - rsp_dict); + + if (GD_OP_CLEARLOCKS_VOLUME == req_ctx->op) { + /*clear locks should be run only on + * originator glusterd*/ + status = 0; + + } else { + status = glusterd_op_commit_perform (req_ctx->op, dict, + &op_errstr, rsp_dict); + } if (status) { gf_log (THIS->name, GF_LOG_ERROR, "Commit failed: %d", status); @@ -2370,6 +2379,10 @@ glusterd_op_stage_validate (glusterd_op_t op, dict_t *dict, char **op_errstr, ret = glusterd_op_stage_statedump_volume (dict, op_errstr); break; + case GD_OP_CLEARLOCKS_VOLUME: + ret = glusterd_op_stage_clearlocks_volume (dict, + op_errstr); + break; default: gf_log ("", GF_LOG_ERROR, "Unknown op %d", @@ -2462,6 +2475,10 @@ glusterd_op_commit_perform (glusterd_op_t op, dict_t *dict, char **op_errstr, ret = glusterd_op_statedump_volume (dict, op_errstr); break; + case GD_OP_CLEARLOCKS_VOLUME: + ret = glusterd_op_clearlocks_volume (dict, op_errstr); + break; + default: gf_log ("", GF_LOG_ERROR, "Unknown op %d", op); @@ -3740,6 +3757,7 @@ glusterd_op_free_ctx (glusterd_op_t op, void *ctx) case GD_OP_REBALANCE: case GD_OP_HEAL_VOLUME: case GD_OP_STATEDUMP_VOLUME: + case GD_OP_CLEARLOCKS_VOLUME: dict_unref (ctx); break; default: diff --git a/xlators/mgmt/glusterd/src/glusterd-rpc-ops.c b/xlators/mgmt/glusterd/src/glusterd-rpc-ops.c index 275e1ccffba..2cf17b3f730 100644 --- a/xlators/mgmt/glusterd/src/glusterd-rpc-ops.c +++ b/xlators/mgmt/glusterd/src/glusterd-rpc-ops.c @@ -147,6 +147,7 @@ glusterd_op_send_cli_response (glusterd_op_t op, int32_t op_ret, case GD_OP_STATUS_VOLUME: case GD_OP_SET_VOLUME: case GD_OP_LIST_VOLUME: + case GD_OP_CLEARLOCKS_VOLUME: { /*nothing specific to be done*/ break; diff --git a/xlators/mgmt/glusterd/src/glusterd-utils.c b/xlators/mgmt/glusterd/src/glusterd-utils.c index a7125825072..864467fd304 100644 --- a/xlators/mgmt/glusterd/src/glusterd-utils.c +++ b/xlators/mgmt/glusterd/src/glusterd-utils.c @@ -4798,3 +4798,23 @@ glusterd_chk_peers_connected_befriended (uuid_t skip_uuid) (ret?"TRUE":"FALSE")); return ret; } + +void +glusterd_get_client_filepath (char *filepath, glusterd_volinfo_t *volinfo, + gf_transport_type type) +{ + char path[PATH_MAX] = {0,}; + glusterd_conf_t *priv = NULL; + + priv = THIS->private; + + GLUSTERD_GET_VOLUME_DIR (path, volinfo, priv); + + if ((volinfo->transport_type == GF_TRANSPORT_BOTH_TCP_RDMA) && + (type == GF_TRANSPORT_RDMA)) + snprintf (filepath, PATH_MAX, "%s/%s.rdma-fuse.vol", + path, volinfo->volname); + else + snprintf (filepath, PATH_MAX, "%s/%s-fuse.vol", + path, volinfo->volname); +} diff --git a/xlators/mgmt/glusterd/src/glusterd-utils.h b/xlators/mgmt/glusterd/src/glusterd-utils.h index e6a655ca780..b8c65cbb073 100644 --- a/xlators/mgmt/glusterd/src/glusterd-utils.h +++ b/xlators/mgmt/glusterd/src/glusterd-utils.h @@ -386,4 +386,7 @@ glusterd_friend_remove_cleanup_vols (uuid_t uuid); gf_boolean_t glusterd_chk_peers_connected_befriended (uuid_t skip_uuid); +void +glusterd_get_client_filepath (char *filepath, glusterd_volinfo_t *volinfo, + gf_transport_type type); #endif diff --git a/xlators/mgmt/glusterd/src/glusterd-volgen.c b/xlators/mgmt/glusterd/src/glusterd-volgen.c index 798ff05650e..fe79ea487b3 100644 --- a/xlators/mgmt/glusterd/src/glusterd-volgen.c +++ b/xlators/mgmt/glusterd/src/glusterd-volgen.c @@ -2871,25 +2871,6 @@ generate_single_transport_client_volfile (glusterd_volinfo_t *volinfo, return ret; } -void -get_client_filepath (char *filepath, glusterd_volinfo_t *volinfo, gf_transport_type type) -{ - char path[PATH_MAX] = {0,}; - glusterd_conf_t *priv = NULL; - - priv = THIS->private; - - GLUSTERD_GET_VOLUME_DIR (path, volinfo, priv); - - if ((volinfo->transport_type == GF_TRANSPORT_BOTH_TCP_RDMA) && - (type == GF_TRANSPORT_RDMA)) - snprintf (filepath, PATH_MAX, "%s/%s.rdma-fuse.vol", - path, volinfo->volname); - else - snprintf (filepath, PATH_MAX, "%s/%s-fuse.vol", - path, volinfo->volname); -} - static void enumerate_transport_reqs (gf_transport_type type, char **types) { @@ -2927,7 +2908,7 @@ generate_client_volfiles (glusterd_volinfo_t *volinfo) if (ret) goto out; type = transport_str_to_type (types[i]); - get_client_filepath (filepath, volinfo, type); + glusterd_get_client_filepath (filepath, volinfo, type); ret = generate_single_transport_client_volfile (volinfo, filepath, dict); diff --git a/xlators/mgmt/glusterd/src/glusterd-volume-ops.c b/xlators/mgmt/glusterd/src/glusterd-volume-ops.c index 3208ad35537..1ce0faf17ee 100644 --- a/xlators/mgmt/glusterd/src/glusterd-volume-ops.c +++ b/xlators/mgmt/glusterd/src/glusterd-volume-ops.c @@ -23,6 +23,7 @@ #endif #include "common-utils.h" +#include "syscall.h" #include "cli1-xdr.h" #include "xdr-generic.h" #include "glusterd.h" @@ -1098,6 +1099,73 @@ out: } int +glusterd_op_stage_clearlocks_volume (dict_t *dict, char **op_errstr) +{ + int ret = -1; + char *volname = NULL; + char *path = NULL; + char *type = NULL; + char *kind = NULL; + glusterd_volinfo_t *volinfo = NULL; + char msg[2048] = {0,}; + + ret = dict_get_str (dict, "volname", &volname); + if (ret) { + snprintf (msg, sizeof(msg), "Failed to get volume name"); + gf_log (THIS->name, GF_LOG_ERROR, "%s", msg); + *op_errstr = gf_strdup (msg); + goto out; + } + + ret = dict_get_str (dict, "path", &path); + if (ret) { + snprintf (msg, sizeof(msg), "Failed to get path"); + gf_log (THIS->name, GF_LOG_ERROR, "%s", msg); + *op_errstr = gf_strdup (msg); + goto out; + } + + ret = dict_get_str (dict, "kind", &kind); + if (ret) { + snprintf (msg, sizeof(msg), "Failed to get kind"); + gf_log ("", GF_LOG_ERROR, "%s", msg); + *op_errstr = gf_strdup (msg); + goto out; + } + + ret = dict_get_str (dict, "type", &type); + if (ret) { + snprintf (msg, sizeof(msg), "Failed to get type"); + gf_log ("", GF_LOG_ERROR, "%s", msg); + *op_errstr = gf_strdup (msg); + goto out; + } + + ret = glusterd_volinfo_find (volname, &volinfo); + if (ret) { + snprintf (msg, sizeof(msg), "Volume %s does not exist", + volname); + gf_log ("", GF_LOG_ERROR, "%s", msg); + *op_errstr = gf_strdup (msg); + goto out; + } + + if (!glusterd_is_volume_started (volinfo)) { + snprintf (msg, sizeof(msg), "Volume %s is not started", + volname); + gf_log ("", GF_LOG_ERROR, "%s", msg); + *op_errstr = gf_strdup (msg); + goto out; + } + + ret = 0; +out: + gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); + return ret; +} + + +int glusterd_op_create_volume (dict_t *dict, char **op_errstr) { int ret = 0; @@ -1431,3 +1499,328 @@ out: return ret; } +int +glusterd_clearlocks_send_cmd (glusterd_volinfo_t *volinfo, char *cmd, + char *path, char *result, char *errstr, + int err_len, char *mntpt) +{ + int ret = -1; + glusterd_conf_t *priv = NULL; + + priv = THIS->private; + + ret = sys_lgetxattr (mntpt, cmd, result, PATH_MAX); + if (ret < 0) { + snprintf (errstr, err_len, "clear-locks getxattr command " + "failed. Reason: %s", strerror (errno)); + gf_log (THIS->name, GF_LOG_DEBUG, "%s", errstr); + goto out; + } + + ret = 0; +out: + return ret; +} + +int +glusterd_clearlocks_rmdir_mount (glusterd_volinfo_t *volinfo, char *mntpt) +{ + int ret = -1; + glusterd_conf_t *priv = NULL; + + priv = THIS->private; + + ret = rmdir (mntpt); + if (ret) { + gf_log (THIS->name, GF_LOG_DEBUG, "rmdir failed"); + goto out; + } + + ret = 0; +out: + return ret; +} + +void +glusterd_clearlocks_unmount (glusterd_volinfo_t *volinfo, char *mntpt) +{ + glusterd_conf_t *priv = NULL; + runner_t runner = {0,}; + int ret = 0; + + priv = THIS->private; + + /*umount failures are ignored. Using stat we could have avoided + * attempting to unmount a non-existent filesystem. But a failure of + * stat() on mount can be due to network failures.*/ + + runinit (&runner); + runner_add_args (&runner, "/bin/umount", "-f", NULL); + runner_argprintf (&runner, "%s", mntpt); + + ret = runner_run (&runner); + if (ret) { + ret = 0; + gf_log ("", GF_LOG_DEBUG, + "umount failed on maintenance client"); + } + + return; +} + +int +glusterd_clearlocks_create_mount (glusterd_volinfo_t *volinfo, char **mntpt) +{ + int ret = -1; + glusterd_conf_t *priv = NULL; + char template[PATH_MAX] = {0,}; + char *tmpl = NULL; + + priv = THIS->private; + + snprintf (template, sizeof (template), "/tmp/%s.XXXXXX", + volinfo->volname); + tmpl = mkdtemp (template); + if (!tmpl) { + gf_log (THIS->name, GF_LOG_DEBUG, "Couldn't create temporary " + "mount directory. Reason %s", strerror (errno)); + goto out; + } + + *mntpt = gf_strdup (tmpl); + ret = 0; +out: + return ret; +} + +int +glusterd_clearlocks_mount (glusterd_volinfo_t *volinfo, char **xl_opts, + char *mntpt) +{ + int ret = -1; + int i = 0; + glusterd_conf_t *priv = NULL; + runner_t runner = {0,}; + char client_volfpath[PATH_MAX] = {0,}; + + priv = THIS->private; + + runinit (&runner); + glusterd_get_client_filepath (client_volfpath, volinfo, + volinfo->transport_type); + runner_add_args (&runner, SBIN_DIR"/glusterfs", "-f", NULL); + runner_argprintf (&runner, "%s", client_volfpath); + + for (i = 0; i < volinfo->brick_count && xl_opts[i]; i++) { + runner_add_arg (&runner, "--xlator-option"); + runner_argprintf (&runner, "%s", xl_opts[i]); + } + + runner_argprintf (&runner, "%s", mntpt); + ret = runner_run (&runner); + if (ret) { + gf_log (THIS->name, GF_LOG_DEBUG, + "Could not start glusterfs"); + goto out; + } + gf_log (THIS->name, GF_LOG_DEBUG, + "Started glusterfs successfully"); + +out: + return ret; +} + +int +glusterd_clearlocks_get_local_client_ports (glusterd_volinfo_t *volinfo, + char **xl_opts) +{ + glusterd_brickinfo_t *brickinfo = NULL; + glusterd_conf_t *priv = NULL; + int index = 0; + int ret = -1; + int i = 0; + int port = 0; + + GF_ASSERT (xl_opts); + if (!xl_opts) { + gf_log (THIS->name, GF_LOG_DEBUG, "Should pass non-NULL " + "xl_opts"); + goto out; + } + + priv = THIS->private; + + index = -1; + list_for_each_entry (brickinfo, &volinfo->bricks, brick_list) { + index++; + if (uuid_compare (brickinfo->uuid, priv->uuid)) + continue; + + port = pmap_registry_search (THIS, brickinfo->path, + GF_PMAP_PORT_BRICKSERVER); + if (!port) { + ret = -1; + gf_log (THIS->name, GF_LOG_DEBUG, "Couldn't get port " + " for brick %s:%s", brickinfo->hostname, + brickinfo->path); + goto out; + } + + ret = gf_asprintf (&xl_opts[i], "%s-client-%d.remote-port=%d", + volinfo->volname, index, port); + if (ret == -1) { + xl_opts[i] = NULL; + goto out; + } + i++; + } + + ret = 0; +out: + return ret; +} + +int +glusterd_op_clearlocks_volume (dict_t *dict, char **op_errstr) +{ + int32_t ret = -1; + int i = 0; + char *volname = NULL; + char *path = NULL; + char *kind = NULL; + char *type = NULL; + char *opts = NULL; + char *cmd_str = NULL; + char *free_ptr = NULL; + char msg[PATH_MAX] = {0,}; + char result[PATH_MAX] = {0,}; + char *mntpt = NULL; + char **xl_opts = NULL; + dict_t *ctx = NULL; + glusterd_volinfo_t *volinfo = NULL; + + ret = dict_get_str (dict, "volname", &volname); + if (ret) { + gf_log (THIS->name, GF_LOG_ERROR, "Failed to get volume name"); + goto out; + } + gf_log ("", GF_LOG_DEBUG, "Performing clearlocks on volume %s", volname); + + ret = dict_get_str (dict, "path", &path); + if (ret) { + gf_log (THIS->name, GF_LOG_ERROR, "Failed to get path"); + goto out; + } + + ret = dict_get_str (dict, "kind", &kind); + if (ret) { + gf_log (THIS->name, GF_LOG_ERROR, "Failed to get kind"); + goto out; + } + + ret = dict_get_str (dict, "type", &type); + if (ret) { + gf_log (THIS->name, GF_LOG_ERROR, "Failed to get type"); + goto out; + } + + ret = dict_get_str (dict, "opts", &opts); + if (ret) + ret = 0; + + gf_log (THIS->name, GF_LOG_INFO, "Received clear-locks request for " + "volume %s with kind %s type %s and options %s", volname, + kind, type, opts); + + if (opts) + ret = gf_asprintf (&cmd_str, GF_XATTR_CLRLK_CMD".t%s.k%s.%s", + type, kind, opts); + else + ret = gf_asprintf (&cmd_str, GF_XATTR_CLRLK_CMD".t%s.k%s", + type, kind); + if (ret == -1) + goto out; + + ret = glusterd_volinfo_find (volname, &volinfo); + if (ret) { + snprintf (msg, sizeof (msg), "Volume %s doesn't exist.", + volname); + gf_log (THIS->name, GF_LOG_ERROR, "%s", msg); + goto out; + } + + xl_opts = GF_CALLOC (volinfo->brick_count+1, sizeof (char*), + gf_gld_mt_charptr); + if (!xl_opts) + goto out; + + ret = glusterd_clearlocks_get_local_client_ports (volinfo, xl_opts); + if (ret) { + snprintf (msg, sizeof (msg), "Couldn't get port numbers of " + "local bricks"); + gf_log (THIS->name, GF_LOG_ERROR, "%s", msg); + goto out; + } + + ret = glusterd_clearlocks_create_mount (volinfo, &mntpt); + if (ret) { + snprintf (msg, sizeof (msg), "Creating mount directory " + "for clear-locks failed."); + gf_log (THIS->name, GF_LOG_ERROR, "%s", msg); + goto out; + } + + ret = glusterd_clearlocks_mount (volinfo, xl_opts, mntpt); + if (ret) { + snprintf (msg, sizeof (msg), "Failed to mount clear-locks " + "maintenance client."); + gf_log (THIS->name, GF_LOG_ERROR, "%s", msg); + goto out; + } + + ret = glusterd_clearlocks_send_cmd (volinfo, cmd_str, path, result, + msg, sizeof (msg), mntpt); + if (ret) { + gf_log (THIS->name, GF_LOG_ERROR, "%s", msg); + goto umount; + } + + ctx = glusterd_op_get_ctx (); + if (!ctx) + /*Impossible. Only originator glusterd can + * come here. */ + goto umount; + + free_ptr = gf_strdup(result); + if (dict_set_dynstr (ctx, "lk-summary", free_ptr)) { + GF_FREE (free_ptr); + snprintf (msg, sizeof (msg), "Failed to set clear-locks " + "result"); + gf_log (THIS->name, GF_LOG_ERROR, "%s", msg); + } + +umount: + glusterd_clearlocks_unmount (volinfo, mntpt); + + if (glusterd_clearlocks_rmdir_mount (volinfo, mntpt)) + gf_log (THIS->name, GF_LOG_WARNING, "Couldn't unmount " + "clear-locks mount point"); + +out: + if (ret) + *op_errstr = gf_strdup (msg); + + if (xl_opts) { + for (i = 0; i < volinfo->brick_count && xl_opts[i]; i++) + GF_FREE (xl_opts[i]); + GF_FREE (xl_opts); + } + + if (cmd_str) + GF_FREE (cmd_str); + + if (mntpt) + GF_FREE (mntpt); + + return ret; +} diff --git a/xlators/mgmt/glusterd/src/glusterd.h b/xlators/mgmt/glusterd/src/glusterd.h index bea15689bc2..60dbe61e04a 100644 --- a/xlators/mgmt/glusterd/src/glusterd.h +++ b/xlators/mgmt/glusterd/src/glusterd.h @@ -78,6 +78,7 @@ typedef enum glusterd_op_ { GD_OP_HEAL_VOLUME, GD_OP_STATEDUMP_VOLUME, GD_OP_LIST_VOLUME, + GD_OP_CLEARLOCKS_VOLUME, GD_OP_MAX, } glusterd_op_t; @@ -537,6 +538,7 @@ int32_t glusterd_op_begin (rpcsvc_request_t *req, glusterd_op_t op, void *ctx); /* removed other definitions as they have been defined elsewhere in this file*/ int glusterd_handle_cli_statedump_volume (rpcsvc_request_t *req); +int glusterd_handle_cli_clearlocks_volume (rpcsvc_request_t *req); int glusterd_handle_defrag_start (glusterd_volinfo_t *volinfo, char *op_errstr, size_t len, int cmd, defrag_cbk_fn_t cbk); @@ -576,6 +578,9 @@ int glusterd_op_rebalance (dict_t *dict, char **op_errstr, dict_t *rsp_dict); int glusterd_op_stage_statedump_volume (dict_t *dict, char **op_errstr); int glusterd_op_statedump_volume (dict_t *dict, char **op_errstr); +int glusterd_op_stage_clearlocks_volume (dict_t *dict, char **op_errstr); +int glusterd_op_clearlocks_volume (dict_t *dict, char **op_errstr); + /* misc */ void glusterd_do_replace_brick (void *data); int glusterd_op_perform_remove_brick (glusterd_volinfo_t *volinfo, char *brick, |