diff options
author | shishir gowda <sgowda@redhat.com> | 2013-10-22 16:57:00 +0530 |
---|---|---|
committer | shishir gowda <sgowda@redhat.com> | 2013-10-23 19:19:45 +0530 |
commit | c535e3aadbb2e9e4d8387b03a72b7fae7f2bebd5 (patch) | |
tree | 18de07cba9ad630a21e9ae0fea8e6380e45ac11b | |
parent | 846cdf3dfa81bca5160c3b566fdf1ad62d14115b (diff) |
mgmt/snapshot: brick op for starting/stopping barrier
Change-Id: Iafbd0ec95de0c41455fb79953fb4bb07721334a5
Signed-off-by: shishir gowda <sgowda@redhat.com>
-rw-r--r-- | cli/src/cli-cmd-parser.c | 6 | ||||
-rw-r--r-- | glusterfsd/src/glusterfsd-mgmt.c | 78 | ||||
-rw-r--r-- | libglusterfs/src/glusterfs.h | 1 | ||||
-rw-r--r-- | rpc/rpc-lib/src/protocol-common.h | 1 | ||||
-rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-jarvis.c | 201 | ||||
-rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-jarvis.h | 3 | ||||
-rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-op-sm.c | 71 | ||||
-rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-snapshot.c | 2 | ||||
-rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-syncop.h | 4 | ||||
-rw-r--r-- | xlators/protocol/server/src/server-helpers.c | 31 | ||||
-rw-r--r-- | xlators/protocol/server/src/server.c | 11 |
11 files changed, 386 insertions, 23 deletions
diff --git a/cli/src/cli-cmd-parser.c b/cli/src/cli-cmd-parser.c index 151aafdb9..915d08304 100644 --- a/cli/src/cli-cmd-parser.c +++ b/cli/src/cli-cmd-parser.c @@ -2924,7 +2924,7 @@ cli_snap_list_parse (dict_t *dict, const char **words, int wordcount, int cmdi) " or volname specified is not equal 1"); goto out; } - snap_name = words[i]; // word followed by -s is snapname + snap_name = (char*) words[i]; // word followed by -s is snapname } else if (strcmp (words[i], "-c") == 0) { if ((wordcount - 1) == i || (cg_name != NULL) || strcmp (words[++i], "-d") == 0 @@ -2936,7 +2936,7 @@ cli_snap_list_parse (dict_t *dict, const char **words, int wordcount, int cmdi) " or cg_name already parsed"); goto out; } - cg_name = words[i]; + cg_name = (char*) words[i]; } else { if (vol_count != 0) { /* if vol names already set */ @@ -2996,7 +2996,7 @@ cli_snap_list_parse (dict_t *dict, const char **words, int wordcount, int cmdi) ret = dict_set_int64 (dict, "vol_count", vol_count); /* fill volume name in dictionary */ for (i = 0; i < vol_count; ++i) { - vol_name = words[vol_start_index + i]; + vol_name = (char*) words[vol_start_index + i]; snprintf (key, sizeof (key), "vol%d", i); ret = dict_set_str (dict, key, vol_name); if (ret) { diff --git a/glusterfsd/src/glusterfsd-mgmt.c b/glusterfsd/src/glusterfsd-mgmt.c index e40d19b08..ad4579c99 100644 --- a/glusterfsd/src/glusterfsd-mgmt.c +++ b/glusterfsd/src/glusterfsd-mgmt.c @@ -1193,6 +1193,83 @@ out: } int +glusterfs_handle_volume_barrier_op (rpcsvc_request_t *req) +{ + int32_t ret = -1; + gd1_mgmt_brick_op_req xlator_req = {0,}; + dict_t *dict = NULL; + xlator_t *xlator = NULL; + xlator_t *any = NULL; + dict_t *output = NULL; + char msg[2048] = {0}; + glusterfs_ctx_t *ctx = NULL; + glusterfs_graph_t *active = NULL; + xlator_t *this = NULL; + + GF_ASSERT (req); + this = THIS; + GF_ASSERT (this); + + ctx = glusterfsd_ctx; + GF_ASSERT (ctx); + + active = ctx->active; + if (!active) { + req->rpc_err = GARBAGE_ARGS; + goto out; + } + + any = active->first; + ret = xdr_to_generic (req->msg[0], &xlator_req, + (xdrproc_t)xdr_gd1_mgmt_brick_op_req); + if (ret < 0) { + //failed to decode msg; + req->rpc_err = GARBAGE_ARGS; + goto out; + } + dict = dict_new (); + if (!dict) + goto out; + + ret = dict_unserialize (xlator_req.input.input_val, + xlator_req.input.input_len, + &dict); + if (ret < 0) { + gf_log (this->name, GF_LOG_ERROR, + "failed to " + "unserialize req-buffer to dictionary"); + goto out; + } + xlator = xlator_search_by_name (any, xlator_req.name); + if (!xlator) { + snprintf (msg, sizeof (msg), "xlator %s is not loaded", + xlator_req.name); + goto out; + } + + output = dict_new (); + if (!output) { + ret = -1; + goto out; + } + + ret = xlator->notify (xlator, GF_EVENT_VOLUME_BARRIER_OP, + dict, output); + + ret = glusterfs_translator_info_response_send (req, ret, + msg, output); +out: + if (dict) + dict_unref (dict); + free (xlator_req.input.input_val); // malloced by xdr + if (output) + dict_unref (output); + free (xlator_req.name); //malloced by xdr + + return ret; + +} +int glusterfs_handle_rpc_msg (rpcsvc_request_t *req) { int ret = -1; @@ -1256,6 +1333,7 @@ rpcsvc_actor_t glusterfs_actors[] = { [GLUSTERD_BRICK_XLATOR_DEFRAG] = {"TRANSLATOR DEFRAG", GLUSTERD_BRICK_XLATOR_DEFRAG, glusterfs_handle_defrag, NULL, 0, DRC_NA}, [GLUSTERD_NODE_PROFILE] = {"NFS PROFILE", GLUSTERD_NODE_PROFILE, glusterfs_handle_nfs_profile, NULL, 0, DRC_NA}, [GLUSTERD_NODE_STATUS] = {"NFS STATUS", GLUSTERD_NODE_STATUS, glusterfs_handle_node_status, NULL, 0, DRC_NA}, + [GLUSTERD_VOLUME_BARRIER_OP] = {"VOLUME BARRIER OP", GLUSTERD_VOLUME_BARRIER_OP, glusterfs_handle_volume_barrier_op, NULL, 0, DRC_NA}, #ifdef HAVE_BD_XLATOR [GLUSTERD_BRICK_BD_OP] = {"BD OP", GLUSTERD_BRICK_BD_OP, glusterfs_handle_bd_op, NULL, 0, DRC_NA} #endif diff --git a/libglusterfs/src/glusterfs.h b/libglusterfs/src/glusterfs.h index 5fd0c1030..59979e99a 100644 --- a/libglusterfs/src/glusterfs.h +++ b/libglusterfs/src/glusterfs.h @@ -448,6 +448,7 @@ typedef enum { GF_EVENT_AUTH_FAILED, GF_EVENT_VOLUME_DEFRAG, GF_EVENT_PARENT_DOWN, + GF_EVENT_VOLUME_BARRIER_OP, GF_EVENT_MAXVAL, } glusterfs_event_t; diff --git a/rpc/rpc-lib/src/protocol-common.h b/rpc/rpc-lib/src/protocol-common.h index 1c020ae92..133a0b9d4 100644 --- a/rpc/rpc-lib/src/protocol-common.h +++ b/rpc/rpc-lib/src/protocol-common.h @@ -195,6 +195,7 @@ enum glusterd_brick_procnum { GLUSTERD_NODE_PROFILE, GLUSTERD_NODE_STATUS, GLUSTERD_BRICK_BD_OP, + GLUSTERD_VOLUME_BARRIER_OP, GLUSTERD_BRICK_MAXVALUE, }; diff --git a/xlators/mgmt/glusterd/src/glusterd-jarvis.c b/xlators/mgmt/glusterd/src/glusterd-jarvis.c index b1f003b89..c878288c2 100644 --- a/xlators/mgmt/glusterd/src/glusterd-jarvis.c +++ b/xlators/mgmt/glusterd/src/glusterd-jarvis.c @@ -140,8 +140,45 @@ gd_jarvis_brick_op_fn (glusterd_op_t op, dict_t *dict, { int ret = -1; xlator_t *this = THIS; + int64_t vol_count = 0; + int64_t count = 1; + char key[1024] = {0,}; + char *volname = NULL; - ret = 0; + switch (op) { + case GD_OP_SNAP: + { + + ret = dict_get_int64 (dict, "volcount", &vol_count); + if (ret) + goto out; + while (count <= vol_count) { + snprintf (key, 1024, "volname%"PRId64, count); + ret = dict_get_str (dict, key, &volname); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, "Unable to get" + " volname"); + goto out; + } + ret = dict_set_str (dict, "volname", volname); + if (ret) + goto out; + + ret = gd_brick_op_phase (op, NULL, dict, op_errstr); + if (ret) + goto out; + volname = NULL; + count++; + } + + dict_del (dict, "volname"); + + break; + } + default: + break; + } +out: gf_log (this->name, GF_LOG_DEBUG, "OP = %d. Returning %d", op, ret); return ret; } @@ -1330,3 +1367,165 @@ cleanup: return 0; } + +int32_t +glusterd_jarvis_initiate_snap_phases (rpcsvc_request_t *req, glusterd_op_t op, + dict_t *dict) +{ + int ret = -1; + int npeers = 0; + dict_t *req_dict = NULL; + dict_t *tmp_dict = NULL; + glusterd_conf_t *conf = NULL; + char *op_errstr = NULL; + char *volname = NULL; + xlator_t *this = NULL; + gf_boolean_t is_acquired = _gf_false; + uuid_t *originator_uuid = NULL; + gf_boolean_t success = _gf_false; + + this = THIS; + GF_ASSERT (this); + conf = this->private; + GF_ASSERT (conf); + + /* Save the MY_UUID as the originator_uuid. This originator_uuid + * will be used by is_origin_glusterd() to determine if a node + * is the originator node for a command. */ + originator_uuid = GF_CALLOC (1, sizeof(uuid_t), + gf_common_mt_uuid_t); + if (!originator_uuid) { + ret = -1; + goto out; + } + + uuid_copy (*originator_uuid, MY_UUID); + ret = dict_set_bin (dict, "originator_uuid", + originator_uuid, sizeof (uuid_t)); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, + "Failed to set originator_uuid."); + goto out; + } + + /* Use a copy at local unlock as cli response will be sent before + * the unlock and the volname in the dict might be removed */ + tmp_dict = dict_new(); + if (!tmp_dict) { + gf_log ("", GF_LOG_ERROR, "Unable to create dict"); + goto out; + } + dict_copy (dict, tmp_dict); + + /* BUILD PEERS LIST */ + INIT_LIST_HEAD (&conf->xaction_peers); + npeers = gd_build_peers_list (&conf->peers, &conf->xaction_peers, op); + + /* LOCKDOWN PHASE - Based on the number of volumes either single + * or multiple volume locks is acquired */ + ret = glusterd_jarvis_initiate_lockdown (conf, op, dict, &op_errstr, + npeers, &is_acquired); + if (ret) { + gf_log ("", GF_LOG_ERROR, "Volume lockdown failed."); + goto out; + } + + /* BUILD PAYLOAD */ + ret = glusterd_jarvis_build_payload (&req_dict, &op_errstr, dict, op); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, LOGSTR_BUILD_PAYLOAD, + gd_op_list[op]); + if (op_errstr == NULL) + gf_asprintf (&op_errstr, OPERRSTR_BUILD_PAYLOAD); + goto out; + } + + /* PRE-COMMIT VALIDATE PHASE */ + ret = glusterd_jarvis_pre_validate (conf, op, req_dict, + &op_errstr, npeers); + if (ret) { + gf_log ("", GF_LOG_ERROR, "Pre Validation Failed"); + goto out; + } + + /* BRICK OP PHASE for initiating barrier*/ + ret = dict_set_int32 (req_dict, "barrier", 1); + if (ret) + goto out; + ret = glusterd_jarvis_brick_op (conf, op, req_dict, + &op_errstr, npeers); + if (ret) { + gf_log ("", GF_LOG_ERROR, "Brick Ops Failed"); + goto unbarrier; + } + + /* COMMIT OP PHASE */ + ret = glusterd_jarvis_commit (conf, op, req_dict, + &op_errstr, npeers); + if (ret) { + gf_log ("", GF_LOG_ERROR, "Commit Op Failed"); + goto unbarrier; + } + + success = _gf_true; +unbarrier: + /* BRICK OP PHASE for removing the barrier*/ + ret = dict_set_int32 (req_dict, "barrier", 0); + if (ret) + goto out; + ret = glusterd_jarvis_brick_op (conf, op, req_dict, + &op_errstr, npeers); + if (ret || (success == _gf_false)) { + gf_log ("", GF_LOG_ERROR, "Brick Ops Failed"); + goto out; + } + /* POST-COMMIT VALIDATE PHASE */ + ret = glusterd_jarvis_post_validate (conf, op, req_dict, + &op_errstr, npeers); + if (ret) { + gf_log ("", GF_LOG_ERROR, "Post Validation Failed"); + goto out; + } + + ret = 0; +out: + + /* UNLOCK PHASE FOR PEERS*/ + (void) glusterd_jarvis_release_peer_locks (conf, op, dict, &op_errstr, + npeers, is_acquired); + + /* SEND CLI RESPONSE */ + glusterd_op_send_cli_response (op, ret, 0, req, dict, op_errstr); + + /* LOCAL VOLUME(S) UNLOCK */ + if (!is_acquired) + goto cleanup; + + ret = dict_get_str (tmp_dict, "volname", &volname); + if (ret) { + /* Trying to release volume locks on multiple volumes */ + ret = glusterd_multiple_volumes_unlock (tmp_dict, MY_UUID); + if (ret) + gf_log ("", GF_LOG_ERROR, + "Failed to release volume locks on localhost"); + } else { + ret = glusterd_volume_unlock (volname, MY_UUID); + if (ret) + gf_log (this->name, GF_LOG_ERROR, + "Unable to release local lock for %s", volname); + } + +cleanup: + if (req_dict) + dict_unref (req_dict); + + if (tmp_dict) + dict_unref (tmp_dict); + + if (op_errstr) { + GF_FREE (op_errstr); + op_errstr = NULL; + } + + return 0; +} diff --git a/xlators/mgmt/glusterd/src/glusterd-jarvis.h b/xlators/mgmt/glusterd/src/glusterd-jarvis.h index d9e4f0af1..5b0e5e183 100644 --- a/xlators/mgmt/glusterd/src/glusterd-jarvis.h +++ b/xlators/mgmt/glusterd/src/glusterd-jarvis.h @@ -35,4 +35,7 @@ int32_t glusterd_jarvis_initiate_all_phases (rpcsvc_request_t *req, glusterd_op_t op, dict_t *dict); +int32_t +glusterd_jarvis_initiate_snap_phases (rpcsvc_request_t *req, glusterd_op_t op, + dict_t *dict); #endif diff --git a/xlators/mgmt/glusterd/src/glusterd-op-sm.c b/xlators/mgmt/glusterd/src/glusterd-op-sm.c index 6c41d6a21..fd2f73f70 100644 --- a/xlators/mgmt/glusterd/src/glusterd-op-sm.c +++ b/xlators/mgmt/glusterd/src/glusterd-op-sm.c @@ -377,6 +377,20 @@ glusterd_brick_op_build_payload (glusterd_op_t op, glusterd_brickinfo_t *brickin } break; #endif + case GD_OP_SNAP: + brick_req = GF_CALLOC (1, sizeof (*brick_req), + gf_gld_mt_mop_brick_req_t); + if (!brick_req) + goto out; + + brick_req->op = GLUSTERD_VOLUME_BARRIER_OP; + ret = dict_get_str (dict, "volname", &volname); + if (ret) + goto out; + snprintf (name, 1024, "%s-server",volname); + brick_req->name = gf_strdup (name); + + break; default: goto out; break; @@ -4926,6 +4940,60 @@ out: #endif static int +glusterd_bricks_select_snap (dict_t *dict, char **op_errstr, + struct list_head *selected) +{ + int ret = -1; + glusterd_conf_t *priv = NULL; + xlator_t *this = NULL; + glusterd_pending_node_t *pending_node = NULL; + glusterd_volinfo_t *volinfo = NULL; + char *volname = NULL; + glusterd_brickinfo_t *brickinfo = NULL; + int brick_index = -1; + + this = THIS; + GF_ASSERT (this); + priv = this->private; + GF_ASSERT (priv); + + ret = dict_get_str (dict, "volname", &volname); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, "Unable to get" + " volname"); + goto out; + } + ret = glusterd_volinfo_find (volname, &volinfo); + if (ret) + goto out; + + list_for_each_entry (brickinfo, &volinfo->bricks, brick_list) { + brick_index++; + if (uuid_compare (brickinfo->uuid, MY_UUID) || + !glusterd_is_brick_started (brickinfo)) { + continue; + } + pending_node = GF_CALLOC (1, sizeof (*pending_node), + gf_gld_mt_pending_node_t); + if (!pending_node) { + ret = -1; + goto out; + } + pending_node->node = brickinfo; + pending_node->type = GD_NODE_BRICK; + pending_node->index = brick_index; + list_add_tail (&pending_node->list, + selected); + pending_node = NULL; + } + + ret = 0; + +out: + gf_log (THIS->name, GF_LOG_DEBUG, "Returning ret %d", ret); + return ret; +} +static int fill_shd_status_for_local_bricks (dict_t *dict, glusterd_volinfo_t *volinfo) { glusterd_brickinfo_t *brickinfo = NULL; @@ -5421,6 +5489,9 @@ glusterd_op_bricks_select (glusterd_op_t op, dict_t *dict, char **op_errstr, ret = glusterd_bricks_select_bd (dict, op_errstr); break; #endif + case GD_OP_SNAP: + ret = glusterd_bricks_select_snap (dict, op_errstr, selected); + break; default: break; } diff --git a/xlators/mgmt/glusterd/src/glusterd-snapshot.c b/xlators/mgmt/glusterd/src/glusterd-snapshot.c index aa6d0b31d..00fc7daa0 100644 --- a/xlators/mgmt/glusterd/src/glusterd-snapshot.c +++ b/xlators/mgmt/glusterd/src/glusterd-snapshot.c @@ -2294,7 +2294,7 @@ glusterd_handle_snapshot_fn (rpcsvc_request_t *req) switch (type) { case GF_SNAP_OPTION_TYPE_CREATE: - ret = glusterd_jarvis_initiate_all_phases (req, cli_op, dict); + ret = glusterd_jarvis_initiate_snap_phases (req, cli_op, dict); break; case GF_SNAP_OPTION_TYPE_LIST: ret = glusterd_handle_snapshot_list (req, cli_op, dict); diff --git a/xlators/mgmt/glusterd/src/glusterd-syncop.h b/xlators/mgmt/glusterd/src/glusterd-syncop.h index cde63c454..35215a78a 100644 --- a/xlators/mgmt/glusterd/src/glusterd-syncop.h +++ b/xlators/mgmt/glusterd/src/glusterd-syncop.h @@ -59,5 +59,7 @@ gd_synctask_barrier_wait (struct syncargs *args, int count); int gd_build_peers_list (struct list_head *peers, struct list_head *xact_peers, glusterd_op_t op); - +int +gd_brick_op_phase (glusterd_op_t op, dict_t *op_ctx, dict_t *req_dict, + char **op_errstr); #endif /* __RPC_SYNCOP_H */ diff --git a/xlators/protocol/server/src/server-helpers.c b/xlators/protocol/server/src/server-helpers.c index 053670765..50aae6714 100644 --- a/xlators/protocol/server/src/server-helpers.c +++ b/xlators/protocol/server/src/server-helpers.c @@ -1144,14 +1144,12 @@ gf_barrier_dequeue (gf_barrier_t *barrier) if (!barrier || list_empty (&barrier->queue)) return NULL; - LOCK (&barrier->lock); - { - payload = list_entry (barrier->queue.next, - gf_barrier_payload_t, list); + payload = list_entry (barrier->queue.next, + gf_barrier_payload_t, list); + if (payload) { list_del_init (&payload->list); barrier->cur_size--; } - UNLOCK (&barrier->lock); return payload; } @@ -1169,17 +1167,20 @@ gf_barrier_dequeue_start (void *data) return; barrier = conf->barrier; - - while (!list_empty (&barrier->queue)) { - payload = gf_barrier_dequeue (barrier); - if (payload) { - if (gf_barrier_transmit (conf, payload)) { - gf_log ("server", GF_LOG_WARNING, - "Failed to transmit"); + LOCK (&barrier->lock); + { + while (barrier->cur_size) { + payload = gf_barrier_dequeue (barrier); + if (payload) { + if (gf_barrier_transmit (conf, payload)) { + gf_log ("server", GF_LOG_WARNING, + "Failed to transmit"); + } + GF_FREE (payload); } - GF_FREE (payload); } } + UNLOCK (&barrier->lock); return; } @@ -1195,6 +1196,7 @@ gf_barrier_timeout (void *data) goto out; barrier = conf->barrier; + gf_log ("", GF_LOG_INFO, "barrier timed-out"); LOCK (&barrier->lock); { need_dequeue = barrier->on; @@ -1225,6 +1227,7 @@ gf_barrier_start (xlator_t *this) barrier = conf->barrier; + gf_log (this->name, GF_LOG_INFO, "barrier start called"); LOCK (&barrier->lock); { /* if barrier is on, reset timer */ @@ -1273,6 +1276,7 @@ gf_barrier_stop (xlator_t *this) barrier = conf->barrier; + gf_log (this->name, GF_LOG_INFO, "barrier stop called"); LOCK (&barrier->lock); { need_dequeue = barrier->on; @@ -1344,6 +1348,7 @@ done: { barrier->fops = fops; } + UNLOCK (&barrier->lock); ret = 0; GF_FREE (dup_str); diff --git a/xlators/protocol/server/src/server.c b/xlators/protocol/server/src/server.c index 9a59634a9..327a4b390 100644 --- a/xlators/protocol/server/src/server.c +++ b/xlators/protocol/server/src/server.c @@ -139,6 +139,7 @@ server_submit_reply (call_frame_t *frame, rpcsvc_request_t *req, void *arg, server_conf_t *conf = NULL; gf_barrier_t *barrier = NULL; gf_barrier_payload_t *stub = NULL; + gf_boolean_t barriered = _gf_false; GF_VALIDATE_OR_GOTO ("server", req, ret); @@ -183,7 +184,7 @@ server_submit_reply (call_frame_t *frame, rpcsvc_request_t *req, void *arg, iob, new_iobref); if (stub) { gf_barrier_enqueue (barrier, stub); - goto ret; + barriered = _gf_true; } else { gf_log ("", GF_LOG_ERROR, "Failed to " " barrier fop %"PRIu64, @@ -192,6 +193,8 @@ server_submit_reply (call_frame_t *frame, rpcsvc_request_t *req, void *arg, } } UNLOCK (&barrier->lock); + if (barriered == _gf_false) + goto ret; } /* Then, submit the message for transmission. */ ret = rpcsvc_submit_generic (req, &rsp, 1, payload, payloadcount, @@ -937,6 +940,7 @@ init (xlator_t *this) } LOCK_INIT (&barrier->lock); + barrier->on = _gf_false; GF_OPTION_INIT ("barrier-queue-length", barrier->max_size, int64, out); @@ -1020,8 +1024,7 @@ notify (xlator_t *this, int32_t event, void *data, ...) va_end (ap); switch (event) { - /* todo: GF_EVENT_BARRIER */ - case 100: + case GF_EVENT_VOLUME_BARRIER_OP: ret = dict_get_int32 (dict, "barrier", &val); if (ret) { gf_log (this->name, GF_LOG_ERROR, @@ -1040,7 +1043,7 @@ notify (xlator_t *this, int32_t event, void *data, ...) gf_log (this->name, GF_LOG_ERROR, "Barrier stop failed"); } - ret = dict_set_int32 (dict, "barrier-status", ret); + ret = dict_set_int32 (output, "barrier-status", ret); if (ret) gf_log (this->name, GF_LOG_ERROR, "Failed to set barrier-status in dict"); |