summaryrefslogtreecommitdiffstats
path: root/xlators/cluster/afr/src/afr-common.c
diff options
context:
space:
mode:
Diffstat (limited to 'xlators/cluster/afr/src/afr-common.c')
-rw-r--r--xlators/cluster/afr/src/afr-common.c820
1 files changed, 466 insertions, 354 deletions
diff --git a/xlators/cluster/afr/src/afr-common.c b/xlators/cluster/afr/src/afr-common.c
index a435a38b1..f49d8c55e 100644
--- a/xlators/cluster/afr/src/afr-common.c
+++ b/xlators/cluster/afr/src/afr-common.c
@@ -328,6 +328,8 @@ afr_local_sh_cleanup (afr_local_t *local, xlator_t *this)
if (sh->linkname)
GF_FREE ((char *)sh->linkname);
+ if (sh->child_success)
+ GF_FREE (sh->child_success);
loc_wipe (&sh->parent_loc);
}
@@ -417,6 +419,18 @@ afr_local_cleanup (afr_local_t *local, xlator_t *this)
if (local->cont.lookup.inode) {
inode_unref (local->cont.lookup.inode);
}
+
+ if (local->cont.lookup.postparents)
+ GF_FREE (local->cont.lookup.postparents);
+
+ if (local->cont.lookup.bufs)
+ GF_FREE (local->cont.lookup.bufs);
+
+ if (local->cont.lookup.child_success)
+ GF_FREE (local->cont.lookup.child_success);
+
+ if (local->cont.lookup.sources)
+ GF_FREE (local->cont.lookup.sources);
}
{ /* getxattr */
@@ -509,6 +523,22 @@ afr_up_children_count (int child_count, unsigned char *child_up)
return ret;
}
+gf_boolean_t
+afr_is_fresh_lookup (loc_t *loc, xlator_t *this)
+{
+ uint64_t ctx = 0;
+ int32_t ret = 0;
+
+ GF_ASSERT (loc);
+ GF_ASSERT (this);
+ GF_ASSERT (loc->inode);
+
+ ret = inode_ctx_get (loc->inode, this, &ctx);
+ if (0 == ret)
+ return _gf_false;
+ return _gf_true;
+}
+
void
afr_update_loc_gfids (loc_t *loc, struct iatt *buf, struct iatt *postparent)
{
@@ -567,68 +597,96 @@ afr_self_heal_lookup_unwind (call_frame_t *frame, xlator_t *this)
}
AFR_STACK_UNWIND (lookup, frame, local->op_ret, local->op_errno,
- local->cont.lookup.inode,
- &local->cont.lookup.buf,
+ local->cont.lookup.inode, &local->cont.lookup.buf,
local->cont.lookup.xattr,
&local->cont.lookup.postparent);
return 0;
}
+void
+afr_lookup_build_response_params (afr_local_t *local, xlator_t *this)
+{
+ int32_t read_child = -1;
+ struct iatt *buf = NULL;
+ struct iatt *postparent = NULL;
+ dict_t **xattr = NULL;
-static void
-afr_lookup_collect_xattr (afr_local_t *local, xlator_t *this,
- int child_index, dict_t *xattr)
+ GF_ASSERT (local);
+ GF_ASSERT (local->cont.lookup.read_child >= 0);
+
+ buf = &local->cont.lookup.buf;
+ postparent = &local->cont.lookup.postparent;
+ xattr = &local->cont.lookup.xattr;
+
+ read_child = local->cont.lookup.read_child;
+ *xattr = dict_ref (local->cont.lookup.xattrs[read_child]);
+ *buf = local->cont.lookup.bufs[read_child];
+ *postparent = local->cont.lookup.postparents[read_child];
+
+ if (IA_INVAL == local->cont.lookup.inode->ia_type) {
+ /* fix for RT #602 */
+ local->cont.lookup.inode->ia_type = buf->ia_type;
+ }
+}
+
+
+ static void
+afr_lookup_update_lk_counts (afr_local_t *local, xlator_t *this,
+ int child_index, dict_t *xattr)
{
uint32_t inodelk_count = 0;
uint32_t entrylk_count = 0;
- int ret = 0;
+ int ret = -1;
+
+ GF_ASSERT (local);
+ GF_ASSERT (this);
+ GF_ASSERT (xattr);
+ GF_ASSERT (child_index >= 0);
+
+ ret = dict_get_uint32 (xattr, GLUSTERFS_INODELK_COUNT,
+ &inodelk_count);
+ if (ret == 0)
+ local->inodelk_count += inodelk_count;
- if (afr_sh_has_metadata_pending (xattr, child_index, this)) {
+ ret = dict_get_uint32 (xattr, GLUSTERFS_ENTRYLK_COUNT,
+ &entrylk_count);
+ if (ret == 0)
+ local->entrylk_count += entrylk_count;
+}
+
+static void
+afr_lookup_detect_self_heal_by_xattr (afr_local_t *local, xlator_t *this,
+ dict_t *xattr)
+{
+ GF_ASSERT (local);
+ GF_ASSERT (this);
+ GF_ASSERT (xattr);
+
+ if (afr_sh_has_metadata_pending (xattr, this)) {
local->self_heal.need_metadata_self_heal = _gf_true;
gf_log(this->name, GF_LOG_DEBUG,
"metadata self-heal is pending for %s.",
local->loc.path);
}
- if (afr_sh_has_entry_pending (xattr, child_index, this)) {
+ if (afr_sh_has_entry_pending (xattr, this)) {
local->self_heal.need_entry_self_heal = _gf_true;
gf_log(this->name, GF_LOG_DEBUG,
"entry self-heal is pending for %s.", local->loc.path);
}
- if (afr_sh_has_data_pending (xattr, child_index, this)) {
+ if (afr_sh_has_data_pending (xattr, this)) {
local->self_heal.need_data_self_heal = _gf_true;
gf_log(this->name, GF_LOG_DEBUG,
"data self-heal is pending for %s.", local->loc.path);
}
-
- ret = dict_get_uint32 (xattr, GLUSTERFS_INODELK_COUNT,
- &inodelk_count);
- if (ret == 0)
- local->inodelk_count += inodelk_count;
-
- ret = dict_get_uint32 (xattr, GLUSTERFS_ENTRYLK_COUNT,
- &entrylk_count);
- if (ret == 0)
- local->entrylk_count += entrylk_count;
}
-
static void
-afr_lookup_self_heal_check (xlator_t *this, afr_local_t *local,
+afr_detect_self_heal_by_iatt (afr_local_t *local, xlator_t *this,
struct iatt *buf, struct iatt *lookup_buf)
{
- if (FILETYPE_DIFFERS (buf, lookup_buf)) {
- /* mismatching filetypes with same name
- */
-
- gf_log (this->name, GF_LOG_INFO,
- "filetype differs for %s ", local->loc.path);
-
- local->govinda_gOvinda = 1;
- }
-
if (PERMISSION_DIFFERS (buf, lookup_buf)) {
/* mismatching permissions */
gf_log (this->name, GF_LOG_INFO,
@@ -674,157 +732,299 @@ out:
return valid;
}
-void
-afr_lookup_set_read_child (xlator_t *this, afr_local_t *local)
+static void
+afr_detect_self_heal_by_lookup_status (afr_local_t *local, xlator_t *this)
{
- ia_type_t ia_type = IA_INVAL;
- afr_transaction_type transaction_type = AFR_DATA_TRANSACTION;
- afr_private_t *priv = NULL;
- int32_t read_child = -1;
- afr_self_heal_t *sh = NULL;
+ GF_ASSERT (local);
+ GF_ASSERT (this);
- priv = this->private;
- sh = &local->self_heal;
+ if ((local->success_count > 0) && (local->enoent_count > 0)) {
+ local->self_heal.need_metadata_self_heal = _gf_true;
+ local->self_heal.need_data_self_heal = _gf_true;
+ local->self_heal.need_entry_self_heal = _gf_true;
+ gf_log(this->name, GF_LOG_INFO,
+ "entries are missing in lookup of %s.",
+ local->loc.path);
+ //If all self-heals are needed no need to check for other rules
+ goto out;
+ }
- ia_type = local->cont.lookup.inode->ia_type;
- if (IA_ISREG (ia_type)) {
- transaction_type = AFR_DATA_TRANSACTION;
- } else if IA_ISDIR (ia_type) {
- transaction_type = AFR_ENTRY_TRANSACTION;
- } else {
- transaction_type = AFR_METADATA_TRANSACTION;
+ if (local->success_count > 0) {
+ if (afr_is_split_brain (this, local->cont.lookup.inode) &&
+ IA_ISREG (local->cont.lookup.inode->ia_type)) {
+ local->self_heal.need_data_self_heal = _gf_true;
+ gf_log (this->name, GF_LOG_WARNING,
+ "split brain detected during lookup of %s.",
+ local->loc.path);
+ }
}
- afr_self_heal_find_sources (this, local,
- local->cont.lookup.xattrs,
- transaction_type);
- if (!sh->sources)
- goto out;
- read_child = local->read_child_index;
- if (afr_is_valid_read_child (sh->sources, priv->child_count,
- read_child))
- goto out;
+out:
+ return;
+}
+
+gf_boolean_t
+afr_can_self_heal_proceed (afr_self_heal_t *sh, afr_private_t *priv)
+{
+ GF_ASSERT (sh);
+ GF_ASSERT (priv);
+
+ return ((priv->data_self_heal && sh->need_data_self_heal)
+ || (priv->metadata_self_heal && sh->need_metadata_self_heal)
+ || (priv->entry_self_heal && sh->need_entry_self_heal));
+}
- read_child = afr_read_child (this, local->loc.inode);
- if (afr_is_valid_read_child (sh->sources, priv->child_count,
- read_child))
+gf_boolean_t
+afr_is_self_heal_enabled (afr_private_t *priv)
+{
+ GF_ASSERT (priv);
+
+ return (priv->data_self_heal || priv->metadata_self_heal
+ || priv->entry_self_heal);
+}
+
+int
+afr_lookup_select_read_child (afr_local_t *local, xlator_t *this,
+ int32_t *read_child)
+{
+ int32_t source = -1;
+ ia_type_t ia_type = 0;
+ int ret = -1;
+ afr_transaction_type type = AFR_METADATA_TRANSACTION;
+ dict_t **xattrs = NULL;
+ int32_t *child_success = NULL;
+ struct iatt *bufs = NULL;
+
+ GF_ASSERT (local);
+ GF_ASSERT (this);
+
+ bufs = local->cont.lookup.bufs;
+ child_success = local->cont.lookup.child_success;
+ ia_type = local->cont.lookup.bufs[child_success[0]].ia_type;
+ if (IA_ISDIR (ia_type)) {
+ type = AFR_ENTRY_TRANSACTION;
+ } else if (IA_ISREG (ia_type)) {
+ type = AFR_DATA_TRANSACTION;
+ }
+ xattrs = local->cont.lookup.xattrs;
+ source = afr_lookup_select_read_child_by_txn_type (this, local, xattrs,
+ type);
+ if (source < 0)
goto out;
- read_child = afr_sh_select_source (sh->sources, priv->child_count);
+ *read_child = source;
+ ret = 0;
out:
- if (read_child >= 0) {
- afr_set_read_child (this,
- local->cont.lookup.inode,
- read_child);
- }
+ return ret;
+}
+
+static inline gf_boolean_t
+afr_is_self_heal_running (afr_local_t *local)
+{
+ GF_ASSERT (local);
+ return ((local->inodelk_count > 0) || (local->entrylk_count > 0));
}
static void
-afr_lookup_done (call_frame_t *frame, xlator_t *this, struct iatt *lookup_buf)
+afr_launch_self_heal (call_frame_t *frame, xlator_t *this,
+ gf_boolean_t is_background, ia_type_t ia_type,
+ int (*unwind) (call_frame_t *frame, xlator_t *this))
{
- int unwind = 1;
- int up_count = 0;
- char sh_type_str[256] = {0,};
- afr_private_t *priv = NULL;
afr_local_t *local = NULL;
+ char sh_type_str[256] = {0,};
+
+ GF_ASSERT (frame);
+ GF_ASSERT (this);
- priv = this->private;
local = frame->local;
+ local->self_heal.background = is_background;
+ local->self_heal.type = ia_type;
+ local->self_heal.unwind = unwind;
- if (local->op_ret != 0)
- goto unwind;
+ afr_self_heal_type_str_get (&local->self_heal,
+ sh_type_str,
+ sizeof (sh_type_str));
- local->cont.lookup.postparent.ia_ino = local->cont.lookup.parent_ino;
+ gf_log (this->name, GF_LOG_INFO,
+ "background %s self-heal triggered. path: %s",
+ sh_type_str, local->loc.path);
- if (local->cont.lookup.ino) {
- local->cont.lookup.buf.ia_ino = local->cont.lookup.ino;
+ afr_self_heal (frame, this);
+}
+
+static void
+afr_lookup_detect_self_heal (afr_local_t *local, xlator_t *this)
+{
+ int i = 0;
+ struct iatt *bufs = NULL;
+ dict_t **xattr = NULL;
+ afr_private_t *priv = NULL;
+ int32_t child1 = -1;
+ int32_t child2 = -1;
+
+ afr_detect_self_heal_by_lookup_status (local, this);
+
+ bufs = local->cont.lookup.bufs;
+ for (i = 1; i < local->success_count; i++) {
+ child1 = local->cont.lookup.child_success[i-1];
+ child2 = local->cont.lookup.child_success[i];;
+ afr_detect_self_heal_by_iatt (local, this,
+ &bufs[child1], &bufs[child2]);
}
- if (local->op_ret == 0) {
- /* KLUDGE: assuming DHT will not itransform in
- revalidate */
- if (local->cont.lookup.inode->ino) {
- local->cont.lookup.buf.ia_ino =
- local->cont.lookup.inode->ino;
- }
+ xattr = local->cont.lookup.xattrs;
+ priv = this->private;
+ for (i = 0; i < local->success_count; i++) {
+ child1 = local->cont.lookup.child_success[i];;
+ afr_lookup_detect_self_heal_by_xattr (local, this,
+ xattr[child1]);
}
+}
+
+static void
+afr_lookup_perform_self_heal_if_needed (call_frame_t *frame, xlator_t *this,
+ gf_boolean_t *sh_launched)
+{
+ size_t up_count = 0;
+ afr_private_t *priv = NULL;
+ afr_local_t *local = NULL;
+
+ GF_ASSERT (sh_launched);
+ *sh_launched = _gf_false;
+ priv = this->private;
+ local = frame->local;
- afr_lookup_set_read_child (this, local);
- up_count = afr_up_children_count (priv->child_count, priv->child_up);
+ up_count = afr_up_children_count (priv->child_count, local->child_up);
if (up_count == 1) {
gf_log (this->name, GF_LOG_DEBUG,
"Only 1 child up - do not attempt to detect self heal");
+ goto out;
+ }
- goto unwind;
+ if (_gf_false == afr_is_self_heal_enabled (priv)) {
+ gf_log (this->name, GF_LOG_DEBUG,
+ "Self heal is not enabled");
+ goto out;
}
- if (local->success_count && local->enoent_count) {
- local->self_heal.need_metadata_self_heal = _gf_true;
- local->self_heal.need_data_self_heal = _gf_true;
- local->self_heal.need_entry_self_heal = _gf_true;
- gf_log(this->name, GF_LOG_INFO,
- "entries are missing in lookup of %s.",
- local->loc.path);
+ afr_lookup_detect_self_heal (local, this);
+ if (afr_can_self_heal_proceed (&local->self_heal, priv)) {
+ if (afr_is_self_heal_running (local)) {
+ goto out;
+ }
+
+ afr_launch_self_heal (frame, this, _gf_true,
+ local->cont.lookup.buf.ia_type,
+ afr_self_heal_lookup_unwind);
+ *sh_launched = _gf_true;
}
+out:
+ return;
+}
- if (local->success_count) {
- /* check for split-brain case in previous lookup */
- if (afr_is_split_brain (this, local->cont.lookup.inode)) {
- local->self_heal.need_data_self_heal = _gf_true;
- gf_log(this->name, GF_LOG_WARNING,
- "split brain detected during lookup of %s.",
- local->loc.path);
+static gf_boolean_t
+afr_lookup_split_brain (afr_local_t *local, xlator_t *this)
+{
+ int i = 0;
+ gf_boolean_t symptom = _gf_false;
+ struct iatt *bufs = NULL;
+ int32_t *child_success = NULL;
+ struct iatt *child1 = NULL;
+ struct iatt *child2 = NULL;
+ const char *path = NULL;
+
+ bufs = local->cont.lookup.bufs;
+ child_success = local->cont.lookup.child_success;
+ for (i = 1; i < local->success_count; i++) {
+ child1 = &bufs[child_success[i-1]];
+ child2 = &bufs[child_success[i]];
+ /*
+ * TODO: gfid self-heal
+ * if (uuid_compare (child1->ia_gfid, child2->ia_gfid)) {
+ * gf_log (this->name, GF_LOG_WARNING, "%s: gfid differs"
+ * " on subvolumes (%d, %d)", local->loc.path,
+ * child_success[i-1], child_success[i]);
+ * symptom = _gf_true;
+ * }
+ */
+
+ if (FILETYPE_DIFFERS (child1, child2)) {
+ path = local->loc.path;
+ gf_log (this->name, GF_LOG_WARNING, "%s: filetype "
+ "differs on subvolumes (%d, %d)", path,
+ child_success[i-1], child_success[i]);
+ symptom = _gf_true;
+ local->govinda_gOvinda = 1;
}
+ if (symptom)
+ break;
}
+ return symptom;
+}
- if (local->self_heal.need_metadata_self_heal
- || local->self_heal.need_data_self_heal
- || local->self_heal.need_entry_self_heal)
- {
+static int
+afr_lookup_set_read_child (afr_local_t *local, xlator_t *this, int32_t read_child)
+{
+ GF_ASSERT (read_child >= 0);
- if (local->inodelk_count || local->entrylk_count) {
+ afr_set_read_child (this, local->cont.lookup.inode, read_child);
+ local->cont.lookup.read_child = read_child;
- /* Someone else is doing self-heal on this file.
- return */
+ return 0;
+}
- goto unwind;
- }
+static void
+afr_lookup_done (call_frame_t *frame, xlator_t *this)
+{
+ int unwind = 1;
+ afr_private_t *priv = NULL;
+ afr_local_t *local = NULL;
+ int ret = -1;
+ gf_boolean_t sh_launched = _gf_false;
+ int32_t read_child = -1;
- if (!local->cont.lookup.inode->ia_type) {
- /* fix for RT #602 */
- local->cont.lookup.inode->ia_type =
- lookup_buf->ia_type;
- }
+ priv = this->private;
+ local = frame->local;
- local->self_heal.background = _gf_true;
- local->self_heal.type = local->cont.lookup.buf.ia_type;
- local->self_heal.unwind = afr_self_heal_lookup_unwind;
+ if (local->op_ret < 0)
+ goto unwind;
- unwind = 0;
+ if (_gf_true == afr_lookup_split_brain (local, this)) {
+ local->op_ret = -1;
+ local->op_errno = EIO;
+ goto unwind;
+ }
- afr_self_heal_type_str_get(&local->self_heal,
- sh_type_str,
- sizeof(sh_type_str));
+ ret = afr_lookup_select_read_child (local, this, &read_child);
+ if (ret) {
+ local->op_ret = -1;
+ local->op_errno = EIO;
+ goto unwind;
+ }
- gf_log (this->name, GF_LOG_INFO,
- "background %s self-heal triggered. path: %s",
- sh_type_str, local->loc.path);
+ ret = afr_lookup_set_read_child (local, this, read_child);
+ if (ret)
+ goto unwind;
- afr_self_heal (frame, this);
+ afr_lookup_build_response_params (local, this);
+ if (afr_is_fresh_lookup (&local->loc, this)) {
+ afr_update_loc_gfids (&local->loc, &local->cont.lookup.buf,
+ &local->cont.lookup.postparent);
}
-unwind:
- if (unwind) {
- AFR_STACK_UNWIND (lookup, frame, local->op_ret,
- local->op_errno,
- local->cont.lookup.inode,
- &local->cont.lookup.buf,
- local->cont.lookup.xattr,
- &local->cont.lookup.postparent);
+ afr_lookup_perform_self_heal_if_needed (frame, this, &sh_launched);
+ if (sh_launched)
+ unwind = 0;
+ unwind:
+ if (unwind) {
+ AFR_STACK_UNWIND (lookup, frame, local->op_ret,
+ local->op_errno, local->cont.lookup.inode,
+ &local->cont.lookup.buf,
+ local->cont.lookup.xattr,
+ &local->cont.lookup.postparent);
}
}
-
/*
* During a lookup, some errors are more "important" than
* others in that they must be given higher priority while
@@ -850,259 +1050,169 @@ __error_more_important (int32_t old_errno, int32_t new_errno)
return ret;
}
-
-int
-afr_fresh_lookup_cbk (call_frame_t *frame, void *cookie,
- xlator_t *this, int32_t op_ret, int32_t op_errno,
- inode_t *inode, struct iatt *buf, dict_t *xattr,
- struct iatt *postparent)
+static void
+afr_lookup_handle_error (afr_local_t *local, int32_t op_ret, int32_t op_errno)
{
- afr_local_t * local = NULL;
- afr_private_t * priv = NULL;
- struct iatt * lookup_buf = NULL;
- int call_count = -1;
- int child_index = -1;
- int first_up_child = -1;
+ GF_ASSERT (local);
+ if (op_errno == ENOENT)
+ local->enoent_count++;
- child_index = (long) cookie;
- priv = this->private;
-
- LOCK (&frame->lock);
- {
- local = frame->local;
-
- lookup_buf = &local->cont.lookup.buf;
-
- if (op_ret == -1) {
- if (op_errno == ENOENT)
- local->enoent_count++;
-
- if (__error_more_important (local->op_errno, op_errno))
- local->op_errno = op_errno;
-
- if (local->op_errno == ESTALE) {
- local->op_ret = -1;
- }
-
- goto unlock;
- }
-
- afr_lookup_collect_xattr (local, this, child_index, xattr);
-
- first_up_child = afr_first_up_child (priv);
-
- if (child_index == first_up_child) {
- local->cont.lookup.ino =
- afr_itransform (buf->ia_ino,
- priv->child_count,
- first_up_child);
- }
-
- if (local->success_count == 0) {
- if (local->op_errno != ESTALE)
- local->op_ret = op_ret;
-
- local->cont.lookup.inode = inode_ref (inode);
- local->cont.lookup.xattr = dict_ref (xattr);
- local->cont.lookup.xattrs[child_index] = dict_ref (xattr);
- local->cont.lookup.postparent = *postparent;
-
- if (priv->first_lookup && inode->ino == 1) {
- gf_log (this->name, GF_LOG_INFO,
- "added root inode");
- priv->root_inode = inode_ref (inode);
- priv->first_lookup = 0;
- }
-
- *lookup_buf = *buf;
-
- uuid_copy (local->loc.gfid, buf->ia_gfid);
- uuid_copy (local->loc.pargfid,
- postparent->ia_gfid);
-
- lookup_buf->ia_ino = afr_itransform (buf->ia_ino,
- priv->child_count,
- child_index);
- if (priv->read_child >= 0) {
- afr_set_read_child (this,
- local->cont.lookup.inode,
- priv->read_child);
- } else {
- afr_set_read_child (this,
- local->cont.lookup.inode,
- child_index);
- //prefer fast child
- local->read_child_index = child_index;
- }
-
- } else {
- afr_lookup_self_heal_check (this, local, buf, lookup_buf);
+ if (__error_more_important (local->op_errno, op_errno))
+ local->op_errno = op_errno;
+ if (local->op_errno == ESTALE) {
+ local->op_ret = -1;
+ }
+}
- local->cont.lookup.xattrs[child_index] = dict_ref (xattr);
- if (child_index == local->read_child_index) {
- /*
- lookup has succeeded on the read child.
- So use its inode number
- */
- if (local->cont.lookup.xattr)
- dict_unref (local->cont.lookup.xattr);
+static void
+afr_set_root_inode_on_first_lookup (afr_local_t *local, xlator_t *this,
+ inode_t *inode)
+{
+ afr_private_t *priv = NULL;
+ GF_ASSERT (inode);
- local->cont.lookup.xattr = dict_ref (xattr);
- local->cont.lookup.postparent = *postparent;
+ if (inode->ino != 1)
+ goto out;
+ if (!afr_is_fresh_lookup (&local->loc, this))
+ goto out;
+ priv = this->private;
+ if ((priv->first_lookup)) {
+ gf_log (this->name, GF_LOG_INFO, "added root inode");
+ priv->root_inode = inode_ref (inode);
+ priv->first_lookup = 0;
+ }
+out:
+ return;
+}
- *lookup_buf = *buf;
+static void
+afr_lookup_cache_args (afr_local_t *local, int child_index, dict_t *xattr,
+ struct iatt *buf, struct iatt *postparent)
+{
+ GF_ASSERT (child_index >= 0);
+ local->cont.lookup.xattrs[child_index] = dict_ref (xattr);
+ local->cont.lookup.postparents[child_index] = *postparent;
+ local->cont.lookup.bufs[child_index] = *buf;
+}
- uuid_copy (local->loc.gfid, buf->ia_gfid);
- uuid_copy (local->loc.pargfid,
- postparent->ia_gfid);
- }
+static void
+afr_lookup_handle_first_success (afr_local_t *local, xlator_t *this,
+ inode_t *inode, struct iatt *buf)
+{
+ local->cont.lookup.inode = inode_ref (inode);
+ local->cont.lookup.buf = *buf;
+ afr_set_root_inode_on_first_lookup (local, this, inode);
+}
+static void
+afr_lookup_handle_success (afr_local_t *local, xlator_t *this, int32_t child_index,
+ int32_t op_ret, int32_t op_errno, inode_t *inode,
+ struct iatt *buf, dict_t *xattr,
+ struct iatt *postparent)
+{
+ if (local->success_count == 0) {
+ if (local->op_errno != ESTALE) {
+ local->op_ret = op_ret;
+ local->op_errno = 0;
}
-
- local->success_count++;
- }
-unlock:
- UNLOCK (&frame->lock);
-
- call_count = afr_frame_return (frame);
-
- if (call_count == 0) {
- afr_lookup_done (frame, this, lookup_buf);
+ afr_lookup_handle_first_success (local, this, inode, buf);
}
+ afr_lookup_update_lk_counts (local, this,
+ child_index, xattr);
- return 0;
+ afr_lookup_cache_args (local, child_index, xattr,
+ buf, postparent);
+ local->cont.lookup.child_success[local->success_count] = child_index;
+ local->success_count++;
}
-
int
-afr_revalidate_lookup_cbk (call_frame_t *frame, void *cookie,
- xlator_t *this, int32_t op_ret, int32_t op_errno,
- inode_t *inode, struct iatt *buf, dict_t *xattr,
- struct iatt *postparent)
+afr_lookup_cbk (call_frame_t *frame, void *cookie,
+ xlator_t *this, int32_t op_ret, int32_t op_errno,
+ inode_t *inode, struct iatt *buf, dict_t *xattr,
+ struct iatt *postparent)
{
afr_local_t * local = NULL;
- afr_private_t * priv = NULL;
- struct iatt * lookup_buf = NULL;
int call_count = -1;
int child_index = -1;
- int first_up_child = -1;
- child_index = (long) cookie;
- priv = this->private;
+ child_index = (long) cookie;
LOCK (&frame->lock);
{
local = frame->local;
- lookup_buf = &local->cont.lookup.buf;
-
if (op_ret == -1) {
- if (op_errno == ENOENT)
- local->enoent_count++;
-
- if (__error_more_important (local->op_errno, op_errno))
- local->op_errno = op_errno;
-
- if (local->op_errno == ESTALE) {
- local->op_ret = -1;
- }
-
+ afr_lookup_handle_error (local, op_ret, op_errno);
goto unlock;
}
+ afr_lookup_handle_success (local, this, child_index, op_ret,
+ op_errno, inode, buf, xattr,
+ postparent);
- afr_lookup_collect_xattr (local, this, child_index, xattr);
-
- first_up_child = afr_first_up_child (priv);
-
- if (child_index == first_up_child) {
- local->cont.lookup.ino =
- afr_itransform (buf->ia_ino,
- priv->child_count,
- first_up_child);
- }
-
- /* in case of revalidate, we need to send stat of the
- * child whose stat was sent during the first lookup.
- * (so that time stamp does not vary with revalidate.
- * in case it is down, stat of the fist success will
- * be replied */
-
- /* inode number should be preserved across revalidates */
-
- if (local->success_count == 0) {
- if (local->op_errno != ESTALE)
- local->op_ret = op_ret;
-
- local->cont.lookup.inode = inode_ref (inode);
- local->cont.lookup.xattr = dict_ref (xattr);
- local->cont.lookup.xattrs[child_index] = dict_ref (xattr);
- local->cont.lookup.postparent = *postparent;
-
- *lookup_buf = *buf;
-
- lookup_buf->ia_ino = afr_itransform (buf->ia_ino,
- priv->child_count,
- child_index);
-
- if (priv->read_child >= 0) {
- afr_set_read_child (this,
- local->cont.lookup.inode,
- priv->read_child);
- } else {
- afr_set_read_child (this,
- local->cont.lookup.inode,
- child_index);
- }
-
- } else {
- afr_lookup_self_heal_check (this, local, buf, lookup_buf);
-
- local->cont.lookup.xattrs[child_index] = dict_ref (xattr);
- if (child_index == local->read_child_index) {
+ }
+unlock:
+ UNLOCK (&frame->lock);
- /*
- lookup has succeeded on the read child.
- So use its inode number
- */
+ call_count = afr_frame_return (frame);
+ if (call_count == 0) {
+ afr_lookup_done (frame, this);
+ }
- if (local->cont.lookup.xattr)
- dict_unref (local->cont.lookup.xattr);
+ return 0;
+}
- local->cont.lookup.xattr = dict_ref (xattr);
- local->cont.lookup.postparent = *postparent;
+int
+afr_lookup_cont_init (afr_local_t *local, unsigned int child_count)
+{
+ int ret = -ENOMEM;
+ int32_t *child_success = NULL;
+ struct iatt *iatts = NULL;
+ int i = 0;
- *lookup_buf = *buf;
- }
+ GF_ASSERT (local);
+ local->cont.lookup.xattrs = GF_CALLOC (child_count,
+ sizeof (*local->cont.lookup.xattr),
+ gf_afr_mt_dict_t);
+ if (NULL == local->cont.lookup.xattrs)
+ goto out;
- }
+ iatts = GF_CALLOC (child_count, sizeof (*iatts), gf_afr_mt_iatt);
+ if (NULL == iatts)
+ goto out;
+ local->cont.lookup.postparents = iatts;
- local->success_count++;
- }
-unlock:
- UNLOCK (&frame->lock);
+ iatts = GF_CALLOC (child_count, sizeof (*iatts), gf_afr_mt_iatt);
+ if (NULL == iatts)
+ goto out;
+ local->cont.lookup.bufs = iatts;
- call_count = afr_frame_return (frame);
+ child_success = GF_CALLOC (child_count, sizeof (*child_success),
+ gf_afr_mt_char);
+ if (NULL == child_success)
+ goto out;
+ for (i = 0; i < child_count; i++)
+ child_success[i] = -1;
- if (call_count == 0) {
- afr_lookup_done (frame, this, lookup_buf);
- }
+ local->cont.lookup.child_success = child_success;
- return 0;
+ local->cont.lookup.read_child = -1;
+ ret = 0;
+out:
+ return ret;
}
-
int
afr_lookup (call_frame_t *frame, xlator_t *this,
loc_t *loc, dict_t *xattr_req)
{
- afr_private_t *priv = NULL;
- afr_local_t *local = NULL;
- int ret = -1;
- int i = 0;
- fop_lookup_cbk_t callback = NULL;
- int call_count = 0;
- uint64_t ctx = 0;
- int32_t op_errno = 0;
+ afr_private_t *priv = NULL;
+ afr_local_t *local = NULL;
+ int ret = -1;
+ int i = 0;
+ int call_count = 0;
+ uint64_t ctx = 0;
+ int32_t op_errno = 0;
priv = this->private;
@@ -1123,14 +1233,9 @@ afr_lookup (call_frame_t *frame, xlator_t *this,
if (ret == 0) {
/* lookup is a revalidate */
- callback = afr_revalidate_lookup_cbk;
-
- local->cont.lookup.is_revalidate = _gf_true;
local->read_child_index = afr_read_child (this,
loc->inode);
} else {
- callback = afr_fresh_lookup_cbk;
-
LOCK (&priv->read_child_lock);
{
local->read_child_index = (++priv->read_child_rr)
@@ -1143,10 +1248,16 @@ afr_lookup (call_frame_t *frame, xlator_t *this,
local->cont.lookup.parent_ino = loc->parent->ino;
local->child_up = memdup (priv->child_up, priv->child_count);
+ if (NULL == local->child_up) {
+ op_errno = ENOMEM;
+ goto out;
+ }
- local->cont.lookup.xattrs = GF_CALLOC (priv->child_count,
- sizeof (*local->cont.lookup.xattr),
- gf_afr_mt_dict_t);
+ ret = afr_lookup_cont_init (local, priv->child_count);
+ if (ret < 0) {
+ op_errno = -ret;
+ goto out;
+ }
local->call_count = afr_up_children_count (priv->child_count,
local->child_up);
@@ -1192,7 +1303,8 @@ afr_lookup (call_frame_t *frame, xlator_t *this,
for (i = 0; i < priv->child_count; i++) {
if (local->child_up[i]) {
- STACK_WIND_COOKIE (frame, callback, (void *) (long) i,
+ STACK_WIND_COOKIE (frame, afr_lookup_cbk,
+ (void *) (long) i,
priv->children[i],
priv->children[i]->fops->lookup,
loc, local->xattr_req);