summaryrefslogtreecommitdiffstats
path: root/xlators/mgmt/glusterd/src/glusterd-handler.c
diff options
context:
space:
mode:
Diffstat (limited to 'xlators/mgmt/glusterd/src/glusterd-handler.c')
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-handler.c310
1 files changed, 139 insertions, 171 deletions
diff --git a/xlators/mgmt/glusterd/src/glusterd-handler.c b/xlators/mgmt/glusterd/src/glusterd-handler.c
index e10dc22b56b..8e4071221de 100644
--- a/xlators/mgmt/glusterd/src/glusterd-handler.c
+++ b/xlators/mgmt/glusterd/src/glusterd-handler.c
@@ -101,9 +101,9 @@ glusterd_handle_friend_req (rpcsvc_request_t *req, uuid_t uuid,
port = GF_DEFAULT_BASE_PORT;
ret = glusterd_remote_hostname_get (req, rhost, sizeof (rhost));
- ret = glusterd_friend_find (uuid, rhost, &peerinfo);
+ peerinfo = glusterd_peerinfo_find (uuid, rhost);
- if (ret) {
+ if (peerinfo == NULL) {
ret = glusterd_xfer_friend_add_resp (req, hostname, rhost, port,
-1, GF_PROBE_UNKNOWN_PEER);
if (friend_req->vols.vols_val) {
@@ -196,9 +196,9 @@ glusterd_handle_unfriend_req (rpcsvc_request_t *req, uuid_t uuid,
if (!port)
port = GF_DEFAULT_BASE_PORT;
- ret = glusterd_friend_find (uuid, hostname, &peerinfo);
+ peerinfo = glusterd_peerinfo_find (uuid, hostname);
- if (ret) {
+ if (peerinfo == NULL) {
gf_log ("glusterd", GF_LOG_CRITICAL,
"Received remove-friend from unknown peer %s",
hostname);
@@ -252,54 +252,6 @@ out:
return ret;
}
-static int
-glusterd_add_peer_detail_to_dict (glusterd_peerinfo_t *peerinfo,
- dict_t *friends, int count)
-{
-
- int ret = -1;
- char key[256] = {0, };
- char *peer_uuid_str = NULL;
-
- GF_ASSERT (peerinfo);
- GF_ASSERT (friends);
-
- snprintf (key, 256, "friend%d.uuid", count);
- peer_uuid_str = gd_peer_uuid_str (peerinfo);
- ret = dict_set_str (friends, key, peer_uuid_str);
- if (ret)
- goto out;
-
- snprintf (key, 256, "friend%d.hostname", count);
- ret = dict_set_str (friends, key, peerinfo->hostname);
- if (ret)
- goto out;
-
- snprintf (key, 256, "friend%d.port", count);
- ret = dict_set_int32 (friends, key, peerinfo->port);
- if (ret)
- goto out;
-
- snprintf (key, 256, "friend%d.stateId", count);
- ret = dict_set_int32 (friends, key, peerinfo->state.state);
- if (ret)
- goto out;
-
- snprintf (key, 256, "friend%d.state", count);
- ret = dict_set_str (friends, key,
- glusterd_friend_sm_state_name_get(peerinfo->state.state));
- if (ret)
- goto out;
-
- snprintf (key, 256, "friend%d.connected", count);
- ret = dict_set_int32 (friends, key, (int32_t)peerinfo->connected);
- if (ret)
- goto out;
-
-out:
- return ret;
-}
-
struct args_pack {
dict_t *dict;
int vol_count;
@@ -561,44 +513,6 @@ out:
return ret;
}
-int
-glusterd_friend_find (uuid_t uuid, char *hostname,
- glusterd_peerinfo_t **peerinfo)
-{
- int ret = -1;
- xlator_t *this = NULL;
-
- this = THIS;
- GF_ASSERT (this);
-
- if (uuid) {
- ret = glusterd_friend_find_by_uuid (uuid, peerinfo);
-
- if (ret) {
- gf_log (this->name, GF_LOG_DEBUG,
- "Unable to find peer by uuid: %s",
- uuid_utoa (uuid));
- } else {
- goto out;
- }
-
- }
-
- if (hostname) {
- ret = glusterd_friend_find_by_hostname (hostname, peerinfo);
-
- if (ret) {
- gf_log (this->name, GF_LOG_DEBUG,
- "Unable to find hostname: %s", hostname);
- } else {
- goto out;
- }
- }
-
-out:
- return ret;
-}
-
int32_t
glusterd_op_txn_begin (rpcsvc_request_t *req, glusterd_op_t op, void *ctx,
char *err_str, size_t err_len)
@@ -752,7 +666,6 @@ __glusterd_handle_cluster_lock (rpcsvc_request_t *req)
gd1_mgmt_cluster_lock_req lock_req = {{0},};
glusterd_op_lock_ctx_t *ctx = NULL;
glusterd_op_t op = GD_OP_EVENT_LOCK;
- glusterd_peerinfo_t *peerinfo = NULL;
glusterd_op_info_t txn_op_info = {{0},};
glusterd_conf_t *priv = NULL;
uuid_t *txn_id = NULL;
@@ -778,7 +691,7 @@ __glusterd_handle_cluster_lock (rpcsvc_request_t *req)
gf_log (this->name, GF_LOG_DEBUG, "Received LOCK from uuid: %s",
uuid_utoa (lock_req.uuid));
- if (glusterd_friend_find_by_uuid (lock_req.uuid, &peerinfo)) {
+ if (glusterd_peerinfo_find_by_uuid (lock_req.uuid) == NULL) {
gf_log (this->name, GF_LOG_WARNING, "%s doesn't "
"belong to the cluster. Ignoring request.",
uuid_utoa (lock_req.uuid));
@@ -891,7 +804,6 @@ __glusterd_handle_stage_op (rpcsvc_request_t *req)
int32_t ret = -1;
glusterd_req_ctx_t *req_ctx = NULL;
gd1_mgmt_stage_op_req op_req = {{0},};
- glusterd_peerinfo_t *peerinfo = NULL;
xlator_t *this = NULL;
uuid_t *txn_id = NULL;
glusterd_op_info_t txn_op_info = {{0},};
@@ -927,7 +839,7 @@ __glusterd_handle_stage_op (rpcsvc_request_t *req)
gf_log (this->name, GF_LOG_DEBUG, "transaction ID = %s",
uuid_utoa (*txn_id));
- if (glusterd_friend_find_by_uuid (op_req.uuid, &peerinfo)) {
+ if (glusterd_peerinfo_find_by_uuid (op_req.uuid) == NULL) {
gf_log (this->name, GF_LOG_WARNING, "%s doesn't "
"belong to the cluster. Ignoring request.",
uuid_utoa (op_req.uuid));
@@ -982,7 +894,6 @@ __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},};
- glusterd_peerinfo_t *peerinfo = NULL;
xlator_t *this = NULL;
uuid_t *txn_id = NULL;
glusterd_conf_t *priv = NULL;
@@ -1004,7 +915,7 @@ __glusterd_handle_commit_op (rpcsvc_request_t *req)
goto out;
}
- if (glusterd_friend_find_by_uuid (op_req.uuid, &peerinfo)) {
+ if (glusterd_peerinfo_find_by_uuid (op_req.uuid) == NULL) {
gf_log (this->name, GF_LOG_WARNING, "%s doesn't "
"belong to the cluster. Ignoring request.",
uuid_utoa (op_req.uuid));
@@ -1119,16 +1030,13 @@ __glusterd_handle_cli_probe (rpcsvc_request_t *req)
goto out;
}
- if (!(ret = glusterd_friend_find_by_hostname (hostname, &peerinfo))) {
- if (strcmp (peerinfo->hostname, hostname) == 0) {
-
- gf_log ("glusterd", GF_LOG_DEBUG, "Probe host %s port "
- "%d already a peer", hostname, port);
- glusterd_xfer_cli_probe_resp (req, 0, GF_PROBE_FRIEND,
- NULL, hostname, port,
- dict);
- goto out;
- }
+ peerinfo = glusterd_peerinfo_find_by_hostname (hostname);
+ if (peerinfo && gd_peer_has_address (peerinfo, hostname)) {
+ gf_log ("glusterd", GF_LOG_DEBUG, "Probe host %s port %d "
+ "already a peer", hostname, port);
+ glusterd_xfer_cli_probe_resp (req, 0, GF_PROBE_FRIEND, NULL,
+ hostname, port, dict);
+ goto out;
}
ret = glusterd_probe_begin (req, hostname, port, dict, &op_errno);
@@ -2021,9 +1929,8 @@ __glusterd_handle_fsm_log (rpcsvc_request_t *req)
conf = this->private;
log = &conf->op_sm_log;
} else {
- ret = glusterd_friend_find_by_hostname (cli_req.name,
- &peerinfo);
- if (ret) {
+ peerinfo = glusterd_peerinfo_find_by_hostname (cli_req.name);
+ if (!peerinfo) {
snprintf (msg, sizeof (msg), "%s is not a peer",
cli_req.name);
goto out;
@@ -2150,7 +2057,6 @@ __glusterd_handle_cluster_unlock (rpcsvc_request_t *req)
gd1_mgmt_cluster_unlock_req unlock_req = {{0}, };
int32_t ret = -1;
glusterd_op_lock_ctx_t *ctx = NULL;
- glusterd_peerinfo_t *peerinfo = NULL;
xlator_t *this = NULL;
uuid_t *txn_id = NULL;
glusterd_conf_t *priv = NULL;
@@ -2176,7 +2082,7 @@ __glusterd_handle_cluster_unlock (rpcsvc_request_t *req)
gf_log (this->name, GF_LOG_DEBUG,
"Received UNLOCK from uuid: %s", uuid_utoa (unlock_req.uuid));
- if (glusterd_friend_find_by_uuid (unlock_req.uuid, &peerinfo)) {
+ if (glusterd_peerinfo_find_by_uuid (unlock_req.uuid) == NULL) {
gf_log (this->name, GF_LOG_WARNING, "%s doesn't "
"belong to the cluster. Ignoring request.",
uuid_utoa (unlock_req.uuid));
@@ -2402,24 +2308,21 @@ out:
}
int
-glusterd_friend_hostname_update (glusterd_peerinfo_t *peerinfo,
- char *hostname,
- gf_boolean_t store_update)
+glusterd_peer_hostname_update (glusterd_peerinfo_t *peerinfo,
+ const char *hostname, gf_boolean_t store_update)
{
- char *new_hostname = NULL;
int ret = 0;
GF_ASSERT (peerinfo);
GF_ASSERT (hostname);
- new_hostname = gf_strdup (hostname);
- if (!new_hostname) {
- ret = -1;
+ ret = gd_add_address_to_peer (peerinfo, hostname);
+ if (ret) {
+ gf_log (THIS->name, GF_LOG_ERROR,
+ "Couldn't add address to the peer info");
goto out;
}
- GF_FREE (peerinfo->hostname);
- peerinfo->hostname = new_hostname;
if (store_update)
ret = glusterd_store_peerinfo (peerinfo);
out:
@@ -2435,12 +2338,10 @@ __glusterd_handle_friend_update (rpcsvc_request_t *req)
glusterd_peerinfo_t *peerinfo = NULL;
glusterd_conf_t *priv = NULL;
xlator_t *this = NULL;
- glusterd_peerinfo_t *tmp = NULL;
gd1_mgmt_friend_update_rsp rsp = {{0},};
dict_t *dict = NULL;
char key[100] = {0,};
char *uuid_buf = NULL;
- char *hostname = NULL;
int i = 1;
int count = 0;
uuid_t uuid = {0,};
@@ -2462,8 +2363,8 @@ __glusterd_handle_friend_update (rpcsvc_request_t *req)
goto out;
}
- ret = glusterd_friend_find (friend_req.uuid, NULL, &tmp);
- if (ret) {
+ if (glusterd_peerinfo_find (friend_req.uuid, NULL) == NULL) {
+ ret = -1;
gf_log ("", GF_LOG_CRITICAL, "Received friend update request "
"from unknown peer %s", uuid_utoa (friend_req.uuid));
goto out;
@@ -2503,46 +2404,59 @@ __glusterd_handle_friend_update (rpcsvc_request_t *req)
args.mode = GD_MODE_ON;
while ( i <= count) {
+ memset (key, 0, sizeof (key));
snprintf (key, sizeof (key), "friend%d.uuid", i);
ret = dict_get_str (dict, key, &uuid_buf);
if (ret)
goto out;
uuid_parse (uuid_buf, uuid);
- snprintf (key, sizeof (key), "friend%d.hostname", i);
- ret = dict_get_str (dict, key, &hostname);
- if (ret)
- goto out;
-
- gf_log ("", GF_LOG_INFO, "Received uuid: %s, hostname:%s",
- uuid_buf, hostname);
-
- if (uuid_is_null (uuid)) {
- gf_log (this->name, GF_LOG_WARNING, "Updates mustn't "
- "contain peer with 'null' uuid");
- continue;
- }
if (!uuid_compare (uuid, MY_UUID)) {
- gf_log ("", GF_LOG_INFO, "Received my uuid as Friend");
+ gf_log (this->name, GF_LOG_INFO,
+ "Received my uuid as Friend");
i++;
continue;
}
- ret = glusterd_friend_find (uuid, hostname, &tmp);
+ memset (key, 0, sizeof (key));
+ snprintf (key, sizeof (key), "friend%d", i);
+
+ peerinfo = glusterd_peerinfo_find (uuid, NULL);
+ if (peerinfo == NULL) {
+ /* Create a new peer and add it to the list as there is
+ * no existing peer with the uuid
+ */
+ peerinfo = gd_peerinfo_from_dict (dict, key);
+ if (peerinfo == NULL) {
+ ret = -1;
+ gf_log (this->name, GF_LOG_ERROR,
+ "Could not create peerinfo from dict "
+ "for prefix %s", key);
+ goto out;
+ }
+
+ /* As this is a new peer, it should be added as a
+ * friend. The friend state machine will take care of
+ * correcting the state as required
+ */
+ peerinfo->state.state = GD_FRIEND_STATE_BEFRIENDED;
- if (!ret) {
- if (strcmp (hostname, tmp->hostname) != 0) {
- glusterd_friend_hostname_update (tmp, hostname,
- _gf_true);
+ ret = glusterd_friend_add_from_peerinfo (peerinfo, 0,
+ &args);
+ } else {
+ /* As an existing peer was found, update it with the new
+ * information
+ */
+ ret = gd_update_peerinfo_from_dict (peerinfo, dict,
+ key);
+ if (ret) {
+ gf_log (this->name, GF_LOG_ERROR, "Failed to "
+ "update peer %s", peerinfo->hostname);
+ goto out;
}
- i++;
- continue;
}
- ret = glusterd_friend_add (hostname, friend_req.port,
- GD_FRIEND_STATE_BEFRIENDED,
- &uuid, &peerinfo, 0, &args);
-
+ peerinfo = NULL;
i++;
}
@@ -2558,6 +2472,9 @@ out:
free (friend_req.friends.friends_val);//malloced by xdr
}
+ if (peerinfo)
+ glusterd_peerinfo_cleanup (peerinfo);
+
glusterd_friend_sm ();
glusterd_op_sm ();
@@ -2625,11 +2542,11 @@ __glusterd_handle_probe_query (rpcsvc_request_t *req)
gf_log ("", GF_LOG_ERROR, "Unable to get the remote hostname");
goto out;
}
- ret = glusterd_friend_find (probe_req.uuid, remote_hostname, &peerinfo);
- if ((ret != 0 ) && (!list_empty (&conf->peers))) {
+ peerinfo = glusterd_peerinfo_find (probe_req.uuid, remote_hostname);
+ if ((peerinfo == NULL) && (!list_empty (&conf->peers))) {
rsp.op_ret = -1;
rsp.op_errno = GF_PROBE_ANOTHER_CLUSTER;
- } else if (ret) {
+ } else if (peerinfo == NULL) {
gf_log ("glusterd", GF_LOG_INFO, "Unable to find peerinfo"
" for host: %s (%d)", remote_hostname, port);
args.mode = GD_MODE_ON;
@@ -2951,17 +2868,17 @@ glusterd_handle_umount (rpcsvc_request_t *req)
int
glusterd_friend_remove (uuid_t uuid, char *hostname)
{
- int ret = 0;
+ int ret = -1;
glusterd_peerinfo_t *peerinfo = NULL;
- ret = glusterd_friend_find (uuid, hostname, &peerinfo);
- if (ret)
+ peerinfo = glusterd_peerinfo_find (uuid, hostname);
+ if (peerinfo == NULL)
goto out;
ret = glusterd_friend_remove_cleanup_vols (peerinfo->uuid);
if (ret)
gf_log (THIS->name, GF_LOG_WARNING, "Volumes cleanup failed");
- ret = glusterd_friend_cleanup (peerinfo);
+ ret = glusterd_peerinfo_cleanup (peerinfo);
out:
gf_log ("", GF_LOG_DEBUG, "returning %d", ret);
return ret;
@@ -3068,10 +2985,10 @@ int
glusterd_friend_rpc_create (xlator_t *this, glusterd_peerinfo_t *peerinfo,
glusterd_peerctx_args_t *args)
{
- dict_t *options = NULL;
- int ret = -1;
- glusterd_peerctx_t *peerctx = NULL;
- data_t *data = NULL;
+ dict_t *options = NULL;
+ int ret = -1;
+ glusterd_peerctx_t *peerctx = NULL;
+ data_t *data = NULL;
peerctx = GF_CALLOC (1, sizeof (*peerctx), gf_gld_mt_peerctx_t);
if (!peerctx)
@@ -3136,9 +3053,11 @@ glusterd_friend_add (const char *hoststr, int port,
conf = this->private;
GF_ASSERT (conf);
GF_ASSERT (hoststr);
+ GF_ASSERT (friend);
- ret = glusterd_peerinfo_new (friend, state, uuid, hoststr, port);
- if (ret) {
+ *friend = glusterd_peerinfo_new (state, uuid, hoststr, port);
+ if (*friend == NULL) {
+ ret = -1;
goto out;
}
@@ -3167,7 +3086,7 @@ glusterd_friend_add (const char *hoststr, int port,
}
if (ret) {
- (void) glusterd_friend_cleanup (*friend);
+ (void) glusterd_peerinfo_cleanup (*friend);
*friend = NULL;
}
@@ -3176,6 +3095,54 @@ out:
return ret;
}
+/* glusterd_friend_add_from_peerinfo() adds a new peer into the local friends
+ * list from a pre created @peerinfo object. It otherwise works similarly to
+ * glusterd_friend_add()
+ */
+int
+glusterd_friend_add_from_peerinfo (glusterd_peerinfo_t *friend,
+ gf_boolean_t restore,
+ glusterd_peerctx_args_t *args)
+{
+ int ret = 0;
+ xlator_t *this = NULL;
+ glusterd_conf_t *conf = NULL;
+
+ this = THIS;
+ conf = this->private;
+ GF_ASSERT (conf);
+
+ GF_VALIDATE_OR_GOTO (this->name, (friend != NULL), out);
+
+ /*
+ * We can't add to the list after calling glusterd_friend_rpc_create,
+ * even if it succeeds, because by then the callback to take it back
+ * off and free might have happened already (notably in the case of an
+ * invalid peer name). That would mean we're adding something that had
+ * just been free, and we're likely to crash later.
+ */
+ list_add_tail (&friend->uuid_list, &conf->peers);
+
+ //restore needs to first create the list of peers, then create rpcs
+ //to keep track of quorum in race-free manner. In restore for each peer
+ //rpc-create calls rpc_notify when the friend-list is partially
+ //constructed, leading to wrong quorum calculations.
+ if (!restore) {
+ ret = glusterd_store_peerinfo (friend);
+ if (ret == 0) {
+ ret = glusterd_friend_rpc_create (this, friend, args);
+ }
+ else {
+ gf_log (this->name, GF_LOG_ERROR,
+ "Failed to store peerinfo");
+ }
+ }
+
+out:
+ gf_log (this->name, GF_LOG_INFO, "connect returned %d", ret);
+ return ret;
+}
+
int
glusterd_probe_begin (rpcsvc_request_t *req, const char *hoststr, int port,
dict_t *dict, int *op_errno)
@@ -3187,15 +3154,15 @@ glusterd_probe_begin (rpcsvc_request_t *req, const char *hoststr, int port,
GF_ASSERT (hoststr);
- ret = glusterd_friend_find (NULL, (char *)hoststr, &peerinfo);
+ peerinfo = glusterd_peerinfo_find (NULL, hoststr);
- if (ret) {
+ if (peerinfo == NULL) {
gf_log ("glusterd", GF_LOG_INFO, "Unable to find peerinfo"
" for host: %s (%d)", hoststr, port);
args.mode = GD_MODE_ON;
args.req = req;
args.dict = dict;
- ret = glusterd_friend_add ((char *)hoststr, port,
+ ret = glusterd_friend_add (hoststr, port,
GD_FRIEND_STATE_DEFAULT,
NULL, &peerinfo, 0, &args);
if ((!ret) && (!peerinfo->connected)) {
@@ -3210,8 +3177,8 @@ glusterd_probe_begin (rpcsvc_request_t *req, const char *hoststr, int port,
*op_errno = GF_PROBE_FRIEND_DETACHING;
goto out;
}
- ret = glusterd_friend_hostname_update (peerinfo, (char*)hoststr,
- _gf_false);
+ ret = glusterd_peer_hostname_update (peerinfo, hoststr,
+ _gf_false);
if (ret)
goto out;
//this is just to rename so inject local acc for cluster update
@@ -3246,9 +3213,10 @@ glusterd_deprobe_begin (rpcsvc_request_t *req, const char *hoststr, int port,
GF_ASSERT (hoststr);
GF_ASSERT (req);
- ret = glusterd_friend_find (uuid, (char *)hoststr, &peerinfo);
+ peerinfo = glusterd_peerinfo_find (uuid, hoststr);
- if (ret) {
+ if (peerinfo == NULL) {
+ ret = -1;
gf_log ("glusterd", GF_LOG_INFO, "Unable to find peerinfo"
" for host: %s %d", hoststr, port);
goto out;
@@ -3614,7 +3582,7 @@ glusterd_list_friends (rpcsvc_request_t *req, dict_t *dict, int32_t flags)
if (!list_empty (&priv->peers)) {
list_for_each_entry (entry, &priv->peers, uuid_list) {
count++;
- ret = glusterd_add_peer_detail_to_dict (entry,
+ ret = gd_add_peer_detail_to_dict (entry,
friends, count);
if (ret)
goto out;