summaryrefslogtreecommitdiffstats
path: root/libglusterfs/src/client_t.c
diff options
context:
space:
mode:
authorZhou Zhengping <johnzzpcrystal@gmail.com>2017-05-09 20:57:34 +0800
committerRaghavendra G <rgowdapp@redhat.com>2017-05-12 04:47:44 +0000
commit333474e0d6efe1a2b3a9ecffc9bdff3e49325910 (patch)
tree176005ae869f739d6e209472d21e87fc7f98d3c0 /libglusterfs/src/client_t.c
parentccfa06767f1282d9a3783e37555515a63cc62e69 (diff)
libglusterfs: fix race condition in client_ctx_set
follow procedures: 1.thread1 client_ctx_get return NULL 2.thread 2 client_ctx_set ctx1 ok 3.thread1 client_ctx_set ctx2 ok thread1 use ctx1, thread2 use ctx2 and ctx1 will leak Change-Id: I990b02905edd1b3179323ada56888f852d20f538 BUG: 1449232 Signed-off-by: Zhou Zhengping <johnzzpcrystal@gmail.com> Reviewed-on: https://review.gluster.org/17219 NetBSD-regression: NetBSD Build System <jenkins@build.gluster.org> CentOS-regression: Gluster Build System <jenkins@build.gluster.org> Reviewed-by: Raghavendra G <rgowdapp@redhat.com> Smoke: Gluster Build System <jenkins@build.gluster.org> Reviewed-by: Jeff Darcy <jeff@pl.atyp.us>
Diffstat (limited to 'libglusterfs/src/client_t.c')
-rw-r--r--libglusterfs/src/client_t.c76
1 files changed, 43 insertions, 33 deletions
diff --git a/libglusterfs/src/client_t.c b/libglusterfs/src/client_t.c
index 1adfef5c7e3..62cfbc422f8 100644
--- a/libglusterfs/src/client_t.c
+++ b/libglusterfs/src/client_t.c
@@ -439,7 +439,31 @@ gf_client_unref (client_t *client)
static int
-client_ctx_set_int (client_t *client, void *key, void *value)
+__client_ctx_get_int (client_t *client, void *key, void **value)
+{
+ int index = 0;
+ int ret = 0;
+
+ for (index = 0; index < client->scratch_ctx.count; index++) {
+ if (client->scratch_ctx.ctx[index].ctx_key == key)
+ break;
+ }
+
+ if (index == client->scratch_ctx.count) {
+ ret = -1;
+ goto out;
+ }
+
+ if (value)
+ *value = client->scratch_ctx.ctx[index].ctx_value;
+
+out:
+ return ret;
+}
+
+
+static int
+__client_ctx_set_int (client_t *client, void *key, void *value)
{
int index = 0;
int ret = 0;
@@ -471,45 +495,31 @@ out:
}
-int
+/*will return success with old value if exist*/
+void *
client_ctx_set (client_t *client, void *key, void *value)
{
int ret = 0;
+ void *ret_value = NULL;
- if (!client || !key)
- return -1;
+ if (!client || !key || !value)
+ return NULL;
LOCK (&client->scratch_ctx.lock);
{
- ret = client_ctx_set_int (client, key, value);
- }
- UNLOCK (&client->scratch_ctx.lock);
-
- return ret;
-}
-
-
-static int
-client_ctx_get_int (client_t *client, void *key, void **value)
-{
- int index = 0;
- int ret = 0;
-
- for (index = 0; index < client->scratch_ctx.count; index++) {
- if (client->scratch_ctx.ctx[index].ctx_key == key)
- break;
- }
+ ret = __client_ctx_get_int (client, key, &ret_value);
+ if (!ret && ret_value) {
+ UNLOCK (&client->scratch_ctx.lock);
+ return ret_value;
+ }
- if (index == client->scratch_ctx.count) {
- ret = -1;
- goto out;
+ ret = __client_ctx_set_int (client, key, value);
}
+ UNLOCK (&client->scratch_ctx.lock);
- if (value)
- *value = client->scratch_ctx.ctx[index].ctx_value;
-
-out:
- return ret;
+ if (ret)
+ return NULL;
+ return value;
}
@@ -523,7 +533,7 @@ client_ctx_get (client_t *client, void *key, void **value)
LOCK (&client->scratch_ctx.lock);
{
- ret = client_ctx_get_int (client, key, value);
+ ret = __client_ctx_get_int (client, key, value);
}
UNLOCK (&client->scratch_ctx.lock);
@@ -532,7 +542,7 @@ client_ctx_get (client_t *client, void *key, void **value)
static int
-client_ctx_del_int (client_t *client, void *key, void **value)
+__client_ctx_del_int (client_t *client, void *key, void **value)
{
int index = 0;
int ret = 0;
@@ -568,7 +578,7 @@ client_ctx_del (client_t *client, void *key, void **value)
LOCK (&client->scratch_ctx.lock);
{
- ret = client_ctx_del_int (client, key, value);
+ ret = __client_ctx_del_int (client, key, value);
}
UNLOCK (&client->scratch_ctx.lock);