diff options
-rw-r--r-- | xlators/cluster/afr/src/afr.c | 70 | ||||
-rw-r--r-- | xlators/cluster/afr/src/afr.h | 17 |
2 files changed, 76 insertions, 11 deletions
diff --git a/xlators/cluster/afr/src/afr.c b/xlators/cluster/afr/src/afr.c index e8a47a6c363..4ae302deb7c 100644 --- a/xlators/cluster/afr/src/afr.c +++ b/xlators/cluster/afr/src/afr.c @@ -306,17 +306,24 @@ afr_self_heal_cbk (call_frame_t *frame, xlator_t *this) afr_local_t *local = NULL; int ret = -1; + afr_inode_ctx_t * inode_ctx = NULL; + uint64_t ctx; + local = frame->local; + ret = inode_ctx_get (local->cont.lookup.inode, this, &ctx); + + inode_ctx = (afr_inode_ctx_t *)(long) ctx; + if (local->govinda_gOvinda) { - ret = inode_ctx_put (local->cont.lookup.inode, this, 1); + inode_ctx->split_brain = 1; if (ret < 0) { local->op_ret = -1; local->op_errno = -ret; } } else { - inode_ctx_del (local->cont.lookup.inode, this, NULL); + inode_ctx->split_brain = 0; } AFR_STACK_UNWIND (frame, local->op_ret, local->op_errno, @@ -497,8 +504,11 @@ afr_lookup (call_frame_t *frame, xlator_t *this, afr_local_t *local = NULL; int ret = -1; int i = 0; + int32_t op_errno = 0; + afr_inode_ctx_t *inode_ctx = NULL; + uint64_t ctx; priv = this->private; @@ -510,6 +520,30 @@ afr_lookup (call_frame_t *frame, xlator_t *this, loc_copy (&local->loc, loc); + ret = inode_ctx_get (loc->inode, this, &ctx); + inode_ctx = (afr_inode_ctx_t *)(long) ctx; + + if (ret < 0) { + inode_ctx = CALLOC (1, sizeof (afr_inode_ctx_t)); + + if (!inode_ctx) { + op_errno = ENOMEM; + gf_log (this->name, GF_LOG_ERROR, + "out of memory :("); + goto out; + } + + ret = inode_ctx_put (loc->inode, this, + (uint64_t)(long) inode_ctx); + + if (ret < 0) { + op_errno = EINVAL; + gf_log (this->name, GF_LOG_ERROR, + "could not set inode ctx"); + goto out; + } + } + local->reval_child_index = 0; local->call_count = priv->child_count; @@ -556,7 +590,7 @@ afr_lookup (call_frame_t *frame, xlator_t *this, ret = 0; out: if (ret == -1) - AFR_STACK_UNWIND (frame, -1, ENOMEM, NULL, NULL, NULL); + AFR_STACK_UNWIND (frame, -1, op_errno, NULL, NULL, NULL); return 0; } @@ -625,7 +659,10 @@ afr_open (call_frame_t *frame, xlator_t *this, { afr_private_t * priv = NULL; afr_local_t * local = NULL; - + + afr_inode_ctx_t * inode_ctx = NULL; + uint64_t ctx; + int i = 0; int ret = -1; @@ -638,22 +675,33 @@ afr_open (call_frame_t *frame, xlator_t *this, VALIDATE_OR_GOTO (this, out); VALIDATE_OR_GOTO (this->private, out); VALIDATE_OR_GOTO (loc, out); - + priv = this->private; - ret = inode_ctx_get (loc->inode, this, NULL); - if (ret == 0) { - /* if ctx is set it means self-heal failed */ + ret = inode_ctx_get (loc->inode, this, &ctx); + + if (ret < 0) { + gf_log (this->name, GF_LOG_ERROR, + "inode ctx not set!"); + op_errno = EINVAL; + goto out; + } + + inode_ctx = (afr_inode_ctx_t *)(long) ctx; - gf_log (this->name, GF_LOG_WARNING, + if (inode_ctx->split_brain) { + /* self-heal failed */ + + gf_log (this->name, GF_LOG_WARNING, "returning EIO, file has to be manually corrected " - "in backend"); + "in the backend"); + op_errno = EIO; goto out; } ALLOC_OR_GOTO (local, afr_local_t, out); - + ret = AFR_LOCAL_INIT (local, priv); if (ret < 0) { op_errno = -ret; diff --git a/xlators/cluster/afr/src/afr.h b/xlators/cluster/afr/src/afr.h index 02c69597b0d..5db6e98092a 100644 --- a/xlators/cluster/afr/src/afr.h +++ b/xlators/cluster/afr/src/afr.h @@ -389,6 +389,23 @@ typedef struct _afr_local { afr_self_heal_t self_heal; } afr_local_t; + +typedef struct { + /* + split-brain situation in which afr + can do nothing + */ + gf_boolean_t split_brain; + + /* + subvolume from which all reads should + happen for this inode + */ + int read_child; + +} afr_inode_ctx_t; + + /* try alloc and if it fails, goto label */ #define ALLOC_OR_GOTO(var, type, label) do { \ var = CALLOC (sizeof (type), 1); \ |