diff options
Diffstat (limited to 'xlators')
| -rw-r--r-- | xlators/cluster/afr/src/afr-self-heal-data.c | 58 | 
1 files changed, 49 insertions, 9 deletions
diff --git a/xlators/cluster/afr/src/afr-self-heal-data.c b/xlators/cluster/afr/src/afr-self-heal-data.c index b40fa7dc6cc..45b4c53dbaf 100644 --- a/xlators/cluster/afr/src/afr-self-heal-data.c +++ b/xlators/cluster/afr/src/afr-self-heal-data.c @@ -366,15 +366,22 @@ afr_selfheal_data_do (call_frame_t *frame, xlator_t *this, fd_t *fd,  	int type = AFR_SELFHEAL_DATA_FULL;  	int ret = -1;  	call_frame_t *iter_frame = NULL; +        unsigned char arbiter_sink_status = 0;  	priv = this->private; +        if (priv->arbiter_count) { +                arbiter_sink_status = healed_sinks[ARBITER_BRICK_INDEX]; +                healed_sinks[ARBITER_BRICK_INDEX] = 0; +        }          type = afr_data_self_heal_type_get (priv, healed_sinks, source,                                              replies);  	iter_frame = afr_copy_frame (frame); -	if (!iter_frame) -		return -ENOMEM; +	if (!iter_frame) { +                ret = -ENOMEM; +                goto out; +        }  	for (off = 0; off < replies[source].poststat.ia_size; off += block) {                  if (AFR_COUNT (healed_sinks, priv->child_count) == 0) { @@ -395,12 +402,12 @@ afr_selfheal_data_do (call_frame_t *frame, xlator_t *this, fd_t *fd,                  }  	} -	afr_selfheal_data_restore_time (frame, this, fd->inode, source, -					healed_sinks, replies); -  	ret = afr_selfheal_data_fsync (frame, this, fd, healed_sinks);  out: +        if (arbiter_sink_status) +                healed_sinks[ARBITER_BRICK_INDEX] = arbiter_sink_status; +  	if (iter_frame)  		AFR_STACK_DESTROY (iter_frame);  	return ret; @@ -414,11 +421,17 @@ __afr_selfheal_truncate_sinks (call_frame_t *frame, xlator_t *this,  {  	afr_local_t *local = NULL;  	afr_private_t *priv = NULL; +        unsigned char arbiter_sink_status = 0;  	int i = 0;  	local = frame->local;  	priv = this->private; +        if (priv->arbiter_count) { +                arbiter_sink_status = healed_sinks[ARBITER_BRICK_INDEX]; +                healed_sinks[ARBITER_BRICK_INDEX] = 0; +        } +  	AFR_ONLIST (healed_sinks, frame, attr_cbk, ftruncate, fd, size, NULL);  	for (i = 0; i < priv->child_count; i++) @@ -427,6 +440,9 @@ __afr_selfheal_truncate_sinks (call_frame_t *frame, xlator_t *this,  			   as successfully healed. Mark it so.  			*/  			healed_sinks[i] = 0; + +        if (arbiter_sink_status) +                healed_sinks[ARBITER_BRICK_INDEX] = arbiter_sink_status;  	return 0;  } @@ -673,6 +689,7 @@ __afr_selfheal_data (call_frame_t *frame, xlator_t *this, fd_t *fd,  	struct afr_reply *locked_replies = NULL;  	int source = -1;          gf_boolean_t did_sh = _gf_true; +        gf_boolean_t is_arbiter_the_only_sink = _gf_false;  	priv = this->private; @@ -718,6 +735,13 @@ __afr_selfheal_data (call_frame_t *frame, xlator_t *this, fd_t *fd,                          goto unlock;                  } +                if (priv->arbiter_count && +                    AFR_COUNT (healed_sinks, priv->child_count) == 1 && +                    healed_sinks[ARBITER_BRICK_INDEX]) { +                        is_arbiter_the_only_sink = _gf_true; +                        goto restore_time; +                } +  		ret = __afr_selfheal_truncate_sinks (frame, this, fd, healed_sinks,  						     locked_replies[source].poststat.ia_size);  		if (ret < 0) @@ -738,11 +762,27 @@ unlock:  	ret = afr_selfheal_data_do (frame, this, fd, source, healed_sinks,  				    locked_replies);  	if (ret) -		goto out; +                goto out; +restore_time: +	afr_selfheal_data_restore_time (frame, this, fd->inode, source, +					healed_sinks, locked_replies); -	ret = afr_selfheal_undo_pending (frame, this, fd->inode, sources, sinks, -					 healed_sinks, AFR_DATA_TRANSACTION, -					 locked_replies, data_lock); +        if (!is_arbiter_the_only_sink) { +                ret = afr_selfheal_inodelk (frame, this, fd->inode, this->name, +                                            0, 0, data_lock); +                if (ret < AFR_SH_MIN_PARTICIPANTS) { +                        ret = -ENOTCONN; +                        did_sh = _gf_false; +                        goto skip_undo_pending; +                } +        } +        ret = afr_selfheal_undo_pending (frame, this, fd->inode, +                                         sources, sinks, healed_sinks, +                                         AFR_DATA_TRANSACTION, +                                         locked_replies, data_lock); +skip_undo_pending: +	afr_selfheal_uninodelk (frame, this, fd->inode, this->name, 0, 0, +				data_lock);  out:          if (did_sh)  | 
