diff options
author | Prasanna Kumar Kalever <prasanna.kalever@redhat.com> | 2016-04-27 19:12:19 +0530 |
---|---|---|
committer | Raghavendra G <rgowdapp@redhat.com> | 2016-05-04 02:25:31 -0700 |
commit | 89759de7e47d99eb1fca2763931b4f33ac765173 (patch) | |
tree | c9ed3003cc4b452a12961b45110928019279a62e /rpc | |
parent | 5ba82c0b9fa043aa4397d6744b079388ea360cc0 (diff) |
glusterd: add defence mechanism to avoid brick port clashes
Intro:
Currently glusterd maintain the portmap registry which contains ports that
are free to use between 49152 - 65535, this registry is initialized
once, and updated accordingly as an then when glusterd sees they are been
used.
Glusterd first checks for a port within the portmap registry and gets a FREE
port marked in it, then checks if that port is currently free using a connect()
function then passes it to brick process which have to bind on it.
Problem:
We see that there is a time gap between glusterd checking the port with
connect() and brick process actually binding on it. In this time gap it could
be so possible that any process would have occupied this port because of which
brick will fail to bind and exit.
Case 1:
To avoid the gluster client process occupying the port supplied by glusterd :
we have separated the client port map range with brick port map range more @
http://review.gluster.org/#/c/13998/
Case 2: (Handled by this patch)
To avoid the other foreign process occupying the port supplied by glusterd :
To handle above situation this patch implements a mechanism to return EADDRINUSE
error code to glusterd, upon which a new port is allocated and try to restart
the brick process with the newly allocated port.
Note: Incase of glusterd restarts i.e. runner_run_nowait() there is no way to
handle Case 2, becuase runner_run_nowait() will not wait to get the return/exit
code of the executed command (brick process). Hence as of now in such case,
we cannot know with what error the brick has failed to connect.
This patch also fix the runner_end() to perform some cleanup w.r.t
return values.
Change-Id: Iec52e7f5d87ce938d173f8ef16aa77fd573f2c5e
BUG: 1322805
Signed-off-by: Prasanna Kumar Kalever <prasanna.kalever@redhat.com>
Reviewed-on: http://review.gluster.org/14043
Tested-by: Prasanna Kumar Kalever <pkalever@redhat.com>
Reviewed-by: Atin Mukherjee <amukherj@redhat.com>
Smoke: Gluster Build System <jenkins@build.gluster.com>
NetBSD-regression: NetBSD Build System <jenkins@build.gluster.org>
CentOS-regression: Gluster Build System <jenkins@build.gluster.com>
Reviewed-by: Raghavendra G <rgowdapp@redhat.com>
Diffstat (limited to 'rpc')
-rw-r--r-- | rpc/rpc-lib/src/rpcsvc.c | 61 | ||||
-rw-r--r-- | rpc/rpc-transport/socket/src/socket.c | 4 |
2 files changed, 24 insertions, 41 deletions
diff --git a/rpc/rpc-lib/src/rpcsvc.c b/rpc/rpc-lib/src/rpcsvc.c index f4cff12762f..05d269609c5 100644 --- a/rpc/rpc-lib/src/rpcsvc.c +++ b/rpc/rpc-lib/src/rpcsvc.c @@ -1580,43 +1580,6 @@ rpcsvc_transport_peeraddr (rpc_transport_t *trans, char *addrstr, int addrlen, sasize); } - -rpc_transport_t * -rpcsvc_transport_create (rpcsvc_t *svc, dict_t *options, char *name) -{ - int ret = -1; - rpc_transport_t *trans = NULL; - - trans = rpc_transport_load (svc->ctx, options, name); - if (!trans) { - gf_log (GF_RPCSVC, GF_LOG_WARNING, "cannot create listener, " - "initing the transport failed"); - goto out; - } - - ret = rpc_transport_listen (trans); - if (ret == -1) { - gf_log (GF_RPCSVC, GF_LOG_WARNING, - "listening on transport failed"); - goto out; - } - - ret = rpc_transport_register_notify (trans, rpcsvc_notify, svc); - if (ret == -1) { - gf_log (GF_RPCSVC, GF_LOG_WARNING, "registering notify failed"); - goto out; - } - - ret = 0; -out: - if ((ret == -1) && (trans)) { - rpc_transport_disconnect (trans); - trans = NULL; - } - - return trans; -} - rpcsvc_listener_t * rpcsvc_listener_alloc (rpcsvc_t *svc, rpc_transport_t *trans) { @@ -1654,9 +1617,23 @@ rpcsvc_create_listener (rpcsvc_t *svc, dict_t *options, char *name) goto out; } - trans = rpcsvc_transport_create (svc, options, name); + trans = rpc_transport_load (svc->ctx, options, name); if (!trans) { - /* LOG TODO */ + gf_log (GF_RPCSVC, GF_LOG_WARNING, "cannot create listener, " + "initing the transport failed"); + goto out; + } + + ret = rpc_transport_listen (trans); + if (ret == -EADDRINUSE || ret == -1) { + gf_log (GF_RPCSVC, GF_LOG_WARNING, + "listening on transport failed"); + goto out; + } + + ret = rpc_transport_register_notify (trans, rpcsvc_notify, svc); + if (ret == -1) { + gf_log (GF_RPCSVC, GF_LOG_WARNING, "registering notify failed"); goto out; } @@ -1759,7 +1736,11 @@ out: GF_FREE (transport_name); - return count; + if (count > 0) { + return count; + } else { + return ret; + } } diff --git a/rpc/rpc-transport/socket/src/socket.c b/rpc/rpc-transport/socket/src/socket.c index 8301f79c5dc..8cdec00f642 100644 --- a/rpc/rpc-transport/socket/src/socket.c +++ b/rpc/rpc-transport/socket/src/socket.c @@ -878,6 +878,8 @@ __socket_server_bind (rpc_transport_t *this) if (errno == EADDRINUSE) { gf_log (this->name, GF_LOG_ERROR, "Port is already in use"); + + ret = -EADDRINUSE; } } @@ -3349,7 +3351,7 @@ socket_listen (rpc_transport_t *this) ret = __socket_server_bind (this); - if (ret == -1) { + if ((ret == -EADDRINUSE) || (ret == -1)) { /* logged inside __socket_server_bind() */ sys_close (priv->sock); priv->sock = -1; |