summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorXavier Hernandez <xhernandez@datalab.es>2014-12-03 16:42:31 +0100
committerVijay Bellur <vbellur@redhat.com>2014-12-04 11:36:32 -0800
commit30ae004100067f52fe156098ffb215417db5559e (patch)
tree26c75f55c6eabeeddd44c1609286653219604e3d
parentca2a3949715fb25862d1e34f9e65283287faa842 (diff)
ec: Fix mutex related coverity scan issues
This patch solves 3 issues detected by coverity scan: CID1241484 Data race condition CID1241486 Data race condition CID1256173 Thread deadlock With this patch, inode lock is never acquired inside a region locked with fop->lock. Change-Id: I35c4633efd1b68b9f72b42661fa7c728b1f52c6a BUG: 1170254 Signed-off-by: Xavier Hernandez <xhernandez@datalab.es> Reviewed-on: http://review.gluster.org/9230 Tested-by: Gluster Build System <jenkins@build.gluster.com> Reviewed-by: Dan Lambright <dlambrig@redhat.com>
-rw-r--r--xlators/cluster/ec/src/ec-common.c16
1 files changed, 14 insertions, 2 deletions
diff --git a/xlators/cluster/ec/src/ec-common.c b/xlators/cluster/ec/src/ec-common.c
index 894d2f552f3..fbdad86950a 100644
--- a/xlators/cluster/ec/src/ec-common.c
+++ b/xlators/cluster/ec/src/ec-common.c
@@ -321,7 +321,7 @@ void ec_resume_parent(ec_fop_data_t * fop, int32_t error)
void ec_complete(ec_fop_data_t * fop)
{
ec_cbk_data_t * cbk = NULL;
- int32_t resume = 0;
+ int32_t resume = 0, update = 0;
LOCK(&fop->lock);
@@ -335,7 +335,7 @@ void ec_complete(ec_fop_data_t * fop)
((cbk->op_ret >= 0) || (cbk->op_errno != ENOTCONN))) {
fop->answer = cbk;
- ec_update_bad(fop, cbk->mask);
+ update = 1;
}
}
@@ -349,6 +349,14 @@ void ec_complete(ec_fop_data_t * fop)
UNLOCK(&fop->lock);
+ /* ec_update_bad() locks inode->lock. This may cause deadlocks with
+ fop->lock when used in another order. Since ec_update_bad() will not
+ be called more than once for each fop, it can be called from outside
+ the fop->lock locked region. */
+ if (update) {
+ ec_update_bad(fop, cbk->mask);
+ }
+
if (resume)
{
ec_resume(fop, 0);
@@ -861,9 +869,13 @@ void ec_lock(ec_fop_data_t * fop)
list_add_tail(&fop->locks[fop->locked].wait_list, &lock->waiting);
+ LOCK(&fop->lock);
+
fop->jobs++;
fop->refs++;
+ UNLOCK(&fop->lock);
+
UNLOCK(&lock->loc.inode->lock);
break;