summaryrefslogtreecommitdiffstats
path: root/xlators
diff options
context:
space:
mode:
Diffstat (limited to 'xlators')
-rw-r--r--xlators/cluster/afr/src/afr.c70
-rw-r--r--xlators/cluster/afr/src/afr.h17
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); \