From 65a84c9d0d691ac4f7a5f33374140e50746a96af Mon Sep 17 00:00:00 2001 From: Pranith K Date: Tue, 28 Sep 2010 02:47:08 +0000 Subject: mgmt/glusterd: prevent detach of peer with its bricks existing in cluster Signed-off-by: Pranith Kumar K Signed-off-by: Vijay Bellur BUG: 1681 () URL: http://bugs.gluster.com/cgi-bin/bugzilla3/show_bug.cgi?id=1681 --- xlators/mgmt/glusterd/src/glusterd-handler.c | 126 ++++++------------- xlators/mgmt/glusterd/src/glusterd-op-sm.c | 17 +++ xlators/mgmt/glusterd/src/glusterd-utils.c | 182 ++++++++++++++++++++++++--- xlators/mgmt/glusterd/src/glusterd-utils.h | 16 +++ xlators/mgmt/glusterd/src/glusterd.h | 3 +- 5 files changed, 234 insertions(+), 110 deletions(-) (limited to 'xlators/mgmt') diff --git a/xlators/mgmt/glusterd/src/glusterd-handler.c b/xlators/mgmt/glusterd/src/glusterd-handler.c index af4b3130648..5de695300fc 100644 --- a/xlators/mgmt/glusterd/src/glusterd-handler.c +++ b/xlators/mgmt/glusterd/src/glusterd-handler.c @@ -54,94 +54,6 @@ #include "defaults.c" #include "common-utils.h" -static 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; - glusterd_peer_hostname_t *name = 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,}; - - GF_ASSERT (hoststr); - GF_ASSERT (peerinfo); - - *peerinfo = NULL; - priv = THIS->private; - - GF_ASSERT (priv); - - list_for_each_entry (entry, &priv->peers, uuid_list) { - list_for_each_entry (name, &entry->hostnames, hostname_list) { - if (!strncmp (name->hostname, hoststr, - 1024)) { - - gf_log ("glusterd", GF_LOG_NORMAL, - "Friend %s found.. state: %d", hoststr, - entry->state.state); - *peerinfo = entry; - return 0; - } - } - } - - ret = getaddrinfo(hoststr, NULL, NULL, &addr); - if (ret != 0) { - gf_log ("", 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) { - list_for_each_entry (name, &entry->hostnames, - hostname_list) { - if (!strncmp (name->hostname, host, - 1024) || !strncmp (name->hostname,hname, - 1024)) { - gf_log ("glusterd", GF_LOG_NORMAL, - "Friend %s found.. state: %d", - hoststr, entry->state.state); - *peerinfo = entry; - freeaddrinfo (addr); - return 0; - } - } - } - } - -out: - if (addr) - freeaddrinfo (addr); - return -1; -} - static int glusterd_friend_find_by_uuid (uuid_t uuid, glusterd_peerinfo_t **peerinfo) @@ -642,7 +554,15 @@ glusterd_handle_cli_deprobe (rpcsvc_request_t *req) { int32_t ret = -1; gf1_cli_probe_req cli_req = {0,}; + uuid_t uuid = {0}; + int op_errno = 0; + xlator_t *this = NULL; + glusterd_conf_t *priv = NULL; + this = THIS; + GF_ASSERT (this); + priv = this->private; + GF_ASSERT (priv); GF_ASSERT (req); if (!gf_xdr_to_cli_probe_req (req->msg[0], &cli_req)) { @@ -653,12 +573,35 @@ glusterd_handle_cli_deprobe (rpcsvc_request_t *req) gf_log ("glusterd", GF_LOG_NORMAL, "Received CLI deprobe req"); + ret = glusterd_hostname_to_uuid (cli_req.hostname, uuid); + if (ret) { + op_errno = GF_DEPROBE_NOT_FRIEND; + goto out; + } - ret = glusterd_deprobe_begin (req, cli_req.hostname, cli_req.port); + if (!uuid_compare (uuid, priv->uuid)) { + op_errno = GF_DEPROBE_LOCALHOST; + ret = -1; + goto out; + } + + ret = glusterd_all_volume_cond_check (glusterd_friend_brick_belongs, + -1, &uuid); + if (ret) { + op_errno = GF_DEPROBE_BRICK_EXIST; + goto out; + } + + ret = glusterd_deprobe_begin (req, cli_req.hostname, + cli_req.port, uuid); gf_cmd_log ("peer deprobe", "on host %s:%d %s", cli_req.hostname, cli_req.port, (ret) ? "FAILED" : "SUCCESS"); out: + if (ret) { + ret = glusterd_xfer_cli_deprobe_resp (req, ret, op_errno, + cli_req.hostname); + } if (cli_req.hostname) free (cli_req.hostname);//malloced by xdr return ret; @@ -2784,7 +2727,8 @@ glusterd_probe_begin (rpcsvc_request_t *req, const char *hoststr, int port) } int -glusterd_deprobe_begin (rpcsvc_request_t *req, const char *hoststr, int port) +glusterd_deprobe_begin (rpcsvc_request_t *req, const char *hoststr, int port, + uuid_t uuid) { int ret = -1; glusterd_peerinfo_t *peerinfo = NULL; @@ -2794,7 +2738,7 @@ glusterd_deprobe_begin (rpcsvc_request_t *req, const char *hoststr, int port) GF_ASSERT (hoststr); GF_ASSERT (req); - ret = glusterd_friend_find (NULL, (char *)hoststr, &peerinfo); + ret = glusterd_friend_find (uuid, (char *)hoststr, &peerinfo); if (ret) { gf_log ("glusterd", GF_LOG_NORMAL, "Unable to find peerinfo" diff --git a/xlators/mgmt/glusterd/src/glusterd-op-sm.c b/xlators/mgmt/glusterd/src/glusterd-op-sm.c index 9c337328235..3f01dc5da6b 100644 --- a/xlators/mgmt/glusterd/src/glusterd-op-sm.c +++ b/xlators/mgmt/glusterd/src/glusterd-op-sm.c @@ -1220,6 +1220,9 @@ glusterd_op_perform_add_bricks (glusterd_volinfo_t *volinfo, int32_t count, if (ret) goto out; + ret = glusterd_resolve_brick (brickinfo); + if (ret) + goto out; list_add_tail (&brickinfo->brick_list, &volinfo->bricks); brick = strtok_r (NULL, " \n", &saveptr); i++; @@ -1558,6 +1561,9 @@ glusterd_op_create_volume (gd1_mgmt_stage_op_req *req, char **op_errstr) if (ret) goto out; + ret = glusterd_resolve_brick (brickinfo); + if (ret) + goto out; list_add_tail (&brickinfo->brick_list, &volinfo->bricks); brick = strtok_r (NULL, " \n", &saveptr); i++; @@ -2521,6 +2527,11 @@ glusterd_op_replace_brick (gd1_mgmt_stage_op_req *req, dict_t *rsp_dict) goto out; } + ret = glusterd_resolve_brick (dst_brickinfo); + if (ret) { + gf_log ("", GF_LOG_DEBUG, "Unable to resolve dst-brickinfo"); + goto out; + } /* Set src-brick's port number to be used in the maintainance mount * after all commit acks are received. */ @@ -3755,6 +3766,12 @@ glusterd_do_replace_brick (void *data) goto out; } + ret = glusterd_resolve_brick (dst_brickinfo); + if (ret) { + gf_log ("", GF_LOG_DEBUG, "Unable to resolve dst-brickinfo"); + goto out; + } + ret = dict_get_int32 (dict, "src-brick-port", &src_port); if (ret) { gf_log ("", GF_LOG_ERROR, "Unable to get src-brick port"); diff --git a/xlators/mgmt/glusterd/src/glusterd-utils.c b/xlators/mgmt/glusterd/src/glusterd-utils.c index f99ddde9c92..71f23a8f139 100644 --- a/xlators/mgmt/glusterd/src/glusterd-utils.c +++ b/xlators/mgmt/glusterd/src/glusterd-utils.c @@ -588,26 +588,10 @@ int32_t glusterd_resolve_brick (glusterd_brickinfo_t *brickinfo) { int32_t ret = -1; - glusterd_peerinfo_t *peerinfo = NULL; - glusterd_conf_t *priv = NULL; - - priv = THIS->private; - GF_ASSERT (priv); GF_ASSERT (brickinfo); - ret = glusterd_friend_find (NULL, brickinfo->hostname, &peerinfo); - - if (!ret) { - uuid_copy (brickinfo->uuid, peerinfo->uuid); - } - - if (ret) { - ret = glusterd_is_local_addr (brickinfo->hostname); - if (!ret) - uuid_copy (brickinfo->uuid, priv->uuid); - } - + ret = glusterd_hostname_to_uuid (brickinfo->hostname, brickinfo->uuid); gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); return ret; } @@ -1853,8 +1837,170 @@ glusterd_set_brick_status (glusterd_brickinfo_t *brickinfo, int glusterd_is_brick_started (glusterd_brickinfo_t *brickinfo) -{ +{ GF_ASSERT (brickinfo); return (!(brickinfo->status == GF_BRICK_STARTED)); } +int +glusterd_friend_brick_belongs (glusterd_volinfo_t *volinfo, + glusterd_brickinfo_t *brickinfo, void* uuid) +{ + GF_ASSERT (volinfo); + GF_ASSERT (brickinfo); + GF_ASSERT (uuid); + + if (!uuid_compare (brickinfo->uuid, *((uuid_t *)uuid))) + return 0; + + return -1; +} + +int +glusterd_all_volume_cond_check (glusterd_condition_func func, int status, + void *ctx) +{ + glusterd_conf_t *priv = NULL; + glusterd_volinfo_t *volinfo = NULL; + glusterd_brickinfo_t *brickinfo = NULL; + int ret = -1; + xlator_t *this = NULL; + + this = THIS; + priv = this->private; + + list_for_each_entry (volinfo, &priv->volumes, vol_list) { + list_for_each_entry (brickinfo, &volinfo->bricks, + brick_list) { + ret = func (volinfo, brickinfo, ctx); + if (ret != status) { + ret = -1; + goto out; + } + } + } + ret = 0; +out: + gf_log ("", GF_LOG_DEBUG, "returning %d", ret); + 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; + glusterd_peer_hostname_t *name = 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,}; + + GF_ASSERT (hoststr); + GF_ASSERT (peerinfo); + + *peerinfo = NULL; + priv = THIS->private; + + GF_ASSERT (priv); + + list_for_each_entry (entry, &priv->peers, uuid_list) { + list_for_each_entry (name, &entry->hostnames, hostname_list) { + if (!strncmp (name->hostname, hoststr, + 1024)) { + + gf_log ("glusterd", GF_LOG_NORMAL, + "Friend %s found.. state: %d", hoststr, + entry->state.state); + *peerinfo = entry; + return 0; + } + } + } + + ret = getaddrinfo(hoststr, NULL, NULL, &addr); + if (ret != 0) { + gf_log ("", 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) { + list_for_each_entry (name, &entry->hostnames, + hostname_list) { + if (!strncmp (name->hostname, host, + 1024) || !strncmp (name->hostname,hname, + 1024)) { + gf_log ("glusterd", GF_LOG_NORMAL, + "Friend %s found.. state: %d", + hoststr, entry->state.state); + *peerinfo = entry; + freeaddrinfo (addr); + return 0; + } + } + } + } + +out: + 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) { + ret = glusterd_is_local_addr (hostname); + if (ret) + goto out; + else + uuid_copy (uuid, priv->uuid); + } else { + uuid_copy (uuid, peerinfo->uuid); + } + +out: + gf_log ("", GF_LOG_DEBUG, "returning %d", ret); + return ret; +} diff --git a/xlators/mgmt/glusterd/src/glusterd-utils.h b/xlators/mgmt/glusterd/src/glusterd-utils.h index 3f49acfda43..9fa272a69f3 100644 --- a/xlators/mgmt/glusterd/src/glusterd-utils.h +++ b/xlators/mgmt/glusterd/src/glusterd-utils.h @@ -43,6 +43,10 @@ struct glusterd_lock_ { time_t timestamp; }; +typedef int (*glusterd_condition_func) (glusterd_volinfo_t *volinfo, + glusterd_brickinfo_t *brickinfo, + void *ctx); + typedef struct glusterd_lock_ glusterd_lock_t; int32_t @@ -173,4 +177,16 @@ glusterd_set_brick_status (glusterd_brickinfo_t *brickinfo, int 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 +glusterd_all_volume_cond_check (glusterd_condition_func func, int status, + void *ctx); #endif diff --git a/xlators/mgmt/glusterd/src/glusterd.h b/xlators/mgmt/glusterd/src/glusterd.h index 2eb430f2798..ac30d3e5c38 100644 --- a/xlators/mgmt/glusterd/src/glusterd.h +++ b/xlators/mgmt/glusterd/src/glusterd.h @@ -311,7 +311,8 @@ int glusterd_xfer_friend_remove_resp (rpcsvc_request_t *req, char *hostname, int port); int -glusterd_deprobe_begin (rpcsvc_request_t *req, const char *hoststr, int port); +glusterd_deprobe_begin (rpcsvc_request_t *req, const char *hoststr, int port, + uuid_t uuid); int glusterd_handle_cli_deprobe (rpcsvc_request_t *req); -- cgit