diff options
author | Xavier Hernandez <xhernandez@datalab.es> | 2014-12-03 16:42:31 +0100 |
---|---|---|
committer | Vijay Bellur <vbellur@redhat.com> | 2014-12-04 11:36:32 -0800 |
commit | 30ae004100067f52fe156098ffb215417db5559e (patch) | |
tree | 26c75f55c6eabeeddd44c1609286653219604e3d | |
parent | ca2a3949715fb25862d1e34f9e65283287faa842 (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.c | 16 |
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; |