diff options
author | Pranith Kumar K <pkarampu@redhat.com> | 2012-11-27 12:34:18 +0530 |
---|---|---|
committer | Anand Avati <avati@redhat.com> | 2012-12-04 14:50:52 -0800 |
commit | 676b8793b9a77babf0275ee78eeacfa7291a8c35 (patch) | |
tree | 7f1a51c139060d43ae4e318961c8d222af760324 /xlators/cluster/afr/src/afr-transaction.c | |
parent | d1bb60ad794dcf0fc8bf0cf8dc4ac13349d749d4 (diff) |
cluster/afr: mark new entry changelog for create/mknod failures
Problem:
When create/mknod fails on some of the nodes, appropriate pending
data/metadata changelogs are not assigned. This was not considered
to be an issue because entry self-heal would do the assigning of
appropriate changelog after creating new entries. But using
the combination of rebalance and remove brick we can construct a
case where a file with same name and gfid can be created in a dir
with different data and link-to xattr without any changelog.
Fix:
When a create/mknod failure is observed mark the appropriate
changelog on the new file created.
Change-Id: I4c32cbf5594a13fb14deaf97ff30b2fff11cbfd6
BUG: 858212
Signed-off-by: Pranith Kumar K <pkarampu@redhat.com>
Reviewed-on: http://review.gluster.org/4207
Tested-by: Gluster Build System <jenkins@build.gluster.com>
Reviewed-by: Anand Avati <avati@redhat.com>
Diffstat (limited to 'xlators/cluster/afr/src/afr-transaction.c')
-rw-r--r-- | xlators/cluster/afr/src/afr-transaction.c | 67 |
1 files changed, 36 insertions, 31 deletions
diff --git a/xlators/cluster/afr/src/afr-transaction.c b/xlators/cluster/afr/src/afr-transaction.c index 3ba8d9b566a..5e636d8dcc5 100644 --- a/xlators/cluster/afr/src/afr-transaction.c +++ b/xlators/cluster/afr/src/afr-transaction.c @@ -203,6 +203,40 @@ __mark_all_success (int32_t *pending[], int child_count, } } +void +_set_all_child_errno (int *child_errno, unsigned int child_count) +{ + int i = 0; + + for (i = 0; i < child_count; i++) + if (child_errno[i] == 0) + child_errno[i] = ENOTCONN; +} + +void +afr_transaction_perform_fop (call_frame_t *frame, xlator_t *this) +{ + afr_local_t *local = NULL; + afr_private_t *priv = NULL; + + local = frame->local; + priv = this->private; + __mark_all_success (local->pending, priv->child_count, + local->transaction.type); + + _set_all_child_errno (local->child_errno, priv->child_count); + + /* Perform fops with the lk-owner from top xlator. + * Eg: lk-owner of posix-lk and flush should be same, + * flush cant clear the posix-lks without that lk-owner. + */ + afr_save_lk_owner (frame); + frame->root->lk_owner = + local->transaction.main_frame->root->lk_owner; + + local->transaction.fop (frame, this); +} + static int __changelog_enabled (afr_private_t *priv, afr_transaction_type type) @@ -778,18 +812,7 @@ afr_changelog_pre_op_cbk (call_frame_t *frame, void *cookie, xlator_t *this, (local->op_errno == ENOTSUP)) { local->transaction.resume (frame, this); } else { - __mark_all_success (local->pending, priv->child_count, - local->transaction.type); - - /* Perform fops with the lk-owner from top xlator. - * Eg: lk-owner of posix-lk and flush should be same, - * flush cant clear the posix-lks without that lk-owner. - */ - afr_save_lk_owner (frame); - frame->root->lk_owner = - local->transaction.main_frame->root->lk_owner; - - local->transaction.fop (frame, this); + afr_transaction_perform_fop (frame, this); } } @@ -1218,28 +1241,10 @@ afr_lock (call_frame_t *frame, xlator_t *this) int afr_internal_lock_finish (call_frame_t *frame, xlator_t *this) { - afr_local_t *local = NULL; - afr_private_t *priv = NULL; - - priv = this->private; - local = frame->local; - if (__fop_changelog_needed (frame, this)) { afr_changelog_pre_op (frame, this); } else { - __mark_all_success (local->pending, priv->child_count, - local->transaction.type); - - - /* Perform fops with the lk-owner from top xlator. - * Eg: lk-owner of posix-lk and flush should be same, - * flush cant clear the posix-lks without that lk-owner. - */ - afr_save_lk_owner (frame); - frame->root->lk_owner = - local->transaction.main_frame->root->lk_owner; - - local->transaction.fop (frame, this); + afr_transaction_perform_fop (frame, this); } return 0; |