summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cli/src/cli-rpc-ops.c39
-rw-r--r--cli/src/cli-xml-output.c47
-rw-r--r--doc/gluster.82
-rw-r--r--libglusterfs/src/common-utils.c33
-rw-r--r--libglusterfs/src/common-utils.h3
-rw-r--r--xlators/mgmt/glusterd/src/Makefile.am6
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-handler.c310
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-mgmt-handler.c18
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-op-sm.c5
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-peer-utils.c902
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-peer-utils.h87
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-replace-brick.c5
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-rpc-ops.c142
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-sm.c20
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-sm.h5
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-store.c91
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-syncop.c10
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-utils.c407
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-utils.h44
-rw-r--r--xlators/mgmt/glusterd/src/glusterd.h8
20 files changed, 1462 insertions, 722 deletions
diff --git a/cli/src/cli-rpc-ops.c b/cli/src/cli-rpc-ops.c
index ee7d3b2c841..b7c6691abd5 100644
--- a/cli/src/cli-rpc-ops.c
+++ b/cli/src/cli-rpc-ops.c
@@ -215,6 +215,31 @@ out:
}
int
+gf_cli_output_peer_hostnames (dict_t *dict, int count, char *prefix)
+{
+ int ret = -1;
+ char key[256] = {0,};
+ int i = 0;
+ char *hostname = NULL;
+
+ cli_out ("Other names:");
+ /* Starting from friend.hostname1, as friend.hostname0 will be the same
+ * as friend.hostname
+ */
+ for (i = 1; i < count; i++) {
+ memset (key, 0, sizeof (key));
+ snprintf (key, sizeof (key), "%s.hostname%d", prefix, i);
+ ret = dict_get_str (dict, key, &hostname);
+ if (ret)
+ break;
+ cli_out ("%s", hostname);
+ hostname = NULL;
+ }
+
+ return ret;
+}
+
+int
gf_cli_output_peer_status (dict_t *dict, int count)
{
int ret = -1;
@@ -225,6 +250,7 @@ gf_cli_output_peer_status (dict_t *dict, int count)
char *state = NULL;
int32_t connected = 0;
char *connected_str = NULL;
+ int hostname_count = 0;
cli_out ("Number of Peers: %d", count);
i = 1;
@@ -256,6 +282,19 @@ gf_cli_output_peer_status (dict_t *dict, int count)
cli_out ("\nHostname: %s\nUuid: %s\nState: %s (%s)",
hostname_buf, uuid_buf, state, connected_str);
+
+ memset (key, 0, sizeof (key));
+ snprintf (key, sizeof (key), "friend%d.hostname_count", i);
+ ret = dict_get_int32 (dict, key, &hostname_count);
+ /* Print other addresses only if there are more than 1.
+ */
+ if ((ret == 0) && (hostname_count > 1)) {
+ memset (key, 0, sizeof (key));
+ snprintf (key, sizeof (key), "friend%d", i);
+ ret = gf_cli_output_peer_hostnames (dict,
+ hostname_count,
+ key);
+ }
i++;
}
diff --git a/cli/src/cli-xml-output.c b/cli/src/cli-xml-output.c
index dd38a51c6c0..78d131583e9 100644
--- a/cli/src/cli-xml-output.c
+++ b/cli/src/cli-xml-output.c
@@ -3018,6 +3018,41 @@ out:
#endif
}
+#if (HAVE_LIB_XML)
+static int
+cli_xml_output_peer_hostnames (xmlTextWriterPtr writer, dict_t *dict,
+ const char *prefix, int count)
+{
+ int ret = -1;
+ int i = 0;
+ char *hostname = NULL;
+ char key[1024] = {0,};
+
+ /* <hostnames> */
+ ret = xmlTextWriterStartElement (writer, (xmlChar *)"hostnames");
+ XML_RET_CHECK_AND_GOTO (ret, out);
+
+ for (i = 0; i < count; i++) {
+ memset (key, 0, sizeof (key));
+ snprintf (key, sizeof (key), "%s.hostname%d", prefix, i);
+ ret = dict_get_str (dict, key, &hostname);
+ if (ret)
+ goto out;
+ ret = xmlTextWriterWriteFormatElement
+ (writer, (xmlChar *)"hostname", "%s", hostname);
+ XML_RET_CHECK_AND_GOTO (ret, out);
+ hostname = NULL;
+ }
+
+ /* </hostnames> */
+ ret = xmlTextWriterEndElement (writer);
+
+out:
+ gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret);
+ return ret;
+}
+#endif
+
int
cli_xml_output_peer_status (dict_t *dict, int op_ret, int op_errno,
char *op_errstr)
@@ -3032,6 +3067,7 @@ cli_xml_output_peer_status (dict_t *dict, int op_ret, int op_errno,
int connected = 0;
int state_id = 0;
char *state_str = NULL;
+ int hostname_count = 0;
int i = 1;
char key[1024] = {0,};
@@ -3082,6 +3118,17 @@ cli_xml_output_peer_status (dict_t *dict, int op_ret, int op_errno,
XML_RET_CHECK_AND_GOTO (ret, out);
memset (key, 0, sizeof (key));
+ snprintf (key, sizeof (key), "friend%d.hostname_count", i);
+ ret = dict_get_int32 (dict, key, &hostname_count);
+ if ((ret == 0) && (hostname_count > 0)) {
+ memset (key, 0, sizeof (key));
+ snprintf (key, sizeof (key), "friend%d", i);
+ ret = cli_xml_output_peer_hostnames (writer, dict, key,
+ hostname_count);
+ XML_RET_CHECK_AND_GOTO (ret, out);
+ }
+
+ memset (key, 0, sizeof (key));
snprintf (key, sizeof (key), "friend%d.connected", i);
ret = dict_get_int32 (dict, key, &connected);
if (ret)
diff --git a/doc/gluster.8 b/doc/gluster.8
index de3eee1b0e2..87b83956ce6 100644
--- a/doc/gluster.8
+++ b/doc/gluster.8
@@ -95,7 +95,7 @@ Rotate the log file for corresponding volume/brick.
.SS "Peer Commands"
.TP
\fB\ peer probe <HOSTNAME> \fR
-Probe the specified peer.
+Probe the specified peer. In case the <HOSTNAME> given belongs to an already probed peer, the peer probe command will add the hostname to the peer if required.
.TP
\fB\ peer detach <HOSTNAME> \fR
Detach the specified peer.
diff --git a/libglusterfs/src/common-utils.c b/libglusterfs/src/common-utils.c
index 124b312f4a1..54ee3e53818 100644
--- a/libglusterfs/src/common-utils.c
+++ b/libglusterfs/src/common-utils.c
@@ -3199,3 +3199,36 @@ gf_check_logger (const char *value)
return logger;
}
+
+/* gf_compare_sockaddr compares the given addresses @addr1 and @addr2 for
+ * equality, ie. if they both refer to the same address.
+ *
+ * This was inspired by sock_addr_cmp_addr() from
+ * https://www.opensource.apple.com/source/postfix/postfix-197/postfix/src/util/sock_addr.c
+ */
+gf_boolean_t
+gf_compare_sockaddr (const struct sockaddr *addr1,
+ const struct sockaddr *addr2)
+{
+ GF_ASSERT (addr1 != NULL);
+ GF_ASSERT (addr2 != NULL);
+
+ /* Obviously, the addresses don't match if their families are different
+ */
+ if (addr1->sa_family != addr2->sa_family)
+ return _gf_false;
+
+
+ if (AF_INET == addr1->sa_family) {
+ if (((struct sockaddr_in *)addr1)->sin_addr.s_addr ==
+ ((struct sockaddr_in *)addr2)->sin_addr.s_addr)
+ return _gf_true;
+
+ } else if (AF_INET6 == addr1->sa_family) {
+ if (memcmp ((char *)&((struct sockaddr_in6 *)addr1)->sin6_addr,
+ (char *)&((struct sockaddr_in6 *)addr2)->sin6_addr,
+ sizeof (struct in6_addr)) == 0)
+ return _gf_true;
+ }
+ return _gf_false;
+}
diff --git a/libglusterfs/src/common-utils.h b/libglusterfs/src/common-utils.h
index b4372f10bbc..1ddb46c6758 100644
--- a/libglusterfs/src/common-utils.h
+++ b/libglusterfs/src/common-utils.h
@@ -639,4 +639,7 @@ gf_check_log_format (const char *value);
int
gf_check_logger (const char *value);
+gf_boolean_t
+gf_compare_sockaddr (const struct sockaddr *addr1,
+ const struct sockaddr *addr2);
#endif /* _COMMON_UTILS_H */
diff --git a/xlators/mgmt/glusterd/src/Makefile.am b/xlators/mgmt/glusterd/src/Makefile.am
index e4636089ee7..7f3e8ddd88f 100644
--- a/xlators/mgmt/glusterd/src/Makefile.am
+++ b/xlators/mgmt/glusterd/src/Makefile.am
@@ -12,8 +12,8 @@ glusterd_la_SOURCES = glusterd.c glusterd-handler.c glusterd-sm.c \
glusterd-geo-rep.c glusterd-replace-brick.c glusterd-log-ops.c \
glusterd-volume-ops.c glusterd-brick-ops.c glusterd-mountbroker.c \
glusterd-syncop.c glusterd-hooks.c glusterd-volume-set.c \
- glusterd-locks.c glusterd-snapshot.c glusterd-mgmt-handler.c \
- glusterd-mgmt.c
+ glusterd-locks.c glusterd-snapshot.c glusterd-mgmt-handler.c \
+ glusterd-mgmt.c glusterd-peer-utils.c
glusterd_la_LIBADD = $(top_builddir)/libglusterfs/src/libglusterfs.la \
$(top_builddir)/rpc/xdr/src/libgfxdr.la \
@@ -24,7 +24,7 @@ noinst_HEADERS = glusterd.h glusterd-utils.h glusterd-op-sm.h \
glusterd-sm.h glusterd-store.h glusterd-mem-types.h \
glusterd-pmap.h glusterd-volgen.h glusterd-mountbroker.h \
glusterd-syncop.h glusterd-hooks.h glusterd-locks.h \
- glusterd-mgmt.h glusterd-messages.h
+ glusterd-mgmt.h glusterd-messages.h glusterd-peer-utils.h
AM_CPPFLAGS = $(GF_CPPFLAGS) -I$(top_srcdir)/libglusterfs/src \
-I$(rpclibdir) -I$(CONTRIBDIR)/rbtree \
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;
diff --git a/xlators/mgmt/glusterd/src/glusterd-mgmt-handler.c b/xlators/mgmt/glusterd/src/glusterd-mgmt-handler.c
index 48e390f5692..c0c1cfcba18 100644
--- a/xlators/mgmt/glusterd/src/glusterd-mgmt-handler.c
+++ b/xlators/mgmt/glusterd/src/glusterd-mgmt-handler.c
@@ -122,7 +122,6 @@ glusterd_handle_mgmt_v3_lock_fn (rpcsvc_request_t *req)
{
gd1_mgmt_v3_lock_req lock_req = {{0},};
int32_t ret = -1;
- glusterd_peerinfo_t *peerinfo = NULL;
glusterd_op_lock_ctx_t *ctx = NULL;
xlator_t *this = NULL;
gf_boolean_t is_synctasked = _gf_false;
@@ -144,7 +143,7 @@ glusterd_handle_mgmt_v3_lock_fn (rpcsvc_request_t *req)
gf_log (this->name, GF_LOG_DEBUG, "Received mgmt_v3 lock req "
"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));
@@ -247,7 +246,6 @@ glusterd_handle_pre_validate_fn (rpcsvc_request_t *req)
{
int32_t ret = -1;
gd1_mgmt_v3_pre_val_req op_req = {{0},};
- glusterd_peerinfo_t *peerinfo = NULL;
xlator_t *this = NULL;
char *op_errstr = NULL;
dict_t *dict = NULL;
@@ -267,7 +265,7 @@ glusterd_handle_pre_validate_fn (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));
@@ -374,7 +372,6 @@ glusterd_handle_brick_op_fn (rpcsvc_request_t *req)
{
int32_t ret = -1;
gd1_mgmt_v3_brick_op_req op_req = {{0},};
- glusterd_peerinfo_t *peerinfo = NULL;
xlator_t *this = NULL;
char *op_errstr = NULL;
dict_t *dict = NULL;
@@ -393,7 +390,7 @@ glusterd_handle_brick_op_fn (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));
@@ -499,7 +496,6 @@ glusterd_handle_commit_fn (rpcsvc_request_t *req)
{
int32_t ret = -1;
gd1_mgmt_v3_commit_req op_req = {{0},};
- glusterd_peerinfo_t *peerinfo = NULL;
xlator_t *this = NULL;
char *op_errstr = NULL;
dict_t *dict = NULL;
@@ -518,7 +514,7 @@ glusterd_handle_commit_fn (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));
@@ -625,7 +621,6 @@ glusterd_handle_post_validate_fn (rpcsvc_request_t *req)
{
int32_t ret = -1;
gd1_mgmt_v3_post_val_req op_req = {{0},};
- glusterd_peerinfo_t *peerinfo = NULL;
xlator_t *this = NULL;
char *op_errstr = NULL;
dict_t *dict = NULL;
@@ -645,7 +640,7 @@ glusterd_handle_post_validate_fn (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));
@@ -794,7 +789,6 @@ glusterd_handle_mgmt_v3_unlock_fn (rpcsvc_request_t *req)
gd1_mgmt_v3_unlock_req lock_req = {{0},};
int32_t ret = -1;
glusterd_op_lock_ctx_t *ctx = NULL;
- glusterd_peerinfo_t *peerinfo = NULL;
xlator_t *this = NULL;
gf_boolean_t is_synctasked = _gf_false;
gf_boolean_t free_ctx = _gf_false;
@@ -815,7 +809,7 @@ glusterd_handle_mgmt_v3_unlock_fn (rpcsvc_request_t *req)
gf_log (this->name, GF_LOG_DEBUG, "Received volume unlock req "
"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));
diff --git a/xlators/mgmt/glusterd/src/glusterd-op-sm.c b/xlators/mgmt/glusterd/src/glusterd-op-sm.c
index 66276bd466d..52ab039b9ec 100644
--- a/xlators/mgmt/glusterd/src/glusterd-op-sm.c
+++ b/xlators/mgmt/glusterd/src/glusterd-op-sm.c
@@ -1200,8 +1200,9 @@ glusterd_op_stage_sync_volume (dict_t *dict, char **op_errstr)
ret = 0;
}
} else {
- ret = glusterd_friend_find (NULL, hostname, &peerinfo);
- if (ret) {
+ peerinfo = glusterd_peerinfo_find (NULL, hostname);
+ if (peerinfo == NULL) {
+ ret = -1;
snprintf (msg, sizeof (msg), "%s, is not a friend",
hostname);
*op_errstr = gf_strdup (msg);
diff --git a/xlators/mgmt/glusterd/src/glusterd-peer-utils.c b/xlators/mgmt/glusterd/src/glusterd-peer-utils.c
new file mode 100644
index 00000000000..be8ae76c77a
--- /dev/null
+++ b/xlators/mgmt/glusterd/src/glusterd-peer-utils.c
@@ -0,0 +1,902 @@
+/*
+ Copyright (c) 2014 Red Hat, Inc. <http://www.redhat.com>
+ This file is part of GlusterFS.
+
+ This file is licensed to you under your choice of the GNU Lesser
+ General Public License, version 3 or any later version (LGPLv3 or
+ later), or the GNU General Public License, version 2 (GPLv2), in all
+ cases as published by the Free Software Foundation.
+*/
+
+#include "glusterd-peer-utils.h"
+#include "glusterd-store.h"
+#include "common-utils.h"
+
+int32_t
+glusterd_peerinfo_cleanup (glusterd_peerinfo_t *peerinfo)
+{
+ GF_ASSERT (peerinfo);
+ glusterd_peerctx_t *peerctx = NULL;
+ gf_boolean_t quorum_action = _gf_false;
+ glusterd_conf_t *priv = THIS->private;
+
+ if (peerinfo->quorum_contrib != QUORUM_NONE)
+ quorum_action = _gf_true;
+ if (peerinfo->rpc) {
+ peerctx = peerinfo->rpc->mydata;
+ peerinfo->rpc->mydata = NULL;
+ peerinfo->rpc = glusterd_rpc_clnt_unref (priv, peerinfo->rpc);
+ peerinfo->rpc = NULL;
+ if (peerctx) {
+ GF_FREE (peerctx->errstr);
+ GF_FREE (peerctx);
+ }
+ }
+ glusterd_peerinfo_destroy (peerinfo);
+
+ if (quorum_action)
+ glusterd_do_quorum_action ();
+ return 0;
+}
+
+int32_t
+glusterd_peerinfo_destroy (glusterd_peerinfo_t *peerinfo)
+{
+ int32_t ret = -1;
+ glusterd_peer_hostname_t *hostname = NULL;
+ glusterd_peer_hostname_t *tmp = NULL;
+
+ if (!peerinfo)
+ goto out;
+
+ list_del_init (&peerinfo->uuid_list);
+
+ ret = glusterd_store_delete_peerinfo (peerinfo);
+ if (ret) {
+ gf_log ("glusterd", GF_LOG_ERROR, "Deleting peer info failed");
+ }
+
+ GF_FREE (peerinfo->hostname);
+ peerinfo->hostname = NULL;
+
+ list_for_each_entry_safe (hostname, tmp, &peerinfo->hostnames,
+ hostname_list) {
+ glusterd_peer_hostname_free (hostname);
+ }
+
+ glusterd_sm_tr_log_delete (&peerinfo->sm_log);
+ GF_FREE (peerinfo);
+ peerinfo = NULL;
+
+ ret = 0;
+
+out:
+ return ret;
+}
+
+/* glusterd_peerinfo_find_by_hostname searches for a peer which matches the
+ * hostname @hoststr and if found returns the pointer to peerinfo object.
+ * Returns NULL otherwise.
+ *
+ * It first attempts a quick search by string matching @hoststr. If that fails,
+ * it'll attempt a more thorough match by resolving the addresses and matching
+ * the resolved addrinfos.
+ */
+glusterd_peerinfo_t *
+glusterd_peerinfo_find_by_hostname (const char *hoststr)
+{
+ int ret = -1;
+ struct addrinfo *addr = NULL;
+ struct addrinfo *p = NULL;
+ xlator_t *this = NULL;
+ glusterd_peerinfo_t *peerinfo = NULL;
+
+
+ this = THIS;
+ GF_ASSERT (hoststr);
+
+ peerinfo = NULL;
+
+ peerinfo = gd_peerinfo_find_from_hostname (hoststr);
+ if (peerinfo)
+ return peerinfo;
+
+ ret = getaddrinfo (hoststr, NULL, NULL, &addr);
+ if (ret != 0) {
+ gf_log (this->name, GF_LOG_ERROR,
+ "error in getaddrinfo: %s\n",
+ gai_strerror(ret));
+ goto out;
+ }
+
+ for (p = addr; p != NULL; p = p->ai_next) {
+ peerinfo = gd_peerinfo_find_from_addrinfo (p);
+ if (peerinfo) {
+ freeaddrinfo (addr);
+ return peerinfo;
+ }
+ }
+
+out:
+ gf_log (this->name, GF_LOG_DEBUG, "Unable to find friend: %s", hoststr);
+ if (addr)
+ freeaddrinfo (addr);
+ return NULL;
+}
+
+int
+glusterd_hostname_to_uuid (char *hostname, uuid_t uuid)
+{
+ GF_ASSERT (hostname);
+ GF_ASSERT (uuid);
+
+ glusterd_peerinfo_t *peerinfo = NULL;
+ glusterd_conf_t *priv = NULL;
+ int ret = -1;
+ xlator_t *this = NULL;
+
+ this = THIS;
+ GF_ASSERT (this);
+ priv = this->private;
+ GF_ASSERT (priv);
+
+ peerinfo = glusterd_peerinfo_find_by_hostname (hostname);
+ if (peerinfo) {
+ ret = 0;
+ uuid_copy (uuid, peerinfo->uuid);
+ } else {
+ if (gf_is_local_addr (hostname)) {
+ uuid_copy (uuid, MY_UUID);
+ ret = 0;
+ } else {
+ ret = -1;
+ }
+ }
+
+ gf_log (this->name, GF_LOG_DEBUG, "returning %d", ret);
+ return ret;
+}
+
+/* glusterd_peerinfo_find_by_uuid searches for a peer which matches the
+ * uuid @uuid and if found returns the pointer to peerinfo object.
+ * Returns NULL otherwise.
+ */
+glusterd_peerinfo_t *
+glusterd_peerinfo_find_by_uuid (uuid_t uuid)
+{
+ glusterd_conf_t *priv = NULL;
+ glusterd_peerinfo_t *entry = NULL;
+ xlator_t *this = NULL;
+
+ this = THIS;
+ GF_ASSERT (this);
+
+ priv = this->private;
+
+ GF_ASSERT (priv);
+
+ if (uuid_is_null (uuid))
+ return NULL;
+
+ list_for_each_entry (entry, &priv->peers, uuid_list) {
+ if (!uuid_compare (entry->uuid, uuid)) {
+
+ gf_log (this->name, GF_LOG_DEBUG,
+ "Friend found... state: %s",
+ glusterd_friend_sm_state_name_get (entry->state.state));
+ return entry;
+ }
+ }
+
+ gf_log (this->name, GF_LOG_DEBUG, "Friend with uuid: %s, not found",
+ uuid_utoa (uuid));
+ return NULL;
+}
+
+/* glusterd_peerinfo_find will search for a peer matching either @uuid or
+ * @hostname and return a pointer to the peerinfo object
+ * Returns NULL otherwise.
+ */
+glusterd_peerinfo_t *
+glusterd_peerinfo_find (uuid_t uuid, const char *hostname)
+{
+ glusterd_peerinfo_t *peerinfo = NULL;
+ xlator_t *this = NULL;
+
+ this = THIS;
+ GF_ASSERT (this);
+
+
+ if (uuid) {
+ peerinfo = glusterd_peerinfo_find_by_uuid (uuid);
+
+ if (peerinfo) {
+ return peerinfo;
+ } else {
+ gf_log (this->name, GF_LOG_DEBUG,
+ "Unable to find peer by uuid: %s",
+ uuid_utoa (uuid));
+ }
+
+ }
+
+ if (hostname) {
+ peerinfo = glusterd_peerinfo_find_by_hostname (hostname);
+
+ if (peerinfo) {
+ return peerinfo;
+ } else {
+ gf_log (this->name, GF_LOG_DEBUG,
+ "Unable to find hostname: %s", hostname);
+ }
+ }
+ return NULL;
+}
+
+/* glusterd_peerinfo_new will create a new peerinfo object and set it's members
+ * values using the passed parameters.
+ * @hostname is added as the first entry in peerinfo->hostnames list and also
+ * set to peerinfo->hostname.
+ * It returns a pointer to peerinfo object if successfull and returns NULL
+ * otherwise. The caller should take care of freeing the created peerinfo
+ * object.
+ */
+glusterd_peerinfo_t *
+glusterd_peerinfo_new (glusterd_friend_sm_state_t state, uuid_t *uuid,
+ const char *hostname, int port)
+{
+ glusterd_peerinfo_t *new_peer = NULL;
+ int ret = -1;
+
+ new_peer = GF_CALLOC (1, sizeof (*new_peer), gf_gld_mt_peerinfo_t);
+ if (!new_peer)
+ goto out;
+
+ INIT_LIST_HEAD (&new_peer->uuid_list);
+
+ new_peer->state.state = state;
+
+ INIT_LIST_HEAD (&new_peer->hostnames);
+ if (hostname) {
+ ret = gd_add_address_to_peer (new_peer, hostname);
+ if (ret)
+ goto out;
+ /* Also set it to peerinfo->hostname. Doing this as we use
+ * peerinfo->hostname in a lot of places and is really hard to
+ * get everything right
+ */
+ new_peer->hostname = gf_strdup (hostname);
+ }
+
+ if (uuid) {
+ uuid_copy (new_peer->uuid, *uuid);
+ }
+
+ ret = glusterd_sm_tr_log_init (&new_peer->sm_log,
+ glusterd_friend_sm_state_name_get,
+ glusterd_friend_sm_event_name_get,
+ GLUSTERD_TR_LOG_SIZE);
+ if (ret)
+ goto out;
+
+ if (new_peer->state.state == GD_FRIEND_STATE_BEFRIENDED)
+ new_peer->quorum_contrib = QUORUM_WAITING;
+ new_peer->port = port;
+out:
+ if (ret && new_peer) {
+ glusterd_peerinfo_cleanup (new_peer);
+ new_peer = NULL;
+ }
+ return new_peer;
+}
+
+/* Check if the all peers are connected and befriended, except the peer
+ * specified (the peer being detached)
+ */
+gf_boolean_t
+glusterd_chk_peers_connected_befriended (uuid_t skip_uuid)
+{
+ gf_boolean_t ret = _gf_true;
+ glusterd_peerinfo_t *peerinfo = NULL;
+ glusterd_conf_t *priv = NULL;
+
+ priv= THIS->private;
+ GF_ASSERT (priv);
+
+ list_for_each_entry (peerinfo, &priv->peers, uuid_list) {
+
+ if (!uuid_is_null (skip_uuid) && !uuid_compare (skip_uuid,
+ peerinfo->uuid))
+ continue;
+
+ if ((GD_FRIEND_STATE_BEFRIENDED != peerinfo->state.state)
+ || !(peerinfo->connected)) {
+ ret = _gf_false;
+ break;
+ }
+ }
+ gf_log (THIS->name, GF_LOG_DEBUG, "Returning %s",
+ (ret?"TRUE":"FALSE"));
+ return ret;
+}
+
+/* Return hostname for given uuid if it exists
+ * else return NULL
+ */
+char *
+glusterd_uuid_to_hostname (uuid_t uuid)
+{
+ char *hostname = NULL;
+ glusterd_conf_t *priv = NULL;
+ glusterd_peerinfo_t *entry = NULL;
+
+ priv = THIS->private;
+ GF_ASSERT (priv);
+
+ if (!uuid_compare (MY_UUID, uuid)) {
+ hostname = gf_strdup ("localhost");
+ }
+ if (!list_empty (&priv->peers)) {
+ list_for_each_entry (entry, &priv->peers, uuid_list) {
+ if (!uuid_compare (entry->uuid, uuid)) {
+ hostname = gf_strdup (entry->hostname);
+ break;
+ }
+ }
+ }
+
+ return hostname;
+}
+
+char*
+gd_peer_uuid_str (glusterd_peerinfo_t *peerinfo)
+{
+ if ((peerinfo == NULL) || uuid_is_null (peerinfo->uuid))
+ return NULL;
+
+ if (peerinfo->uuid_str[0] == '\0')
+ uuid_utoa_r (peerinfo->uuid, peerinfo->uuid_str);
+
+ return peerinfo->uuid_str;
+}
+
+gf_boolean_t
+glusterd_are_vol_all_peers_up (glusterd_volinfo_t *volinfo,
+ struct list_head *peers,
+ char **down_peerstr)
+{
+ glusterd_peerinfo_t *peerinfo = NULL;
+ glusterd_brickinfo_t *brickinfo = NULL;
+ gf_boolean_t ret = _gf_false;
+
+ list_for_each_entry (brickinfo, &volinfo->bricks, brick_list) {
+ if (!uuid_compare (brickinfo->uuid, MY_UUID))
+ continue;
+
+ list_for_each_entry (peerinfo, peers, uuid_list) {
+ if (uuid_compare (peerinfo->uuid, brickinfo->uuid))
+ continue;
+
+ /*Found peer who owns the brick, return false
+ * if peer is not connected or not friend */
+ if (!(peerinfo->connected) ||
+ (peerinfo->state.state !=
+ GD_FRIEND_STATE_BEFRIENDED)) {
+ *down_peerstr = gf_strdup (peerinfo->hostname);
+ gf_log ("", GF_LOG_DEBUG, "Peer %s is down. ",
+ peerinfo->hostname);
+ goto out;
+ }
+ }
+ }
+
+ ret = _gf_true;
+out:
+ gf_log ("glusterd", GF_LOG_DEBUG, "Returning %d", ret);
+ return ret;
+}
+
+int32_t
+glusterd_peer_hostname_new (const char *hostname,
+ glusterd_peer_hostname_t **name)
+{
+ glusterd_peer_hostname_t *peer_hostname = NULL;
+ int32_t ret = -1;
+
+ GF_ASSERT (hostname);
+ GF_ASSERT (name);
+
+ peer_hostname = GF_CALLOC (1, sizeof (*peer_hostname),
+ gf_gld_mt_peer_hostname_t);
+
+ if (!peer_hostname)
+ goto out;
+
+ peer_hostname->hostname = gf_strdup (hostname);
+ INIT_LIST_HEAD (&peer_hostname->hostname_list);
+
+ *name = peer_hostname;
+ ret = 0;
+
+out:
+ gf_log ("glusterd", GF_LOG_DEBUG, "Returning %d", ret);
+ return ret;
+}
+
+void
+glusterd_peer_hostname_free (glusterd_peer_hostname_t *name)
+{
+ if (!name)
+ return;
+
+ list_del_init (&name->hostname_list);
+
+ GF_FREE (name->hostname);
+ name->hostname = NULL;
+
+ GF_FREE (name);
+
+ return;
+}
+
+gf_boolean_t
+gd_peer_has_address (glusterd_peerinfo_t *peerinfo, const char *address)
+{
+ gf_boolean_t ret = _gf_false;
+ glusterd_peer_hostname_t *hostname = NULL;
+
+ GF_VALIDATE_OR_GOTO ("glusterd", (peerinfo != NULL), out);
+ GF_VALIDATE_OR_GOTO ("glusterd", (address != NULL), out);
+
+ list_for_each_entry (hostname, &peerinfo->hostnames, hostname_list) {
+ if (strcmp (hostname->hostname, address) == 0) {
+ ret = _gf_true;
+ break;
+ }
+ }
+
+out:
+ return ret;
+}
+
+int
+gd_add_address_to_peer (glusterd_peerinfo_t *peerinfo, const char *address)
+{
+
+ int ret = -1;
+ glusterd_peer_hostname_t *hostname = NULL;
+
+ GF_VALIDATE_OR_GOTO ("glusterd", (peerinfo != NULL), out);
+ GF_VALIDATE_OR_GOTO ("glusterd", (address != NULL), out);
+
+ if (gd_peer_has_address (peerinfo, address)) {
+ ret = 0;
+ goto out;
+ }
+
+ ret = glusterd_peer_hostname_new (address, &hostname);
+ if (ret)
+ goto out;
+
+ list_add_tail (&hostname->hostname_list, &peerinfo->hostnames);
+
+ ret = 0;
+out:
+ return ret;
+}
+
+/* gd_add_friend_to_dict() adds details of @friend into @dict with the given
+ * @prefix. All the parameters are compulsary.
+ *
+ * The complete address list is added to the dict only if the cluster op-version
+ * is >= GD_OP_VERSION_3_6_0
+ */
+int
+gd_add_friend_to_dict (glusterd_peerinfo_t *friend, dict_t *dict,
+ const char *prefix)
+{
+ int ret = -1;
+ xlator_t *this = NULL;
+ glusterd_conf_t *conf = NULL;
+ char key[100] = {0,};
+ glusterd_peer_hostname_t *address = NULL;
+ int count = 0;
+
+ this = THIS;
+ GF_VALIDATE_OR_GOTO ("glusterd", (this != NULL), out);
+
+ conf = this->private;
+ GF_VALIDATE_OR_GOTO (this->name, (conf != NULL), out);
+
+ GF_VALIDATE_OR_GOTO (this->name, (friend != NULL), out);
+ GF_VALIDATE_OR_GOTO (this->name, (dict != NULL), out);
+ GF_VALIDATE_OR_GOTO (this->name, (prefix != NULL), out);
+
+ snprintf (key, sizeof (key), "%s.uuid", prefix);
+ ret = dict_set_dynstr_with_alloc (dict, key, uuid_utoa (friend->uuid));
+ if (ret) {
+ gf_log (this->name, GF_LOG_ERROR,
+ "Failed to set key %s in dict", key);
+ goto out;
+ }
+
+ /* Setting the first hostname from the list with this key for backward
+ * compatability
+ */
+ memset (key, 0, sizeof (key));
+ snprintf (key, sizeof (key), "%s.hostname", prefix);
+ address = list_entry (&friend->hostnames, glusterd_peer_hostname_t,
+ hostname_list);
+ if (!address) {
+ ret = -1;
+ gf_log (this->name, GF_LOG_ERROR, "Could not retrieve first "
+ "address for peer");
+ goto out;
+ }
+ ret = dict_set_dynstr_with_alloc (dict, key, address->hostname);
+ if (ret) {
+ gf_log (this->name, GF_LOG_ERROR,
+ "Failed to set key %s in dict", key);
+ goto out;
+ }
+
+ if (conf->op_version < GD_OP_VERSION_3_6_0) {
+ ret = 0;
+ goto out;
+ }
+
+ address = NULL;
+ count = 0;
+ list_for_each_entry (address, &friend->hostnames, hostname_list) {
+ GF_VALIDATE_OR_GOTO (this->name, (address != NULL), out);
+
+ memset (key, 0, sizeof (key));
+ snprintf (key, sizeof (key), "%s.hostname%d", prefix, count);
+ ret = dict_set_dynstr_with_alloc (dict, key, address->hostname);
+ if (ret) {
+ gf_log (this->name, GF_LOG_ERROR,
+ "Failed to set key %s in dict", key);
+ goto out;
+ }
+ count++;
+ }
+ memset (key, 0, sizeof (key));
+ snprintf (key, sizeof (key), "%s.address-count", prefix);
+ ret = dict_set_int32 (dict, key, count);
+ if (ret)
+ gf_log (this->name, GF_LOG_ERROR,
+ "Failed to set key %s in dict", key);
+
+out:
+ gf_log (this ? this->name : "glusterd", GF_LOG_DEBUG, "Returning %d",
+ ret);
+ return ret;
+}
+
+/* gd_peerinfo_find_from_hostname iterates over all the addresses saved for each
+ * peer and matches it to @hoststr.
+ * Returns the matched peer if found else returns NULL
+ */
+glusterd_peerinfo_t *
+gd_peerinfo_find_from_hostname (const char *hoststr)
+{
+ xlator_t *this = NULL;
+ glusterd_conf_t *priv = NULL;
+ glusterd_peerinfo_t *peer = NULL;
+ glusterd_peer_hostname_t *tmphost = NULL;
+
+ this = THIS;
+ GF_ASSERT (this != NULL);
+ priv = this->private;
+ GF_VALIDATE_OR_GOTO (this->name, (priv != NULL), out);
+
+ GF_VALIDATE_OR_GOTO (this->name, (hoststr != NULL), out);
+
+ list_for_each_entry (peer, &priv->peers, uuid_list) {
+ list_for_each_entry (tmphost, &peer->hostnames,hostname_list) {
+ if (!strncasecmp (tmphost->hostname, hoststr, 1024)) {
+ gf_log (this->name, GF_LOG_DEBUG,
+ "Friend %s found.. state: %d",
+ tmphost->hostname, peer->state.state);
+ return peer;
+ }
+ }
+ }
+out:
+ return NULL;
+}
+
+/* gd_peerinfo_find_from_addrinfo iterates over all the addresses saved for each
+ * peer, resolves them and compares them to @addr.
+ *
+ *
+ * NOTE: As getaddrinfo is a blocking call and is being performed multiple times
+ * in this function, it could lead to the calling thread to be blocked for
+ * significant amounts of time.
+ *
+ * Returns the matched peer if found else returns NULL
+ */
+glusterd_peerinfo_t *
+gd_peerinfo_find_from_addrinfo (const struct addrinfo *addr)
+{
+ xlator_t *this = NULL;
+ glusterd_conf_t *conf = NULL;
+ glusterd_peerinfo_t *peer = NULL;
+ glusterd_peer_hostname_t *address = NULL;
+ int ret = 0;
+ struct addrinfo *paddr = NULL;
+ struct addrinfo *tmp = NULL;
+
+ this = THIS;
+ GF_ASSERT (this != NULL);
+ conf = this->private;
+ GF_VALIDATE_OR_GOTO (this->name, (conf != NULL), out);
+
+ GF_VALIDATE_OR_GOTO (this->name, (addr != NULL), out);
+
+ list_for_each_entry (peer, &conf->peers, uuid_list) {
+ list_for_each_entry (address, &peer->hostnames, hostname_list) {
+ /* TODO: Cache the resolved addrinfos to improve
+ * performance
+ */
+ ret = getaddrinfo (address->hostname, NULL, NULL,
+ &paddr);
+ if (ret) {
+ /* Don't fail if getaddrinfo fails, continue
+ * onto the next address
+ */
+ gf_log (this->name, GF_LOG_TRACE,
+ "getaddrinfo for %s failed (%s)",
+ address->hostname, gai_strerror (ret));
+ ret = 0;
+ continue;
+ }
+
+ for (tmp = paddr; tmp != NULL; tmp = tmp->ai_next) {
+ if (gf_compare_sockaddr (addr->ai_addr,
+ tmp->ai_addr)) {
+ freeaddrinfo (paddr);
+ return peer;
+ }
+ }
+ }
+ }
+out:
+ return NULL;
+}
+
+/* gd_update_peerinfo_from_dict will update the hostnames for @peerinfo from
+ * peer details with @prefix in @dict.
+ * Returns 0 on sucess and -1 on failure.
+ */
+int
+gd_update_peerinfo_from_dict (glusterd_peerinfo_t *peerinfo, dict_t *dict,
+ const char *prefix)
+{
+ int ret = -1;
+ xlator_t *this = NULL;
+ glusterd_conf_t *conf = NULL;
+ char key[100] = {0,};
+ char *hostname = NULL;
+ int count = 0;
+ int i = 0;
+
+ this = THIS;
+ GF_ASSERT (this != NULL);
+
+ conf = this->private;
+ GF_VALIDATE_OR_GOTO (this->name, (conf != NULL), out);
+
+ GF_VALIDATE_OR_GOTO (this->name, (peerinfo != NULL), out);
+ GF_VALIDATE_OR_GOTO (this->name, (dict != NULL), out);
+ GF_VALIDATE_OR_GOTO (this->name, (prefix != NULL), out);
+
+ memset (key, 0, sizeof (key));
+ snprintf (key, sizeof (key), "%s.hostname", prefix);
+ ret = dict_get_str (dict, key, &hostname);
+ if (ret) {
+ gf_log (this->name, GF_LOG_ERROR, "Key %s not present in "
+ "dictionary", key);
+ goto out;
+ }
+ ret = gd_add_address_to_peer (peerinfo, hostname);
+ if (ret) {
+ gf_log (this->name, GF_LOG_ERROR,
+ "Could not add address to peer");
+ goto out;
+ }
+ /* Also set peerinfo->hostname to the first address */
+ if (peerinfo->hostname != NULL)
+ GF_FREE (peerinfo->hostname);
+ peerinfo->hostname = gf_strdup (hostname);
+
+ if (conf->op_version < GD_OP_VERSION_3_6_0) {
+ ret = 0;
+ goto out;
+ }
+
+ memset (key, 0, sizeof (key));
+ snprintf (key, sizeof (key), "%s.address-count", prefix);
+ ret = dict_get_int32 (dict, key, &count);
+ if (ret) {
+ gf_log (this->name, GF_LOG_ERROR, "Key %s not present in "
+ "dictionary", key);
+ goto out;
+ }
+ hostname = NULL;
+ for (i = 0; i < count; i++) {
+ memset (key, 0, sizeof (key));
+ snprintf (key, sizeof (key), "%s.hostname%d",prefix, i);
+ ret = dict_get_str (dict, key, &hostname);
+ if (ret) {
+ gf_log (this->name, GF_LOG_ERROR, "Key %s not present "
+ "in dictionary", key);
+ goto out;
+ }
+ ret = gd_add_address_to_peer (peerinfo, hostname);
+ if (ret) {
+ gf_log (this->name, GF_LOG_ERROR,
+ "Could not add address to peer");
+ goto out;
+ }
+
+ hostname = NULL;
+ }
+
+out:
+ gf_log (this->name, GF_LOG_DEBUG, "Returning %d", ret);
+ return ret;
+}
+
+/* gd_peerinfo_from_dict creates a peerinfo object from details of peer with
+ * @prefix in @dict.
+ * Returns a pointer to the created peerinfo object on success, and NULL on
+ * failure.
+ */
+glusterd_peerinfo_t *
+gd_peerinfo_from_dict (dict_t *dict, const char *prefix)
+{
+ int ret = -1;
+ xlator_t *this = NULL;
+ glusterd_conf_t *conf = NULL;
+ glusterd_peerinfo_t *new_peer = NULL;
+ char key[100] = {0,};
+ char *uuid_str = NULL;
+
+ this = THIS;
+ GF_VALIDATE_OR_GOTO ("glusterd", (this != NULL), out);
+
+ conf = this->private;
+ GF_VALIDATE_OR_GOTO (this->name, (conf != NULL), out);
+
+ GF_VALIDATE_OR_GOTO (this->name, (dict != NULL), out);
+ GF_VALIDATE_OR_GOTO (this->name, (prefix != NULL), out);
+
+ new_peer = glusterd_peerinfo_new (GD_FRIEND_STATE_DEFAULT, NULL, NULL,
+ 0);
+ if (new_peer == NULL) {
+ ret = -1;
+ gf_log (this->name, GF_LOG_ERROR, "Could not create peerinfo "
+ "object");
+ goto out;
+ }
+
+ snprintf (key, sizeof (key), "%s.uuid", prefix);
+ ret = dict_get_str (dict, key, &uuid_str);
+ if (ret) {
+ gf_log (this->name, GF_LOG_ERROR, "Key %s not present in "
+ "dictionary", key);
+ goto out;
+ }
+ uuid_parse (uuid_str, new_peer->uuid);
+
+ ret = gd_update_peerinfo_from_dict (new_peer, dict, prefix);
+
+out:
+ if ((ret != 0) && (new_peer != NULL)) {
+ glusterd_peerinfo_cleanup (new_peer);
+ new_peer = NULL;
+ }
+
+ return new_peer;
+}
+
+int
+gd_add_peer_hostnames_to_dict (glusterd_peerinfo_t *peerinfo, dict_t *dict,
+ const char *prefix)
+{
+ int ret = -1;
+ xlator_t *this = NULL;
+ glusterd_conf_t *conf = NULL;
+ char key[256] = {0,};
+ glusterd_peer_hostname_t *addr = NULL;
+ int count = 0;
+
+ this = THIS;
+ GF_ASSERT (this != NULL);
+
+ conf = this->private;
+ GF_VALIDATE_OR_GOTO (this->name, (conf != NULL), out);
+
+ if (conf->op_version < GD_OP_VERSION_3_6_0) {
+ ret = 0;
+ goto out;
+ }
+
+ GF_VALIDATE_OR_GOTO (this->name, (peerinfo != NULL), out);
+ GF_VALIDATE_OR_GOTO (this->name, (dict != NULL), out);
+ GF_VALIDATE_OR_GOTO (this->name, (prefix != NULL), out);
+
+ list_for_each_entry (addr, &peerinfo->hostnames, hostname_list) {
+ memset (key, 0, sizeof (key));
+ snprintf (key, sizeof (key), "%s.hostname%d", prefix, count);
+ ret = dict_set_dynstr_with_alloc (dict, key, addr->hostname);
+ if (ret)
+ goto out;
+ count++;
+ }
+
+ memset (key, 0, sizeof (key));
+ snprintf (key, sizeof (key), "%s.hostname_count", prefix);
+ ret = dict_set_int32 (dict, key, count);
+
+out:
+ return ret;
+}
+
+int
+gd_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, sizeof (key), "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;
+
+ memset (key, 0, sizeof (key));
+ snprintf (key, sizeof (key), "friend%d.hostname", count);
+ ret = dict_set_str (friends, key, peerinfo->hostname);
+ if (ret)
+ goto out;
+
+ memset (key, 0, sizeof (key));
+ snprintf (key, sizeof (key), "friend%d.port", count);
+ ret = dict_set_int32 (friends, key, peerinfo->port);
+ if (ret)
+ goto out;
+
+ memset (key, 0, sizeof (key));
+ snprintf (key, sizeof (key), "friend%d.stateId", count);
+ ret = dict_set_int32 (friends, key, peerinfo->state.state);
+ if (ret)
+ goto out;
+
+ memset (key, 0, sizeof (key));
+ snprintf (key, sizeof (key), "friend%d.state", count);
+ ret = dict_set_str (friends, key,
+ glusterd_friend_sm_state_name_get(peerinfo->state.state));
+ if (ret)
+ goto out;
+
+ memset (key, 0, sizeof (key));
+ snprintf (key, sizeof (key), "friend%d.connected", count);
+ ret = dict_set_int32 (friends, key, (int32_t)peerinfo->connected);
+ if (ret)
+ goto out;
+
+ memset (key, 0, sizeof (key));
+ snprintf (key, sizeof (key), "friend%d", count);
+ ret = gd_add_peer_hostnames_to_dict (peerinfo, friends, key);
+
+out:
+ return ret;
+}
diff --git a/xlators/mgmt/glusterd/src/glusterd-peer-utils.h b/xlators/mgmt/glusterd/src/glusterd-peer-utils.h
new file mode 100644
index 00000000000..9877d861af7
--- /dev/null
+++ b/xlators/mgmt/glusterd/src/glusterd-peer-utils.h
@@ -0,0 +1,87 @@
+/*
+ Copyright (c) 2014 Red Hat, Inc. <http://www.redhat.com>
+ This file is part of GlusterFS.
+
+ This file is licensed to you under your choice of the GNU Lesser
+ General Public License, version 3 or any later version (LGPLv3 or
+ later), or the GNU General Public License, version 2 (GPLv2), in all
+ cases as published by the Free Software Foundation.
+*/
+
+#ifndef _GLUSTERD_PEER_UTILS_H
+#define _GLUSTERD_PEER_UTILS_H
+
+#include "glusterd.h"
+#include "glusterd-utils.h"
+
+int32_t
+glusterd_peerinfo_cleanup (glusterd_peerinfo_t *peerinfo);
+
+int32_t
+glusterd_peerinfo_destroy (glusterd_peerinfo_t *peerinfo);
+
+glusterd_peerinfo_t *
+glusterd_peerinfo_find_by_hostname (const char *hoststr);
+
+int
+glusterd_hostname_to_uuid (char *hostname, uuid_t uuid);
+
+glusterd_peerinfo_t *
+glusterd_peerinfo_find_by_uuid (uuid_t uuid);
+
+glusterd_peerinfo_t *
+glusterd_peerinfo_find (uuid_t uuid, const char *hostname);
+
+glusterd_peerinfo_t *
+glusterd_peerinfo_new (glusterd_friend_sm_state_t state, uuid_t *uuid,
+ const char *hostname, int port);
+
+gf_boolean_t
+glusterd_chk_peers_connected_befriended (uuid_t skip_uuid);
+
+char *
+glusterd_uuid_to_hostname (uuid_t uuid);
+
+char*
+gd_peer_uuid_str (glusterd_peerinfo_t *peerinfo);
+
+gf_boolean_t
+glusterd_are_vol_all_peers_up (glusterd_volinfo_t *volinfo,
+ struct list_head *peers, char **down_peerstr);
+
+int32_t
+glusterd_peer_hostname_new (const char *hostname,
+ glusterd_peer_hostname_t **name);
+void
+glusterd_peer_hostname_free (glusterd_peer_hostname_t *name);
+
+gf_boolean_t
+gd_peer_has_address (glusterd_peerinfo_t *peerinfo, const char *address);
+
+int
+gd_add_address_to_peer (glusterd_peerinfo_t *peerinfo, const char *address);
+
+int
+gd_add_friend_to_dict (glusterd_peerinfo_t *friend, dict_t *dict,
+ const char *prefix);
+
+glusterd_peerinfo_t *
+gd_peerinfo_find_from_hostname (const char *hoststr);
+
+glusterd_peerinfo_t *
+gd_peerinfo_find_from_addrinfo (const struct addrinfo *addr);
+
+int
+gd_update_peerinfo_from_dict (glusterd_peerinfo_t *peerinfo, dict_t *dict,
+ const char *prefix);
+
+glusterd_peerinfo_t *
+gd_peerinfo_from_dict (dict_t *dict, const char *prefix);
+
+int
+gd_add_peer_hostnames_to_dict (glusterd_peerinfo_t *peerinfo, dict_t *dict,
+ const char *prefix);
+int
+gd_add_peer_detail_to_dict (glusterd_peerinfo_t *peerinfo, dict_t *friends,
+ int count);
+#endif /* _GLUSTERD_PEER_UTILS_H */
diff --git a/xlators/mgmt/glusterd/src/glusterd-replace-brick.c b/xlators/mgmt/glusterd/src/glusterd-replace-brick.c
index d33dc7a32ee..7c2b545905d 100644
--- a/xlators/mgmt/glusterd/src/glusterd-replace-brick.c
+++ b/xlators/mgmt/glusterd/src/glusterd-replace-brick.c
@@ -521,8 +521,9 @@ glusterd_op_stage_replace_brick (dict_t *dict, char **op_errstr,
}
if (!gf_is_local_addr (host)) {
- ret = glusterd_friend_find (NULL, host, &peerinfo);
- if (ret) {
+ peerinfo = glusterd_peerinfo_find (NULL, host);
+ if (peerinfo == NULL) {
+ ret = -1;
snprintf (msg, sizeof (msg), "%s, is not a friend",
host);
*op_errstr = gf_strdup (msg);
diff --git a/xlators/mgmt/glusterd/src/glusterd-rpc-ops.c b/xlators/mgmt/glusterd/src/glusterd-rpc-ops.c
index 10d5d7f2752..19b66ac06d8 100644
--- a/xlators/mgmt/glusterd/src/glusterd-rpc-ops.c
+++ b/xlators/mgmt/glusterd/src/glusterd-rpc-ops.c
@@ -214,25 +214,32 @@ int
__glusterd_probe_cbk (struct rpc_req *req, struct iovec *iov,
int count, void *myframe)
{
- gd1_mgmt_probe_rsp rsp = {{0},};
- int ret = 0;
- glusterd_peerinfo_t *peerinfo = NULL;
- glusterd_friend_sm_event_t *event = NULL;
- glusterd_probe_ctx_t *ctx = NULL;
+ gd1_mgmt_probe_rsp rsp = {{0},};
+ int ret = 0;
+ glusterd_peerinfo_t *peerinfo = NULL;
+ glusterd_friend_sm_event_t *event = NULL;
+ glusterd_probe_ctx_t *ctx = NULL;
+ xlator_t *this = NULL;
+ glusterd_conf_t *conf = NULL;
if (-1 == req->rpc_status) {
goto out;
}
+ this = THIS;
+ GF_ASSERT (this != NULL);
+ conf = this->private;
+ GF_VALIDATE_OR_GOTO (this->name, (conf != NULL), out);
+
ret = xdr_to_generic (*iov, &rsp, (xdrproc_t)xdr_gd1_mgmt_probe_rsp);
if (ret < 0) {
- gf_log ("", GF_LOG_ERROR, "error");
+ gf_log (this->name, GF_LOG_ERROR, "error");
//rsp.op_ret = -1;
//rsp.op_errno = EINVAL;
goto out;
}
- gf_log ("glusterd", GF_LOG_INFO,
+ gf_log (this->name, GF_LOG_INFO,
"Received probe resp from uuid: %s, host: %s",
uuid_utoa (rsp.uuid), rsp.hostname);
if (rsp.op_ret != 0) {
@@ -254,12 +261,82 @@ __glusterd_probe_cbk (struct rpc_req *req, struct iovec *iov,
ret = rsp.op_ret;
goto out;
}
- ret = glusterd_friend_find (rsp.uuid, rsp.hostname, &peerinfo);
- if (ret) {
+
+ peerinfo = glusterd_peerinfo_find (rsp.uuid, rsp.hostname);
+ if (peerinfo == NULL) {
GF_ASSERT (0);
}
- if (strncasecmp (rsp.hostname, peerinfo->hostname, 1024)) {
+ /*
+ * In the case of a fresh probe rsp.uuid and peerinfo.uuid will not
+ * match, as peerinfo->uuid will be NULL.
+ *
+ * In the case of a peer probe being done to add a new network to a
+ * peer, rsp.uuid will match an existing peerinfo.uuid. If we have this
+ * stage it means that the current address/hostname being used isn't
+ * present in the found peerinfo. If it were, we would have found out
+ * earlier in the probe process and wouldn't even reach till here. So,
+ * we need to add the new hostname to the peer.
+ *
+ * This addition should only be done for cluster op-version >=
+ * GD_OP_VERSION_3_6_0 as address lists are only supported from then on.
+ * Also, this update should only be done when an explicit CLI probe
+ * command was used to begin the probe process.
+ */
+ if ((conf->op_version >= GD_OP_VERSION_3_6_0) &&
+ (uuid_compare (rsp.uuid, peerinfo->uuid) == 0)) {
+ ctx = ((call_frame_t *)myframe)->local;
+ /* Presence of ctx->req implies this probe was started by a cli
+ * probe command
+ */
+ if (ctx->req == NULL)
+ goto cont;
+
+ gf_log (this->name, GF_LOG_DEBUG, "Adding address '%s' to "
+ "existing peer %s", rsp.hostname, uuid_utoa (rsp.uuid));
+
+ ret = glusterd_friend_remove (NULL, rsp.hostname);
+ if (ret) {
+ gf_log (this->name, GF_LOG_ERROR, "Could not remove "
+ "stale peerinfo with name %s", rsp.hostname);
+ goto reply;
+ }
+
+ ret = gd_add_address_to_peer (peerinfo, rsp.hostname);
+ if (ret) {
+ gf_log (this->name, GF_LOG_ERROR,
+ "Couldn't add hostname to peer list");
+ goto reply;
+ }
+
+ /* Injecting LOCAL_ACC to send update */
+ ret = glusterd_friend_sm_new_event (GD_FRIEND_EVENT_LOCAL_ACC,
+ &event);
+ if (!ret) {
+ event->peerinfo = peerinfo;
+ ret = glusterd_friend_sm_inject_event (event);
+ }
+ rsp.op_errno = GF_PROBE_FRIEND;
+
+reply:
+ ctx = ((call_frame_t *)myframe)->local;
+ ((call_frame_t *)myframe)->local = NULL;
+
+ GF_ASSERT (ctx);
+
+ if (ctx->req) {
+ glusterd_xfer_cli_probe_resp (ctx->req, ret,
+ rsp.op_errno,
+ rsp.op_errstr,
+ ctx->hostname, ctx->port,
+ ctx->dict);
+ }
+
+ glusterd_destroy_probe_ctx (ctx);
+
+ goto out;
+
+ } else if (strncasecmp (rsp.hostname, peerinfo->hostname, 1024)) {
gf_log (THIS->name, GF_LOG_INFO, "Host: %s with uuid: %s "
"already present in cluster with alias hostname: %s",
rsp.hostname, uuid_utoa (rsp.uuid), peerinfo->hostname);
@@ -283,7 +360,7 @@ __glusterd_probe_cbk (struct rpc_req *req, struct iovec *iov,
ret = rsp.op_ret;
goto out;
}
-
+cont:
uuid_copy (peerinfo->uuid, rsp.uuid);
ret = glusterd_friend_sm_new_event
@@ -358,9 +435,9 @@ __glusterd_friend_add_cbk (struct rpc_req * req, struct iovec *iov,
"Received %s from uuid: %s, host: %s, port: %d",
(op_ret)?"RJT":"ACC", uuid_utoa (rsp.uuid), rsp.hostname, rsp.port);
- ret = glusterd_friend_find (rsp.uuid, rsp.hostname, &peerinfo);
-
- if (ret) {
+ peerinfo = glusterd_peerinfo_find (rsp.uuid, rsp.hostname);
+ if (peerinfo == NULL) {
+ ret = -1;
gf_log ("", GF_LOG_ERROR, "received friend add response from"
" unknown peer uuid: %s", uuid_utoa (rsp.uuid));
goto out;
@@ -469,11 +546,11 @@ __glusterd_friend_remove_cbk (struct rpc_req * req, struct iovec *iov,
(op_ret)?"RJT":"ACC", uuid_utoa (rsp.uuid), rsp.hostname, rsp.port);
inject:
- ret = glusterd_friend_find (rsp.uuid, ctx->hostname, &peerinfo);
-
- if (ret) {
+ peerinfo = glusterd_peerinfo_find (rsp.uuid, ctx->hostname);
+ if (peerinfo == NULL) {
//can happen as part of rpc clnt connection cleanup
//when the frame timeout happens after 30 minutes
+ ret = -1;
goto respond;
}
@@ -610,9 +687,9 @@ out:
"Received lock %s from uuid: %s", (op_ret) ? "RJT" : "ACC",
uuid_utoa (rsp.uuid));
- ret = glusterd_friend_find (rsp.uuid, NULL, &peerinfo);
-
- if (ret) {
+ peerinfo = glusterd_peerinfo_find (rsp.uuid, NULL);
+ if (peerinfo == NULL) {
+ ret = -1;
gf_log (this->name, GF_LOG_CRITICAL, "Lock response received "
"from unknown peer: %s", uuid_utoa (rsp.uuid));
}
@@ -687,8 +764,9 @@ glusterd_mgmt_v3_lock_peers_cbk_fn (struct rpc_req *req, struct iovec *iov,
"Received mgmt_v3 lock %s from uuid: %s",
(op_ret) ? "RJT" : "ACC", uuid_utoa (rsp.uuid));
- ret = glusterd_friend_find (rsp.uuid, NULL, &peerinfo);
- if (ret) {
+ peerinfo = glusterd_peerinfo_find (rsp.uuid, NULL);
+ if (peerinfo == NULL) {
+ ret = -1;
gf_log (this->name, GF_LOG_CRITICAL,
"mgmt_v3 lock response received "
"from unknown peer: %s. Ignoring response",
@@ -768,9 +846,9 @@ glusterd_mgmt_v3_unlock_peers_cbk_fn (struct rpc_req *req, struct iovec *iov,
(op_ret) ? "RJT" : "ACC",
uuid_utoa (rsp.uuid));
- ret = glusterd_friend_find (rsp.uuid, NULL, &peerinfo);
-
- if (ret) {
+ peerinfo = glusterd_peerinfo_find (rsp.uuid, NULL);
+ if (peerinfo == NULL) {
+ ret = -1;
gf_log (this->name, GF_LOG_CRITICAL,
"mgmt_v3 unlock response received "
"from unknown peer: %s. Ignoring response",
@@ -851,9 +929,8 @@ out:
"Received unlock %s from uuid: %s",
(op_ret)?"RJT":"ACC", uuid_utoa (rsp.uuid));
- ret = glusterd_friend_find (rsp.uuid, NULL, &peerinfo);
-
- if (ret) {
+ peerinfo = glusterd_peerinfo_find (rsp.uuid, NULL);
+ if (peerinfo == NULL) {
gf_log (this->name, GF_LOG_CRITICAL, "Unlock response received "
"from unknown peer %s", uuid_utoa (rsp.uuid));
}
@@ -959,11 +1036,12 @@ out:
gf_log (this->name, GF_LOG_DEBUG, "transaction ID = %s",
uuid_utoa (*txn_id));
- ret = glusterd_friend_find (rsp.uuid, NULL, &peerinfo);
- if (ret)
+ peerinfo = glusterd_peerinfo_find (rsp.uuid, NULL);
+ if (peerinfo == NULL) {
gf_log (this->name, GF_LOG_CRITICAL, "Stage response received "
"from unknown peer: %s. Ignoring response.",
uuid_utoa (rsp.uuid));
+ }
if (op_ret) {
event_type = GD_OP_EVENT_RCVD_RJT;
@@ -1094,8 +1172,8 @@ __glusterd_commit_op_cbk (struct rpc_req *req, struct iovec *iov,
gf_log (this->name, GF_LOG_DEBUG, "transaction ID = %s",
uuid_utoa (*txn_id));
- ret = glusterd_friend_find (rsp.uuid, NULL, &peerinfo);
- if (ret) {
+ peerinfo = glusterd_peerinfo_find (rsp.uuid, NULL);
+ if (peerinfo == NULL) {
gf_log (this->name, GF_LOG_CRITICAL, "Commit response for "
"'Volume %s' received from unknown peer: %s",
gd_op_list[opinfo.op], uuid_utoa (rsp.uuid));
diff --git a/xlators/mgmt/glusterd/src/glusterd-sm.c b/xlators/mgmt/glusterd/src/glusterd-sm.c
index 8807ef94a72..ca047bd3322 100644
--- a/xlators/mgmt/glusterd/src/glusterd-sm.c
+++ b/xlators/mgmt/glusterd/src/glusterd-sm.c
@@ -313,8 +313,8 @@ glusterd_ac_friend_probe (glusterd_friend_sm_event_t *event, void *ctx)
GF_ASSERT (conf);
- ret = glusterd_friend_find (NULL, probe_ctx->hostname, &peerinfo);
- if (ret) {
+ peerinfo = glusterd_peerinfo_find (NULL, probe_ctx->hostname);
+ if (peerinfo == NULL) {
//We should not reach this state ideally
GF_ASSERT (0);
goto out;
@@ -456,7 +456,6 @@ glusterd_ac_send_friend_update (glusterd_friend_sm_event_t *event, void *ctx)
glusterd_conf_t *priv = NULL;
dict_t *friends = NULL;
char key[100] = {0,};
- char *dup_buf = NULL;
int32_t count = 0;
GF_ASSERT (event);
@@ -483,17 +482,12 @@ glusterd_ac_send_friend_update (glusterd_friend_sm_event_t *event, void *ctx)
continue;
count++;
- snprintf (key, sizeof (key), "friend%d.uuid", count);
- dup_buf = gf_strdup (uuid_utoa (peerinfo->uuid));
- ret = dict_set_dynstr (friends, key, dup_buf);
- if (ret)
- goto out;
- snprintf (key, sizeof (key), "friend%d.hostname", count);
- ret = dict_set_str (friends, key, peerinfo->hostname);
+
+ memset (key, 0, sizeof (key));
+ snprintf (key, sizeof (key), "friend%d", count);
+ ret = gd_add_friend_to_dict (peerinfo, friends, key);
if (ret)
goto out;
- gf_log ("", GF_LOG_INFO, "Added uuid: %s, host: %s",
- dup_buf, peerinfo->hostname);
}
ret = dict_set_int32 (friends, "count", count);
@@ -622,7 +616,7 @@ glusterd_ac_friend_remove (glusterd_friend_sm_event_t *event, void *ctx)
gf_msg (THIS->name, GF_LOG_WARNING, 0, GD_MSG_VOL_CLEANUP_FAIL,
"Volumes cleanup failed");
- ret = glusterd_friend_cleanup (event->peerinfo);
+ ret = glusterd_peerinfo_cleanup (event->peerinfo);
if (ret) {
gf_log (THIS->name, GF_LOG_ERROR, "Cleanup returned: %d", ret);
}
diff --git a/xlators/mgmt/glusterd/src/glusterd-sm.h b/xlators/mgmt/glusterd/src/glusterd-sm.h
index 6b3b61dfc5c..294dbacc9d0 100644
--- a/xlators/mgmt/glusterd/src/glusterd-sm.h
+++ b/xlators/mgmt/glusterd/src/glusterd-sm.h
@@ -59,7 +59,7 @@ typedef struct glusterd_peer_state_info_ {
typedef struct glusterd_peer_hostname_ {
char *hostname;
struct list_head hostname_list;
-}glusterd_peer_hostname_t;
+} glusterd_peer_hostname_t;
typedef struct glusterd_sm_transition_ {
int old_state;
@@ -84,6 +84,7 @@ struct glusterd_peerinfo_ {
*/
glusterd_peer_state_info_t state;
char *hostname;
+ struct list_head hostnames;
int port;
struct list_head uuid_list;
struct list_head op_peers_list;
@@ -92,7 +93,7 @@ struct glusterd_peerinfo_ {
rpc_clnt_prog_t *peer;
rpc_clnt_prog_t *mgmt_v3;
int connected;
- gf_store_handle_t *shandle;
+ gf_store_handle_t *shandle;
glusterd_sm_tr_log_t sm_log;
gf_boolean_t quorum_action;
gd_quorum_contrib_t quorum_contrib;
diff --git a/xlators/mgmt/glusterd/src/glusterd-store.c b/xlators/mgmt/glusterd/src/glusterd-store.c
index 086a6550a72..06e8101a3a5 100644
--- a/xlators/mgmt/glusterd/src/glusterd-store.c
+++ b/xlators/mgmt/glusterd/src/glusterd-store.c
@@ -3853,7 +3853,7 @@ glusterd_store_create_peer_shandle (glusterd_peerinfo_t *peerinfo)
GF_ASSERT (peerinfo);
- if (glusterd_peerinfo_is_uuid_unknown (peerinfo)) {
+ if (uuid_is_null (peerinfo->uuid)) {
ret = glusterd_store_peerinfo_hostname_shandle_create (peerinfo);
} else {
ret = glusterd_peerinfo_hostname_shandle_check_destroy (peerinfo);
@@ -3865,8 +3865,11 @@ glusterd_store_create_peer_shandle (glusterd_peerinfo_t *peerinfo)
int32_t
glusterd_store_peer_write (int fd, glusterd_peerinfo_t *peerinfo)
{
- char buf[50] = {0};
- int32_t ret = 0;
+ char buf[50] = {0};
+ int32_t ret = 0;
+ int32_t i = 1;
+ glusterd_peer_hostname_t *hostname = NULL;
+ char *key = NULL;
ret = gf_store_save_value (fd, GLUSTERD_STORE_KEY_PEER_UUID,
uuid_utoa (peerinfo->uuid));
@@ -3878,10 +3881,18 @@ glusterd_store_peer_write (int fd, glusterd_peerinfo_t *peerinfo)
if (ret)
goto out;
- ret = gf_store_save_value (fd, GLUSTERD_STORE_KEY_PEER_HOSTNAME "1",
- peerinfo->hostname);
- if (ret)
- goto out;
+ list_for_each_entry (hostname, &peerinfo->hostnames, hostname_list) {
+ ret = gf_asprintf (&key, GLUSTERD_STORE_KEY_PEER_HOSTNAME"%d",
+ i);
+ if (ret < 0)
+ goto out;
+ ret = gf_store_save_value (fd, key, hostname->hostname);
+ if (ret)
+ goto out;
+ GF_FREE (key);
+ key = NULL;
+ i++;
+ }
out:
gf_log ("", GF_LOG_DEBUG, "Returning with %d", ret);
@@ -3938,22 +3949,21 @@ out:
int32_t
glusterd_store_retrieve_peers (xlator_t *this)
{
- int32_t ret = 0;
- glusterd_conf_t *priv = NULL;
- DIR *dir = NULL;
- struct dirent *entry = NULL;
- char path[PATH_MAX] = {0,};
- glusterd_peerinfo_t *peerinfo = NULL;
- uuid_t uuid = {0,};
- char *hostname = NULL;
- int32_t state = 0;
- gf_store_handle_t *shandle = NULL;
- char filepath[PATH_MAX] = {0,};
- gf_store_iter_t *iter = NULL;
- char *key = NULL;
- char *value = NULL;
- glusterd_peerctx_args_t args = {0};
- gf_store_op_errno_t op_errno = GD_STORE_SUCCESS;
+ int32_t ret = 0;
+ glusterd_conf_t *priv = NULL;
+ DIR *dir = NULL;
+ struct dirent *entry = NULL;
+ char path[PATH_MAX] = {0,};
+ glusterd_peerinfo_t *peerinfo = NULL;
+ char *hostname = NULL;
+ gf_store_handle_t *shandle = NULL;
+ char filepath[PATH_MAX] = {0,};
+ gf_store_iter_t *iter = NULL;
+ char *key = NULL;
+ char *value = NULL;
+ glusterd_peerctx_args_t args = {0};
+ gf_store_op_errno_t op_errno = GD_STORE_SUCCESS;
+ glusterd_peer_hostname_t *address = NULL;
GF_ASSERT (this);
priv = this->private;
@@ -3987,20 +3997,30 @@ glusterd_store_retrieve_peers (xlator_t *this)
if (ret)
goto out;
+ /* Create an empty peerinfo object before reading in the
+ * details
+ */
+ peerinfo = glusterd_peerinfo_new (GD_FRIEND_STATE_DEFAULT, NULL,
+ NULL, 0);
+ if (peerinfo == NULL) {
+ ret = -1;
+ goto out;
+ }
+
while (!ret) {
if (!strncmp (GLUSTERD_STORE_KEY_PEER_UUID, key,
strlen (GLUSTERD_STORE_KEY_PEER_UUID))) {
if (value)
- uuid_parse (value, uuid);
+ uuid_parse (value, peerinfo->uuid);
} else if (!strncmp (GLUSTERD_STORE_KEY_PEER_STATE,
key,
strlen (GLUSTERD_STORE_KEY_PEER_STATE))) {
- state = atoi (value);
+ peerinfo->state.state = atoi (value);
} else if (!strncmp (GLUSTERD_STORE_KEY_PEER_HOSTNAME,
key,
strlen (GLUSTERD_STORE_KEY_PEER_HOSTNAME))) {
- hostname = gf_strdup (value);
+ ret = gd_add_address_to_peer (peerinfo, value);
} else {
gf_log ("", GF_LOG_ERROR, "Unknown key: %s",
key);
@@ -4021,14 +4041,23 @@ glusterd_store_retrieve_peers (xlator_t *this)
(void) gf_store_iter_destroy (iter);
- ret = glusterd_friend_add (hostname, 0, state, &uuid,
- &peerinfo, 1, NULL);
+ /* Set first hostname from peerinfo->hostnames to
+ * peerinfo->hostname
+ */
+ address = list_entry (peerinfo->hostnames.next,
+ glusterd_peer_hostname_t, hostname_list);
+ if (!address) {
+ ret = -1;
+ goto out;
+ }
+ peerinfo->hostname = gf_strdup (address->hostname);
- GF_FREE (hostname);
+ ret = glusterd_friend_add_from_peerinfo (peerinfo, 1, NULL);
if (ret)
goto out;
peerinfo->shandle = shandle;
+ peerinfo = NULL;
glusterd_for_each_entry (entry, dir);
}
@@ -4038,8 +4067,12 @@ glusterd_store_retrieve_peers (xlator_t *this)
if (ret)
goto out;
}
+ peerinfo = NULL;
out:
+ if (peerinfo)
+ glusterd_peerinfo_cleanup (peerinfo);
+
if (dir)
closedir (dir);
gf_log ("", GF_LOG_DEBUG, "Returning with %d", ret);
diff --git a/xlators/mgmt/glusterd/src/glusterd-syncop.c b/xlators/mgmt/glusterd/src/glusterd-syncop.c
index 6e7a9b6c8be..67ceb20c2e7 100644
--- a/xlators/mgmt/glusterd/src/glusterd-syncop.c
+++ b/xlators/mgmt/glusterd/src/glusterd-syncop.c
@@ -673,8 +673,9 @@ _gd_syncop_stage_op_cbk (struct rpc_req *req, struct iovec *iov,
}
}
- ret = glusterd_friend_find (rsp.uuid, NULL, &peerinfo);
- if (ret) {
+ peerinfo = glusterd_peerinfo_find (rsp.uuid, NULL);
+ if (peerinfo == NULL) {
+ ret = -1;
gf_log (this->name, GF_LOG_CRITICAL, "Staging response "
"for 'Volume %s' received from unknown "
"peer: %s", gd_op_list[rsp.op],
@@ -929,8 +930,9 @@ _gd_syncop_commit_op_cbk (struct rpc_req *req, struct iovec *iov,
}
}
- ret = glusterd_friend_find (rsp.uuid, NULL, &peerinfo);
- if (ret) {
+ peerinfo = glusterd_peerinfo_find (rsp.uuid, NULL);
+ if (peerinfo == NULL) {
+ ret = -1;
gf_log (this->name, GF_LOG_CRITICAL, "Commit response "
"for 'Volume %s' received from unknown "
"peer: %s", gd_op_list[rsp.op],
diff --git a/xlators/mgmt/glusterd/src/glusterd-utils.c b/xlators/mgmt/glusterd/src/glusterd-utils.c
index baa845b0a91..7eddb753dc6 100644
--- a/xlators/mgmt/glusterd/src/glusterd-utils.c
+++ b/xlators/mgmt/glusterd/src/glusterd-utils.c
@@ -82,18 +82,6 @@
static glusterd_lock_t lock;
-char*
-gd_peer_uuid_str (glusterd_peerinfo_t *peerinfo)
-{
- if ((peerinfo == NULL) || uuid_is_null (peerinfo->uuid))
- return NULL;
-
- if (peerinfo->uuid_str[0] == '\0')
- uuid_utoa_r (peerinfo->uuid, peerinfo->uuid_str);
-
- return peerinfo->uuid_str;
-}
-
int32_t
glusterd_get_lock_owner (uuid_t *uuid)
@@ -1403,38 +1391,6 @@ out:
return decommissioned;
}
-int32_t
-glusterd_friend_cleanup (glusterd_peerinfo_t *peerinfo)
-{
- GF_ASSERT (peerinfo);
- glusterd_peerctx_t *peerctx = NULL;
- gf_boolean_t quorum_action = _gf_false;
- glusterd_conf_t *priv = THIS->private;
-
- if (peerinfo->quorum_contrib != QUORUM_NONE)
- quorum_action = _gf_true;
- if (peerinfo->rpc) {
- /* cleanup the saved-frames before last unref */
- synclock_unlock (&priv->big_lock);
- rpc_clnt_connection_cleanup (&peerinfo->rpc->conn);
- synclock_lock (&priv->big_lock);
-
- peerctx = peerinfo->rpc->mydata;
- peerinfo->rpc->mydata = NULL;
- peerinfo->rpc = glusterd_rpc_clnt_unref (priv, peerinfo->rpc);
- peerinfo->rpc = NULL;
- if (peerctx) {
- GF_FREE (peerctx->errstr);
- GF_FREE (peerctx);
- }
- }
- glusterd_peer_destroy (peerinfo);
-
- if (quorum_action)
- glusterd_do_quorum_action ();
- return 0;
-}
-
int
glusterd_volinfo_find_by_volume_id (uuid_t volume_id, glusterd_volinfo_t **volinfo)
{
@@ -1986,32 +1942,6 @@ glusterd_volume_stop_glusterfs (glusterd_volinfo_t *volinfo,
return ret;
}
-int32_t
-glusterd_peer_hostname_new (char *hostname, glusterd_peer_hostname_t **name)
-{
- glusterd_peer_hostname_t *peer_hostname = NULL;
- int32_t ret = -1;
-
- GF_ASSERT (hostname);
- GF_ASSERT (name);
-
- peer_hostname = GF_CALLOC (1, sizeof (*peer_hostname),
- gf_gld_mt_peer_hostname_t);
-
- if (!peer_hostname)
- goto out;
-
- peer_hostname->hostname = gf_strdup (hostname);
- INIT_LIST_HEAD (&peer_hostname->hostname_list);
-
- *name = peer_hostname;
- ret = 0;
-
-out:
- gf_log ("", GF_LOG_DEBUG, "Returning %d", ret);
- return ret;
-}
-
/* Free LINE[0..N-1] and then the LINE buffer. */
static void
free_lines (char **line, size_t n)
@@ -7671,163 +7601,6 @@ out:
return ret;
}
-int
-glusterd_friend_find_by_uuid (uuid_t uuid,
- glusterd_peerinfo_t **peerinfo)
-{
- int ret = -1;
- glusterd_conf_t *priv = NULL;
- glusterd_peerinfo_t *entry = NULL;
- xlator_t *this = NULL;
-
- this = THIS;
- GF_ASSERT (this);
- GF_ASSERT (peerinfo);
-
- *peerinfo = NULL;
- priv = this->private;
-
- GF_ASSERT (priv);
-
- if (uuid_is_null (uuid))
- return -1;
-
- list_for_each_entry (entry, &priv->peers, uuid_list) {
- if (!uuid_compare (entry->uuid, uuid)) {
-
- gf_log (this->name, GF_LOG_DEBUG,
- "Friend found... state: %s",
- glusterd_friend_sm_state_name_get (entry->state.state));
- *peerinfo = entry;
- return 0;
- }
- }
-
- gf_log (this->name, GF_LOG_DEBUG, "Friend with uuid: %s, not found",
- uuid_utoa (uuid));
- return ret;
-}
-
-
-int
-glusterd_friend_find_by_hostname (const char *hoststr,
- glusterd_peerinfo_t **peerinfo)
-{
- int ret = -1;
- glusterd_conf_t *priv = NULL;
- glusterd_peerinfo_t *entry = NULL;
- struct addrinfo *addr = NULL;
- struct addrinfo *p = NULL;
- char *host = NULL;
- struct sockaddr_in6 *s6 = NULL;
- struct sockaddr_in *s4 = NULL;
- struct in_addr *in_addr = NULL;
- char hname[1024] = {0,};
- xlator_t *this = NULL;
-
-
- this = THIS;
- GF_ASSERT (hoststr);
- GF_ASSERT (peerinfo);
-
- *peerinfo = NULL;
- priv = this->private;
-
- GF_ASSERT (priv);
-
- list_for_each_entry (entry, &priv->peers, uuid_list) {
- if (!strncasecmp (entry->hostname, hoststr,
- 1024)) {
-
- gf_log (this->name, GF_LOG_DEBUG,
- "Friend %s found.. state: %d", hoststr,
- entry->state.state);
- *peerinfo = entry;
- return 0;
- }
- }
-
- ret = getaddrinfo (hoststr, NULL, NULL, &addr);
- if (ret != 0) {
- gf_log (this->name, GF_LOG_ERROR,
- "error in getaddrinfo: %s\n",
- gai_strerror(ret));
- goto out;
- }
-
- for (p = addr; p != NULL; p = p->ai_next) {
- switch (p->ai_family) {
- case AF_INET:
- s4 = (struct sockaddr_in *) p->ai_addr;
- in_addr = &s4->sin_addr;
- break;
- case AF_INET6:
- s6 = (struct sockaddr_in6 *) p->ai_addr;
- in_addr =(struct in_addr *) &s6->sin6_addr;
- break;
- default: ret = -1;
- goto out;
- }
- host = inet_ntoa(*in_addr);
-
- ret = getnameinfo (p->ai_addr, p->ai_addrlen, hname,
- 1024, NULL, 0, 0);
- if (ret)
- goto out;
-
- list_for_each_entry (entry, &priv->peers, uuid_list) {
- if (!strncasecmp (entry->hostname, host,
- 1024) || !strncasecmp (entry->hostname,hname,
- 1024)) {
- gf_log (this->name, GF_LOG_DEBUG,
- "Friend %s found.. state: %d",
- hoststr, entry->state.state);
- *peerinfo = entry;
- freeaddrinfo (addr);
- return 0;
- }
- }
- }
-
-out:
- gf_log (this->name, GF_LOG_DEBUG, "Unable to find friend: %s", hoststr);
- if (addr)
- freeaddrinfo (addr);
- return -1;
-}
-
-int
-glusterd_hostname_to_uuid (char *hostname, uuid_t uuid)
-{
- GF_ASSERT (hostname);
- GF_ASSERT (uuid);
-
- glusterd_peerinfo_t *peerinfo = NULL;
- glusterd_conf_t *priv = NULL;
- int ret = -1;
- xlator_t *this = NULL;
-
- this = THIS;
- GF_ASSERT (this);
- priv = this->private;
- GF_ASSERT (priv);
-
- ret = glusterd_friend_find_by_hostname (hostname, &peerinfo);
- if (ret) {
- if (gf_is_local_addr (hostname)) {
- uuid_copy (uuid, MY_UUID);
- ret = 0;
- } else {
- goto out;
- }
- } else {
- uuid_copy (uuid, peerinfo->uuid);
- }
-
-out:
- gf_log (this->name, GF_LOG_DEBUG, "returning %d", ret);
- return ret;
-}
int
glusterd_brick_stop (glusterd_volinfo_t *volinfo,
@@ -7946,9 +7719,9 @@ glusterd_new_brick_validate (char *brick, glusterd_brickinfo_t *brickinfo,
}
} else {
- ret = glusterd_friend_find_by_uuid (newbrickinfo->uuid,
- &peerinfo);
- if (ret) {
+ peerinfo = glusterd_peerinfo_find_by_uuid (newbrickinfo->uuid);
+ if (peerinfo == NULL) {
+ ret = -1;
snprintf (op_errstr, len, "Failed to find host %s",
newbrickinfo->hostname);
goto out;
@@ -8375,76 +8148,6 @@ out:
}
int
-glusterd_peerinfo_new (glusterd_peerinfo_t **peerinfo,
- glusterd_friend_sm_state_t state, uuid_t *uuid,
- const char *hostname, int port)
-{
- glusterd_peerinfo_t *new_peer = NULL;
- int ret = -1;
-
- GF_ASSERT (peerinfo);
- if (!peerinfo)
- goto out;
-
- new_peer = GF_CALLOC (1, sizeof (*new_peer), gf_gld_mt_peerinfo_t);
- if (!new_peer)
- goto out;
-
- new_peer->state.state = state;
- if (hostname)
- new_peer->hostname = gf_strdup (hostname);
-
- INIT_LIST_HEAD (&new_peer->uuid_list);
-
- if (uuid) {
- uuid_copy (new_peer->uuid, *uuid);
- }
-
- ret = glusterd_sm_tr_log_init (&new_peer->sm_log,
- glusterd_friend_sm_state_name_get,
- glusterd_friend_sm_event_name_get,
- GLUSTERD_TR_LOG_SIZE);
- if (ret)
- goto out;
-
- if (new_peer->state.state == GD_FRIEND_STATE_BEFRIENDED)
- new_peer->quorum_contrib = QUORUM_WAITING;
- new_peer->port = port;
- *peerinfo = new_peer;
-out:
- if (ret && new_peer)
- glusterd_friend_cleanup (new_peer);
- gf_log ("", GF_LOG_DEBUG, "returning %d", ret);
- return ret;
-}
-
-int32_t
-glusterd_peer_destroy (glusterd_peerinfo_t *peerinfo)
-{
- int32_t ret = -1;
-
- if (!peerinfo)
- goto out;
-
- ret = glusterd_store_delete_peerinfo (peerinfo);
-
- if (ret) {
- gf_log ("", GF_LOG_ERROR, "Deleting peer info failed");
- }
-
- list_del_init (&peerinfo->uuid_list);
- GF_FREE (peerinfo->hostname);
- glusterd_sm_tr_log_delete (&peerinfo->sm_log);
- GF_FREE (peerinfo);
- peerinfo = NULL;
-
- ret = 0;
-
-out:
- return ret;
-}
-
-int
glusterd_remove_pending_entry (struct list_head *list, void *elem)
{
glusterd_pending_node_t *pending_node = NULL;
@@ -8479,16 +8182,6 @@ glusterd_clear_pending_nodes (struct list_head *list)
return 0;
}
-gf_boolean_t
-glusterd_peerinfo_is_uuid_unknown (glusterd_peerinfo_t *peerinfo)
-{
- GF_ASSERT (peerinfo);
-
- if (uuid_is_null (peerinfo->uuid))
- return _gf_true;
- return _gf_false;
-}
-
int32_t
glusterd_delete_volume (glusterd_volinfo_t *volinfo)
{
@@ -9149,36 +8842,6 @@ out:
return ret;
}
-/* Check if the all peers are connected and befriended, except the peer
- * specified (the peer being detached)
- */
-gf_boolean_t
-glusterd_chk_peers_connected_befriended (uuid_t skip_uuid)
-{
- gf_boolean_t ret = _gf_true;
- glusterd_peerinfo_t *peerinfo = NULL;
- glusterd_conf_t *priv = NULL;
-
- priv= THIS->private;
- GF_ASSERT (priv);
-
- list_for_each_entry (peerinfo, &priv->peers, uuid_list) {
-
- if (!uuid_is_null (skip_uuid) && !uuid_compare (skip_uuid,
- peerinfo->uuid))
- continue;
-
- if ((GD_FRIEND_STATE_BEFRIENDED != peerinfo->state.state)
- || !(peerinfo->connected)) {
- ret = _gf_false;
- break;
- }
- }
- gf_log (THIS->name, GF_LOG_DEBUG, "Returning %s",
- (ret?"TRUE":"FALSE"));
- return ret;
-}
-
void
glusterd_get_client_filepath (char *filepath, glusterd_volinfo_t *volinfo,
gf_transport_type type)
@@ -9303,34 +8966,6 @@ glusterd_volinfo_reset_defrag_stats (glusterd_volinfo_t *volinfo)
}
-/* Return hostname for given uuid if it exists
- * else return NULL
- */
-char *
-glusterd_uuid_to_hostname (uuid_t uuid)
-{
- char *hostname = NULL;
- glusterd_conf_t *priv = NULL;
- glusterd_peerinfo_t *entry = NULL;
-
- priv = THIS->private;
- GF_ASSERT (priv);
-
- if (!uuid_compare (MY_UUID, uuid)) {
- hostname = gf_strdup ("localhost");
- }
- if (!list_empty (&priv->peers)) {
- list_for_each_entry (entry, &priv->peers, uuid_list) {
- if (!uuid_compare (entry->uuid, uuid)) {
- hostname = gf_strdup (entry->hostname);
- break;
- }
- }
- }
-
- return hostname;
-}
-
gf_boolean_t
glusterd_is_local_brick (xlator_t *this, glusterd_volinfo_t *volinfo,
glusterd_brickinfo_t *brickinfo)
@@ -11787,42 +11422,6 @@ gd_is_remove_brick_committed (glusterd_volinfo_t *volinfo)
}
gf_boolean_t
-glusterd_are_vol_all_peers_up (glusterd_volinfo_t *volinfo,
- struct list_head *peers,
- char **down_peerstr)
-{
- glusterd_peerinfo_t *peerinfo = NULL;
- glusterd_brickinfo_t *brickinfo = NULL;
- gf_boolean_t ret = _gf_false;
-
- list_for_each_entry (brickinfo, &volinfo->bricks, brick_list) {
- if (!uuid_compare (brickinfo->uuid, MY_UUID))
- continue;
-
- list_for_each_entry (peerinfo, peers, uuid_list) {
- if (uuid_compare (peerinfo->uuid, brickinfo->uuid))
- continue;
-
- /*Found peer who owns the brick, return false
- * if peer is not connected or not friend */
- if (!(peerinfo->connected) ||
- (peerinfo->state.state !=
- GD_FRIEND_STATE_BEFRIENDED)) {
- *down_peerstr = gf_strdup (peerinfo->hostname);
- gf_log ("", GF_LOG_DEBUG, "Peer %s is down. ",
- peerinfo->hostname);
- goto out;
- }
- }
- }
-
- ret = _gf_true;
-out:
- gf_log ("", GF_LOG_DEBUG, "Returning %d", ret);
- return ret;
-}
-
-gf_boolean_t
glusterd_is_status_tasks_op (glusterd_op_t op, dict_t *dict)
{
int ret = -1;
diff --git a/xlators/mgmt/glusterd/src/glusterd-utils.h b/xlators/mgmt/glusterd/src/glusterd-utils.h
index aef28de1b8d..f8dfce7ca82 100644
--- a/xlators/mgmt/glusterd/src/glusterd-utils.h
+++ b/xlators/mgmt/glusterd/src/glusterd-utils.h
@@ -29,6 +29,7 @@
#include "protocol-common.h"
#include "glusterfs3-xdr.h"
+#include "glusterd-peer-utils.h"
#define GLUSTERD_SOCK_DIR "/var/run"
#define GLUSTERD_ASSIGN_BRICKID_TO_BRICKINFO(brickinfo, volinfo, brickid) do {\
@@ -125,15 +126,6 @@ int32_t
glusterd_brickinfo_new_from_brick (char *brick, glusterd_brickinfo_t **brickinfo);
int32_t
-glusterd_friend_cleanup (glusterd_peerinfo_t *peerinfo);
-
-int32_t
-glusterd_peer_destroy (glusterd_peerinfo_t *peerinfo);
-
-int32_t
-glusterd_peer_hostname_new (char *hostname, glusterd_peer_hostname_t **name);
-
-int32_t
glusterd_snap_volinfo_find (char *volname, glusterd_snap_t *snap,
glusterd_volinfo_t **volinfo);
int32_t
@@ -312,12 +304,6 @@ gf_boolean_t
glusterd_is_brick_started (glusterd_brickinfo_t *brickinfo);
int
-glusterd_friend_find_by_hostname (const char *hoststr,
- glusterd_peerinfo_t **peerinfo);
-int
-glusterd_hostname_to_uuid (char *hostname, uuid_t uuid);
-
-int
glusterd_friend_brick_belongs (glusterd_volinfo_t *volinfo,
glusterd_brickinfo_t *brickinfo, void *uuid);
int
@@ -339,9 +325,6 @@ int32_t
glusterd_volinfo_bricks_delete (glusterd_volinfo_t *volinfo);
int
-glusterd_friend_find_by_uuid (uuid_t uuid,
- glusterd_peerinfo_t **peerinfo);
-int
glusterd_new_brick_validate (char *brick, glusterd_brickinfo_t *brickinfo,
char *op_errstr, size_t len);
int32_t
@@ -385,10 +368,6 @@ glusterd_sm_tr_log_transition_add (glusterd_sm_tr_log_t *log,
int old_state, int new_state,
int event);
int
-glusterd_peerinfo_new (glusterd_peerinfo_t **peerinfo,
- glusterd_friend_sm_state_t state, uuid_t *uuid,
- const char *hostname, int port);
-int
glusterd_sm_tr_log_init (glusterd_sm_tr_log_t *log,
char * (*state_name_get) (int),
char * (*event_name_get) (int),
@@ -403,8 +382,6 @@ int
glusterd_remove_pending_entry (struct list_head *list, void *elem);
int
glusterd_clear_pending_nodes (struct list_head *list);
-gf_boolean_t
-glusterd_peerinfo_is_uuid_unknown (glusterd_peerinfo_t *peerinfo);
int32_t
glusterd_brick_connect (glusterd_volinfo_t *volinfo,
glusterd_brickinfo_t *brickinfo, char *socketpath);
@@ -481,9 +458,6 @@ glusterd_friend_contains_vol_bricks (glusterd_volinfo_t *volinfo,
int
glusterd_friend_remove_cleanup_vols (uuid_t uuid);
-gf_boolean_t
-glusterd_chk_peers_connected_befriended (uuid_t skip_uuid);
-
void
glusterd_get_client_filepath (char *filepath,
glusterd_volinfo_t *volinfo,
@@ -503,9 +477,6 @@ int
glusterd_add_node_to_dict (char *server, dict_t *dict, int count,
dict_t *vol_opts);
-char *
-glusterd_uuid_to_hostname (uuid_t uuid);
-
int
glusterd_get_dist_leaf_count (glusterd_volinfo_t *volinfo);
@@ -577,11 +548,6 @@ glusterd_profile_volume_brick_rsp (void *pending_entry,
dict_t *rsp_dict, dict_t *op_ctx,
char **op_errstr, gd_node_type type);
-gf_boolean_t
-glusterd_are_vol_all_peers_up (glusterd_volinfo_t *volinfo,
- struct list_head *peers,
- char **down_peerstr);
-
int32_t
glusterd_set_originator_uuid (dict_t *dict);
@@ -632,17 +598,9 @@ gd_update_volume_op_versions (glusterd_volinfo_t *volinfo);
int
op_version_check (xlator_t *this, int min_op_version, char *msg, int msglen);
-char*
-gd_peer_uuid_str (glusterd_peerinfo_t *peerinfo);
-
gf_boolean_t
gd_is_remove_brick_committed (glusterd_volinfo_t *volinfo);
-gf_boolean_t
-glusterd_are_vol_all_peers_up (glusterd_volinfo_t *volinfo,
- struct list_head *peers,
- char **down_peerstr);
-
int
glusterd_get_slave_details_confpath (glusterd_volinfo_t *volinfo,
dict_t *dict, char **slave_url,
diff --git a/xlators/mgmt/glusterd/src/glusterd.h b/xlators/mgmt/glusterd/src/glusterd.h
index ddbb2c81338..ec036f8cf06 100644
--- a/xlators/mgmt/glusterd/src/glusterd.h
+++ b/xlators/mgmt/glusterd/src/glusterd.h
@@ -651,16 +651,16 @@ glusterd_xfer_friend_add_resp (rpcsvc_request_t *req, char *myhostname,
int32_t op_errno);
int
-glusterd_friend_find (uuid_t uuid, char *hostname,
- glusterd_peerinfo_t **peerinfo);
-
-int
glusterd_friend_add (const char *hoststr, int port,
glusterd_friend_sm_state_t state,
uuid_t *uuid, glusterd_peerinfo_t **friend,
gf_boolean_t restore, glusterd_peerctx_args_t *args);
int
+glusterd_friend_add_from_peerinfo (glusterd_peerinfo_t *friend,
+ gf_boolean_t restore,
+ glusterd_peerctx_args_t *args);
+int
glusterd_friend_rpc_create (xlator_t *this, glusterd_peerinfo_t *peerinfo,
glusterd_peerctx_args_t *args);
int