summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSusant Palai <spalai@redhat.com>2015-04-26 23:49:56 +0530
committerVijay Bellur <vbellur@redhat.com>2015-05-01 07:48:22 -0700
commit85a0fb6d304babb9d7f35e26a45677d8210da8eb (patch)
treef2c5ac1be3792047f1a192d93d7021303de407cd
parent265fb714b0ef7ebfa9296ff0571502b7eb49eee5 (diff)
dht: tackle thread race in dht_getxattr_cbk
problem: 1. When two threads execute in parallel in dht_getxattr_cbk it may so happen that, both may find local->xattr to be NULL. As a result dht_aggregate_xattr may not get executed. 2. In dht_getxattr_cbk, thread1 thread2 T1 this_call_cnt = 2 -1 T2 this_call_cnt = 1 - 1 T3 fills local_xattr T4 DHT_STACK_UNWIND -> local_wipe T5 tries to dereference local which is already freed, leading to crash. Solution: for problem1: Execute critical section inside frame lock to resolve race. for problem2: Calculate this_call_count just before out section. BUG: 1217386 Change-Id: I14fdb0cb1825896721670d71f48c93053448be7b Signed-off-by: Susant Palai <spalai@redhat.com> Reviewed-on: http://review.gluster.org/10389 Reviewed-by: Anuradha Talur <atalur@redhat.com> Reviewed-by: N Balachandran <nbalacha@redhat.com> Reviewed-by: Kotresh HR <khiremat@redhat.com> Reviewed-by: Shyamsundar Ranganathan <srangana@redhat.com> Signed-off-by: Susant Palai <spalai@redhat.com> Reviewed-on: http://review.gluster.org/10467 Tested-by: Gluster Build System <jenkins@build.gluster.com>
-rw-r--r--xlators/cluster/dht/src/dht-common.c41
1 files changed, 24 insertions, 17 deletions
diff --git a/xlators/cluster/dht/src/dht-common.c b/xlators/cluster/dht/src/dht-common.c
index e0b159ace32..2cfd862de65 100644
--- a/xlators/cluster/dht/src/dht-common.c
+++ b/xlators/cluster/dht/src/dht-common.c
@@ -2686,29 +2686,36 @@ dht_getxattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
conf = this->private;
local = frame->local;
- this_call_cnt = dht_frame_return (frame);
+ LOCK (&frame->lock);
+ {
+ if (!xattr || (op_ret == -1)) {
+ local->op_ret = op_ret;
+ goto unlock;
+ }
- if (!xattr || (op_ret == -1)) {
- local->op_ret = op_ret;
- goto out;
- }
+ if (dict_get (xattr, conf->xattr_name)) {
+ dict_del (xattr, conf->xattr_name);
+ }
- if (dict_get (xattr, conf->xattr_name)) {
- dict_del (xattr, conf->xattr_name);
- }
+ if (frame->root->pid >= 0) {
+ GF_REMOVE_INTERNAL_XATTR
+ ("trusted.glusterfs.quota*", xattr);
+ GF_REMOVE_INTERNAL_XATTR("trusted.pgfid*", xattr);
+ }
- if (frame->root->pid >= 0 ) {
- GF_REMOVE_INTERNAL_XATTR("trusted.glusterfs.quota*", xattr);
- GF_REMOVE_INTERNAL_XATTR("trusted.pgfid*", xattr);
- }
+ local->op_ret = 0;
- local->op_ret = 0;
+ if (!local->xattr) {
+ local->xattr = dict_copy_with_ref (xattr, NULL);
+ } else {
+ dht_aggregate_xattr (local->xattr, xattr);
+ }
- if (!local->xattr) {
- local->xattr = dict_copy_with_ref (xattr, NULL);
- } else {
- dht_aggregate_xattr (local->xattr, xattr);
}
+unlock:
+ UNLOCK (&frame->lock);
+
+ this_call_cnt = dht_frame_return (frame);
out:
if (is_last_call (this_call_cnt)) {
DHT_STACK_UNWIND (getxattr, frame, local->op_ret, op_errno,