diff options
Diffstat (limited to 'xlators')
-rw-r--r-- | xlators/cluster/ec/src/ec-combine.c | 14 | ||||
-rw-r--r-- | xlators/cluster/ec/src/ec-common.c | 16 |
2 files changed, 19 insertions, 11 deletions
diff --git a/xlators/cluster/ec/src/ec-combine.c b/xlators/cluster/ec/src/ec-combine.c index a98380adfb8..e605f7ba567 100644 --- a/xlators/cluster/ec/src/ec-combine.c +++ b/xlators/cluster/ec/src/ec-combine.c @@ -851,12 +851,9 @@ void ec_combine(ec_cbk_data_t * cbk, ec_combine_f combine) ec_trace("ANSWER", fop, "combine=%s[%d]", ec_bin(str, sizeof(str), cbk->mask, 0), cbk->count); - if ((cbk->count == fop->expected) && (fop->answer == NULL)) - { + if ((cbk->count == fop->expected) && (fop->answer == NULL)) { fop->answer = cbk; - ec_update_bad(fop, cbk->mask); - resume = 1; } @@ -865,12 +862,11 @@ void ec_combine(ec_cbk_data_t * cbk, ec_combine_f combine) UNLOCK(&fop->lock); - if (needed > 0) - { + if (needed > 0) { ec_dispatch_next(fop, cbk->idx); - } - else if (resume) - { + } else if (resume) { + ec_update_bad(fop, cbk->mask); + ec_resume(fop, 0); } } diff --git a/xlators/cluster/ec/src/ec-common.c b/xlators/cluster/ec/src/ec-common.c index 88cc103e513..dbf2238ea8e 100644 --- a/xlators/cluster/ec/src/ec-common.c +++ b/xlators/cluster/ec/src/ec-common.c @@ -322,7 +322,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); @@ -336,7 +336,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; } } @@ -350,6 +350,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); @@ -862,9 +870,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; |