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 /xlators/cluster/ec/src | |
| 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>
Diffstat (limited to 'xlators/cluster/ec/src')
| -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;  | 
