diff options
Diffstat (limited to 'xlators/cluster/ec/src/ec.c')
-rw-r--r-- | xlators/cluster/ec/src/ec.c | 97 |
1 files changed, 76 insertions, 21 deletions
diff --git a/xlators/cluster/ec/src/ec.c b/xlators/cluster/ec/src/ec.c index 3dd04299541..4028aa4d2bb 100644 --- a/xlators/cluster/ec/src/ec.c +++ b/xlators/cluster/ec/src/ec.c @@ -278,6 +278,7 @@ ec_notify_cbk (void *data) { ec_t *ec = data; glusterfs_event_t event = GF_EVENT_MAXVAL; + gf_boolean_t propagate = _gf_false; LOCK(&ec->lock); { @@ -309,10 +310,14 @@ ec_notify_cbk (void *data) /* CHILD_DOWN should not come here as no grace period is given * for notifying CHILD_DOWN. */ - default_notify (ec->xl, event, NULL); + propagate = _gf_true; } unlock: UNLOCK(&ec->lock); + + if (propagate) { + default_notify (ec->xl, event, NULL); + } } void @@ -360,6 +365,49 @@ ec_handle_down (xlator_t *this, ec_t *ec, int32_t idx) } } +gf_boolean_t +ec_force_unlocks(ec_t *ec) +{ + struct list_head list; + ec_fop_data_t *fop; + + if (list_empty(&ec->pending_fops)) { + return _gf_true; + } + + INIT_LIST_HEAD(&list); + + /* All pending fops when GF_EVENT_PARENT_DOWN is received should only + * be fops waiting for a delayed unlock. However the unlock can + * generate new fops. We don't want to trverse these new fops while + * forcing unlocks, so we move all fops to a temporal list. To process + * them without interferences.*/ + list_splice_init(&ec->pending_fops, &list); + + while (!list_empty(&list)) { + fop = list_entry(list.next, ec_fop_data_t, pending_list); + list_move_tail(&fop->pending_list, &ec->pending_fops); + + UNLOCK(&ec->lock); + + ec_unlock_force(fop); + + LOCK(&ec->lock); + } + + ec->shutdown = _gf_true; + + return list_empty(&ec->pending_fops); +} + +void +ec_pending_fops_completed(ec_t *ec) +{ + if (ec->shutdown) { + default_notify(ec->xl, GF_EVENT_PARENT_DOWN, NULL); + } +} + int32_t ec_notify (xlator_t *this, int32_t event, void *data, void *data2) { @@ -367,14 +415,16 @@ ec_notify (xlator_t *this, int32_t event, void *data, void *data2) int32_t idx = 0; int32_t error = 0; glusterfs_event_t old_event = GF_EVENT_MAXVAL; - glusterfs_event_t new_event = GF_EVENT_MAXVAL; dict_t *input = NULL; dict_t *output = NULL; + gf_boolean_t propagate = _gf_true; + + gf_log (this->name, GF_LOG_TRACE, "NOTIFY(%d): %p, %p", + event, data, data2); if (event == GF_EVENT_TRANSLATOR_OP) { if (!ec->up) { error = -1; - goto out; } else { input = data; output = data2; @@ -400,13 +450,14 @@ ec_notify (xlator_t *this, int32_t event, void *data, void *data2) */ ec_launch_notify_timer (this, ec); goto unlock; + } else if (event == GF_EVENT_PARENT_DOWN) { + /* If there aren't pending fops running after we have waken up + * them, we immediately propagate the notification. */ + propagate = ec_force_unlocks(ec); + goto unlock; } - gf_log (this->name, GF_LOG_TRACE, "NOTIFY(%d): %p, %d", - event, data, idx); - if (idx < ec->nodes) { /* CHILD_* events */ - old_event = ec_get_event_from_state (ec); if (event == GF_EVENT_CHILD_UP) { @@ -415,28 +466,30 @@ ec_notify (xlator_t *this, int32_t event, void *data, void *data2) ec_handle_down (this, ec, idx); } - new_event = ec_get_event_from_state (ec); + event = ec_get_event_from_state (ec); - if (new_event == GF_EVENT_CHILD_UP && !ec->up) { + if (event == GF_EVENT_CHILD_UP && !ec->up) { ec_up (this, ec); - } else if (new_event == GF_EVENT_CHILD_DOWN && ec->up) { + } else if (event == GF_EVENT_CHILD_DOWN && ec->up) { ec_down (this, ec); } - if ((new_event == old_event) && (new_event != GF_EVENT_MAXVAL)) - new_event = GF_EVENT_CHILD_MODIFIED; - - event = GF_EVENT_MAXVAL;/* Take care of notifying inside lock */ - if (new_event != GF_EVENT_MAXVAL) - error = default_notify (this, new_event, data); + if (event != GF_EVENT_MAXVAL) { + if (event == old_event) { + event = GF_EVENT_CHILD_MODIFIED; + } + } else { + propagate = _gf_false; + } } - unlock: - UNLOCK (&ec->lock); +unlock: + UNLOCK (&ec->lock); - if (event != GF_EVENT_MAXVAL) - return default_notify (this, event, data); + if (propagate) { + error = default_notify (this, event, data); + } out: - return error; + return error; } int32_t @@ -478,6 +531,8 @@ init (xlator_t *this) ec->xl = this; LOCK_INIT(&ec->lock); + INIT_LIST_HEAD(&ec->pending_fops); + ec->fop_pool = mem_pool_new(ec_fop_data_t, 1024); ec->cbk_pool = mem_pool_new(ec_cbk_data_t, 4096); ec->lock_pool = mem_pool_new(ec_lock_t, 1024); |