diff options
Diffstat (limited to 'xlators/mgmt/glusterd/src/glusterd-handler.c')
-rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-handler.c | 189 |
1 files changed, 150 insertions, 39 deletions
diff --git a/xlators/mgmt/glusterd/src/glusterd-handler.c b/xlators/mgmt/glusterd/src/glusterd-handler.c index eaa05969656..cc97baf6f21 100644 --- a/xlators/mgmt/glusterd/src/glusterd-handler.c +++ b/xlators/mgmt/glusterd/src/glusterd-handler.c @@ -103,6 +103,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)); + + rcu_read_lock (); + peerinfo = glusterd_peerinfo_find (uuid, rhost); if (peerinfo == NULL) { @@ -120,10 +123,11 @@ glusterd_handle_friend_req (rpcsvc_request_t *req, uuid_t uuid, if (ret) { gf_log ("", GF_LOG_ERROR, "event generation failed: %d", ret); - return ret; + goto out; } - event->peerinfo = peerinfo; + event->peername = gf_strdup (peerinfo->hostname); + uuid_copy (event->peerid, peerinfo->uuid); ctx = GF_CALLOC (1, sizeof (*ctx), gf_gld_mt_friend_req_ctx_t); @@ -164,9 +168,13 @@ glusterd_handle_friend_req (rpcsvc_request_t *req, uuid_t uuid, } ret = 0; + if (peerinfo && (0 == peerinfo->connected)) + ret = GLUSTERD_CONNECTION_AWAITED; out: - if (0 != ret) { + rcu_read_unlock (); + + if (ret && (ret != GLUSTERD_CONNECTION_AWAITED)) { if (ctx && ctx->hostname) GF_FREE (ctx->hostname); GF_FREE (ctx); @@ -178,11 +186,12 @@ out: } else { free (friend_req->vols.vols_val); } + if (event) + GF_FREE (event->peername); GF_FREE (event); - } else { - if (peerinfo && (0 == peerinfo->connected)) - ret = GLUSTERD_CONNECTION_AWAITED; } + + return ret; } @@ -198,6 +207,8 @@ glusterd_handle_unfriend_req (rpcsvc_request_t *req, uuid_t uuid, if (!port) port = GF_DEFAULT_BASE_PORT; + rcu_read_lock (); + peerinfo = glusterd_peerinfo_find (uuid, hostname); if (peerinfo == NULL) { @@ -214,10 +225,11 @@ glusterd_handle_unfriend_req (rpcsvc_request_t *req, uuid_t uuid, if (ret) { gf_log ("", GF_LOG_ERROR, "event generation failed: %d", ret); - return ret; + goto out; } - event->peerinfo = peerinfo; + event->peername = gf_strdup (hostname); + uuid_copy (event->peerid, uuid); ctx = GF_CALLOC (1, sizeof (*ctx), gf_gld_mt_friend_req_ctx_t); @@ -245,10 +257,15 @@ glusterd_handle_unfriend_req (rpcsvc_request_t *req, uuid_t uuid, ret = 0; out: + rcu_read_unlock (); + if (0 != ret) { if (ctx && ctx->hostname) GF_FREE (ctx->hostname); GF_FREE (ctx); + if (event) + GF_FREE (event->peername); + GF_FREE (event); } return ret; @@ -698,7 +715,10 @@ __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_peerinfo_find_by_uuid (lock_req.uuid) == NULL) { + rcu_read_lock (); + ret = (glusterd_peerinfo_find_by_uuid (lock_req.uuid) == NULL); + rcu_read_unlock (); + if (ret) { gf_log (this->name, GF_LOG_WARNING, "%s doesn't " "belong to the cluster. Ignoring request.", uuid_utoa (lock_req.uuid)); @@ -846,7 +866,10 @@ __glusterd_handle_stage_op (rpcsvc_request_t *req) gf_log (this->name, GF_LOG_DEBUG, "transaction ID = %s", uuid_utoa (*txn_id)); - if (glusterd_peerinfo_find_by_uuid (op_req.uuid) == NULL) { + rcu_read_lock (); + ret = (glusterd_peerinfo_find_by_uuid (op_req.uuid) == NULL); + rcu_read_unlock (); + if (ret) { gf_log (this->name, GF_LOG_WARNING, "%s doesn't " "belong to the cluster. Ignoring request.", uuid_utoa (op_req.uuid)); @@ -922,7 +945,10 @@ __glusterd_handle_commit_op (rpcsvc_request_t *req) goto out; } - if (glusterd_peerinfo_find_by_uuid (op_req.uuid) == NULL) { + rcu_read_lock (); + ret = (glusterd_peerinfo_find_by_uuid (op_req.uuid) == NULL); + rcu_read_unlock (); + if (ret) { gf_log (this->name, GF_LOG_WARNING, "%s doesn't " "belong to the cluster. Ignoring request.", uuid_utoa (op_req.uuid)); @@ -1037,14 +1063,22 @@ __glusterd_handle_cli_probe (rpcsvc_request_t *req) goto out; } + rcu_read_lock (); + peerinfo = glusterd_peerinfo_find_by_hostname (hostname); - if (peerinfo && gd_peer_has_address (peerinfo, hostname)) { + ret = (peerinfo && gd_peer_has_address (peerinfo, hostname)); + + rcu_read_unlock (); + + if (ret) { 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); + ret = 0; goto out; } + ret = glusterd_probe_begin (req, hostname, port, dict, &op_errno); if (ret == GLUSTERD_CONNECTION_AWAITED) { @@ -1931,27 +1965,32 @@ __glusterd_handle_fsm_log (rpcsvc_request_t *req) goto out; } + dict = dict_new (); + if (!dict) { + ret = -1; + goto out; + } + if (strcmp ("", cli_req.name) == 0) { this = THIS; conf = this->private; - log = &conf->op_sm_log; + ret = glusterd_sm_tr_log_add_to_dict (dict, &conf->op_sm_log); } else { + rcu_read_lock (); + peerinfo = glusterd_peerinfo_find_by_hostname (cli_req.name); if (!peerinfo) { + ret = -1; snprintf (msg, sizeof (msg), "%s is not a peer", cli_req.name); - goto out; + } else { + ret = glusterd_sm_tr_log_add_to_dict + (dict, &peerinfo->sm_log); } - log = &peerinfo->sm_log; - } - dict = dict_new (); - if (!dict) { - ret = -1; - goto out; + rcu_read_unlock (); } - ret = glusterd_sm_tr_log_add_to_dict (dict, log); out: (void)glusterd_fsm_log_send_resp (req, ret, msg, dict); free (cli_req.name);//malloced by xdr @@ -2089,7 +2128,10 @@ __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_peerinfo_find_by_uuid (unlock_req.uuid) == NULL) { + rcu_read_lock (); + ret = (glusterd_peerinfo_find_by_uuid (unlock_req.uuid) == NULL); + rcu_read_unlock (); + if (ret) { gf_log (this->name, GF_LOG_WARNING, "%s doesn't " "belong to the cluster. Ignoring request.", uuid_utoa (unlock_req.uuid)); @@ -2370,12 +2412,18 @@ __glusterd_handle_friend_update (rpcsvc_request_t *req) goto out; } + ret = 0; + rcu_read_lock (); if (glusterd_peerinfo_find (friend_req.uuid, NULL) == NULL) { ret = -1; + } + rcu_read_unlock (); + if (ret) { gf_log ("", GF_LOG_CRITICAL, "Received friend update request " "from unknown peer %s", uuid_utoa (friend_req.uuid)); goto out; } + gf_log ("glusterd", GF_LOG_INFO, "Received friend update from uuid: %s", uuid_utoa (friend_req.uuid)); @@ -2428,6 +2476,7 @@ __glusterd_handle_friend_update (rpcsvc_request_t *req) memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "friend%d", i); + rcu_read_lock (); peerinfo = glusterd_peerinfo_find (uuid, NULL); if (peerinfo == NULL) { /* Create a new peer and add it to the list as there is @@ -2439,7 +2488,7 @@ __glusterd_handle_friend_update (rpcsvc_request_t *req) gf_log (this->name, GF_LOG_ERROR, "Could not create peerinfo from dict " "for prefix %s", key); - goto out; + goto unlock; } /* As this is a new peer, it should be added as a @@ -2459,9 +2508,12 @@ __glusterd_handle_friend_update (rpcsvc_request_t *req) if (ret) { gf_log (this->name, GF_LOG_ERROR, "Failed to " "update peer %s", peerinfo->hostname); - goto out; } } +unlock: + rcu_read_unlock (); + if (ret) + break; peerinfo = NULL; i++; @@ -2549,6 +2601,8 @@ __glusterd_handle_probe_query (rpcsvc_request_t *req) gf_log ("", GF_LOG_ERROR, "Unable to get the remote hostname"); goto out; } + + rcu_read_lock (); peerinfo = glusterd_peerinfo_find (probe_req.uuid, remote_hostname); if ((peerinfo == NULL) && (!cds_list_empty (&conf->peers))) { rsp.op_ret = -1; @@ -2566,6 +2620,7 @@ __glusterd_handle_probe_query (rpcsvc_request_t *req) rsp.op_errno = GF_PROBE_ADD_FAILED; } } + rcu_read_unlock (); respond: uuid_copy (rsp.uuid, MY_UUID); @@ -2882,6 +2937,8 @@ glusterd_friend_remove (uuid_t uuid, char *hostname) int ret = -1; glusterd_peerinfo_t *peerinfo = NULL; + rcu_read_lock (); + peerinfo = glusterd_peerinfo_find (uuid, hostname); if (peerinfo == NULL) goto out; @@ -2889,6 +2946,11 @@ glusterd_friend_remove (uuid_t uuid, char *hostname) ret = glusterd_friend_remove_cleanup_vols (peerinfo->uuid); if (ret) gf_log (THIS->name, GF_LOG_WARNING, "Volumes cleanup failed"); + + rcu_read_unlock (); + /* Giving up the critical section here as glusterd_peerinfo_cleanup must + * be called from outside a critical section + */ ret = glusterd_peerinfo_cleanup (peerinfo); out: gf_log ("", GF_LOG_DEBUG, "returning %d", ret); @@ -3008,7 +3070,8 @@ glusterd_friend_rpc_create (xlator_t *this, glusterd_peerinfo_t *peerinfo, if (args) peerctx->args = *args; - peerctx->peerinfo = peerinfo; + uuid_copy (peerctx->peerid, peerinfo->uuid); + peerctx->peername = gf_strdup (peerinfo->hostname); ret = glusterd_transport_inet_options_build (&options, peerinfo->hostname, @@ -3079,7 +3142,7 @@ glusterd_friend_add (const char *hoststr, int port, * invalid peer name). That would mean we're adding something that had * just been free, and we're likely to crash later. */ - cds_list_add_tail (&(*friend)->uuid_list, &conf->peers); + cds_list_add_tail_rcu (&(*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 @@ -3132,7 +3195,7 @@ glusterd_friend_add_from_peerinfo (glusterd_peerinfo_t *friend, * invalid peer name). That would mean we're adding something that had * just been free, and we're likely to crash later. */ - cds_list_add_tail (&friend->uuid_list, &conf->peers); + cds_list_add_tail_rcu (&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 @@ -3165,6 +3228,7 @@ glusterd_probe_begin (rpcsvc_request_t *req, const char *hoststr, int port, GF_ASSERT (hoststr); + rcu_read_lock (); peerinfo = glusterd_peerinfo_find (NULL, hoststr); if (peerinfo == NULL) { @@ -3196,7 +3260,9 @@ glusterd_probe_begin (rpcsvc_request_t *req, const char *hoststr, int port, ret = glusterd_friend_sm_new_event (GD_FRIEND_EVENT_LOCAL_ACC, &event); if (!ret) { - event->peerinfo = peerinfo; + event->peername = gf_strdup (peerinfo->hostname); + uuid_copy (event->peerid, peerinfo->uuid); + ret = glusterd_friend_sm_inject_event (event); glusterd_xfer_cli_probe_resp (req, 0, GF_PROBE_SUCCESS, NULL, (char*)hoststr, @@ -3208,6 +3274,7 @@ glusterd_probe_begin (rpcsvc_request_t *req, const char *hoststr, int port, } out: + rcu_read_unlock (); gf_log ("", GF_LOG_DEBUG, "returning %d", ret); return ret; } @@ -3224,8 +3291,9 @@ glusterd_deprobe_begin (rpcsvc_request_t *req, const char *hoststr, int port, GF_ASSERT (hoststr); GF_ASSERT (req); - peerinfo = glusterd_peerinfo_find (uuid, hoststr); + rcu_read_lock (); + peerinfo = glusterd_peerinfo_find (uuid, hoststr); if (peerinfo == NULL) { ret = -1; gf_log ("glusterd", GF_LOG_INFO, "Unable to find peerinfo" @@ -3251,7 +3319,7 @@ glusterd_deprobe_begin (rpcsvc_request_t *req, const char *hoststr, int port, if (ret) { gf_log ("glusterd", GF_LOG_ERROR, "Unable to get new event"); - return ret; + goto out; } ctx = GF_CALLOC (1, sizeof(*ctx), gf_gld_mt_probe_ctx_t); @@ -3267,7 +3335,8 @@ glusterd_deprobe_begin (rpcsvc_request_t *req, const char *hoststr, int port, event->ctx = ctx; - event->peerinfo = peerinfo; + event->peername = gf_strdup (hoststr); + uuid_copy (event->peerid, uuid); ret = glusterd_friend_sm_inject_event (event); @@ -3279,6 +3348,7 @@ glusterd_deprobe_begin (rpcsvc_request_t *req, const char *hoststr, int port, peerinfo->detaching = _gf_true; out: + rcu_read_unlock (); return ret; } @@ -3590,15 +3660,23 @@ glusterd_list_friends (rpcsvc_request_t *req, dict_t *dict, int32_t flags) gf_log ("", GF_LOG_WARNING, "Out of Memory"); goto out; } + + /* Reset ret to 0, needed to prevent failure incase no peers exist */ + ret = 0; + rcu_read_lock (); if (!cds_list_empty (&priv->peers)) { - cds_list_for_each_entry (entry, &priv->peers, uuid_list) { + cds_list_for_each_entry_rcu (entry, &priv->peers, uuid_list) { count++; ret = gd_add_peer_detail_to_dict (entry, friends, count); if (ret) - goto out; + goto unlock; } } +unlock: + rcu_read_unlock (); + if (ret) + goto out; if (flags == GF_CLI_LIST_POOL_NODES) { count++; @@ -4417,14 +4495,23 @@ glusterd_friend_remove_notify (glusterd_peerctx_t *peerctx) { int ret = -1; glusterd_friend_sm_event_t *new_event = NULL; - glusterd_peerinfo_t *peerinfo = peerctx->peerinfo; - rpcsvc_request_t *req = peerctx->args.req; - char *errstr = peerctx->errstr; + glusterd_peerinfo_t *peerinfo = NULL; + rpcsvc_request_t *req = NULL; + char *errstr = NULL; dict_t *dict = NULL; GF_ASSERT (peerctx); - peerinfo = peerctx->peerinfo; + rcu_read_lock (); + peerinfo = glusterd_peerinfo_find (peerctx->peerid, peerctx->peername); + if (!peerinfo) { + gf_log (THIS->name, GF_LOG_DEBUG, "Could not find peer %s(%s). " + "Peer could have been deleted.", peerctx->peername, + uuid_utoa (peerctx->peerid)); + ret = 0; + goto out; + } + req = peerctx->args.req; dict = peerctx->args.dict; errstr = peerctx->errstr; @@ -4443,7 +4530,8 @@ glusterd_friend_remove_notify (glusterd_peerctx_t *peerctx) peerinfo->hostname, peerinfo->port, dict); - new_event->peerinfo = peerinfo; + new_event->peername = gf_strdup (peerinfo->hostname); + uuid_copy (new_event->peerid, peerinfo->uuid); ret = glusterd_friend_sm_inject_event (new_event); } else { @@ -4453,6 +4541,7 @@ glusterd_friend_remove_notify (glusterd_peerctx_t *peerctx) } out: + rcu_read_unlock (); return ret; } @@ -4473,10 +4562,29 @@ __glusterd_peer_rpc_notify (struct rpc_clnt *rpc, void *mydata, if (!peerctx) return 0; - peerinfo = peerctx->peerinfo; this = THIS; conf = this->private; + if (RPC_CLNT_DESTROY == event) { + GF_FREE (peerctx->errstr); + GF_FREE (peerctx->peername); + GF_FREE (peerctx); + return 0; + } + + rcu_read_lock (); + + peerinfo = glusterd_peerinfo_find (peerctx->peerid, peerctx->peername); + if (!peerinfo) { + /* Peerinfo should be available at this point. Not finding it + * means that something terrible has happened + */ + gf_log (THIS->name, GF_LOG_CRITICAL, "Could not find peer " + "%s(%s)", peerctx->peername, uuid_utoa (peerctx->peerid)); + ret = -1; + goto out; + } + switch (event) { case RPC_CLNT_CONNECT: { @@ -4545,6 +4653,7 @@ __glusterd_peer_rpc_notify (struct rpc_clnt *rpc, void *mydata, peerinfo->connected = 0; break; } + default: gf_log (this->name, GF_LOG_TRACE, "got some other RPC event %d", event); @@ -4553,6 +4662,8 @@ __glusterd_peer_rpc_notify (struct rpc_clnt *rpc, void *mydata, } out: + rcu_read_unlock (); + glusterd_friend_sm (); glusterd_op_sm (); if (quorum_action) |