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