summaryrefslogtreecommitdiffstats
path: root/rpc/rpc-lib/src/rpc-transport.c
diff options
context:
space:
mode:
authorMohammed Rafi KC <rkavunga@redhat.com>2019-02-26 18:04:18 +0530
committerAmar Tumballi <amarts@redhat.com>2019-03-20 13:24:44 +0000
commitf2f07591b2de9ba45bbc3eb4f601d1e9a327190b (patch)
tree1eb628f99b91246759e3bc1e9de1238c9fea2cc4 /rpc/rpc-lib/src/rpc-transport.c
parent6d6a3b298ee81c6c7d93941365852c1bdb42c3c1 (diff)
rpc/transport: Missing a ref on dict while creating transport object
while creating rpc_tranpsort object, we store a dictionary without taking a ref on dict but it does an unref during the cleaning of the transport object. So the rpc layer expect the caller to take a ref on the dictionary before passing dict to rpc layer. This leads to a lot of confusion across the code base and leads to ref leaks. Semantically, this is not correct. It is the rpc layer responsibility to take a ref when storing it, and free during the cleanup. I'm listing down the total issues or leaks across the code base because of this confusion. These issues are currently present in the upstream master. 1) changelog_rpc_client_init 2) quota_enforcer_init 3) rpcsvc_create_listeners : when there are two transport, like tcp,rdma. 4) quotad_aggregator_init 5) glusterd: init 6) nfs3_init_state 7) server: init 8) client:init This patch does the cleanup according to the semantics. Change-Id: I46373af9630373eb375ee6de0e6f2bbe2a677425 updates: bz#1659708 Signed-off-by: Mohammed Rafi KC <rkavunga@redhat.com>
Diffstat (limited to 'rpc/rpc-lib/src/rpc-transport.c')
-rw-r--r--rpc/rpc-lib/src/rpc-transport.c38
1 files changed, 11 insertions, 27 deletions
diff --git a/rpc/rpc-lib/src/rpc-transport.c b/rpc/rpc-lib/src/rpc-transport.c
index ce984426cbe..baa8593f6c6 100644
--- a/rpc/rpc-lib/src/rpc-transport.c
+++ b/rpc/rpc-lib/src/rpc-transport.c
@@ -170,6 +170,11 @@ rpc_transport_cleanup(rpc_transport_t *trans)
if (trans->fini)
trans->fini(trans);
+ if (trans->options) {
+ dict_unref(trans->options);
+ trans->options = NULL;
+ }
+
GF_FREE(trans->name);
if (trans->xl)
@@ -354,7 +359,7 @@ rpc_transport_load(glusterfs_ctx_t *ctx, dict_t *options, char *trans_name)
}
}
- trans->options = options;
+ trans->options = dict_ref(options);
pthread_mutex_init(&trans->lock, NULL);
trans->xl = this;
@@ -593,19 +598,14 @@ out:
}
int
-rpc_transport_unix_options_build(dict_t **options, char *filepath,
+rpc_transport_unix_options_build(dict_t *dict, char *filepath,
int frame_timeout)
{
- dict_t *dict = NULL;
char *fpath = NULL;
int ret = -1;
GF_ASSERT(filepath);
- GF_ASSERT(options);
-
- dict = dict_new();
- if (!dict)
- goto out;
+ GF_VALIDATE_OR_GOTO("rpc-transport", dict, out);
fpath = gf_strdup(filepath);
if (!fpath) {
@@ -640,20 +640,14 @@ rpc_transport_unix_options_build(dict_t **options, char *filepath,
if (ret)
goto out;
}
-
- *options = dict;
out:
- if (ret && dict) {
- dict_unref(dict);
- }
return ret;
}
int
-rpc_transport_inet_options_build(dict_t **options, const char *hostname,
- int port, char *af)
+rpc_transport_inet_options_build(dict_t *dict, const char *hostname, int port,
+ char *af)
{
- dict_t *dict = NULL;
char *host = NULL;
int ret = -1;
#ifdef IPV6_DEFAULT
@@ -662,13 +656,9 @@ rpc_transport_inet_options_build(dict_t **options, const char *hostname,
char *addr_family = "inet";
#endif
- GF_ASSERT(options);
GF_ASSERT(hostname);
GF_ASSERT(port >= 1024);
-
- dict = dict_new();
- if (!dict)
- goto out;
+ GF_VALIDATE_OR_GOTO("rpc-transport", dict, out);
host = gf_strdup((char *)hostname);
if (!host) {
@@ -704,12 +694,6 @@ rpc_transport_inet_options_build(dict_t **options, const char *hostname,
"failed to set trans-type with socket");
goto out;
}
-
- *options = dict;
out:
- if (ret && dict) {
- dict_unref(dict);
- }
-
return ret;
}