>From 39b180fa54a2adbdf55d78454514b9a403a20709 Mon Sep 17 00:00:00 2001 From: Pranith Kumar K Date: Thu, 28 Feb 2013 14:50:16 +0530 Subject: [PATCH 1/1] wip Change-Id: I3b3a7931954da2166a9cba19ff9f76f37739d751 Signed-off-by: Pranith Kumar K --- xlators/cluster/afr/src/afr-dir-write.c | 85 ++++++++++++++++++++++++++++- xlators/cluster/afr/src/afr-transaction.c | 2 +- xlators/cluster/afr/src/afr-transaction.h | 3 + 3 files changed, 88 insertions(+), 2 deletions(-) diff --git a/xlators/cluster/afr/src/afr-dir-write.c b/xlators/cluster/afr/src/afr-dir-write.c index a988ea2..a32daaf 100644 --- a/xlators/cluster/afr/src/afr-dir-write.c +++ b/xlators/cluster/afr/src/afr-dir-write.c @@ -231,7 +231,88 @@ afr_dir_fop_mark_entry_pending_changelog (call_frame_t *frame, xlator_t *this) afr_mark_new_entry_changelog (frame, this); out: - local->transaction.resume (frame, this); + return; +} + +static gf_boolean_t +did_all_winds_fail_with_same_errno (afr_local_t *local, afr_private_t *priv, + int32_t op_errno) +{ + int i = 0; + for (i = 0; i < priv->child_count; i++) { + if (local->transaction.pre_op[i] && + (local->child_errno[i] != op_errno)) + return _gf_false; + } + return _gf_true; +} + +static gf_boolean_t +are_fops_wound (afr_local_t *local, afr_private_t *priv) +{ + int i = 0; + + for (i = 0; i < priv->child_count; i++) { + if (local->transaction.pre_op[i]) + return _gf_true; + } + return _gf_false; +} + +void +afr_dir_fop_handle_all_fop_failures (call_frame_t *frame) +{ + xlator_t *this = NULL; + afr_local_t *local = NULL; + afr_private_t *priv = NULL; + int32_t skip_errnos[3] = {0, 0, 0}; + int i = 0; + + this = frame->this; + local = frame->local; + priv = this->private; + + if (local->op_ret >= 0) + goto out; + + if (!are_fops_wound (local, priv)) + goto out; + + switch (local->op) { + case GF_FOP_CREATE: + case GF_FOP_MKNOD: + case GF_FOP_LINK: + case GF_FOP_SYMLINK: + case GF_FOP_MKDIR: + skip_errnos[0] = EEXIST; + break; + case GF_FOP_RMDIR: + case GF_FOP_UNLINK: + skip_errnos[0] = ENOENT; + break; + case GF_FOP_RENAME: + skip_errnos[0] = ENOENT; + skip_errnos[1] = EEXIST; + break; + default: + break; + } + + /* + * If a new entry creation fop fails with EEXIST or a delete entry fop + * fails with ENOENT, on all the subvols the fop is wound, then no + * change took place to the directory. So treat these cases as success + * from the point of view of changelog. + */ + + for (i = 0; skip_errnos[i]; i++) { + if (did_all_winds_fail_with_same_errno (local, priv, + skip_errnos[i])) + __mark_all_success (local->pending, priv->child_count, + local->transaction.type); + } +out: + return; } void @@ -253,6 +334,8 @@ afr_dir_fop_done (call_frame_t *frame, xlator_t *this) done: local->transaction.unwind (frame, this); afr_dir_fop_mark_entry_pending_changelog (frame, this); + afr_dir_fop_handle_all_fop_failures (frame); + local->transaction.resume (frame, this); } /* {{{ create */ diff --git a/xlators/cluster/afr/src/afr-transaction.c b/xlators/cluster/afr/src/afr-transaction.c index d20928d..b38da54 100644 --- a/xlators/cluster/afr/src/afr-transaction.c +++ b/xlators/cluster/afr/src/afr-transaction.c @@ -192,7 +192,7 @@ __mark_non_participant_children (int32_t *pending[], int child_count, } -static void +void __mark_all_success (int32_t *pending[], int child_count, afr_transaction_type type) { diff --git a/xlators/cluster/afr/src/afr-transaction.h b/xlators/cluster/afr/src/afr-transaction.h index e95bc5b..55e8bbc 100644 --- a/xlators/cluster/afr/src/afr-transaction.h +++ b/xlators/cluster/afr/src/afr-transaction.h @@ -37,4 +37,7 @@ afr_set_delayed_post_op (call_frame_t *frame, xlator_t *this); void afr_delayed_changelog_wake_up (xlator_t *this, fd_t *fd); +void +__mark_all_success (int32_t *pending[], int child_count, + afr_transaction_type type); #endif /* __TRANSACTION_H__ */ -- 1.7.10.2