diff options
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  | 
