diff options
Diffstat (limited to 'xlators')
-rw-r--r-- | xlators/mgmt/glusterd/src/Makefile.am | 2 | ||||
-rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-handler.c | 517 | ||||
-rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-handshake.c | 2 | ||||
-rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-mem-types.h | 12 | ||||
-rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-op-sm.c | 1144 | ||||
-rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-op-sm.h | 45 | ||||
-rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-pmap.c | 8 | ||||
-rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-rpc-ops.c | 321 | ||||
-rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-utils.c | 157 | ||||
-rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-utils.h | 9 | ||||
-rw-r--r-- | xlators/mgmt/glusterd/src/glusterd.c | 2 | ||||
-rw-r--r-- | xlators/mgmt/glusterd/src/glusterd.h | 38 |
12 files changed, 1895 insertions, 362 deletions
diff --git a/xlators/mgmt/glusterd/src/Makefile.am b/xlators/mgmt/glusterd/src/Makefile.am index 84209b6f8cf..cfed2fd4b22 100644 --- a/xlators/mgmt/glusterd/src/Makefile.am +++ b/xlators/mgmt/glusterd/src/Makefile.am @@ -15,7 +15,7 @@ noinst_HEADERS = glusterd.h glusterd-utils.h glusterd-op-sm.h glusterd-sm.h \ AM_CFLAGS = -fPIC -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE -Wall -D$(GF_HOST_OS)\ -I$(top_srcdir)/libglusterfs/src -shared -nostartfiles $(GF_CFLAGS)\ -I$(rpclibdir) -L$(xlatordir)/ -I$(CONTRIBDIR)/rbtree -I$(top_srcdir)/rpc/xdr/src\ - -I$(top_srcdir)/rpc/rpc-lib/src -I$(CONTRIBDIR)/uuid -DGFS_PREFIX=\"$(prefix)\" \ + -I$(top_srcdir)/rpc/rpc-lib/src -I$(CONTRIBDIR)/uuid -I$(top_srcdir)/contrib/md5 -DGFS_PREFIX=\"$(prefix)\" \ -DDATADIR=\"$(localstatedir)\" -DGSYNCD_PREFIX=\"$(libexecdir)\" diff --git a/xlators/mgmt/glusterd/src/glusterd-handler.c b/xlators/mgmt/glusterd/src/glusterd-handler.c index 0db5992fc2c..7635f15546c 100644 --- a/xlators/mgmt/glusterd/src/glusterd-handler.c +++ b/xlators/mgmt/glusterd/src/glusterd-handler.c @@ -398,6 +398,37 @@ out: return ret; } +int32_t +glusterd_op_txn_begin () +{ + int32_t ret = -1; + glusterd_conf_t *priv = NULL; + int32_t locked = 0; + + priv = THIS->private; + GF_ASSERT (priv); + + ret = glusterd_lock (priv->uuid); + + if (ret) { + gf_log ("glusterd", GF_LOG_ERROR, + "Unable to acquire local lock, ret: %d", ret); + goto out; + } + + locked = 1; + gf_log ("glusterd", GF_LOG_NORMAL, "Acquired local lock"); + + ret = glusterd_op_sm_inject_event (GD_OP_EVENT_START_LOCK, NULL); + + gf_log ("glusterd", GF_LOG_DEBUG, "Returning %d", ret); + +out: + if (locked && ret) + glusterd_unlock (priv->uuid); + return ret; +} + int glusterd_handle_cluster_lock (rpcsvc_request_t *req) { @@ -439,147 +470,137 @@ out: } int -glusterd_handle_stage_op (rpcsvc_request_t *req) +glusterd_req_ctx_create (rpcsvc_request_t *rpc_req, + glusterd_op_t op, uuid_t uuid, + char *buf_val, size_t buf_len, + gf_gld_mem_types_t mem_type, + glusterd_req_ctx_t **req_ctx_out) { - int32_t ret = -1; - gd1_mgmt_stage_op_req stage_req = {{0,}}; - glusterd_op_stage_ctx_t *ctx = NULL; + int ret = -1; + glusterd_req_ctx_t *req_ctx = NULL; + char str[50] = {0,}; + dict_t *dict = NULL; char volname[GLUSTERD_MAX_VOLUME_NAME] = {0}; char *dup_volname = NULL; - GF_ASSERT (req); - - if (!gd_xdr_to_mgmt_stage_op_req (req->msg[0], &stage_req)) { - //failed to decode msg; - req->rpc_err = GARBAGE_ARGS; - goto out; - } - + uuid_unparse (uuid, str); gf_log ("glusterd", GF_LOG_NORMAL, - "Received stage op from uuid: %s", uuid_utoa (stage_req.uuid)); - - ctx = GF_CALLOC (1, sizeof (*ctx), gf_gld_mt_op_stage_ctx_t); - if (!ctx) { - //respond here - goto err; - } - - ctx->dict = dict_new(); - if (!ctx->dict) - goto err; + "Received op from uuid: %s", str); - uuid_copy (ctx->uuid, stage_req.uuid); - ctx->op = stage_req.op; - ctx->req = req; + dict = dict_new (); + if (!dict) + goto out; + req_ctx = GF_CALLOC (1, sizeof (*req_ctx), mem_type); - if (!stage_req.buf.buf_val) + if (!req_ctx) { goto out; + } - if (GD_OP_DELETE_VOLUME == stage_req.op) { - strncpy (volname, stage_req.buf.buf_val, stage_req.buf.buf_len); + uuid_copy (req_ctx->uuid, uuid); + req_ctx->op = op; + if (GD_OP_DELETE_VOLUME == op) { + strncpy (volname, buf_val, buf_len); dup_volname = gf_strdup (volname); if (dup_volname) { - ret = dict_set_dynstr (ctx->dict, "volname", dup_volname); - if (ret) + ret = dict_set_dynstr (dict, "volname", dup_volname); + if (ret) { gf_log ("", GF_LOG_WARNING, - "failed to set volume name from payload"); + "failed to set volume name from payload"); + goto out; + } + } else { + ret = -1; + goto out; } - } else { - ret = dict_unserialize (stage_req.buf.buf_val, - stage_req.buf.buf_len, - &ctx->dict); + ret = dict_unserialize (buf_val, buf_len, &dict); - if (ret) + if (ret) { gf_log ("", GF_LOG_WARNING, - "failed to unserialize the dictionary"); + "failed to unserialize the dictionary"); + goto out; + } } - ret = glusterd_op_sm_inject_event (GD_OP_EVENT_STAGE_OP, ctx); - + req_ctx->dict = dict; + req_ctx->req = rpc_req; + *req_ctx_out = req_ctx; + ret = 0; out: - if (stage_req.buf.buf_val) - free (stage_req.buf.buf_val);//malloced by xdr - - glusterd_friend_sm (); - glusterd_op_sm (); -err: + if (ret) { + if (dict) + dict_unref (dict); + if (req_ctx) + GF_FREE (req_ctx); + } return ret; } int -glusterd_handle_commit_op (rpcsvc_request_t *req) +glusterd_handle_stage_op (rpcsvc_request_t *req) { int32_t ret = -1; - gd1_mgmt_commit_op_req commit_req = {{0},}; - glusterd_op_commit_ctx_t *ctx = NULL; - char volname[GLUSTERD_MAX_VOLUME_NAME] = {0}; - char *dup_volname = NULL; + glusterd_req_ctx_t *req_ctx = NULL; + gd1_mgmt_stage_op_req op_req = {{0},}; GF_ASSERT (req); - - if (!gd_xdr_to_mgmt_commit_op_req (req->msg[0], &commit_req)) { + if (!gd_xdr_to_mgmt_stage_op_req (req->msg[0], &op_req)) { //failed to decode msg; req->rpc_err = GARBAGE_ARGS; goto out; } + ret = glusterd_req_ctx_create (req, op_req.op, op_req.uuid, + op_req.buf.buf_val, op_req.buf.buf_len, + gf_gld_mt_op_stage_ctx_t, &req_ctx); + if (ret) + goto out; - gf_log ("glusterd", GF_LOG_NORMAL, - "Received commit op from uuid: %s", uuid_utoa (commit_req.uuid)); - - ctx = GF_CALLOC (1, sizeof (*ctx), gf_gld_mt_op_commit_ctx_t); - - if (!ctx) { - //respond here - goto err; - } + ret = glusterd_op_sm_inject_event (GD_OP_EVENT_STAGE_OP, req_ctx); - ctx->req = req; + out: + if (op_req.buf.buf_val) + free (op_req.buf.buf_val);//malloced by xdr + glusterd_friend_sm (); + glusterd_op_sm (); + return ret; +} - uuid_copy (ctx->uuid, commit_req.uuid); - ctx->op = commit_req.op; +int +glusterd_handle_commit_op (rpcsvc_request_t *req) +{ + int32_t ret = -1; + glusterd_req_ctx_t *req_ctx = NULL; + gd1_mgmt_commit_op_req op_req = {{0},}; - ctx->dict = dict_new(); - if (!ctx->dict) - goto err; + GF_ASSERT (req); - if (!commit_req.buf.buf_val) + if (!gd_xdr_to_mgmt_commit_op_req (req->msg[0], &op_req)) { + //failed to decode msg; + req->rpc_err = GARBAGE_ARGS; goto out; - - if (GD_OP_DELETE_VOLUME == commit_req.op) { - strncpy (volname, commit_req.buf.buf_val, commit_req.buf.buf_len); - dup_volname = gf_strdup (volname); - if (dup_volname) { - ret = dict_set_dynstr (ctx->dict, "volname", dup_volname); - if (ret) - gf_log ("", GF_LOG_WARNING, - "failed to set volume name from payload"); - } - - } else { - ret = dict_unserialize (commit_req.buf.buf_val, - commit_req.buf.buf_len, - &ctx->dict); - - if (ret) - gf_log ("", GF_LOG_WARNING, - "failed to unserialize the dictionary"); } - ret = glusterd_op_sm_inject_event (GD_OP_EVENT_COMMIT_OP, ctx); + //the structures should always be equal + GF_ASSERT (sizeof (gd1_mgmt_commit_op_req) == sizeof (gd1_mgmt_stage_op_req)); + ret = glusterd_req_ctx_create (req, op_req.op, op_req.uuid, + op_req.buf.buf_val, op_req.buf.buf_len, + gf_gld_mt_op_commit_ctx_t, &req_ctx); + if (ret) + goto out; -out: - if (commit_req.buf.buf_val) - free (commit_req.buf.buf_val);//malloced by xdr + ret = glusterd_op_sm_inject_event (GD_OP_EVENT_COMMIT_OP, req_ctx); + if (ret) + goto out; + ret = glusterd_op_init_ctx (op_req.op); +out: + if (op_req.buf.buf_val) + free (op_req.buf.buf_val);//malloced by xdr glusterd_friend_sm (); glusterd_op_sm (); - -err: return ret; } - int glusterd_handle_cli_probe (rpcsvc_request_t *req) { @@ -804,37 +825,6 @@ out: } int32_t -glusterd_op_txn_begin () -{ - int32_t ret = -1; - glusterd_conf_t *priv = NULL; - int32_t locked = 0; - - priv = THIS->private; - GF_ASSERT (priv); - - ret = glusterd_lock (priv->uuid); - - if (ret) { - gf_log ("glusterd", GF_LOG_ERROR, - "Unable to acquire local lock, ret: %d", ret); - goto out; - } - - locked = 1; - gf_log ("glusterd", GF_LOG_NORMAL, "Acquired local lock"); - - ret = glusterd_op_sm_inject_event (GD_OP_EVENT_START_LOCK, NULL); - - gf_log ("glusterd", GF_LOG_DEBUG, "Returning %d", ret); - -out: - if (locked && ret) - glusterd_unlock (priv->uuid); - return ret; -} - -int32_t glusterd_op_begin (rpcsvc_request_t *req, glusterd_op_t op, void *ctx, gf_boolean_t is_ctx_free) { @@ -2924,6 +2914,77 @@ out: } int +glusterd_handle_cli_profile_volume (rpcsvc_request_t *req) +{ + int32_t ret = -1; + gf1_cli_stats_volume_req cli_req = {0,}; + dict_t *dict = NULL; + char msg[2048] = {0,}; + gf_boolean_t free_volname = _gf_true; + int lock_fail = 0; + glusterd_op_t cli_op = GD_OP_PROFILE_VOLUME; + + + GF_ASSERT (req); + + ret = glusterd_op_set_cli_op (cli_op); + if (ret) { + gf_log ("", GF_LOG_ERROR, "Unable to set cli op: %d", + ret); + lock_fail = 1; + goto out; + } + + ret = -1; + if (!gf_xdr_to_cli_stats_volume_req (req->msg[0], &cli_req)) { + //failed to decode msg; + req->rpc_err = GARBAGE_ARGS; + goto out; + } + + gf_log ("glusterd", GF_LOG_NORMAL, "Received volume profile req " + "for volume %s", cli_req.volname); + + dict = dict_new (); + if (!dict) + goto out; + ret = dict_set_dynmstr (dict, "volname", cli_req.volname); + if (ret) { + gf_log ("", GF_LOG_ERROR, "volume name set failed"); + snprintf (msg, sizeof (msg), "volume name set failed"); + goto out; + } else { + free_volname = _gf_false; + } + + ret = dict_set_int32 (dict, "op", cli_req.op); + if (ret) { + gf_log ("", GF_LOG_ERROR, "op set failed"); + goto out; + } + + ret = glusterd_op_begin (req, cli_op, dict, _gf_true); + +out: + glusterd_friend_sm (); + glusterd_op_sm (); + if (ret) + dict_unref (dict); + if (free_volname) + free (cli_req.volname); // malloced by xdr + if (ret) { + ret = glusterd_op_send_cli_response (cli_op, ret, 0, req, + NULL, "operation failed"); + if (!lock_fail) + (void) glusterd_opinfo_unlock (); + + } + + gf_log ("glusterd", GF_LOG_DEBUG, "Returning %d", ret); + return ret; +} + +int glusterd_friend_remove (uuid_t uuid, char *hostname) { int ret = 0; @@ -2940,96 +3001,83 @@ out: } int -glusterd_friend_rpc_create (struct rpc_clnt **rpc, - const char *hoststr, int port, - glusterd_peerctx_t *peerctx) +glusterd_rpc_create (struct rpc_clnt **rpc, + dict_t *options, + rpc_clnt_notify_t notify_fn, + void *notify_data) { struct rpc_clnt *new_rpc = NULL; - dict_t *options = NULL; - struct rpc_clnt_config rpc_cfg = {0,}; int ret = -1; - char *hostname = NULL; - int32_t intvl = 0; xlator_t *this = NULL; - GF_ASSERT (hoststr); this = THIS; GF_ASSERT (this); - options = dict_new (); - if (!options) + GF_ASSERT (options); + new_rpc = rpc_clnt_new (options, this->ctx, this->name); + + if (!new_rpc) goto out; - ret = dict_get_int32 (this->options, - "transport.socket.keepalive-interval", - &intvl); - if (!ret) { - ret = dict_set_int32 (options, - "transport.socket.keepalive-interval", intvl); - if (ret) - goto out; + ret = rpc_clnt_register_notify (new_rpc, notify_fn, notify_data); + *rpc = new_rpc; + if (ret) + goto out; + ret = rpc_clnt_start (new_rpc); +out: + if (ret) { + if (new_rpc) { + (void) rpc_clnt_unref (new_rpc); + } } + gf_log ("", GF_LOG_DEBUG, "returning %d", ret); + return ret; +} + +int +glusterd_transport_keepalive_options_get (int *interval, int *time) +{ + int ret = 0; + xlator_t *this = NULL; + + this = THIS; + GF_ASSERT (this); + + ret = dict_get_int32 (this->options, + "transport.socket.keepalive-interval", + interval); ret = dict_get_int32 (this->options, "transport.socket.keepalive-time", - &intvl); - if (!ret) { - ret = dict_set_int32 (options, - "transport.socket.keepalive-time", intvl); - if (ret) - goto out; - } + time); + return 0; +} - hostname = gf_strdup((char*)hoststr); - if (!hostname) { - ret = -1; - goto out; - } +int +glusterd_transport_inet_keepalive_options_build (dict_t **options, + const char *hostname, int port) +{ + dict_t *dict = NULL; + int32_t interval = -1; + int32_t time = -1; + int ret = 0; - ret = dict_set_dynstr (options, "remote-host", hostname); - if (ret) - goto out; + GF_ASSERT (options); + GF_ASSERT (hostname); if (!port) port = GLUSTERD_DEFAULT_PORT; - - rpc_cfg.remote_host = (char *)hoststr; - rpc_cfg.remote_port = port; - - ret = dict_set_int32 (options, "remote-port", port); - if (ret) - goto out; - - ret = dict_set_str (options, "transport.address-family", "inet"); + ret = rpc_transport_inet_options_build (&dict, hostname, port); if (ret) goto out; - new_rpc = rpc_clnt_new (options, this->ctx, this->name); + glusterd_transport_keepalive_options_get (&interval, &time); - if (!new_rpc) { - gf_log ("glusterd", GF_LOG_ERROR, - "new_rpc init failed for peer: %s!", hoststr); - ret = -1; - goto out; - } - - ret = rpc_clnt_register_notify (new_rpc, glusterd_rpc_notify, - peerctx); - if (ret) - goto out; - *rpc = new_rpc; - rpc_clnt_start (new_rpc); + if ((interval > 0) || (time > 0)) + ret = rpc_transport_keepalive_options_set (dict, interval, time); + *options = dict; out: - if (ret) { - if (new_rpc) { - (void) rpc_clnt_unref (new_rpc); - } - if (options) - dict_unref (options); - *rpc = NULL; - } - - gf_log ("", GF_LOG_DEBUG, "returning %d", ret); + gf_log ("glusterd", GF_LOG_DEBUG, "Returning %d", ret); return ret; } @@ -3042,14 +3090,16 @@ glusterd_friend_add (const char *hoststr, int port, gf_boolean_t restore, glusterd_peerctx_args_t *args) { - int ret = 0; - glusterd_conf_t *conf = NULL; - glusterd_peerinfo_t *peerinfo = NULL; + int ret = 0; + glusterd_conf_t *conf = NULL; + glusterd_peerinfo_t *peerinfo = NULL; glusterd_peerctx_t *peerctx = NULL; - gf_boolean_t is_allocated = _gf_false; + gf_boolean_t is_allocated = _gf_false; + dict_t *options = NULL; conf = THIS->private; GF_ASSERT (conf) + GF_ASSERT (hoststr); peerctx = GF_CALLOC (1, sizeof (*peerctx), gf_gld_mt_peerctx_t); if (!peerctx) { @@ -3067,17 +3117,24 @@ glusterd_friend_add (const char *hoststr, int port, if (friend) *friend = peerinfo; - if (hoststr) { - if (!rpc) { - ret = glusterd_friend_rpc_create (&rpc, hoststr, port, - peerctx); - if (ret) - goto out; - is_allocated = _gf_true; + if (!rpc) { + ret = glusterd_transport_inet_keepalive_options_build (&options, + hoststr, port); + if (ret) + goto out; + ret = glusterd_rpc_create (&rpc, options, + glusterd_peer_rpc_notify, + peerctx); + if (ret) { + gf_log ("glusterd", GF_LOG_ERROR, "failed to create rpc for" + " peer %s", (char*)hoststr); + goto out; } - peerinfo->rpc = rpc; + is_allocated = _gf_true; } + peerinfo->rpc = rpc; + if (!restore) ret = glusterd_store_update_peerinfo (peerinfo); @@ -3482,14 +3539,58 @@ out: } int -glusterd_rpc_notify (struct rpc_clnt *rpc, void *mydata, rpc_clnt_event_t event, - void *data) +glusterd_brick_rpc_notify (struct rpc_clnt *rpc, void *mydata, + rpc_clnt_event_t event, + void *data) +{ + xlator_t *this = NULL; + glusterd_conf_t *conf = NULL; + int ret = 0; + glusterd_brickinfo_t *brickinfo = NULL; + + brickinfo = mydata; + if (!brickinfo) + return 0; + + this = THIS; + GF_ASSERT (this); + conf = this->private; + GF_ASSERT (conf); + + switch (event) { + case RPC_CLNT_CONNECT: + gf_log (this->name, GF_LOG_DEBUG, "got RPC_CLNT_CONNECT"); + glusterd_set_brick_status (brickinfo, GF_BRICK_STARTED); + 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"); + glusterd_set_brick_status (brickinfo, GF_BRICK_STOPPED); + if (brickinfo->timer && brickinfo->timer->callbk) + brickinfo->timer->callbk (brickinfo->timer->data); + break; + + default: + gf_log (this->name, GF_LOG_TRACE, + "got some other RPC event %d", event); + break; + } + + return ret; +} + +int +glusterd_peer_rpc_notify (struct rpc_clnt *rpc, void *mydata, + rpc_clnt_event_t event, + void *data) { xlator_t *this = NULL; glusterd_conf_t *conf = NULL; int ret = 0; glusterd_peerinfo_t *peerinfo = NULL; - glusterd_peerctx_t *peerctx = NULL; + glusterd_peerctx_t *peerctx = NULL; peerctx = mydata; if (!peerctx) @@ -3579,6 +3680,7 @@ rpcsvc_actor_t gd_svc_cli_actors[] = { [GLUSTER_CLI_RESET_VOLUME] = { "RESET_VOLUME", GLUSTER_CLI_RESET_VOLUME, glusterd_handle_reset_volume, NULL, NULL}, [GLUSTER_CLI_FSM_LOG] = { "FSM_LOG", GLUSTER_CLI_FSM_LOG, glusterd_handle_fsm_log, NULL, NULL}, [GLUSTER_CLI_GSYNC_SET] = { "GSYNC_SET", GLUSTER_CLI_GSYNC_SET, glusterd_handle_gsync_set, NULL, NULL}, + [GLUSTER_CLI_PROFILE_VOLUME] = { "STATS_VOLUME", GLUSTER_CLI_PROFILE_VOLUME, glusterd_handle_cli_profile_volume, NULL, NULL} }; struct rpcsvc_program gd_svc_cli_prog = { @@ -3621,6 +3723,7 @@ rpcsvc_actor_t glusterd1_mgmt_actors[] = { [GD_MGMT_CLI_RESET_VOLUME] = { "RESET_VOLUME", GD_MGMT_CLI_RESET_VOLUME, glusterd_handle_reset_volume, NULL, NULL}, [GD_MGMT_CLI_FSM_LOG] = { "FSM_LOG", GD_MGMT_CLI_FSM_LOG, glusterd_handle_fsm_log, NULL, NULL}, [GD_MGMT_CLI_GSYNC_SET] = {"GSYNC_SET", GD_MGMT_CLI_GSYNC_SET, glusterd_handle_gsync_set, NULL, NULL}, + [GD_MGMT_CLI_PROFILE_VOLUME] = { "STATS_VOLUME", GD_MGMT_CLI_PROFILE_VOLUME, glusterd_handle_cli_profile_volume, NULL, NULL} }; struct rpcsvc_program glusterd1_mop_prog = { diff --git a/xlators/mgmt/glusterd/src/glusterd-handshake.c b/xlators/mgmt/glusterd/src/glusterd-handshake.c index d364339a671..dda8a03bb12 100644 --- a/xlators/mgmt/glusterd/src/glusterd-handshake.c +++ b/xlators/mgmt/glusterd/src/glusterd-handshake.c @@ -418,7 +418,7 @@ glusterd_peer_handshake (xlator_t *this, struct rpc_clnt *rpc, req.gfs_id = 0xcafe; - ret = glusterd_submit_request (peerctx->peerinfo, &req, frame, + ret = glusterd_submit_request (peerctx->peerinfo->rpc, &req, frame, &glusterd_dump_prog, GF_DUMP_DUMP, NULL, xdr_from_dump_req, this, glusterd_peer_dump_version_cbk); diff --git a/xlators/mgmt/glusterd/src/glusterd-mem-types.h b/xlators/mgmt/glusterd/src/glusterd-mem-types.h index 5a4da805671..bd7b1b65fd2 100644 --- a/xlators/mgmt/glusterd/src/glusterd-mem-types.h +++ b/xlators/mgmt/glusterd/src/glusterd-mem-types.h @@ -23,7 +23,7 @@ #include "mem-types.h" -enum gf_gld_mem_types_ { +typedef enum gf_gld_mem_types_ { gf_gld_mt_dir_entry_t = gf_common_mt_end + 1, gf_gld_mt_volfile_ctx = gf_common_mt_end + 2, gf_gld_mt_glusterd_state_t = gf_common_mt_end + 3, @@ -59,8 +59,12 @@ enum gf_gld_mem_types_ { gf_gld_mt_log_locate_ctx_t = gf_common_mt_end + 33, gf_gld_mt_log_rotate_ctx_t = gf_common_mt_end + 34, gf_gld_mt_peerctx_t = gf_common_mt_end + 35, - gf_gld_mt_sm_tr_log_t = gf_common_mt_end + 36, - gf_gld_mt_end = gf_common_mt_end + 37 -}; + gf_gld_mt_sm_tr_log_t = gf_common_mt_end + 36, + gf_gld_mt_pending_node_t = gf_common_mt_end + 37, + gf_gld_mt_brick_rsp_ctx_t = gf_common_mt_end + 38, + gf_gld_mt_mop_brick_req_t = gf_common_mt_end + 39, + gf_gld_mt_op_allack_ctx_t = gf_common_mt_end + 40, + gf_gld_mt_end = gf_common_mt_end + 41 +} 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 a25f4909b10..a1bd2b43f8e 100644 --- a/xlators/mgmt/glusterd/src/glusterd-op-sm.c +++ b/xlators/mgmt/glusterd/src/glusterd-op-sm.c @@ -67,6 +67,12 @@ static char *glusterd_op_sm_state_names[] = { "Commit op sent", "Commited", "Unlock sent", + "Stage op failed", + "Commit op failed", + "Brick op sent", + "Brick op failed", + "Brick op Committed", + "Brick op Commit failed", "Invalid", }; @@ -83,6 +89,7 @@ static char *glusterd_op_sm_event_names[] = { "GD_OP_EVENT_COMMIT_OP", "GD_OP_EVENT_UNLOCK", "GD_OP_EVENT_START_UNLOCK", + "GD_OP_EVENT_ALL_ACK", "GD_OP_EVENT_INVALID" }; @@ -128,30 +135,6 @@ glusterd_destroy_lock_ctx (glusterd_op_lock_ctx_t *ctx) } void -glusterd_destroy_stage_ctx (glusterd_op_stage_ctx_t *ctx) -{ - if (!ctx) - return; - - if (ctx->dict) - dict_unref (ctx->dict); - - GF_FREE (ctx); -} - -void -glusterd_destroy_commit_ctx (glusterd_op_commit_ctx_t *ctx) -{ - if (!ctx) - return; - - if (ctx->dict) - dict_unref (ctx->dict); - - GF_FREE (ctx); -} - -void glusterd_set_volume_status (glusterd_volinfo_t *volinfo, glusterd_volume_status status) { @@ -196,6 +179,67 @@ glusterd_op_sm_inject_all_acc () return ret; } +int +glusterd_brick_op_build_payload (glusterd_op_t op, glusterd_brickinfo_t *brickinfo, + gd1_mgmt_brick_op_req **req) +{ + int ret = -1; + gd1_mgmt_brick_op_req *brick_req = NULL; + dict_t *dict = NULL; + + GF_ASSERT (op < GD_OP_MAX); + GF_ASSERT (op > GD_OP_NONE); + GF_ASSERT (req); + + dict = dict_new (); + if (!dict) + goto out; + + switch (op) { + case GD_OP_REMOVE_BRICK: + case GD_OP_STOP_VOLUME: + brick_req = GF_CALLOC (1, sizeof (*brick_req), + gf_gld_mt_mop_brick_req_t); + if (!brick_req) { + gf_log ("", GF_LOG_ERROR, "Out of Memory"); + goto out; + } + brick_req->op = GF_BRICK_TERMINATE; + brick_req->name = ""; + break; + case GD_OP_PROFILE_VOLUME: + brick_req = GF_CALLOC (1, sizeof (*brick_req), + gf_gld_mt_mop_brick_req_t); + + if (!brick_req) { + gf_log ("", GF_LOG_ERROR, "Out of Memory"); + goto out; + } + + brick_req->op = GF_BRICK_XLATOR_INFO; + brick_req->name = brickinfo->path; + break; + default: + goto out; + break; + } + + 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 (dict) + dict_unref (dict); + if (ret && brick_req) + GF_FREE (brick_req); + gf_log ("glusterd", GF_LOG_DEBUG, "Returning %d", ret); + return ret; +} + static int glusterd_op_stage_create_volume (dict_t *dict, char **op_errstr) { @@ -1897,6 +1941,90 @@ out: } static int +glusterd_op_stage_stats_volume (dict_t *dict, char **op_errstr) +{ + int ret = -1; + char *volname = NULL; + gf_boolean_t exists = _gf_false; + char msg[2048] = {0,}; + int32_t stats_op = GF_CLI_STATS_NONE; + char *latency_key = NULL; + char *fd_stats_key = NULL; + char *value = NULL; + gf_boolean_t enabled = _gf_false; + glusterd_volinfo_t *volinfo = NULL; + + latency_key = "diagnostics.latency-measurement"; + fd_stats_key = "diagnostics.dump-fd-stats"; + + ret = dict_get_str (dict, "volname", &volname); + if (ret) { + gf_log ("glusterd", GF_LOG_ERROR, "volume name get failed"); + goto out; + } + + exists = glusterd_check_volume_exists (volname); + ret = glusterd_volinfo_find (volname, &volinfo); + if ((!exists) || (ret < 0)) { + snprintf (msg, sizeof (msg), "volume %s, " + "doesn't exist", volname); + gf_log ("glusterd", GF_LOG_ERROR, "%s", msg); + *op_errstr = gf_strdup (msg); + ret = -1; + goto out; + } + + ret = dict_get_int32 (dict, "op", &stats_op); + if (ret) { + gf_log ("glusterd", GF_LOG_ERROR, "volume profile op get failed"); + goto out; + } + + if (GF_CLI_STATS_INFO == stats_op) { + if (glusterd_is_volume_started (volinfo)) { + snprintf (msg, sizeof (msg), "volume %s is not started.", + volinfo->volname); + gf_log ("glusterd", GF_LOG_ERROR, "%s", msg); + *op_errstr = gf_strdup (msg); + ret = -1; + goto out; + } + + ret = dict_get_str (volinfo->dict, latency_key, &value); + if (value) { + ret = gf_string2boolean (value, &enabled); + } + if (ret || (_gf_false == enabled)) { + snprintf (msg, sizeof (msg), "Profiling is not enabled for " + "volume %s", volinfo->volname); + gf_log ("glusterd", GF_LOG_ERROR, "%s", msg); + *op_errstr = gf_strdup (msg); + ret = -1; + goto out; + } + enabled = _gf_false; + value = NULL; + ret = dict_get_str (volinfo->dict, fd_stats_key, &value); + if (value) { + ret = gf_string2boolean (value, &enabled); + } + if (ret || (_gf_false == enabled)) { + snprintf (msg, sizeof (msg), "Profiling is not enabled for " + "volume %s", volinfo->volname); + gf_log ("glusterd", GF_LOG_ERROR, "%s", msg); + *op_errstr = gf_strdup (msg); + ret = -1; + goto out; + } + } + +out: + gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); + + return ret; +} + +static int glusterd_op_create_volume (dict_t *dict, char **op_errstr) { int ret = 0; @@ -4541,10 +4669,8 @@ glusterd_op_sync_volume (dict_t *dict, char **op_errstr, if (!ret) { 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); + gf_log ("", GF_LOG_ERROR, "Volume with name: %s " + "not exists", volname); goto out; } } @@ -4578,6 +4704,156 @@ out: } static int +glusterd_op_stats_volume (dict_t *dict, char **op_errstr, + dict_t *rsp_dict) +{ + int ret = -1; + char *volname = NULL; + char msg[2048] = {0,}; + glusterd_conf_t *priv = NULL; + glusterd_volinfo_t *volinfo = NULL; + xlator_t *this = NULL; + int32_t stats_op = GF_CLI_STATS_NONE; + char *fd_stats_value = NULL; + char *latency_value = NULL; + char *latency_key = NULL; + char *fd_stats_key = NULL; + char *key_found = NULL; + int exists = 0; + + this = THIS; + GF_ASSERT (this); + priv = this->private; + GF_ASSERT (priv); + + latency_key = "diagnostics.latency-measurement"; + fd_stats_key = "diagnostics.dump-fd-stats"; + + ret = dict_get_str (dict, "volname", &volname); + if (ret) { + gf_log ("glusterd", GF_LOG_ERROR, "volume name get failed"); + goto out; + } + + ret = glusterd_volinfo_find (volname, &volinfo); + if (ret) { + snprintf (msg, sizeof (msg), "Volume %s does not exists", + volname); + + gf_log ("", GF_LOG_ERROR, "%s", msg); + goto out; + } + + ret = dict_get_int32 (dict, "op", &stats_op); + if (ret) { + gf_log ("glusterd", GF_LOG_ERROR, "volume profile op get failed"); + goto out; + } + + exists = glusterd_check_option_exists (latency_key, &key_found); + if (key_found) + GF_FREE (key_found); + if (!exists) { + snprintf (msg, sizeof (msg), "Volume Option %s does not exist", + latency_key); + gf_log ("glusterd", GF_LOG_ERROR, "%s", msg); + *op_errstr = gf_strdup (msg); + ret = -1; + goto out; + } + + exists = glusterd_check_option_exists (fd_stats_key, &key_found); + if (key_found) + GF_FREE (key_found); + if (!exists) { + snprintf (msg, sizeof (msg), "Volume Option %s does not exist", + fd_stats_key); + gf_log ("glusterd", GF_LOG_ERROR, "%s", msg); + *op_errstr = gf_strdup (msg); + ret = -1; + goto out; + } + + switch (stats_op) { + case GF_CLI_STATS_START: + fd_stats_value = gf_strdup ("on"); + latency_value = gf_strdup ("on"); + break; + case GF_CLI_STATS_STOP: + fd_stats_value = gf_strdup ("off"); + latency_value = gf_strdup ("off"); + break; + case GF_CLI_STATS_INFO: + //info is already collected in brick op. + //just goto out; + ret = 0; + goto out; + break; + default: + GF_ASSERT (0); + gf_log ("glusterd", GF_LOG_ERROR, "Invalid profile op: %d", + stats_op); + ret = -1; + goto out; + break; + } + + if (!fd_stats_value || !latency_value) { + ret = -1; + gf_log ("glusterd", GF_LOG_ERROR, "Out of memory"); + goto out; + } + + ret = dict_set_dynstr (volinfo->dict, latency_key, latency_value); + if (ret) { + gf_log ("glusterd", GF_LOG_ERROR, "failed to set the volume %s " + + + "option %s value %s", + volinfo->volname, latency_key, latency_value); + goto out; + } + + ret = dict_set_dynstr (volinfo->dict, fd_stats_key, fd_stats_value); + if (ret) { + gf_log ("glusterd", GF_LOG_ERROR, "failed to set the volume %s " + "option %s value %s", + volinfo->volname, fd_stats_key, fd_stats_value); + goto out; + } + ret = glusterd_create_volfiles (volinfo); + + if (ret) { + gf_log ("", GF_LOG_ERROR, "Unable to create volfile for" + " 'volume set'"); + ret = -1; + goto out; + } + + ret = glusterd_store_update_volume (volinfo); + if (ret) + goto out; + + ret = glusterd_volume_compute_cksum (volinfo); + if (ret) + goto out; + + if (GLUSTERD_STATUS_STARTED == volinfo->status) + ret = glusterd_check_generate_start_nfs (volinfo); + + ret = 0; + +out: + if (ret && fd_stats_value) + GF_FREE (fd_stats_value); + if (ret && latency_value) + GF_FREE (latency_value); + gf_log ("", 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; @@ -4729,9 +5005,10 @@ glusterd_op_ac_rcvd_lock_acc (glusterd_op_sm_event_t *event, void *ctx) GF_ASSERT (event); - opinfo.pending_count--; + if (opinfo.pending_count > 0) + opinfo.pending_count--; - if (opinfo.pending_count) + if (opinfo.pending_count > 0) goto out; ret = glusterd_op_sm_inject_event (GD_OP_EVENT_ALL_ACC, NULL); @@ -4798,6 +5075,7 @@ glusterd_op_build_payload (glusterd_op_t op, dict_t **req) case GD_OP_LOG_ROTATE: case GD_OP_SYNC_VOLUME: case GD_OP_GSYNC_SET: + case GD_OP_PROFILE_VOLUME: { dict_t *dict = ctx; dict_copy (dict, req_dict); @@ -5046,9 +5324,10 @@ glusterd_op_ac_rcvd_stage_op_acc (glusterd_op_sm_event_t *event, void *ctx) GF_ASSERT (event); - opinfo.pending_count--; + if (opinfo.pending_count > 0) + opinfo.pending_count--; - if (opinfo.pending_count) + if (opinfo.pending_count > 0) goto out; ret = glusterd_op_sm_inject_event (GD_OP_EVENT_STAGE_ACC, NULL); @@ -5059,6 +5338,118 @@ out: return ret; } +static int +glusterd_op_ac_stage_op_failed (glusterd_op_sm_event_t *event, void *ctx) +{ + int ret = 0; + + GF_ASSERT (event); + + if (opinfo.pending_count > 0) + opinfo.pending_count--; + + if (opinfo.pending_count > 0) + goto out; + + ret = glusterd_op_sm_inject_event (GD_OP_EVENT_ALL_ACK, NULL); + +out: + gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); + + return ret; +} + +static int +glusterd_op_ac_commit_op_failed (glusterd_op_sm_event_t *event, void *ctx) +{ + int ret = 0; + + GF_ASSERT (event); + + if (opinfo.pending_count > 0) + opinfo.pending_count--; + + if (opinfo.pending_count > 0) + goto out; + + ret = glusterd_op_sm_inject_event (GD_OP_EVENT_ALL_ACK, NULL); + +out: + gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); + + return ret; +} + +static int +glusterd_op_ac_brick_op_failed (glusterd_op_sm_event_t *event, void *ctx) +{ + int ret = 0; + glusterd_op_brick_rsp_ctx_t *ev_ctx = NULL; + glusterd_brickinfo_t *brickinfo = NULL; + gf_boolean_t free_errstr = _gf_false; + + GF_ASSERT (event); + GF_ASSERT (ctx); + ev_ctx = ctx; + brickinfo = ev_ctx->brickinfo; + GF_ASSERT (brickinfo); + + ret = glusterd_remove_pending_entry (&opinfo.pending_bricks, brickinfo); + if (ret) { + gf_log ("glusterd", GF_LOG_ERROR, "unknown response received " + "from %s:%s", brickinfo->hostname, brickinfo->path); + ret = -1; + free_errstr = _gf_true; + goto out; + } + if (opinfo.brick_pending_count > 0) + opinfo.brick_pending_count--; + if (opinfo.op_ret == 0) + opinfo.op_ret = ev_ctx->op_ret; + + if (opinfo.op_errstr == NULL) + opinfo.op_errstr = ev_ctx->op_errstr; + else + free_errstr = _gf_true; + + if (opinfo.brick_pending_count > 0) + goto out; + + ret = glusterd_op_sm_inject_event (GD_OP_EVENT_ALL_ACK, ev_ctx->commit_ctx); + +out: + if (ev_ctx->rsp_dict) + dict_unref (ev_ctx->rsp_dict); + if (free_errstr && ev_ctx->op_errstr) + GF_FREE (ev_ctx->op_errstr); + GF_FREE (ctx); + gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); + + return ret; +} + +void +glusterd_op_brick_disconnect (void *data) +{ + glusterd_brickinfo_t *brickinfo = NULL; + glusterd_op_brick_rsp_ctx_t *ev_ctx = NULL; + + ev_ctx = data; + GF_ASSERT (ev_ctx); + brickinfo = ev_ctx->brickinfo; + GF_ASSERT (brickinfo); + + if (brickinfo->timer) { + gf_timer_call_cancel (THIS->ctx, brickinfo->timer); + brickinfo->timer = NULL; + gf_log ("", GF_LOG_DEBUG, + "Cancelled timer thread"); + } + + glusterd_op_sm_inject_event (GD_OP_EVENT_RCVD_ACC, ev_ctx); + glusterd_op_sm (); +} + void glusterd_do_replace_brick (void *data) { @@ -5210,9 +5601,10 @@ glusterd_op_ac_rcvd_commit_op_acc (glusterd_op_sm_event_t *event, void *ctx) priv = THIS->private; GF_ASSERT (event); - opinfo.pending_count--; + if (opinfo.pending_count > 0) + opinfo.pending_count--; - if (opinfo.pending_count) + if (opinfo.pending_count > 0) goto out; dict = glusterd_op_get_ctx (GD_OP_REPLACE_BRICK); @@ -5243,9 +5635,10 @@ glusterd_op_ac_rcvd_unlock_acc (glusterd_op_sm_event_t *event, void *ctx) GF_ASSERT (event); - opinfo.pending_count--; + if (opinfo.pending_count > 0) + opinfo.pending_count--; - if (opinfo.pending_count) + if (opinfo.pending_count > 0) goto out; ret = glusterd_op_sm_inject_event (GD_OP_EVENT_ALL_ACC, NULL); @@ -5352,23 +5745,10 @@ glusterd_op_ac_unlocked_all (glusterd_op_sm_event_t *event, void *ctx) static int -glusterd_op_ac_commit_error (glusterd_op_sm_event_t *event, void *ctx) -{ - int ret = 0; - - //Log here with who failed the commit - // - - ret = glusterd_op_sm_inject_event (GD_OP_EVENT_START_UNLOCK, NULL); - - return ret; -} - -static int glusterd_op_ac_stage_op (glusterd_op_sm_event_t *event, void *ctx) { int ret = -1; - glusterd_op_stage_ctx_t *stage_ctx = NULL; + glusterd_req_ctx_t *req_ctx = NULL; int32_t status = 0; dict_t *rsp_dict = NULL; char *op_errstr = NULL; @@ -5376,9 +5756,9 @@ glusterd_op_ac_stage_op (glusterd_op_sm_event_t *event, void *ctx) GF_ASSERT (ctx); - stage_ctx = ctx; + req_ctx = ctx; - dict = stage_ctx->dict; + dict = req_ctx->dict; rsp_dict = dict_new (); if (!rsp_dict) { @@ -5387,14 +5767,14 @@ glusterd_op_ac_stage_op (glusterd_op_sm_event_t *event, void *ctx) return -1; } - status = glusterd_op_stage_validate (stage_ctx->op, dict, &op_errstr, + status = glusterd_op_stage_validate (req_ctx->op, dict, &op_errstr, rsp_dict); if (status) { gf_log ("", GF_LOG_ERROR, "Validate failed: %d", status); } - ret = glusterd_op_stage_send_resp (stage_ctx->req, stage_ctx->op, + ret = glusterd_op_stage_send_resp (req_ctx->req, req_ctx->op, status, op_errstr, rsp_dict); if (op_errstr && (strcmp (op_errstr, ""))) @@ -5412,39 +5792,30 @@ static int glusterd_op_ac_commit_op (glusterd_op_sm_event_t *event, void *ctx) { int ret = 0; - glusterd_op_commit_ctx_t *commit_ctx = NULL; + glusterd_req_ctx_t *req_ctx = NULL; int32_t status = 0; char *op_errstr = NULL; - dict_t *rsp_dict = NULL; + dict_t *op_ctx = NULL; dict_t *dict = NULL; GF_ASSERT (ctx); - commit_ctx = ctx; + req_ctx = ctx; - dict = commit_ctx->dict; + dict = req_ctx->dict; - rsp_dict = dict_new (); - if (!rsp_dict) { - gf_log ("", GF_LOG_DEBUG, - "Out of memory"); - ret = -1; - goto out; - } - - status = glusterd_op_commit_perform (commit_ctx->op, dict, &op_errstr, - rsp_dict); + op_ctx = glusterd_op_get_ctx (req_ctx->op); + status = glusterd_op_commit_perform (req_ctx->op, dict, &op_errstr, + op_ctx); if (status) { gf_log ("", GF_LOG_ERROR, "Commit failed: %d", status); } - ret = glusterd_op_commit_send_resp (commit_ctx->req, commit_ctx->op, - status, op_errstr, rsp_dict); + ret = glusterd_op_commit_send_resp (req_ctx->req, req_ctx->op, + status, op_errstr, op_ctx); -out: - if (rsp_dict) - dict_unref (rsp_dict); + glusterd_op_fini_ctx (req_ctx->op); if (op_errstr && (strcmp (op_errstr, ""))) GF_FREE (op_errstr); @@ -5453,6 +5824,32 @@ out: return ret; } +static int +glusterd_op_ac_send_commit_failed (glusterd_op_sm_event_t *event, void *ctx) +{ + int ret = 0; + glusterd_req_ctx_t *req_ctx = NULL; + dict_t *op_ctx = NULL; + + GF_ASSERT (ctx); + + req_ctx = ctx; + + op_ctx = glusterd_op_get_ctx (req_ctx->op); + + ret = glusterd_op_commit_send_resp (req_ctx->req, req_ctx->op, + opinfo.op_ret, opinfo.op_errstr, + op_ctx); + + glusterd_op_fini_ctx (req_ctx->op); + if (opinfo.op_errstr && (strcmp (opinfo.op_errstr, ""))) { + GF_FREE (opinfo.op_errstr); + opinfo.op_errstr = NULL; + } + + gf_log ("", GF_LOG_DEBUG, "Returning with %d", ret); + return ret; +} static int glusterd_op_sm_transition_state (glusterd_op_info_t *opinfo, @@ -5536,6 +5933,11 @@ glusterd_op_stage_validate (glusterd_op_t op, dict_t *dict, char **op_errstr, ret = glusterd_op_stage_gsync_set (dict, op_errstr); break; + case GD_OP_PROFILE_VOLUME: + ret = glusterd_op_stage_stats_volume (dict, op_errstr); + break; + + default: gf_log ("", GF_LOG_ERROR, "Unknown op %d", op); @@ -5606,11 +6008,419 @@ glusterd_op_commit_perform (glusterd_op_t op, dict_t *dict, char **op_errstr, ret = glusterd_op_gsync_set (dict); break; + case GD_OP_PROFILE_VOLUME: + ret = glusterd_op_stats_volume (dict, op_errstr, + rsp_dict); + break; + default: gf_log ("", GF_LOG_ERROR, "Unknown op %d", op); + break; + } + + gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); + + return ret; +} + +void +_profile_volume_add_brick_rsp (dict_t *this, char *key, data_t *value, + void *data) +{ + char new_key[256] = {0}; + glusterd_pr_brick_rsp_conv_t *rsp_ctx = NULL; + data_t *new_value = NULL; + + rsp_ctx = data; + new_value = data_copy (value); + GF_ASSERT (new_value); + snprintf (new_key, sizeof (new_key), "%d-%s", rsp_ctx->count, key); + dict_set (rsp_ctx->dict, new_key, new_value); +} + +int +glusterd_profile_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; + char brick[PATH_MAX+1024] = {0}; + char key[256] = {0}; + char *full_brick = NULL; + + 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 = 1; + } else { + count++; + } + snprintf (key, sizeof (key), "%d-brick", count); + snprintf (brick, sizeof (brick), "%s:%s", brickinfo->hostname, + brickinfo->path); + full_brick = gf_strdup (brick); + GF_ASSERT (full_brick); + ret = dict_set_dynstr (op_ctx, key, full_brick); + + rsp_ctx.count = count; + rsp_ctx.dict = op_ctx; + dict_foreach (rsp_dict, _profile_volume_add_brick_rsp, &rsp_ctx); + dict_del (op_ctx, "count"); + ret = dict_set_int32 (op_ctx, "count", count); + return ret; +} + +int32_t +glusterd_handle_brick_rsp (glusterd_brickinfo_t *brickinfo, + glusterd_op_t op, dict_t *rsp_dict, dict_t *op_ctx, + char **op_errstr) +{ + int ret = 0; + + GF_ASSERT (op_errstr); + + switch (op) { + case GD_OP_PROFILE_VOLUME: + ret = glusterd_profile_volume_brick_rsp (brickinfo, rsp_dict, + op_ctx, op_errstr); + break; + + default: + break; + } + + gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); + return ret; +} + +static int +glusterd_bricks_select_stop_volume (dict_t *dict, char **op_errstr) +{ + int ret = 0; + int flags = 0; + char *volname = NULL; + glusterd_volinfo_t *volinfo = NULL; + glusterd_brickinfo_t *brickinfo = NULL; + glusterd_pending_node_t *pending_node = NULL; + + ret = glusterd_op_stop_volume_args_get (dict, &volname, &flags); + if (ret) + goto out; + + ret = glusterd_volinfo_find (volname, &volinfo); + + if (ret) + 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), + gf_gld_mt_pending_node_t); + if (!pending_node) { + ret = -1; + goto out; + } else { + pending_node->node = brickinfo; + list_add_tail (&pending_node->list, &opinfo.pending_bricks); + pending_node = NULL; + } + } + } + +out: + return ret; +} + +static int +glusterd_bricks_select_remove_brick (dict_t *dict, char **op_errstr) +{ + int ret = -1; + char *volname = NULL; + glusterd_volinfo_t *volinfo = NULL; + glusterd_brickinfo_t *brickinfo = NULL; + char *brick = NULL; + int32_t count = 0; + int32_t i = 1; + char key[256] = {0,}; + glusterd_pending_node_t *pending_node = NULL; + + ret = dict_get_str (dict, "volname", &volname); + + if (ret) { + gf_log ("", GF_LOG_ERROR, "Unable to get volume name"); + goto out; + } + + ret = glusterd_volinfo_find (volname, &volinfo); + + if (ret) { + gf_log ("", GF_LOG_ERROR, "Unable to allocate memory"); + goto out; + } + + ret = dict_get_int32 (dict, "count", &count); + if (ret) { + gf_log ("", GF_LOG_ERROR, "Unable to get count"); + goto out; + } + + + while ( i <= count) { + snprintf (key, 256, "brick%d", i); + ret = dict_get_str (dict, key, &brick); + if (ret) { + gf_log ("glusterd", GF_LOG_ERROR, "Unable to get brick"); + goto out; + } + + ret = glusterd_volume_brickinfo_get_by_brick (brick, volinfo, + &brickinfo); + if (ret) + goto out; + if (!glusterd_is_brick_started (brickinfo)) { + pending_node = GF_CALLOC (1, sizeof (*pending_node), + gf_gld_mt_pending_node_t); + if (!pending_node) { + ret = -1; + goto out; + } else { + pending_node->node = brickinfo; + list_add_tail (&pending_node->list, &opinfo.pending_bricks); + pending_node = NULL; + } + } + i++; + } + +out: + return ret; +} + +static int +glusterd_bricks_select_profile_volume (dict_t *dict, char **op_errstr) +{ + int ret = -1; + char *volname = NULL; + char msg[2048] = {0,}; + glusterd_conf_t *priv = NULL; + glusterd_volinfo_t *volinfo = NULL; + xlator_t *this = NULL; + int32_t stats_op = GF_CLI_STATS_NONE; + glusterd_brickinfo_t *brickinfo = NULL; + glusterd_pending_node_t *pending_node = NULL; + + this = THIS; + GF_ASSERT (this); + priv = this->private; + GF_ASSERT (priv); + + ret = dict_get_str (dict, "volname", &volname); + if (ret) { + gf_log ("glusterd", GF_LOG_ERROR, "volume name get failed"); + goto out; + } + + ret = glusterd_volinfo_find (volname, &volinfo); + if (ret) { + snprintf (msg, sizeof (msg), "Volume %s does not exists", + volname); + + gf_log ("", GF_LOG_ERROR, "%s", msg); + goto out; + } + + ret = dict_get_int32 (dict, "op", &stats_op); + if (ret) { + gf_log ("glusterd", GF_LOG_ERROR, "volume profile op get failed"); + goto out; + } + + switch (stats_op) { + case GF_CLI_STATS_START: + case GF_CLI_STATS_STOP: + goto out; + break; + case GF_CLI_STATS_INFO: + list_for_each_entry (brickinfo, &volinfo->bricks, brick_list) { + if (!glusterd_is_brick_started (brickinfo)) { + pending_node = GF_CALLOC (1, sizeof (*pending_node), + gf_gld_mt_pending_node_t); + if (!pending_node) { + ret = -1; + goto out; + } else { + pending_node->node = brickinfo; + list_add_tail (&pending_node->list, + &opinfo.pending_bricks); + pending_node = NULL; + } + } + } + break; + default: + GF_ASSERT (0); + gf_log ("glusterd", GF_LOG_ERROR, "Invalid profile op: %d", + stats_op); + ret = -1; + goto out; + break; } + +out: + gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); + + return ret; +} + +static int +glusterd_op_ac_send_brick_op (glusterd_op_sm_event_t *event, void *ctx) +{ + int ret = 0; + rpc_clnt_procedure_t *proc = NULL; + glusterd_conf_t *priv = NULL; + xlator_t *this = NULL; + glusterd_op_t op = GD_OP_NONE; + glusterd_req_ctx_t *req_ctx = NULL; + + this = THIS; + priv = this->private; + + if (ctx) { + req_ctx = ctx; + } else { + req_ctx = GF_CALLOC (1, sizeof (*req_ctx), + gf_gld_mt_op_allack_ctx_t); + op = glusterd_op_get_op (); + req_ctx->op = op; + uuid_copy (req_ctx->uuid, priv->uuid); + ret = glusterd_op_build_payload (op, &req_ctx->dict); + if (ret)//TODO:what to do?? + goto out; + } + + proc = &priv->gfs_mgmt->proctable[GD_MGMT_BRICK_OP]; + if (proc->fn) { + ret = proc->fn (NULL, this, req_ctx); + if (ret) + goto out; + } + + if (!opinfo.pending_count && !opinfo.brick_pending_count) { + glusterd_clear_pending_nodes (&opinfo.pending_bricks); + ret = glusterd_op_sm_inject_event (GD_OP_EVENT_ALL_ACK, req_ctx); + } + +out: + gf_log ("", GF_LOG_DEBUG, "Returning with %d", ret); + + return ret; +} + + +static int +glusterd_op_ac_rcvd_brick_op_acc (glusterd_op_sm_event_t *event, void *ctx) +{ + int ret = 0; + glusterd_op_brick_rsp_ctx_t *ev_ctx = NULL; + glusterd_brickinfo_t *brickinfo = NULL; + char *op_errstr = NULL; + glusterd_op_t op = GD_OP_NONE; + dict_t *op_ctx = NULL; + gf_boolean_t free_errstr = _gf_true; + glusterd_req_ctx_t *req_ctx = NULL; + + GF_ASSERT (event); + GF_ASSERT (ctx); + ev_ctx = ctx; + + req_ctx = ev_ctx->commit_ctx; + GF_ASSERT (req_ctx); + + brickinfo = ev_ctx->brickinfo; + GF_ASSERT (brickinfo); + + ret = glusterd_remove_pending_entry (&opinfo.pending_bricks, brickinfo); + if (ret) { + gf_log ("glusterd", GF_LOG_ERROR, "unknown response received " + "from %s:%s", brickinfo->hostname, brickinfo->path); + ret = -1; + free_errstr = _gf_true; + goto out; + } + + if (opinfo.brick_pending_count > 0) + opinfo.brick_pending_count--; + op = req_ctx->op; + op_ctx = glusterd_op_get_ctx (op); + + glusterd_handle_brick_rsp (brickinfo, op, ev_ctx->rsp_dict, + op_ctx, &op_errstr); + if (opinfo.brick_pending_count > 0) + goto out; + + ret = glusterd_op_sm_inject_event (GD_OP_EVENT_ALL_ACK, ev_ctx->commit_ctx); + +out: + if (ev_ctx->rsp_dict) + dict_unref (ev_ctx->rsp_dict); + GF_FREE (ev_ctx); + gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); + + return ret; +} + +int32_t +glusterd_op_bricks_select (glusterd_op_t op, dict_t *dict, char **op_errstr) +{ + int ret = 0; + + GF_ASSERT (dict); + GF_ASSERT (op_errstr); + + switch (op) { + case GD_OP_CREATE_VOLUME: + case GD_OP_START_BRICK: + case GD_OP_STOP_BRICK: + case GD_OP_DELETE_VOLUME: + case GD_OP_START_VOLUME: + case GD_OP_RENAME_VOLUME: + case GD_OP_DEFRAG_VOLUME: + case GD_OP_ADD_BRICK: + case GD_OP_REPLACE_BRICK: + case GD_OP_SET_VOLUME: + case GD_OP_RESET_VOLUME: + case GD_OP_SYNC_VOLUME: + case GD_OP_LOG_FILENAME: + case GD_OP_LOG_LOCATE: + case GD_OP_LOG_ROTATE: + //nothing to be done + break; + case GD_OP_STOP_VOLUME: + ret = glusterd_bricks_select_stop_volume (dict, op_errstr); + break; + + case GD_OP_REMOVE_BRICK: + ret = glusterd_bricks_select_remove_brick (dict, op_errstr); + break; + + case GD_OP_PROFILE_VOLUME: + ret = glusterd_bricks_select_profile_volume (dict, op_errstr); + break; + + default: + gf_log ("", GF_LOG_ERROR, "Unknown op %d", op); + ret = -1; + break; + } + gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); return ret; @@ -5629,6 +6439,7 @@ glusterd_op_sm_t glusterd_op_state_default [] = { {GD_OP_STATE_DEFAULT, glusterd_op_ac_none}, //EVENT_COMMIT_OP {GD_OP_STATE_DEFAULT, glusterd_op_ac_unlock}, //EVENT_UNLOCK {GD_OP_STATE_DEFAULT, glusterd_op_ac_none}, //EVENT_START_UNLOCK + {GD_OP_STATE_DEFAULT, glusterd_op_ac_none}, //EVENT_ALL_ACK {GD_OP_STATE_DEFAULT, glusterd_op_ac_none}, //EVENT_MAX }; @@ -5645,6 +6456,7 @@ glusterd_op_sm_t glusterd_op_state_lock_sent [] = { {GD_OP_STATE_LOCK_SENT, glusterd_op_ac_none}, //EVENT_COMMIT_OP {GD_OP_STATE_DEFAULT, glusterd_op_ac_unlock}, //EVENT_UNLOCK {GD_OP_STATE_LOCK_SENT, glusterd_op_ac_none}, //EVENT_START_UNLOCK + {GD_OP_STATE_LOCK_SENT, glusterd_op_ac_none}, //EVENT_ALL_ACK {GD_OP_STATE_LOCK_SENT, glusterd_op_ac_none}, //EVENT_MAX }; @@ -5661,6 +6473,7 @@ glusterd_op_sm_t glusterd_op_state_locked [] = { {GD_OP_STATE_LOCKED, glusterd_op_ac_none}, //EVENT_COMMIT_OP {GD_OP_STATE_DEFAULT, glusterd_op_ac_unlock}, //EVENT_UNLOCK {GD_OP_STATE_LOCKED, glusterd_op_ac_none}, //EVENT_START_UNLOCK + {GD_OP_STATE_LOCKED, glusterd_op_ac_none}, //EVENT_ALL_ACK {GD_OP_STATE_LOCKED, glusterd_op_ac_none}, //EVENT_MAX }; @@ -5669,17 +6482,35 @@ glusterd_op_sm_t glusterd_op_state_stage_op_sent [] = { {GD_OP_STATE_STAGE_OP_SENT, glusterd_op_ac_none},//EVENT_START_LOCK {GD_OP_STATE_STAGE_OP_SENT, glusterd_op_ac_none}, //EVENT_LOCK {GD_OP_STATE_STAGE_OP_SENT, glusterd_op_ac_rcvd_stage_op_acc}, //EVENT_RCVD_ACC - {GD_OP_STATE_STAGE_OP_SENT, glusterd_op_ac_send_stage_op}, //EVENT_ALL_ACC - {GD_OP_STATE_COMMIT_OP_SENT, glusterd_op_ac_send_commit_op}, //EVENT_STAGE_ACC + {GD_OP_STATE_BRICK_OP_SENT, glusterd_op_ac_send_brick_op}, //EVENT_ALL_ACC + {GD_OP_STATE_BRICK_OP_SENT, glusterd_op_ac_send_brick_op}, //EVENT_STAGE_ACC {GD_OP_STATE_STAGE_OP_SENT, glusterd_op_ac_none}, //EVENT_COMMIT_ACC - {GD_OP_STATE_UNLOCK_SENT, glusterd_op_ac_send_unlock}, //EVENT_RCVD_RJT + {GD_OP_STATE_STAGE_OP_FAILED, glusterd_op_ac_stage_op_failed}, //EVENT_RCVD_RJT {GD_OP_STATE_STAGE_OP_SENT, glusterd_op_ac_none}, //EVENT_STAGE_OP {GD_OP_STATE_STAGE_OP_SENT, glusterd_op_ac_none}, //EVENT_COMMIT_OP - {GD_OP_STATE_STAGE_OP_SENT, glusterd_op_ac_unlock}, //EVENT_UNLOCK + {GD_OP_STATE_DEFAULT, glusterd_op_ac_unlock}, //EVENT_UNLOCK {GD_OP_STATE_STAGE_OP_SENT, glusterd_op_ac_none}, //EVENT_START_UNLOCK + {GD_OP_STATE_STAGE_OP_SENT, glusterd_op_ac_none}, //EVENT_ALL_ACK {GD_OP_STATE_STAGE_OP_SENT, glusterd_op_ac_none}, //EVENT_MAX }; +glusterd_op_sm_t glusterd_op_state_stage_op_failed [] = { + {GD_OP_STATE_STAGE_OP_FAILED, glusterd_op_ac_none}, //EVENT_NONE + {GD_OP_STATE_STAGE_OP_FAILED, glusterd_op_ac_none},//EVENT_START_LOCK + {GD_OP_STATE_STAGE_OP_FAILED, glusterd_op_ac_none}, //EVENT_LOCK + {GD_OP_STATE_STAGE_OP_FAILED, glusterd_op_ac_stage_op_failed}, //EVENT_RCVD_ACC + {GD_OP_STATE_STAGE_OP_FAILED, glusterd_op_ac_none}, //EVENT_ALL_ACC + {GD_OP_STATE_STAGE_OP_FAILED, glusterd_op_ac_none}, //EVENT_STAGE_ACC + {GD_OP_STATE_STAGE_OP_FAILED, glusterd_op_ac_none}, //EVENT_COMMIT_ACC + {GD_OP_STATE_STAGE_OP_FAILED, glusterd_op_ac_stage_op_failed}, //EVENT_RCVD_RJT + {GD_OP_STATE_STAGE_OP_FAILED, glusterd_op_ac_none}, //EVENT_STAGE_OP + {GD_OP_STATE_STAGE_OP_FAILED, glusterd_op_ac_none}, //EVENT_COMMIT_OP + {GD_OP_STATE_DEFAULT, glusterd_op_ac_unlock}, //EVENT_UNLOCK + {GD_OP_STATE_STAGE_OP_FAILED, glusterd_op_ac_none}, //EVENT_START_UNLOCK + {GD_OP_STATE_UNLOCK_SENT, glusterd_op_ac_send_unlock}, //EVENT_ALL_ACK + {GD_OP_STATE_STAGE_OP_FAILED, glusterd_op_ac_none}, //EVENT_MAX +}; + glusterd_op_sm_t glusterd_op_state_staged [] = { {GD_OP_STATE_STAGED, glusterd_op_ac_none}, //EVENT_NONE {GD_OP_STATE_STAGED, glusterd_op_ac_none},//EVENT_START_LOCK @@ -5690,12 +6521,98 @@ glusterd_op_sm_t glusterd_op_state_staged [] = { {GD_OP_STATE_STAGED, glusterd_op_ac_none}, //EVENT_COMMIT_ACC {GD_OP_STATE_STAGED, glusterd_op_ac_none}, //EVENT_RCVD_RJT {GD_OP_STATE_STAGED, glusterd_op_ac_none}, //EVENT_STAGE_OP - {GD_OP_STATE_COMMITED, glusterd_op_ac_commit_op}, //EVENT_COMMIT_OP + {GD_OP_STATE_BRICK_COMMITTED, glusterd_op_ac_send_brick_op}, //EVENT_COMMIT_OP {GD_OP_STATE_DEFAULT, glusterd_op_ac_unlock}, //EVENT_UNLOCK {GD_OP_STATE_STAGED, glusterd_op_ac_none}, //EVENT_START_UNLOCK + {GD_OP_STATE_STAGED, glusterd_op_ac_none}, //EVENT_ALL_ACK {GD_OP_STATE_STAGED, glusterd_op_ac_none}, //EVENT_MAX }; +glusterd_op_sm_t glusterd_op_state_brick_op_sent [] = { + {GD_OP_STATE_BRICK_OP_SENT, glusterd_op_ac_none}, //EVENT_NONE + {GD_OP_STATE_BRICK_OP_SENT, glusterd_op_ac_none},//EVENT_START_LOCK + {GD_OP_STATE_BRICK_OP_SENT, glusterd_op_ac_none}, //EVENT_LOCK + {GD_OP_STATE_BRICK_OP_SENT, glusterd_op_ac_rcvd_brick_op_acc}, //EVENT_RCVD_ACC + {GD_OP_STATE_BRICK_OP_SENT, glusterd_op_ac_none}, //EVENT_ALL_ACC + {GD_OP_STATE_BRICK_OP_SENT, glusterd_op_ac_none}, //EVENT_STAGE_ACC + {GD_OP_STATE_BRICK_OP_SENT, glusterd_op_ac_none}, //EVENT_COMMIT_ACC + {GD_OP_STATE_BRICK_OP_FAILED, glusterd_op_ac_brick_op_failed}, //EVENT_RCVD_RJT + {GD_OP_STATE_BRICK_OP_SENT, glusterd_op_ac_none}, //EVENT_BRICK_OP + {GD_OP_STATE_BRICK_OP_SENT, glusterd_op_ac_none}, //EVENT_COMMIT_OP + {GD_OP_STATE_DEFAULT, glusterd_op_ac_unlock}, //EVENT_UNLOCK + {GD_OP_STATE_BRICK_OP_SENT, glusterd_op_ac_none}, //EVENT_START_UNLOCK + {GD_OP_STATE_COMMIT_OP_SENT, glusterd_op_ac_send_commit_op}, //EVENT_ALL_ACK + {GD_OP_STATE_BRICK_OP_SENT, glusterd_op_ac_none}, //EVENT_MAX +}; + +glusterd_op_sm_t glusterd_op_state_brick_op_failed [] = { + {GD_OP_STATE_BRICK_OP_FAILED, glusterd_op_ac_none}, //EVENT_NONE + {GD_OP_STATE_BRICK_OP_FAILED, glusterd_op_ac_none},//EVENT_START_LOCK + {GD_OP_STATE_BRICK_OP_FAILED, glusterd_op_ac_none}, //EVENT_LOCK + {GD_OP_STATE_BRICK_OP_FAILED, glusterd_op_ac_brick_op_failed}, //EVENT_RCVD_ACC + {GD_OP_STATE_BRICK_OP_FAILED, glusterd_op_ac_none}, //EVENT_ALL_ACC + {GD_OP_STATE_BRICK_OP_FAILED, glusterd_op_ac_none}, //EVENT_STAGE_ACC + {GD_OP_STATE_BRICK_OP_FAILED, glusterd_op_ac_none}, //EVENT_COMMIT_ACC + {GD_OP_STATE_BRICK_OP_FAILED, glusterd_op_ac_brick_op_failed}, //EVENT_RCVD_RJT + {GD_OP_STATE_BRICK_OP_FAILED, glusterd_op_ac_none}, //EVENT_BRICK_OP + {GD_OP_STATE_BRICK_OP_FAILED, glusterd_op_ac_none}, //EVENT_COMMIT_OP + {GD_OP_STATE_DEFAULT, glusterd_op_ac_unlock}, //EVENT_UNLOCK + {GD_OP_STATE_BRICK_OP_FAILED, glusterd_op_ac_none}, //EVENT_START_UNLOCK + {GD_OP_STATE_UNLOCK_SENT, glusterd_op_ac_send_unlock}, //EVENT_ALL_ACK + {GD_OP_STATE_BRICK_OP_FAILED, glusterd_op_ac_none}, //EVENT_MAX +}; + +glusterd_op_sm_t glusterd_op_state_brick_committed [] = { + {GD_OP_STATE_BRICK_COMMITTED, glusterd_op_ac_none}, //EVENT_NONE + {GD_OP_STATE_BRICK_COMMITTED, glusterd_op_ac_none},//EVENT_START_LOCK + {GD_OP_STATE_BRICK_COMMITTED, glusterd_op_ac_none}, //EVENT_LOCK + {GD_OP_STATE_BRICK_COMMITTED, glusterd_op_ac_rcvd_brick_op_acc}, //EVENT_RCVD_ACC + {GD_OP_STATE_BRICK_COMMITTED, glusterd_op_ac_none}, //EVENT_ALL_ACC + {GD_OP_STATE_BRICK_COMMITTED, glusterd_op_ac_none}, //EVENT_STAGE_ACC + {GD_OP_STATE_BRICK_COMMITTED, glusterd_op_ac_none}, //EVENT_COMMIT_ACC + {GD_OP_STATE_BRICK_COMMIT_FAILED, glusterd_op_ac_brick_op_failed}, //EVENT_RCVD_RJT + {GD_OP_STATE_BRICK_COMMITTED, glusterd_op_ac_none}, //EVENT_STAGE_OP + {GD_OP_STATE_BRICK_COMMITTED, glusterd_op_ac_none}, //EVENT_COMMIT_OP + {GD_OP_STATE_DEFAULT, glusterd_op_ac_unlock}, //EVENT_UNLOCK + {GD_OP_STATE_BRICK_COMMITTED, glusterd_op_ac_none}, //EVENT_START_UNLOCK + {GD_OP_STATE_COMMITED, glusterd_op_ac_commit_op}, //EVENT_ALL_ACK + {GD_OP_STATE_BRICK_COMMITTED, glusterd_op_ac_none}, //EVENT_MAX +}; + +glusterd_op_sm_t glusterd_op_state_brick_commit_failed [] = { + {GD_OP_STATE_BRICK_COMMIT_FAILED, glusterd_op_ac_none}, //EVENT_NONE + {GD_OP_STATE_BRICK_COMMIT_FAILED, glusterd_op_ac_none},//EVENT_START_LOCK + {GD_OP_STATE_BRICK_COMMIT_FAILED, glusterd_op_ac_none}, //EVENT_LOCK + {GD_OP_STATE_BRICK_COMMIT_FAILED, glusterd_op_ac_brick_op_failed}, //EVENT_RCVD_ACC + {GD_OP_STATE_BRICK_COMMIT_FAILED, glusterd_op_ac_none}, //EVENT_ALL_ACC + {GD_OP_STATE_BRICK_COMMIT_FAILED, glusterd_op_ac_none}, //EVENT_STAGE_ACC + {GD_OP_STATE_BRICK_COMMIT_FAILED, glusterd_op_ac_none}, //EVENT_COMMIT_ACC + {GD_OP_STATE_BRICK_COMMIT_FAILED, glusterd_op_ac_brick_op_failed}, //EVENT_RCVD_RJT + {GD_OP_STATE_BRICK_COMMIT_FAILED, glusterd_op_ac_none}, //EVENT_STAGE_OP + {GD_OP_STATE_BRICK_COMMIT_FAILED, glusterd_op_ac_none}, //EVENT_COMMIT_OP + {GD_OP_STATE_DEFAULT, glusterd_op_ac_unlock}, //EVENT_UNLOCK + {GD_OP_STATE_BRICK_COMMIT_FAILED, glusterd_op_ac_none}, //EVENT_START_UNLOCK + {GD_OP_STATE_BRICK_COMMIT_FAILED, glusterd_op_ac_send_commit_failed}, //EVENT_ALL_ACK + {GD_OP_STATE_BRICK_COMMIT_FAILED, glusterd_op_ac_none}, //EVENT_MAX +}; + +glusterd_op_sm_t glusterd_op_state_commit_op_failed [] = { + {GD_OP_STATE_COMMIT_OP_FAILED, glusterd_op_ac_none}, //EVENT_NONE + {GD_OP_STATE_COMMIT_OP_FAILED, glusterd_op_ac_none},//EVENT_START_LOCK + {GD_OP_STATE_COMMIT_OP_FAILED, glusterd_op_ac_none}, //EVENT_LOCK + {GD_OP_STATE_COMMIT_OP_FAILED, glusterd_op_ac_commit_op_failed}, //EVENT_RCVD_ACC + {GD_OP_STATE_COMMIT_OP_FAILED, glusterd_op_ac_none}, //EVENT_ALL_ACC + {GD_OP_STATE_COMMIT_OP_FAILED, glusterd_op_ac_none}, //EVENT_STAGE_ACC + {GD_OP_STATE_COMMIT_OP_FAILED, glusterd_op_ac_none}, //EVENT_COMMIT_ACC + {GD_OP_STATE_COMMIT_OP_FAILED, glusterd_op_ac_commit_op_failed}, //EVENT_RCVD_RJT + {GD_OP_STATE_COMMIT_OP_FAILED, glusterd_op_ac_none}, //EVENT_STAGE_OP + {GD_OP_STATE_COMMIT_OP_FAILED, glusterd_op_ac_none}, //EVENT_COMMIT_OP + {GD_OP_STATE_DEFAULT, glusterd_op_ac_unlock}, //EVENT_UNLOCK + {GD_OP_STATE_COMMIT_OP_FAILED, glusterd_op_ac_none}, //EVENT_START_UNLOCK + {GD_OP_STATE_UNLOCK_SENT, glusterd_op_ac_send_unlock}, //EVENT_ALL_ACK + {GD_OP_STATE_COMMIT_OP_FAILED, glusterd_op_ac_none}, //EVENT_MAX +}; + glusterd_op_sm_t glusterd_op_state_commit_op_sent [] = { {GD_OP_STATE_COMMIT_OP_SENT, glusterd_op_ac_none}, //EVENT_NONE {GD_OP_STATE_COMMIT_OP_SENT, glusterd_op_ac_none},//EVENT_START_LOCK @@ -5704,11 +6621,12 @@ glusterd_op_sm_t glusterd_op_state_commit_op_sent [] = { {GD_OP_STATE_UNLOCK_SENT, glusterd_op_ac_send_unlock}, //EVENT_ALL_ACC {GD_OP_STATE_COMMIT_OP_SENT, glusterd_op_ac_none}, //EVENT_STAGE_ACC {GD_OP_STATE_UNLOCK_SENT, glusterd_op_ac_send_unlock}, //EVENT_COMMIT_ACC - {GD_OP_STATE_COMMIT_OP_SENT, glusterd_op_ac_commit_error}, //EVENT_RCVD_RJT + {GD_OP_STATE_COMMIT_OP_FAILED, glusterd_op_ac_commit_op_failed}, //EVENT_RCVD_RJT {GD_OP_STATE_COMMIT_OP_SENT, glusterd_op_ac_none}, //EVENT_STAGE_OP {GD_OP_STATE_COMMIT_OP_SENT, glusterd_op_ac_none}, //EVENT_COMMIT_OP - {GD_OP_STATE_COMMIT_OP_SENT, glusterd_op_ac_unlock}, //EVENT_UNLOCK + {GD_OP_STATE_DEFAULT, glusterd_op_ac_unlock}, //EVENT_UNLOCK {GD_OP_STATE_UNLOCK_SENT, glusterd_op_ac_send_unlock}, //EVENT_START_UNLOCK + {GD_OP_STATE_COMMIT_OP_SENT, glusterd_op_ac_none}, //EVENT_ALL_ACK {GD_OP_STATE_COMMIT_OP_SENT, glusterd_op_ac_none}, //EVENT_MAX }; @@ -5725,6 +6643,7 @@ glusterd_op_sm_t glusterd_op_state_commited [] = { {GD_OP_STATE_COMMITED, glusterd_op_ac_none}, //EVENT_COMMIT_OP {GD_OP_STATE_DEFAULT, glusterd_op_ac_unlock}, //EVENT_UNLOCK {GD_OP_STATE_COMMITED, glusterd_op_ac_none}, //EVENT_START_UNLOCK + {GD_OP_STATE_COMMITED, glusterd_op_ac_none}, //EVENT_ALL_ACK {GD_OP_STATE_COMMITED, glusterd_op_ac_none}, //EVENT_MAX }; @@ -5739,8 +6658,9 @@ glusterd_op_sm_t glusterd_op_state_unlock_sent [] = { {GD_OP_STATE_UNLOCK_SENT, glusterd_op_ac_none}, //EVENT_RCVD_RJT {GD_OP_STATE_UNLOCK_SENT, glusterd_op_ac_none}, //EVENT_STAGE_OP {GD_OP_STATE_UNLOCK_SENT, glusterd_op_ac_none}, //EVENT_COMMIT_OP - {GD_OP_STATE_UNLOCK_SENT, glusterd_op_ac_unlock}, //EVENT_UNLOCK + {GD_OP_STATE_DEFAULT, glusterd_op_ac_unlock}, //EVENT_UNLOCK {GD_OP_STATE_UNLOCK_SENT, glusterd_op_ac_none}, //EVENT_START_UNLOCK + {GD_OP_STATE_UNLOCK_SENT, glusterd_op_ac_none}, //EVENT_ALL_ACK {GD_OP_STATE_UNLOCK_SENT, glusterd_op_ac_none}, //EVENT_MAX }; @@ -5753,7 +6673,13 @@ glusterd_op_sm_t *glusterd_op_state_table [] = { glusterd_op_state_staged, glusterd_op_state_commit_op_sent, glusterd_op_state_commited, - glusterd_op_state_unlock_sent + glusterd_op_state_unlock_sent, + glusterd_op_state_stage_op_failed, + glusterd_op_state_commit_op_failed, + glusterd_op_state_brick_op_sent, + glusterd_op_state_brick_op_failed, + glusterd_op_state_brick_committed, + glusterd_op_state_brick_commit_failed }; int @@ -5804,6 +6730,16 @@ out: } void +glusterd_destroy_req_ctx (glusterd_req_ctx_t *ctx) +{ + if (!ctx) + return; + if (ctx->dict) + dict_unref (ctx->dict); + GF_FREE (ctx); +} + +void glusterd_destroy_op_event_ctx (glusterd_op_sm_event_t *event) { if (!event) @@ -5815,10 +6751,8 @@ glusterd_destroy_op_event_ctx (glusterd_op_sm_event_t *event) glusterd_destroy_lock_ctx (event->ctx); break; case GD_OP_EVENT_STAGE_OP: - glusterd_destroy_stage_ctx (event->ctx); - break; - case GD_OP_EVENT_COMMIT_OP: - glusterd_destroy_commit_ctx (event->ctx); + case GD_OP_EVENT_ALL_ACK: + glusterd_destroy_req_ctx (event->ctx); break; default: break; @@ -5929,7 +6863,7 @@ int32_t glusterd_op_set_cli_op (glusterd_op_t op) { - int32_t ret; + int32_t ret = 0; ret = pthread_mutex_trylock (&opinfo.lock); @@ -5992,6 +6926,41 @@ glusterd_op_clear_op (glusterd_op_t op) } int32_t +glusterd_op_init_ctx (glusterd_op_t op) +{ + int ret = 0; + dict_t *dict = NULL; + + dict = dict_new (); + if (dict == NULL) { + ret = -1; + goto out; + } + ret = glusterd_op_set_ctx (op, dict); + if (ret) + goto out; + ret = glusterd_op_set_ctx_free (op, _gf_true); + if (ret) + goto out; +out: + gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); + return ret; +} + +int32_t +glusterd_op_fini_ctx (glusterd_op_t op) +{ + dict_t *dict = NULL; + + if (glusterd_op_get_ctx_free (op)) { + dict = glusterd_op_get_ctx (op); + if (dict) + dict_unref (dict); + } + return 0; +} + +int32_t glusterd_op_set_ctx (glusterd_op_t op, void *ctx) { @@ -6025,6 +6994,7 @@ glusterd_op_free_ctx (glusterd_op_t op, void *ctx, gf_boolean_t ctx_free) case GD_OP_START_VOLUME: case GD_OP_RESET_VOLUME: case GD_OP_GSYNC_SET: + case GD_OP_PROFILE_VOLUME: dict_unref (ctx); break; case GD_OP_DELETE_VOLUME: diff --git a/xlators/mgmt/glusterd/src/glusterd-op-sm.h b/xlators/mgmt/glusterd/src/glusterd-op-sm.h index 30d4fe9c8d2..c9c3889b57f 100644 --- a/xlators/mgmt/glusterd/src/glusterd-op-sm.h +++ b/xlators/mgmt/glusterd/src/glusterd-op-sm.h @@ -48,6 +48,12 @@ typedef enum glusterd_op_sm_state_ { GD_OP_STATE_COMMIT_OP_SENT, GD_OP_STATE_COMMITED, GD_OP_STATE_UNLOCK_SENT, + GD_OP_STATE_STAGE_OP_FAILED, + GD_OP_STATE_COMMIT_OP_FAILED, + GD_OP_STATE_BRICK_OP_SENT, + GD_OP_STATE_BRICK_OP_FAILED, + GD_OP_STATE_BRICK_COMMITTED, + GD_OP_STATE_BRICK_COMMIT_FAILED, GD_OP_STATE_MAX, } glusterd_op_sm_state_t; @@ -64,6 +70,7 @@ typedef enum glusterd_op_sm_event_type_ { GD_OP_EVENT_COMMIT_OP, GD_OP_EVENT_UNLOCK, GD_OP_EVENT_START_UNLOCK, + GD_OP_EVENT_ALL_ACK, GD_OP_EVENT_MAX } glusterd_op_sm_event_type_t; @@ -91,6 +98,7 @@ typedef struct glusterd_op_sm_state_info_ { struct glusterd_op_info_ { glusterd_op_sm_state_info_t state; int32_t pending_count; + int32_t brick_pending_count; int32_t op_count; glusterd_op_t op[GD_OP_MAX]; glusterd_op_t pending_op[GD_OP_MAX]; @@ -104,6 +112,7 @@ struct glusterd_op_info_ { int32_t cli_op; gf_boolean_t ctx_free[GD_OP_MAX]; char *op_errstr; + struct list_head pending_bricks; }; typedef struct glusterd_op_info_ glusterd_op_info_t; @@ -128,23 +137,27 @@ struct glusterd_op_lock_ctx_ { typedef struct glusterd_op_lock_ctx_ glusterd_op_lock_ctx_t; -struct glusterd_op_stage_ctx_ { +struct glusterd_req_ctx_ { rpcsvc_request_t *req; u_char uuid[16]; int op; dict_t *dict; }; -typedef struct glusterd_op_stage_ctx_ glusterd_op_stage_ctx_t; +typedef struct glusterd_req_ctx_ glusterd_req_ctx_t; -struct glusterd_op_commit_ctx_ { - rpcsvc_request_t *req; - u_char uuid[16]; - int op; - dict_t *dict; -}; +typedef struct glusterd_op_brick_rsp_ctx_ { + int op_ret; + char *op_errstr; + dict_t *rsp_dict; + glusterd_req_ctx_t *commit_ctx; + glusterd_brickinfo_t *brickinfo; +} glusterd_op_brick_rsp_ctx_t; -typedef struct glusterd_op_commit_ctx_ glusterd_op_commit_ctx_t; +typedef struct glusterd_pr_brick_rsp_conv_t { + int count; + dict_t *dict; +} glusterd_pr_brick_rsp_conv_t; int glusterd_op_sm_new_event (glusterd_op_sm_event_type_t event_type, @@ -241,4 +254,18 @@ glusterd_op_sm_state_name_get (int state); char* glusterd_op_sm_event_name_get (int event); +int32_t +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); +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); +void glusterd_op_brick_disconnect (void *data); +int32_t +glusterd_op_init_ctx (glusterd_op_t op); +int32_t +glusterd_op_fini_ctx (glusterd_op_t op); #endif diff --git a/xlators/mgmt/glusterd/src/glusterd-pmap.c b/xlators/mgmt/glusterd/src/glusterd-pmap.c index 67d10bfa65e..f1f49fc60b1 100644 --- a/xlators/mgmt/glusterd/src/glusterd-pmap.c +++ b/xlators/mgmt/glusterd/src/glusterd-pmap.c @@ -418,9 +418,6 @@ gluster_pmap_signin (rpcsvc_request_t *req) ret = glusterd_get_brickinfo (THIS, args.brick, args.port, _gf_true, &brickinfo); - if (!ret) - glusterd_set_brick_status (brickinfo, GF_BRICK_STARTED); - fail: glusterd_submit_reply (req, &rsp, NULL, 0, NULL, (gd_serialize_t)xdr_from_pmap_signin_rsp); @@ -452,11 +449,8 @@ gluster_pmap_signout (rpcsvc_request_t *req) rsp.op_ret = pmap_registry_remove (THIS, args.port, args.brick, GF_PMAP_PORT_BRICKSERVER, req->trans); - ret = glusterd_get_brickinfo (THIS, args.brick, args.port, _gf_true, + ret = glusterd_get_brickinfo (THIS, args.brick, args.port, _gf_true, &brickinfo); - if (!ret) - glusterd_set_brick_status (brickinfo, GF_BRICK_STOPPED); - fail: glusterd_submit_reply (req, &rsp, NULL, 0, NULL, (gd_serialize_t)xdr_from_pmap_signout_rsp); diff --git a/xlators/mgmt/glusterd/src/glusterd-rpc-ops.c b/xlators/mgmt/glusterd/src/glusterd-rpc-ops.c index e7134c990b7..8eba024a919 100644 --- a/xlators/mgmt/glusterd/src/glusterd-rpc-ops.c +++ b/xlators/mgmt/glusterd/src/glusterd-rpc-ops.c @@ -41,10 +41,12 @@ #define SERVER_PATH_MAX (16 * 1024) -extern glusterd_op_info_t opinfo; - +extern glusterd_op_info_t opinfo; int32_t +glusterd3_1_brick_op (call_frame_t *frame, xlator_t *this, + void *data); +int32_t glusterd_op_send_cli_response (glusterd_op_t op, int32_t op_ret, int32_t op_errno, rpcsvc_request_t *req, void *op_ctx, char *op_errstr) @@ -53,6 +55,7 @@ glusterd_op_send_cli_response (glusterd_op_t op, int32_t op_ret, gd_serialize_t sfunc = NULL; void *cli_rsp = NULL; dict_t *ctx = NULL; + char *free_ptr = NULL; switch (op) { case GD_OP_CREATE_VOLUME: @@ -307,19 +310,37 @@ glusterd_op_send_cli_response (glusterd_op_t op, int32_t op_ret, gf_log ("", GF_LOG_DEBUG, "not supported op %d", op); break; } + case GD_OP_PROFILE_VOLUME: + { + gf1_cli_stats_volume_rsp rsp = {0,}; + rsp.op_ret = op_ret; + rsp.op_errno = op_errno; + if (op_errstr) + rsp.op_errstr = op_errstr; + else + rsp.op_errstr = ""; + ctx = op_ctx; + dict_allocate_and_serialize (ctx, + &rsp.stats_info.stats_info_val, + (size_t*)&rsp.stats_info.stats_info_len); + free_ptr = rsp.stats_info.stats_info_val; + cli_rsp = &rsp; + sfunc = gf_xdr_from_cli_stats_volume_rsp; + break; + } case GD_OP_NONE: case GD_OP_MAX: + { gf_log ("", GF_LOG_ERROR, "invalid operation %d", op); break; } + } ret = glusterd_submit_reply (req, cli_rsp, NULL, 0, NULL, sfunc); - if (ret) - goto out; - -out: + if (free_ptr) + GF_FREE (free_ptr); gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); return ret; } @@ -867,7 +888,8 @@ glusterd3_1_stage_op_cbk (struct rpc_req *req, struct iovec *iov, if (op_ret) { event_type = GD_OP_EVENT_RCVD_RJT; opinfo.op_ret = op_ret; - opinfo.op_errstr = gf_strdup(rsp.op_errstr); + if (strcmp ("", rsp.op_errstr)) + opinfo.op_errstr = gf_strdup(rsp.op_errstr); if (!opinfo.op_errstr) { gf_log ("", GF_LOG_ERROR, "memory allocation failed"); ret = -1; @@ -922,6 +944,59 @@ out: } +void +_profile_volume_add_friend_rsp (dict_t *this, char *key, data_t *value, + void *data) +{ + char new_key[256] = {0}; + glusterd_pr_brick_rsp_conv_t *rsp_ctx = NULL; + data_t *new_value = NULL; + int brick_count = 0; + char brick_key[256]; + + if (strcmp (key, "count") == 0) + return; + sscanf (key, "%d%s", &brick_count, brick_key); + rsp_ctx = data; + new_value = data_copy (value); + GF_ASSERT (new_value); + snprintf (new_key, sizeof (new_key), "%d%s", + rsp_ctx->count + brick_count, brick_key); + dict_set (rsp_ctx->dict, new_key, new_value); +} + +int +glusterd_profile_volume_use_rsp_dict (dict_t *rsp_dict) +{ + int ret = 0; + glusterd_pr_brick_rsp_conv_t rsp_ctx = {0}; + int32_t brick_count = 0; + int32_t count = 0; + dict_t *ctx_dict = NULL; + glusterd_op_t op = GD_OP_NONE; + + GF_ASSERT (rsp_dict); + + ret = dict_get_int32 (rsp_dict, "count", &brick_count); + if (ret) { + ret = 0; //no bricks in the rsp + goto out; + } + + op = glusterd_op_get_op (); + GF_ASSERT (GD_OP_PROFILE_VOLUME == op); + ctx_dict = glusterd_op_get_ctx (op); + + ret = dict_get_int32 (ctx_dict, "count", &count); + rsp_ctx.count = count; + rsp_ctx.dict = ctx_dict; + dict_foreach (rsp_dict, _profile_volume_add_friend_rsp, &rsp_ctx); + dict_del (ctx_dict, "count"); + ret = dict_set_int32 (ctx_dict, "count", count + brick_count); +out: + return ret; +} + int32_t glusterd3_1_commit_op_cbk (struct rpc_req *req, struct iovec *iov, int count, void *myframe) @@ -1001,14 +1076,22 @@ glusterd3_1_commit_op_cbk (struct rpc_req *req, struct iovec *iov, ret = glusterd_rb_use_rsp_dict (dict); if (ret) goto out; - break; + break; + case GD_OP_SYNC_VOLUME: ret = glusterd_sync_use_rsp_dict (dict); if (ret) goto out; - break; + break; + + case GD_OP_PROFILE_VOLUME: + ret = glusterd_profile_volume_use_rsp_dict (dict); + if (ret) + goto out; + break; + default: - break; + break; } } @@ -1066,7 +1149,7 @@ glusterd3_1_probe (call_frame_t *frame, xlator_t *this, req.hostname = gf_strdup (hostname); req.port = port; - ret = glusterd_submit_request (peerinfo, &req, frame, peerinfo->mgmt, + ret = glusterd_submit_request (peerinfo->rpc, &req, frame, peerinfo->mgmt, GD_MGMT_PROBE_QUERY, NULL, gd_xdr_from_mgmt_probe_req, this, glusterd3_1_probe_cbk); @@ -1119,7 +1202,7 @@ glusterd3_1_friend_add (call_frame_t *frame, xlator_t *this, if (ret) goto out; - ret = glusterd_submit_request (peerinfo, &req, frame, peerinfo->mgmt, + ret = glusterd_submit_request (peerinfo->rpc, &req, frame, peerinfo->mgmt, GD_MGMT_FRIEND_ADD, NULL, gd_xdr_from_mgmt_friend_req, this, glusterd3_1_friend_add_cbk); @@ -1161,7 +1244,7 @@ glusterd3_1_friend_remove (call_frame_t *frame, xlator_t *this, uuid_copy (req.uuid, priv->uuid); req.hostname = peerinfo->hostname; req.port = peerinfo->port; - ret = glusterd_submit_request (peerinfo, &req, frame, peerinfo->mgmt, + ret = glusterd_submit_request (peerinfo->rpc, &req, frame, peerinfo->mgmt, GD_MGMT_FRIEND_REMOVE, NULL, gd_xdr_from_mgmt_friend_req, this, glusterd3_1_friend_remove_cbk); @@ -1206,7 +1289,7 @@ glusterd3_1_friend_update (call_frame_t *frame, xlator_t *this, uuid_copy (req.uuid, priv->uuid); dummy_frame = create_frame (this, this->ctx->pool); - ret = glusterd_submit_request (peerinfo, &req, dummy_frame, + ret = glusterd_submit_request (peerinfo->rpc, &req, dummy_frame, peerinfo->mgmt, GD_MGMT_FRIEND_UPDATE, NULL, gd_xdr_from_mgmt_friend_update, @@ -1244,7 +1327,7 @@ glusterd3_1_cluster_lock (call_frame_t *frame, xlator_t *this, if (!dummy_frame) goto out; - ret = glusterd_submit_request (peerinfo, &req, dummy_frame, + ret = glusterd_submit_request (peerinfo->rpc, &req, dummy_frame, peerinfo->mgmt, GD_MGMT_CLUSTER_LOCK, NULL, gd_xdr_from_mgmt_cluster_lock_req, @@ -1278,7 +1361,7 @@ glusterd3_1_cluster_unlock (call_frame_t *frame, xlator_t *this, if (!dummy_frame) goto out; - ret = glusterd_submit_request (peerinfo, &req, dummy_frame, + ret = glusterd_submit_request (peerinfo->rpc, &req, dummy_frame, peerinfo->mgmt, GD_MGMT_CLUSTER_UNLOCK, NULL, gd_xdr_from_mgmt_cluster_unlock_req, @@ -1337,7 +1420,7 @@ glusterd3_1_stage_op (call_frame_t *frame, xlator_t *this, if (!dummy_frame) goto out; - ret = glusterd_submit_request (peerinfo, &req, dummy_frame, + ret = glusterd_submit_request (peerinfo->rpc, &req, dummy_frame, peerinfo->mgmt, GD_MGMT_STAGE_OP, NULL, gd_xdr_from_mgmt_stage_op_req, @@ -1399,7 +1482,7 @@ glusterd3_1_commit_op (call_frame_t *frame, xlator_t *this, if (!dummy_frame) goto out; - ret = glusterd_submit_request (peerinfo, &req, dummy_frame, + ret = glusterd_submit_request (peerinfo->rpc, &req, dummy_frame, peerinfo->mgmt, GD_MGMT_COMMIT_OP, NULL, gd_xdr_from_mgmt_commit_op_req, @@ -1413,6 +1496,118 @@ out: return ret; } +int32_t +glusterd_start_brick_disconnect_timer (glusterd_op_brick_rsp_ctx_t *ev_ctx) +{ + struct timeval timeout = {0, }; + int32_t ret = -1; + xlator_t *this = NULL; + glusterd_brickinfo_t *brickinfo = NULL; + + timeout.tv_sec = 5; + timeout.tv_usec = 0; + brickinfo = ev_ctx->brickinfo; + GF_ASSERT (brickinfo); + this = THIS; + GF_ASSERT (this); + + brickinfo->timer = gf_timer_call_after (this->ctx, timeout, + glusterd_op_brick_disconnect, + (void *) ev_ctx); + + ret = 0; + + return ret; +} + +int32_t +glusterd3_1_brick_op_cbk (struct rpc_req *req, struct iovec *iov, + int count, void *myframe) +{ + gd1_mgmt_brick_op_rsp rsp = {0}; + int ret = -1; + int32_t op_ret = -1; + glusterd_op_sm_event_type_t event_type = GD_OP_EVENT_NONE; + call_frame_t *frame = NULL; + glusterd_op_brick_rsp_ctx_t *ev_ctx = NULL; + int32_t op = -1; + dict_t *dict = NULL; + + GF_ASSERT (req); + frame = myframe; + + if (-1 == req->rpc_status) { + rsp.op_ret = -1; + rsp.op_errno = EINVAL; + rsp.op_errstr = "error"; + event_type = GD_OP_EVENT_RCVD_RJT; + goto out; + } + + ret = gd_xdr_to_mgmt_brick_op_rsp (*iov, &rsp); + if (ret < 0) { + gf_log ("", GF_LOG_ERROR, "error"); + rsp.op_ret = -1; + rsp.op_errno = EINVAL; + rsp.op_errstr = "error"; + event_type = GD_OP_EVENT_RCVD_RJT; + goto out; + } + + if (rsp.output.output_len) { + /* Unserialize the dictionary */ + dict = dict_new (); + + ret = dict_unserialize (rsp.output.output_val, + rsp.output.output_len, + &dict); + if (ret < 0) { + gf_log ("glusterd", GF_LOG_ERROR, + "failed to " + "unserialize rsp-buffer to dictionary"); + event_type = GD_OP_EVENT_RCVD_RJT; + goto out; + } else { + dict->extra_stdfree = rsp.output.output_val; + } + } + + op_ret = rsp.op_ret; + +out: + ev_ctx = GF_CALLOC (1, sizeof (*ev_ctx), gf_gld_mt_brick_rsp_ctx_t); + GF_ASSERT (ev_ctx); + if (op_ret) { + event_type = GD_OP_EVENT_RCVD_RJT; + ev_ctx->op_ret = op_ret; + ev_ctx->op_errstr = gf_strdup(rsp.op_errstr); + } else { + event_type = GD_OP_EVENT_RCVD_ACC; + } + ev_ctx->brickinfo = frame->cookie; + ev_ctx->rsp_dict = dict; + ev_ctx->commit_ctx = frame->local; + op = glusterd_op_get_op (); + if ((op == GD_OP_STOP_VOLUME) || + (op == GD_OP_REMOVE_BRICK)) { + ret = glusterd_start_brick_disconnect_timer (ev_ctx); + } else { + ret = glusterd_op_sm_inject_event (event_type, ev_ctx); + if (!ret) { + glusterd_friend_sm (); + glusterd_op_sm (); + } + } + + if (ret && dict) + dict_unref (dict); + if (rsp.op_errstr && strcmp (rsp.op_errstr, "error")) + free (rsp.op_errstr); //malloced by xdr + GLUSTERD_STACK_DESTROY (frame); + return ret; +} + + struct rpc_clnt_procedure glusterd3_1_clnt_mgmt_actors[GD_MGMT_MAXVALUE] = { [GD_MGMT_NULL] = {"NULL", NULL }, [GD_MGMT_PROBE_QUERY] = { "PROBE_QUERY", glusterd3_1_probe}, @@ -1425,6 +1620,11 @@ struct rpc_clnt_procedure glusterd3_1_clnt_mgmt_actors[GD_MGMT_MAXVALUE] = { [GD_MGMT_FRIEND_UPDATE] = { "FRIEND_UPDATE", glusterd3_1_friend_update}, }; +struct rpc_clnt_procedure glusterd3_1_fs_mgmt_actors[GD_MGMT_MAXVALUE] = { + [GD_MGMT_NULL] = {"NULL", NULL }, + [GD_MGMT_BRICK_OP] = {"BRICK_OP", glusterd3_1_brick_op}, +}; + struct rpc_clnt_program glusterd3_1_mgmt_prog = { .progname = "Mgmt 3.1", .prognum = GLUSTERD1_MGMT_PROGRAM, @@ -1452,3 +1652,88 @@ struct rpc_clnt_program gd_clnt_mgmt_prog = { .numproc = GD_MGMT_PROCCNT, .proctable = gd_clnt_mgmt_actors, }; + +struct rpc_clnt_program glusterd_glusterfs_3_1_mgmt_prog = { + .progname = "GlusterFS Mops", + .prognum = GLUSTERFS_PROGRAM, + .progver = GLUSTERFS_VERSION, + .proctable = glusterd3_1_fs_mgmt_actors, + .numproc = GLUSTERFS_PROCCNT, +}; + +int32_t +glusterd3_1_brick_op (call_frame_t *frame, xlator_t *this, + void *data) +{ + gd1_mgmt_brick_op_req *req = NULL; + int ret = 0; + glusterd_conf_t *priv = NULL; + call_frame_t *dummy_frame = NULL; + char *op_errstr = NULL; + int pending_bricks = 0; + glusterd_pending_node_t *pending_brick; + glusterd_brickinfo_t *brickinfo = NULL; + glusterd_req_ctx_t *req_ctx = NULL; + + if (!this) { + ret = -1; + goto out; + } + priv = this->private; + GF_ASSERT (priv); + + req_ctx = data; + GF_ASSERT (req_ctx); + INIT_LIST_HEAD (&opinfo.pending_bricks); + ret = glusterd_op_bricks_select (req_ctx->op, req_ctx->dict, &op_errstr); + + if (ret) { + gf_log ("", GF_LOG_ERROR, "Brick Op failed"); + opinfo.op_errstr = op_errstr; + goto out; + } + + list_for_each_entry (pending_brick, &opinfo.pending_bricks, list) { + dummy_frame = create_frame (this, this->ctx->pool); + brickinfo = pending_brick->node; + + if (!dummy_frame) + continue; + if (glusterd_is_brick_started (brickinfo)) + continue; + + ret = glusterd_brick_op_build_payload (req_ctx->op, brickinfo, + (gd1_mgmt_brick_op_req **)&req); + + if (ret) + goto out; + + dummy_frame->local = data; + dummy_frame->cookie = brickinfo; + ret = glusterd_submit_request (brickinfo->rpc, req, dummy_frame, + &glusterd_glusterfs_3_1_mgmt_prog, + req->op, NULL, + gd_xdr_from_mgmt_brick_op_req, + this, glusterd3_1_brick_op_cbk); + if (req) { + if (req->input.input_val) + GF_FREE (req->input.input_val); + GF_FREE (req); + req = NULL; + } + if (!ret) + pending_bricks++; + } + + gf_log ("glusterd", GF_LOG_DEBUG, "Sent op req to %d bricks", + pending_bricks); + opinfo.brick_pending_count = pending_bricks; + +out: + if (ret) { + glusterd_op_sm_inject_event (GD_OP_EVENT_RCVD_RJT, data); + opinfo.op_ret = ret; + } + gf_log ("glusterd", GF_LOG_DEBUG, "Returning %d", ret); + return ret; +} diff --git a/xlators/mgmt/glusterd/src/glusterd-utils.c b/xlators/mgmt/glusterd/src/glusterd-utils.c index cb38ddf88f6..458cd6c5888 100644 --- a/xlators/mgmt/glusterd/src/glusterd-utils.c +++ b/xlators/mgmt/glusterd/src/glusterd-utils.c @@ -23,7 +23,6 @@ #endif #include <inttypes.h> - #include "globals.h" #include "glusterfs.h" #include "compat.h" @@ -33,6 +32,7 @@ #include "timer.h" #include "defaults.h" #include "compat.h" +#include "md5.h" #include "compat-errno.h" #include "statedump.h" #include "glusterd-mem-types.h" @@ -63,6 +63,7 @@ #define MOUNTV3_VERSION 3 #define MOUNTV1_VERSION 1 +char *glusterd_sock_dir = "/tmp"; static glusterd_lock_t lock; static int32_t @@ -303,7 +304,7 @@ glusterd_get_uuid (uuid_t *uuid) } int -glusterd_submit_request (glusterd_peerinfo_t *peerinfo, void *req, +glusterd_submit_request (struct rpc_clnt *rpc, void *req, call_frame_t *frame, rpc_clnt_prog_t *prog, int procnum, struct iobref *iobref, gd_serialize_t sfunc, xlator_t *this, @@ -315,7 +316,7 @@ glusterd_submit_request (glusterd_peerinfo_t *peerinfo, void *req, char new_iobref = 0, start_ping = 0; struct iovec iov = {0, }; - GF_ASSERT (peerinfo); + GF_ASSERT (rpc); GF_ASSERT (this); iobuf = iobuf_get (this->ctx->iobuf_pool); @@ -347,18 +348,18 @@ glusterd_submit_request (glusterd_peerinfo_t *peerinfo, void *req, count = 1; } /* Send the msg */ - ret = rpc_clnt_submit (peerinfo->rpc, prog, procnum, cbkfn, + ret = rpc_clnt_submit (rpc, prog, procnum, cbkfn, &iov, count, NULL, 0, iobref, frame, NULL, 0, NULL, 0, NULL); if (ret == 0) { - pthread_mutex_lock (&peerinfo->rpc->conn.lock); + pthread_mutex_lock (&rpc->conn.lock); { - if (!peerinfo->rpc->conn.ping_started) { + if (!rpc->conn.ping_started) { start_ping = 1; } } - pthread_mutex_unlock (&peerinfo->rpc->conn.lock); + pthread_mutex_unlock (&rpc->conn.lock); } if (start_ping) @@ -375,7 +376,6 @@ out: return ret; } - struct iobuf * glusterd_serialize_reply (rpcsvc_request_t *req, void *arg, gd_serialize_t sfunc, struct iovec *outmsg) @@ -901,6 +901,37 @@ out: return ret; } +void +glusterd_set_brick_socket_filepath (glusterd_volinfo_t *volinfo, + glusterd_brickinfo_t *brickinfo, + char *sockpath, size_t len) +{ + char export_path[PATH_MAX] = {0,}; + char sock_filepath[PATH_MAX] = {0,}; + char md5_sum[MD5_DIGEST_LEN*2+1] = {0,}; + char volume_dir[PATH_MAX] = {0,}; + xlator_t *this = NULL; + glusterd_conf_t *priv = NULL; + int expected_file_len = 0; + + expected_file_len = strlen (glusterd_sock_dir) + strlen ("/") + + MD5_DIGEST_LEN*2 + strlen (".socket") + 1; + GF_ASSERT (len >= expected_file_len); + this = THIS; + GF_ASSERT (this); + + priv = this->private; + + GLUSTERD_GET_VOLUME_DIR (volume_dir, volinfo, priv); + GLUSTERD_REMOVE_SLASH_FROM_PATH (brickinfo->path, export_path); + snprintf (sock_filepath, PATH_MAX, "%s/run/%s-%s", + volume_dir, brickinfo->hostname, export_path); + _get_md5_str (md5_sum, sizeof (md5_sum), + (uint8_t*)sock_filepath, strlen (sock_filepath)); + + snprintf (sockpath, len, "%s/%s.socket", glusterd_sock_dir, md5_sum); +} + int32_t glusterd_volume_start_glusterfs (glusterd_volinfo_t *volinfo, glusterd_brickinfo_t *brickinfo) @@ -918,6 +949,9 @@ glusterd_volume_start_glusterfs (glusterd_volinfo_t *volinfo, int port = 0; FILE *file = NULL; gf_boolean_t is_locked = _gf_false; + dict_t *options = NULL; + char socketpath[PATH_MAX] = {0}; + struct rpc_clnt *rpc = NULL; GF_ASSERT (volinfo); GF_ASSERT (brickinfo); @@ -937,6 +971,8 @@ glusterd_volume_start_glusterfs (glusterd_volinfo_t *volinfo, goto out; } + glusterd_set_brick_socket_filepath (volinfo, brickinfo, socketpath, + sizeof (socketpath)); GLUSTERD_GET_BRICK_PIDFILE (pidfile, path, brickinfo->hostname, brickinfo->path); @@ -948,7 +984,7 @@ glusterd_volume_start_glusterfs (glusterd_volinfo_t *volinfo, gf_log ("", GF_LOG_NORMAL, "brick %s:%s " "already started", brickinfo->hostname, brickinfo->path); - goto out; + goto connect; } } @@ -964,7 +1000,7 @@ glusterd_volume_start_glusterfs (glusterd_volinfo_t *volinfo, gf_log ("", GF_LOG_NORMAL, "brick %s:%s " "already started", brickinfo->hostname, brickinfo->path); - goto out; + goto connect; } else if (0 == ret) { is_locked = _gf_true; } @@ -998,9 +1034,9 @@ glusterd_volume_start_glusterfs (glusterd_volinfo_t *volinfo, snprintf (cmd_str, 8192, "%s/sbin/glusterfsd --xlator-option %s-server.listen-port=%d " - "-s localhost --volfile-id %s -p %s --brick-name %s " + "-s localhost --volfile-id %s -p %s -S %s --brick-name %s " "--brick-port %d -l %s", GFS_PREFIX, volinfo->volname, - port, volfile, pidfile, brickinfo->path, port, + port, volfile, pidfile, socketpath, brickinfo->path, port, brickinfo->logfile); gf_log ("",GF_LOG_DEBUG,"Starting GlusterFS Command Executed: \n %s \n", cmd_str); @@ -1010,6 +1046,19 @@ glusterd_volume_start_glusterfs (glusterd_volinfo_t *volinfo, //pmap_registry_bind (THIS, port, brickinfo->path); brickinfo->port = port; } + +connect: + if (brickinfo->rpc == NULL) { + ret = rpc_clnt_transport_unix_options_build (&options, socketpath); + if (ret) + goto out; + ret = glusterd_rpc_create (&rpc, options, + glusterd_brick_rpc_notify, + brickinfo); + if (ret) + goto out; + brickinfo->rpc = rpc; + } out: if (is_locked && file) lockf (fileno (file), F_ULOCK, 0); @@ -1019,6 +1068,36 @@ out: } int32_t +glusterd_brick_unlink_socket_file (glusterd_volinfo_t *volinfo, + glusterd_brickinfo_t *brickinfo) +{ + char path[PATH_MAX] = {0,}; + char socketpath[PATH_MAX] = {0}; + xlator_t *this = NULL; + glusterd_conf_t *priv = NULL; + int ret = 0; + + GF_ASSERT (volinfo); + GF_ASSERT (brickinfo); + + this = THIS; + GF_ASSERT (this); + + priv = this->private; + GLUSTERD_GET_VOLUME_DIR (path, volinfo, priv); + glusterd_set_brick_socket_filepath (volinfo, brickinfo, socketpath, + sizeof (socketpath)); + ret = unlink (socketpath); + if (ret && (ENOENT == errno)) { + ret = 0; + } else { + gf_log ("glusterd", GF_LOG_ERROR, "Failed to remove %s" + " error: %s", socketpath, strerror (errno)); + } + + return ret; +} +int32_t glusterd_volume_stop_glusterfs (glusterd_volinfo_t *volinfo, glusterd_brickinfo_t *brickinfo) { @@ -1026,6 +1105,7 @@ glusterd_volume_stop_glusterfs (glusterd_volinfo_t *volinfo, glusterd_conf_t *priv = NULL; char pidfile[PATH_MAX] = {0,}; char path[PATH_MAX] = {0,}; + int ret = 0; GF_ASSERT (volinfo); GF_ASSERT (brickinfo); @@ -1035,11 +1115,19 @@ glusterd_volume_stop_glusterfs (glusterd_volinfo_t *volinfo, priv = this->private; + if (brickinfo->rpc) { + rpc_clnt_unref (brickinfo->rpc); + brickinfo->rpc = NULL; + } GLUSTERD_GET_VOLUME_DIR (path, volinfo, priv); GLUSTERD_GET_BRICK_PIDFILE (pidfile, path, brickinfo->hostname, brickinfo->path); - return glusterd_service_stop ("brick", pidfile, SIGTERM, _gf_false); + ret = glusterd_service_stop ("brick", pidfile, SIGTERM, _gf_false); + if (ret == 0) { + ret = glusterd_brick_unlink_socket_file (volinfo, brickinfo); + } + return ret; } int32_t @@ -1920,7 +2008,6 @@ glusterd_brick_start (glusterd_volinfo_t *volinfo, goto out; } - out: gf_log ("", GF_LOG_DEBUG, "returning %d ", ret); return ret; @@ -1982,6 +2069,13 @@ glusterd_set_brick_status (glusterd_brickinfo_t *brickinfo, { GF_ASSERT (brickinfo); brickinfo->status = status; + if (GF_BRICK_STARTED == status) { + gf_log ("glusterd", GF_LOG_DEBUG, "Setting brick %s:%s status " + "to started", brickinfo->hostname, brickinfo->path); + } else { + gf_log ("glusterd", GF_LOG_DEBUG, "Setting brick %s:%s status " + "to stopped", brickinfo->hostname, brickinfo->path); + } } int @@ -2676,3 +2770,38 @@ glusterd_peer_destroy (glusterd_peerinfo_t *peerinfo) out: return ret; } + +int +glusterd_remove_pending_entry (struct list_head *list, void *elem) +{ + glusterd_pending_node_t *pending_node = NULL; + glusterd_pending_node_t *tmp = NULL; + int ret = -1; + + list_for_each_entry_safe (pending_node, tmp, list, list) { + if (elem == pending_node->node) { + list_del_init (&pending_node->list); + GF_FREE (pending_node); + ret = 0; + goto out; + } + } +out: + gf_log ("", GF_LOG_DEBUG, "returning %d", ret); + return ret; + +} + +int +glusterd_clear_pending_nodes (struct list_head *list) +{ + glusterd_pending_node_t *pending_node = NULL; + glusterd_pending_node_t *tmp = NULL; + + list_for_each_entry_safe (pending_node, tmp, list, list) { + list_del_init (&pending_node->list); + GF_FREE (pending_node); + } + + return 0; +} diff --git a/xlators/mgmt/glusterd/src/glusterd-utils.h b/xlators/mgmt/glusterd/src/glusterd-utils.h index 79b2454c085..a903cf8d3a8 100644 --- a/xlators/mgmt/glusterd/src/glusterd-utils.h +++ b/xlators/mgmt/glusterd/src/glusterd-utils.h @@ -70,12 +70,11 @@ glusterd_submit_reply (rpcsvc_request_t *req, void *arg, struct iobref *iobref, gd_serialize_t sfunc); int -glusterd_submit_request (glusterd_peerinfo_t *peerinfo, void *req, - call_frame_t *frame, struct rpc_clnt_program *prog, +glusterd_submit_request (struct rpc_clnt *rpc, void *req, + call_frame_t *frame, rpc_clnt_prog_t *prog, int procnum, struct iobref *iobref, gd_serialize_t sfunc, xlator_t *this, fop_cbk_fn_t cbkfn); - int32_t glusterd_volinfo_new (glusterd_volinfo_t **volinfo); @@ -252,4 +251,8 @@ glusterd_sm_tr_log_delete (glusterd_sm_tr_log_t *log); int glusterd_sm_tr_log_add_to_dict (dict_t *dict, glusterd_sm_tr_log_t *circular_log); +int +glusterd_remove_pending_entry (struct list_head *list, void *elem); +int +glusterd_clear_pending_nodes (struct list_head *list); #endif diff --git a/xlators/mgmt/glusterd/src/glusterd.c b/xlators/mgmt/glusterd/src/glusterd.c index 675713585d5..732a9a3e2b5 100644 --- a/xlators/mgmt/glusterd/src/glusterd.c +++ b/xlators/mgmt/glusterd/src/glusterd.c @@ -53,6 +53,7 @@ extern struct rpcsvc_program gd_svc_cli_prog; extern struct rpcsvc_program gluster_handshake_prog; extern struct rpcsvc_program gluster_pmap_prog; extern glusterd_op_info_t opinfo; +extern struct rpc_clnt_program glusterd_glusterfs_3_1_mgmt_prog; rpcsvc_cbk_program_t glusterd_cbk_prog = { .progname = "Gluster Callback", @@ -391,6 +392,7 @@ init (xlator_t *this) INIT_LIST_HEAD (&conf->volumes); pthread_mutex_init (&conf->mutex, NULL); conf->rpc = rpc; + conf->gfs_mgmt = &glusterd_glusterfs_3_1_mgmt_prog; strncpy (conf->workdir, dirname, PATH_MAX); INIT_LIST_HEAD (&conf->xprt_list); diff --git a/xlators/mgmt/glusterd/src/glusterd.h b/xlators/mgmt/glusterd/src/glusterd.h index 2b02a513981..a38c9a799e8 100644 --- a/xlators/mgmt/glusterd/src/glusterd.h +++ b/xlators/mgmt/glusterd/src/glusterd.h @@ -73,6 +73,7 @@ typedef enum glusterd_op_ { GD_OP_LOG_LOCATE, GD_OP_LOG_ROTATE, GD_OP_GSYNC_SET, + GD_OP_PROFILE_VOLUME, GD_OP_MAX, } glusterd_op_t; @@ -104,6 +105,7 @@ typedef struct { glusterd_store_handle_t *handle; gf_timer_t *timer; glusterd_sm_tr_log_t op_sm_log; + struct rpc_clnt_program *gfs_mgmt; } glusterd_conf_t; typedef enum gf_brick_status { @@ -120,7 +122,9 @@ struct glusterd_brickinfo { char *logfile; gf_boolean_t signed_in; glusterd_store_handle_t *shandle; - gf_brick_status_t status; + gf_brick_status_t status; + struct rpc_clnt *rpc; + gf_timer_t *timer; }; typedef struct glusterd_brickinfo glusterd_brickinfo_t; @@ -205,6 +209,11 @@ struct glusterd_volinfo_ { typedef struct glusterd_volinfo_ glusterd_volinfo_t; +typedef struct glusterd_pending_node_ { + void *node; + struct list_head list; +} glusterd_pending_node_t; + enum glusterd_op_ret { GLUSTERD_CONNECTION_AWAITED = 100, }; @@ -326,10 +335,6 @@ int32_t glusterd_create_volume (rpcsvc_request_t *req, dict_t *dict); int -glusterd_rpc_notify (struct rpc_clnt *rpc, void *mydata, - rpc_clnt_event_t event, - void *data); -int glusterd_handle_incoming_friend_req (rpcsvc_request_t *req); int @@ -408,9 +413,6 @@ glusterd_handle_cli_get_volume (rpcsvc_request_t *req); int32_t glusterd_get_volumes (rpcsvc_request_t *req, dict_t *dict, int32_t flags); -int32_t -glusterd_add_brick (rpcsvc_request_t *req, dict_t *dict); - int glusterd_handle_add_brick (rpcsvc_request_t *req); @@ -470,9 +472,6 @@ glusterd_xfer_cli_deprobe_resp (rpcsvc_request_t *req, int32_t op_ret, int glusterd_fetchspec_notify (xlator_t *this); -int32_t -glusterd_sync_volume (rpcsvc_request_t *req, dict_t *ctx); - int glusterd_add_volume_detail_to_dict (glusterd_volinfo_t *volinfo, dict_t *volumes, int count); @@ -490,4 +489,21 @@ glusterd_peer_handshake (xlator_t *this, struct rpc_clnt *rpc, int glusterd_validate_reconfopts (glusterd_volinfo_t *volinfo, dict_t *val_dict, char **op_errstr); +int +glusterd_handle_cli_profile_volume (rpcsvc_request_t *req); + +int32_t +glusterd_set_volume (rpcsvc_request_t *req, dict_t *dict); +int +glusterd_peer_rpc_notify (struct rpc_clnt *rpc, void *mydata, + rpc_clnt_event_t event, + void *data); +int +glusterd_brick_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, + rpc_clnt_notify_t notify_fn, void *notify_data); + #endif |