From fb648cf39c8715e5a25752defdfc95ec0ba04217 Mon Sep 17 00:00:00 2001 From: Pranith Kumar K Date: Tue, 27 Sep 2011 14:44:01 +0530 Subject: cluster/afr: Handle files without gfid in self-heal Change-Id: Ibcaaa9c928195939ff1e31b28b592e524e63a423 BUG: 3557 Reviewed-on: http://review.gluster.com/519 Tested-by: Gluster Build System Reviewed-by: Vijay Bellur --- xlators/cluster/afr/src/afr-common.c | 5 +- xlators/cluster/afr/src/afr-self-heal-common.c | 464 +++++++++++-------- xlators/cluster/afr/src/afr-self-heal-common.h | 19 +- xlators/cluster/afr/src/afr-self-heal-entry.c | 546 +++++++++-------------- xlators/cluster/afr/src/afr-self-heal-metadata.c | 49 +- xlators/cluster/afr/src/afr-self-heald.c | 169 +++---- xlators/cluster/afr/src/afr-self-heald.h | 4 - xlators/cluster/afr/src/afr.h | 8 +- xlators/cluster/afr/src/pump.c | 32 +- 9 files changed, 642 insertions(+), 654 deletions(-) diff --git a/xlators/cluster/afr/src/afr-common.c b/xlators/cluster/afr/src/afr-common.c index c23e329df..0131feaa0 100644 --- a/xlators/cluster/afr/src/afr-common.c +++ b/xlators/cluster/afr/src/afr-common.c @@ -723,6 +723,7 @@ afr_local_sh_cleanup (afr_local_t *local, xlator_t *this) GF_FREE (sh->fresh_parent_dirs); loc_wipe (&sh->parent_loc); + loc_wipe (&sh->lookup_loc); if (sh->checksum) GF_FREE (sh->checksum); @@ -1235,12 +1236,12 @@ afr_launch_self_heal (call_frame_t *frame, xlator_t *this, inode_t *inode, afr_self_heal (frame, this, inode); } -int +unsigned int afr_gfid_missing_count (const char *xlator_name, int32_t *success_children, struct iatt *bufs, unsigned int child_count, const char *path) { - int gfid_miss_count = 0; + unsigned int gfid_miss_count = 0; int i = 0; struct iatt *child1 = NULL; diff --git a/xlators/cluster/afr/src/afr-self-heal-common.c b/xlators/cluster/afr/src/afr-self-heal-common.c index 8f50c6251..d1456d936 100644 --- a/xlators/cluster/afr/src/afr-self-heal-common.c +++ b/xlators/cluster/afr/src/afr-self-heal-common.c @@ -993,6 +993,37 @@ afr_sh_missing_entries_finish (call_frame_t *frame, xlator_t *this) return 0; } +int +afr_sh_common_create (afr_self_heal_t *sh, unsigned int child_count) +{ + int ret = -ENOMEM; + sh->buf = GF_CALLOC (child_count, sizeof (*sh->buf), + gf_afr_mt_iatt); + if (!sh->buf) + goto out; + sh->parentbufs = GF_CALLOC (child_count, sizeof (*sh->parentbufs), + gf_afr_mt_iatt); + if (!sh->parentbufs) + goto out; + sh->child_errno = GF_CALLOC (child_count, sizeof (*sh->child_errno), + gf_afr_mt_int); + if (!sh->child_errno) + goto out; + sh->success_children = afr_children_create (child_count); + if (!sh->success_children) + goto out; + sh->fresh_children = afr_children_create (child_count); + if (!sh->fresh_children) + goto out; + sh->xattr = GF_CALLOC (child_count, sizeof (*sh->xattr), + gf_afr_mt_dict_t); + if (!sh->xattr) + goto out; + ret = 0; +out: + return ret; +} + void afr_sh_common_lookup_resp_handler (call_frame_t *frame, void *cookie, xlator_t *this, @@ -1049,6 +1080,56 @@ afr_valid_ia_type (ia_type_t ia_type) return _gf_false; } +int +afr_impunge_frame_create (call_frame_t *frame, xlator_t *this, + int active_source, int ret_child, mode_t entry_mode, + call_frame_t **impunge_frame) +{ + afr_local_t *local = NULL; + afr_local_t *impunge_local = NULL; + afr_self_heal_t *sh = NULL; + afr_self_heal_t *impunge_sh = NULL; + int32_t op_errno = 0; + afr_private_t *priv = NULL; + int ret = 0; + call_frame_t *new_frame = NULL; + + op_errno = ENOMEM; + priv = this->private; + new_frame = copy_frame (frame); + if (!new_frame) { + goto out; + } + + ALLOC_OR_GOTO (impunge_local, afr_local_t, out); + + local = frame->local; + sh = &local->self_heal; + new_frame->local = impunge_local; + impunge_sh = &impunge_local->self_heal; + impunge_sh->sh_frame = frame; + impunge_sh->active_source = active_source; + impunge_sh->impunge_ret_child = ret_child; + impunge_sh->impunging_entry_mode = entry_mode; + impunge_local->child_up = memdup (local->child_up, + sizeof (*local->child_up) * + priv->child_count); + if (!impunge_local->child_up) + goto out; + + ret = afr_sh_common_create (impunge_sh, priv->child_count); + if (ret) { + op_errno = -ret; + goto out; + } + op_errno = 0; + *impunge_frame = new_frame; +out: + if (op_errno && new_frame) + AFR_STACK_DESTROY (new_frame); + return -op_errno; +} + void afr_sh_call_entry_impunge_recreate (call_frame_t *frame, xlator_t *this, int child_index, struct iatt *buf, @@ -1059,26 +1140,17 @@ afr_sh_call_entry_impunge_recreate (call_frame_t *frame, xlator_t *this, afr_local_t *local = NULL; afr_local_t *impunge_local = NULL; afr_self_heal_t *sh = NULL; - afr_self_heal_t *impunge_sh = NULL; - int32_t op_errno = 0; - - impunge_frame = copy_frame (frame); - if (!impunge_frame) { - op_errno = ENOMEM; - goto out; - } - - ALLOC_OR_GOTO (impunge_local, afr_local_t, out); + int ret = 0; + mode_t mode = 0; local = frame->local; - sh = &local->self_heal; - impunge_frame->local = impunge_local; - impunge_sh = &impunge_local->self_heal; - impunge_sh->sh_frame = frame; - impunge_sh->active_source = sh->source; - impunge_sh->impunging_entry_mode = st_mode_from_ia (buf->ia_prot, - buf->ia_type); - impunge_sh->impunge_ret_child = child_index; + sh = &local->self_heal; + mode = st_mode_from_ia (buf->ia_prot, buf->ia_type); + ret = afr_impunge_frame_create (frame, this, sh->source, child_index, + mode, &impunge_frame); + if (ret) + goto out; + impunge_local = impunge_frame->local; loc_copy (&impunge_local->loc, &local->loc); sh->impunge_done = impunge_done; impunge_local->call_count = 1; @@ -1087,8 +1159,8 @@ afr_sh_call_entry_impunge_recreate (call_frame_t *frame, xlator_t *this, return; out: gf_log (this->name, GF_LOG_ERROR, "impunge of %s failed, reason: %s", - local->loc.path, strerror (op_errno)); - impunge_done (frame, this, child_index, -1, op_errno); + local->loc.path, strerror (-ret)); + impunge_done (frame, this, child_index, -1, -ret); } int @@ -1165,12 +1237,12 @@ out: } void -afr_sh_missing_entries_lookup_done (call_frame_t *frame, xlator_t *this) +afr_sh_missing_entries_lookup_done (call_frame_t *frame, xlator_t *this, + int32_t op_ret, int32_t op_errno) { afr_local_t *local = NULL; afr_self_heal_t *sh = NULL; afr_private_t *priv = NULL; - int32_t op_errno = 0; ia_type_t ia_type = IA_INVAL; int32_t nsources = 0; @@ -1178,23 +1250,10 @@ afr_sh_missing_entries_lookup_done (call_frame_t *frame, xlator_t *this) sh = &local->self_heal; priv = this->private; - if (afr_get_children_count (sh->success_children, - priv->child_count) == 0) { - op_errno = afr_resultant_errno_get (NULL, sh->child_errno, - priv->child_count); - goto out; - } - - if (afr_gfid_missing_count (this->name, sh->success_children, - sh->buf, priv->child_count, - local->loc.path) || - afr_conflicting_iattrs (sh->buf, sh->success_children, - priv->child_count, local->loc.path, - this->name)) { - //this can happen if finding the fresh parent dir failed - local->govinda_gOvinda = 1; - sh->op_failed = 1; - op_errno = EIO; + if (op_ret < 0) { + if (op_errno == EIO) + local->govinda_gOvinda = 1; + // EIO can happen if finding the fresh parent dir failed goto out; } @@ -1227,31 +1286,68 @@ afr_sh_missing_entries_lookup_done (call_frame_t *frame, xlator_t *this) sh_missing_entries_create (frame, this); return; out: + sh->op_failed = 1; afr_sh_set_error (sh, op_errno); afr_sh_missing_entries_finish (frame, this); return; } static int -afr_sh_missing_entries_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_sh_common_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) { int call_count = 0; afr_local_t *local = NULL; + afr_self_heal_t *sh = NULL; + afr_private_t *priv = NULL; local = frame->local; + sh = &local->self_heal; + priv = this->private; afr_sh_common_lookup_resp_handler (frame, cookie, this, op_ret, op_errno, inode, buf, xattr, - postparent, &local->loc); + postparent, &sh->lookup_loc); call_count = afr_frame_return (frame); - if (call_count == 0) - afr_sh_missing_entries_lookup_done (frame, this); + if (call_count) + goto out; + op_ret = -1; + if (!sh->success_count) { + op_errno = afr_resultant_errno_get (NULL, sh->child_errno, + priv->child_count); + gf_log (this->name, GF_LOG_ERROR, "Failed to lookup %s, " + "reason %s", sh->lookup_loc.path, + strerror (op_errno)); + goto done; + } + if ((sh->lookup_flags & AFR_LOOKUP_FAIL_CONFLICTS) && + (afr_conflicting_iattrs (sh->buf, sh->success_children, + priv->child_count, + sh->lookup_loc.path, this->name))) { + op_errno = EIO; + gf_log (this->name, GF_LOG_ERROR, "Conflicting entries " + "for %s", sh->lookup_loc.path); + goto done; + } + + if ((sh->lookup_flags & AFR_LOOKUP_FAIL_MISSING_GFIDS) && + (afr_gfid_missing_count (this->name, sh->success_children, + sh->buf, priv->child_count, + sh->lookup_loc.path))) { + op_errno = ENODATA; + gf_log (this->name, GF_LOG_ERROR, "Missing Gfids " + "for %s", sh->lookup_loc.path); + goto done; + } + op_ret = 0; + +done: + sh->lookup_done (frame, this, op_ret, op_errno); +out: return 0; } @@ -1354,8 +1450,10 @@ afr_sh_purge_stale_entries_done (call_frame_t *frame, xlator_t *this) sh->buf, priv->child_count, local->loc.path)) { afr_sh_common_lookup (frame, this, &local->loc, - afr_sh_missing_entries_lookup_cbk, - _gf_true); + afr_sh_missing_entries_lookup_done, + sh->sh_gfid_req, + AFR_LOOKUP_FAIL_CONFLICTS| + AFR_LOOKUP_FAIL_MISSING_GFIDS); } else { //No need to set gfid so goto missing entries lookup done //Behave as if you have done the lookup @@ -1366,7 +1464,7 @@ afr_sh_purge_stale_entries_done (call_frame_t *frame, xlator_t *this) afr_children_copy (sh->success_children, sh->fresh_children, priv->child_count); - afr_sh_missing_entries_lookup_done (frame, this); + afr_sh_missing_entries_lookup_done (frame, this, 0, 0); } } return 0; @@ -1521,35 +1619,34 @@ afr_sh_save_child_iatts_from_policy (int32_t *children, struct iatt *bufs, } void -afr_sh_children_lookup_done (call_frame_t *frame, xlator_t *this) +afr_get_children_of_fresh_parent_dirs (afr_self_heal_t *sh, + unsigned int child_count) +{ + afr_children_intersection_get (sh->success_children, + sh->fresh_parent_dirs, + sh->sources, child_count); + afr_get_fresh_children (sh->success_children, sh->sources, + sh->fresh_children, child_count); + memset (sh->sources, 0, sizeof (*sh->sources) * child_count); +} + +void +afr_sh_children_lookup_done (call_frame_t *frame, xlator_t *this, + int32_t op_ret, int32_t op_errno) { afr_local_t *local = NULL; afr_self_heal_t *sh = NULL; afr_private_t *priv = NULL; int32_t fresh_child_enoents = 0; int32_t fresh_parent_count = 0; - int32_t op_errno = 0; local = frame->local; sh = &local->self_heal; priv = this->private; - if (afr_get_children_count (sh->success_children, - priv->child_count) == 0) { - op_errno = afr_resultant_errno_get (NULL, sh->child_errno, - priv->child_count); + if (op_ret < 0) goto fail; - } - - //make intersection of (success_children & fresh_parent_dirs) fresh_children - //the other success_children will be added to it if they are not stale - afr_children_intersection_get (sh->success_children, - sh->fresh_parent_dirs, - sh->sources, priv->child_count); - afr_get_fresh_children (sh->success_children, sh->sources, - sh->fresh_children, priv->child_count); - memset (sh->sources, 0, sizeof (*sh->sources) * priv->child_count); - + afr_get_children_of_fresh_parent_dirs (sh, priv->child_count); fresh_parent_count = afr_get_children_count (sh->fresh_parent_dirs, priv->child_count); //we need the enoent count of the subvols present in fresh_parent_dirs @@ -1581,35 +1678,15 @@ afr_sh_children_lookup_done (call_frame_t *frame, xlator_t *this) return; fail: + sh->op_failed = 1; afr_sh_set_error (sh, op_errno); afr_sh_missing_entries_finish (frame, this); return; } -static int -afr_sh_children_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) -{ - int call_count = 0; - afr_local_t *local = NULL; - - local = frame->local; - - afr_sh_common_lookup_resp_handler (frame, cookie, this, op_ret, - op_errno, inode, buf, xattr, - postparent, &local->loc); - call_count = afr_frame_return (frame); - - if (call_count == 0) - afr_sh_children_lookup_done (frame, this); - - return 0; -} - -static int -afr_sh_find_fresh_parents (call_frame_t *frame, xlator_t *this) +static void +afr_sh_find_fresh_parents (call_frame_t *frame, xlator_t *this, + int32_t op_ret, int32_t op_errno) { afr_self_heal_t *sh = NULL; afr_private_t *priv = NULL; @@ -1632,28 +1709,14 @@ afr_sh_find_fresh_parents (call_frame_t *frame, xlator_t *this) * create so fail with EIO, * If there are conflicting xattr fail with EIO. */ - if (afr_get_children_count (sh->success_children, - priv->child_count) == 0) { - gf_log (this->name, GF_LOG_ERROR, "Parent dir lookup failed " - "for %s, in missing entry self-heal, continuing with " - "the rest of the self-heals", local->loc.path); + if (op_ret < 0) goto out; - } - enoent_count = afr_errno_count (NULL, sh->child_errno, priv->child_count, ENOENT); if (enoent_count > 0) { - gf_log (this->name, GF_LOG_INFO, "Parent dir missing for %s," - " in missing entry self-heal, continuing with the rest" - " of the self-heals", local->loc.path); - goto out; - } - - if (afr_conflicting_iattrs (sh->buf, sh->success_children, - priv->child_count, sh->parent_loc.path, - this->name)) { - gf_log (this->name, GF_LOG_INFO, "conflicting stat info for " - "parent dirs of %s", local->loc.path); + gf_log (this->name, GF_LOG_ERROR, "Parent dir missing for %s," + " in missing entry self-heal, aborting self-heal", + local->loc.path); goto out; } @@ -1662,9 +1725,9 @@ afr_sh_find_fresh_parents (call_frame_t *frame, xlator_t *this) sh->success_children, AFR_ENTRY_TRANSACTION); if (nsources < 0) { - gf_log (this->name, GF_LOG_INFO, "No sources for dir of %s," - " in missing entry self-heal, continuing with the rest" - " of the self-heals", local->loc.path); + gf_log (this->name, GF_LOG_ERROR, "No sources for dir of %s," + " in missing entry self-heal, aborting self-heal", + local->loc.path); goto out; } @@ -1677,39 +1740,14 @@ afr_sh_find_fresh_parents (call_frame_t *frame, xlator_t *this) afr_get_fresh_children (sh->success_children, sh->sources, sh->fresh_parent_dirs, priv->child_count); afr_sh_common_lookup (frame, this, &local->loc, - afr_sh_children_lookup_cbk, _gf_false); - return 0; + afr_sh_children_lookup_done, NULL, 0); + return; out: afr_sh_set_error (sh, EIO); sh->op_failed = 1; afr_sh_missing_entries_finish (frame, this); - return 0; -} - -int -afr_sh_conflicting_entry_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) -{ - int call_count = 0; - afr_local_t *local = NULL; - afr_self_heal_t *sh = NULL; - - local = frame->local; - sh = &local->self_heal; - - afr_sh_common_lookup_resp_handler (frame, cookie, this, op_ret, - op_errno, inode, buf, xattr, - postparent, &sh->parent_loc); - call_count = afr_frame_return (frame); - - if (call_count == 0) - afr_sh_find_fresh_parents (frame, this); - - return 0; + return; } void @@ -1727,6 +1765,7 @@ afr_sh_common_reset (afr_self_heal_t *sh, unsigned int child_count) afr_reset_children (sh->success_children, child_count); afr_reset_children (sh->fresh_children, child_count); afr_reset_xattr (sh->xattr, child_count); + loc_wipe (&sh->lookup_loc); } /* afr self-heal state will be lost if this call is made @@ -1734,7 +1773,8 @@ afr_sh_common_reset (afr_self_heal_t *sh, unsigned int child_count) */ int afr_sh_common_lookup (call_frame_t *frame, xlator_t *this, loc_t *loc, - afr_lookup_cbk_t lookup_cbk, gf_boolean_t set_gfid) + afr_lookup_done_cbk_t lookup_done , uuid_t gfid, + int32_t flags) { afr_local_t *local = NULL; int i = 0; @@ -1755,16 +1795,19 @@ afr_sh_common_lookup (call_frame_t *frame, xlator_t *this, loc_t *loc, if (xattr_req) { afr_xattr_req_prepare (this, xattr_req, loc->path); - if (set_gfid) { + if (gfid) { gf_log (this->name, GF_LOG_DEBUG, "looking up %s with gfid: %s", - loc->path, uuid_utoa (sh->sh_gfid_req)); - GF_ASSERT (!uuid_is_null (sh->sh_gfid_req)); - afr_set_dict_gfid (xattr_req, sh->sh_gfid_req); + loc->path, uuid_utoa (gfid)); + GF_ASSERT (!uuid_is_null (gfid)); + afr_set_dict_gfid (xattr_req, gfid); } } afr_sh_common_reset (sh, priv->child_count); + sh->lookup_done = lookup_done; + loc_copy (&sh->lookup_loc, loc); + sh->lookup_flags = flags; for (i = 0; i < priv->child_count; i++) { if (local->child_up[i]) { gf_log (this->name, GF_LOG_DEBUG, @@ -1772,7 +1815,7 @@ afr_sh_common_lookup (call_frame_t *frame, xlator_t *this, loc_t *loc, loc->path, priv->children[i]->name); STACK_WIND_COOKIE (frame, - lookup_cbk, + afr_sh_common_lookup_cbk, (void *) (long) i, priv->children[i], priv->children[i]->fops->lookup, @@ -1811,8 +1854,8 @@ afr_sh_post_nb_entrylk_conflicting_sh_cbk (call_frame_t *frame, xlator_t *this) gf_log (this->name, GF_LOG_DEBUG, "Non blocking entrylks done. Proceeding to FOP"); afr_sh_common_lookup (frame, this, &sh->parent_loc, - afr_sh_conflicting_entry_lookup_cbk, - _gf_false); + afr_sh_find_fresh_parents, + NULL, AFR_LOOKUP_FAIL_CONFLICTS); } return 0; @@ -1823,8 +1866,10 @@ afr_sh_post_nb_entrylk_gfid_sh_cbk (call_frame_t *frame, xlator_t *this) { afr_internal_lock_t *int_lock = NULL; afr_local_t *local = NULL; + afr_self_heal_t *sh = NULL; local = frame->local; + sh = &local->self_heal; int_lock = &local->internal_lock; if (int_lock->lock_op_ret < 0) { @@ -1835,8 +1880,9 @@ afr_sh_post_nb_entrylk_gfid_sh_cbk (call_frame_t *frame, xlator_t *this) gf_log (this->name, GF_LOG_DEBUG, "Non blocking entrylks done. Proceeding to FOP"); afr_sh_common_lookup (frame, this, &local->loc, - afr_sh_missing_entries_lookup_cbk, - _gf_true); + afr_sh_missing_entries_lookup_done, + sh->sh_gfid_req, AFR_LOOKUP_FAIL_CONFLICTS| + AFR_LOOKUP_FAIL_MISSING_GFIDS); } return 0; @@ -2038,30 +2084,19 @@ afr_self_heal (call_frame_t *frame, xlator_t *this, inode_t *inode) afr_self_heal_t *sh = NULL; afr_private_t *priv = NULL; int i = 0; + int32_t op_errno = 0; + int ret = 0; + afr_self_heal_t *orig_sh = NULL; call_frame_t *sh_frame = NULL; afr_local_t *sh_local = NULL; local = frame->local; + orig_sh = &local->self_heal; priv = this->private; GF_ASSERT (local->loc.path); - if (local->self_heal.background) { - LOCK (&priv->lock); - { - if (priv->background_self_heals_started - < priv->background_self_heal_count) { - priv->background_self_heals_started++; - - - } else { - local->self_heal.background = _gf_false; - } - } - UNLOCK (&priv->lock); - } - gf_log (this->name, GF_LOG_TRACE, "performing self heal on %s (metadata=%d data=%d entry=%d)", local->loc.path, @@ -2069,11 +2104,16 @@ afr_self_heal (call_frame_t *frame, xlator_t *this, inode_t *inode) local->self_heal.do_data_self_heal, local->self_heal.do_entry_self_heal); + op_errno = ENOMEM; sh_frame = copy_frame (frame); + if (!sh_frame) + goto out; afr_set_lk_owner (sh_frame, this); afr_set_low_priority (sh_frame); sh_local = afr_local_copy (local, this); + if (!sh_local) + goto out; sh_frame->local = sh_local; sh = &sh_local->self_heal; @@ -2083,42 +2123,67 @@ afr_self_heal (call_frame_t *frame, xlator_t *this, inode_t *inode) sh->completion_cbk = afr_self_heal_completion_cbk; - sh->buf = GF_CALLOC (priv->child_count, sizeof (struct iatt), - gf_afr_mt_iatt); - sh->parentbufs = GF_CALLOC (priv->child_count, sizeof (struct iatt), - gf_afr_mt_iatt); - sh->child_errno = GF_CALLOC (priv->child_count, sizeof (int), - gf_afr_mt_int); sh->success = GF_CALLOC (priv->child_count, sizeof (*sh->success), gf_afr_mt_char); - sh->xattr = GF_CALLOC (priv->child_count, sizeof (dict_t *), - gf_afr_mt_dict_t); + if (!sh->success) + goto out; sh->sources = GF_CALLOC (sizeof (*sh->sources), priv->child_count, gf_afr_mt_int); + if (!sh->sources) + goto out; sh->locked_nodes = GF_CALLOC (sizeof (*sh->locked_nodes), priv->child_count, gf_afr_mt_int); + if (!sh->locked_nodes) + goto out; sh->pending_matrix = GF_CALLOC (sizeof (int32_t *), priv->child_count, gf_afr_mt_int32_t); + if (!sh->pending_matrix) + goto out; for (i = 0; i < priv->child_count; i++) { sh->pending_matrix[i] = GF_CALLOC (sizeof (int32_t), priv->child_count, gf_afr_mt_int32_t); + if (!sh->pending_matrix[i]) + goto out; } sh->delta_matrix = GF_CALLOC (sizeof (int32_t *), priv->child_count, gf_afr_mt_int32_t); + if (!sh->delta_matrix) + goto out; for (i = 0; i < priv->child_count; i++) { sh->delta_matrix[i] = GF_CALLOC (sizeof (int32_t), priv->child_count, gf_afr_mt_int32_t); + if (!sh->delta_matrix) + goto out; } - sh->success_children = afr_children_create (priv->child_count); - sh->fresh_children = afr_children_create (priv->child_count); sh->fresh_parent_dirs = afr_children_create (priv->child_count); + if (!sh->fresh_parent_dirs) + goto out; + ret = afr_sh_common_create (sh, priv->child_count); + if (ret) { + op_errno = -ret; + goto out; + } + if (local->self_heal.background) { + LOCK (&priv->lock); + { + if (priv->background_self_heals_started + < priv->background_self_heal_count) { + priv->background_self_heals_started++; + + + } else { + local->self_heal.background = _gf_false; + } + } + UNLOCK (&priv->lock); + } FRAME_SU_DO (sh_frame, afr_local_t); if (sh->do_missing_entry_self_heal) { @@ -2133,7 +2198,12 @@ afr_self_heal (call_frame_t *frame, xlator_t *this, inode_t *inode) afr_sh_missing_entries_done (sh_frame, this); } + op_errno = 0; +out: + if (op_errno) { + orig_sh->unwind (frame, this, -1, op_errno); + } return 0; } @@ -2187,3 +2257,47 @@ afr_self_heal_type_for_transaction (afr_transaction_type type) } return sh_type; } + +int +afr_build_child_loc (xlator_t *this, loc_t *child, loc_t *parent, char *name) +{ + int ret = -1; + + if (!child) { + goto out; + } + + if (strcmp (parent->path, "/") == 0) + ret = gf_asprintf ((char **)&child->path, "/%s", name); + else + ret = gf_asprintf ((char **)&child->path, "%s/%s", parent->path, + name); + + if (-1 == ret) { + gf_log (this->name, GF_LOG_ERROR, + "asprintf failed while setting child path"); + } + + if (!child->path) { + goto out; + } + + child->name = strrchr (child->path, '/'); + if (child->name) + child->name++; + + child->parent = inode_ref (parent->inode); + child->inode = inode_new (parent->inode->table); + + if (!child->inode) { + ret = -1; + goto out; + } + + ret = 0; +out: + if (ret == -1) + loc_wipe (child); + + return ret; +} diff --git a/xlators/cluster/afr/src/afr-self-heal-common.h b/xlators/cluster/afr/src/afr-self-heal-common.h index 3df5f0a0a..bc0dcd78c 100644 --- a/xlators/cluster/afr/src/afr-self-heal-common.h +++ b/xlators/cluster/afr/src/afr-self-heal-common.h @@ -29,11 +29,11 @@ typedef enum { AFR_SELF_HEAL_INVALID = -1, } afr_self_heal_type; -typedef int -(*afr_lookup_cbk_t) (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); +typedef enum { + AFR_LOOKUP_FAIL_CONFLICTS = 1, + AFR_LOOKUP_FAIL_MISSING_GFIDS = 2, +} afr_lookup_flags_t; + int afr_sh_select_source (int sources[], int child_count); @@ -93,7 +93,8 @@ afr_sh_common_lookup_resp_handler (call_frame_t *frame, void *cookie, int afr_sh_common_lookup (call_frame_t *frame, xlator_t *this, loc_t *loc, - afr_lookup_cbk_t lookup_cbk, gf_boolean_t set_gfid); + afr_lookup_done_cbk_t lookup_cbk, uuid_t uuid, + int32_t flags); int afr_sh_entry_expunge_remove (call_frame_t *expunge_frame, xlator_t *this, int active_src, struct iatt *buf); @@ -122,4 +123,10 @@ typedef int (*afr_fxattrop_cbk_t) (call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, int32_t op_errno, dict_t *xattr); +int +afr_build_child_loc (xlator_t *this, loc_t *child, loc_t *parent, char *name); +int +afr_impunge_frame_create (call_frame_t *frame, xlator_t *this, + int active_source, int ret_child, mode_t entry_mode, + call_frame_t **impunge_frame); #endif /* __AFR_SELF_HEAL_COMMON_H__ */ diff --git a/xlators/cluster/afr/src/afr-self-heal-entry.c b/xlators/cluster/afr/src/afr-self-heal-entry.c index 356b15e63..af41c480e 100644 --- a/xlators/cluster/afr/src/afr-self-heal-entry.c +++ b/xlators/cluster/afr/src/afr-self-heal-entry.c @@ -49,6 +49,15 @@ #include "afr-self-heal.h" #include "afr-self-heal-common.h" +#define AFR_INIT_SH_FRAME_VALS(_frame, _local, _sh, _sh_frame, _sh_local, _sh_sh)\ + do {\ + _local = _frame->local;\ + _sh = &_local->self_heal;\ + _sh_frame = _sh->sh_frame;\ + _sh_local = _sh_frame->local;\ + _sh_sh = &_sh_local->self_heal;\ + } while (0); + int afr_sh_entry_done (call_frame_t *frame, xlator_t *this) { @@ -298,51 +307,6 @@ next_active_sink (call_frame_t *frame, xlator_t *this, return next_active_sink; } - -int -build_child_loc (xlator_t *this, loc_t *child, loc_t *parent, char *name) -{ - int ret = -1; - - if (!child) { - goto out; - } - - if (strcmp (parent->path, "/") == 0) - ret = gf_asprintf ((char **)&child->path, "/%s", name); - else - ret = gf_asprintf ((char **)&child->path, "%s/%s", parent->path, - name); - - if (-1 == ret) { - gf_log (this->name, GF_LOG_ERROR, - "asprintf failed while setting child path"); - } - - if (!child->path) { - goto out; - } - - child->name = strrchr (child->path, '/'); - if (child->name) - child->name++; - - child->parent = inode_ref (parent->inode); - child->inode = inode_new (parent->inode->table); - - if (!child->inode) { - goto out; - } - - ret = 0; -out: - if (ret == -1) - loc_wipe (child); - - return ret; -} - - int afr_sh_entry_impunge_all (call_frame_t *frame, xlator_t *this); @@ -757,7 +721,7 @@ afr_sh_entry_expunge_entry (call_frame_t *frame, xlator_t *this, expunge_sh->active_source = active_src; expunge_sh->entrybuf = entry->d_stat; - ret = build_child_loc (this, &expunge_local->loc, &local->loc, name); + ret = afr_build_child_loc (this, &expunge_local->loc, &local->loc, name); if (ret != 0) { op_errno = EINVAL; goto out; @@ -923,6 +887,27 @@ afr_sh_entry_impunge_entry_done (call_frame_t *frame, xlator_t *this, return 0; } +void +afr_sh_entry_call_impunge_done (call_frame_t *impunge_frame, xlator_t *this, + int32_t op_ret, int32_t op_errno) +{ + afr_local_t *impunge_local = NULL; + afr_local_t *local = NULL; + afr_self_heal_t *sh = NULL; + afr_self_heal_t *impunge_sh = NULL; + call_frame_t *frame = NULL; + int32_t impunge_ret_child = 0; + afr_private_t *priv = NULL; + + priv = this->private; + AFR_INIT_SH_FRAME_VALS (impunge_frame, impunge_local, impunge_sh, + frame, local, sh); + + impunge_ret_child = impunge_sh->impunge_ret_child; + AFR_STACK_DESTROY (impunge_frame); + sh->impunge_done (frame, this, impunge_ret_child, op_ret, + op_errno); +} int afr_sh_entry_impunge_setattr_cbk (call_frame_t *impunge_frame, void *cookie, @@ -933,19 +918,12 @@ afr_sh_entry_impunge_setattr_cbk (call_frame_t *impunge_frame, void *cookie, int call_count = 0; afr_private_t *priv = NULL; afr_local_t *impunge_local = NULL; - afr_local_t *local = NULL; - afr_self_heal_t *sh = NULL; afr_self_heal_t *impunge_sh = NULL; - call_frame_t *frame = NULL; int child_index = 0; - int32_t impunge_ret_child = 0; priv = this->private; impunge_local = impunge_frame->local; impunge_sh = &impunge_local->self_heal; - frame = impunge_sh->sh_frame; - local = frame->local; - sh = &local->self_heal; child_index = (long) cookie; if (op_ret == 0) { @@ -967,12 +945,9 @@ afr_sh_entry_impunge_setattr_cbk (call_frame_t *impunge_frame, void *cookie, } UNLOCK (&impunge_frame->lock); - if (call_count == 0) { - impunge_ret_child = impunge_sh->impunge_ret_child; - AFR_STACK_DESTROY (impunge_frame); - sh->impunge_done (frame, this, impunge_ret_child, op_ret, - op_errno); - } + if (call_count == 0) + afr_sh_entry_call_impunge_done (impunge_frame, this, + op_ret, op_errno); return 0; } @@ -1053,7 +1028,6 @@ afr_sh_entry_impunge_parent_setattr_cbk (call_frame_t *setattr_frame, return 0; } - int afr_sh_entry_impunge_newfile_cbk (call_frame_t *impunge_frame, void *cookie, xlator_t *this, @@ -1066,27 +1040,20 @@ afr_sh_entry_impunge_newfile_cbk (call_frame_t *impunge_frame, void *cookie, afr_private_t *priv = NULL; afr_local_t *impunge_local = NULL; afr_self_heal_t *impunge_sh = NULL; - call_frame_t *frame = NULL; int active_src = 0; int child_index = 0; int32_t *pending_array = NULL; dict_t *xattr = NULL; int ret = 0; int idx = 0; - afr_local_t *local = NULL; - afr_self_heal_t *sh = NULL; call_frame_t *setattr_frame = NULL; int32_t valid = 0; loc_t *parent_loc = NULL; struct iatt parentbuf = {0,}; - int32_t impunge_ret_child = 0; priv = this->private; impunge_local = impunge_frame->local; impunge_sh = &impunge_local->self_heal; - frame = impunge_sh->sh_frame; - local = frame->local; - sh = &local->self_heal; active_src = impunge_sh->active_source; child_index = (long) cookie; @@ -1172,12 +1139,9 @@ out: } UNLOCK (&impunge_frame->lock); - if (call_count == 0) { - impunge_ret_child = impunge_sh->impunge_ret_child; - AFR_STACK_DESTROY (impunge_frame); - sh->impunge_done (frame, this, impunge_ret_child, -1, - op_errno); - } + if (call_count == 0) + afr_sh_entry_call_impunge_done (impunge_frame, this, + -1, op_errno); } return 0; @@ -1205,6 +1169,7 @@ afr_sh_entry_impunge_mknod (call_frame_t *impunge_frame, xlator_t *this, if (!dict) gf_log (this->name, GF_LOG_ERROR, "Out of memory"); + GF_ASSERT (!uuid_is_null (stbuf->ia_gfid)); ret = afr_set_dict_gfid (dict, stbuf->ia_gfid); if (ret) gf_log (this->name, GF_LOG_INFO, "%s: gfid set failed", @@ -1247,6 +1212,7 @@ afr_sh_entry_impunge_mkdir (call_frame_t *impunge_frame, xlator_t *this, return 0; } + GF_ASSERT (!uuid_is_null (stbuf->ia_gfid)); ret = afr_set_dict_gfid (dict, stbuf->ia_gfid); if (ret) gf_log (this->name, GF_LOG_INFO, "%s: gfid set failed", @@ -1281,32 +1247,22 @@ afr_sh_entry_impunge_symlink (call_frame_t *impunge_frame, xlator_t *this, dict_t *dict = NULL; struct iatt *buf = NULL; int ret = 0; - call_frame_t *frame = NULL; - afr_local_t *local = NULL; - afr_self_heal_t *sh = NULL; afr_self_heal_t *impunge_sh = NULL; - int32_t impunge_ret_child = 0; priv = this->private; impunge_local = impunge_frame->local; impunge_sh = &impunge_local->self_heal; - frame = impunge_sh->sh_frame; - local = frame->local; - sh = &local->self_heal; buf = &impunge_local->cont.symlink.buf; dict = dict_new (); if (!dict) { - gf_log (this->name, GF_LOG_ERROR, - "Out of memory"); - impunge_ret_child = impunge_sh->impunge_ret_child; - AFR_STACK_DESTROY (impunge_frame); - sh->impunge_done (impunge_frame, this, impunge_ret_child, -1, - ENOMEM); + afr_sh_entry_call_impunge_done (impunge_frame, this, + -1, ENOMEM); goto out; } + GF_ASSERT (!uuid_is_null (buf->ia_gfid)); ret = afr_set_dict_gfid (dict, buf->ia_gfid); if (ret) gf_log (this->name, GF_LOG_INFO, @@ -1342,18 +1298,11 @@ afr_sh_entry_impunge_symlink_unlink_cbk (call_frame_t *impunge_frame, afr_local_t *impunge_local = NULL; afr_self_heal_t *impunge_sh = NULL; int child_index = -1; - call_frame_t *frame = NULL; int call_count = -1; - afr_local_t *local = NULL; - afr_self_heal_t *sh = NULL; - int32_t impunge_ret_child = 0; priv = this->private; impunge_local = impunge_frame->local; impunge_sh = &impunge_local->self_heal; - frame = impunge_sh->sh_frame; - local = frame->local; - sh = &local->self_heal; child_index = (long) cookie; @@ -1377,12 +1326,9 @@ out: } UNLOCK (&impunge_frame->lock); - if (call_count == 0) { - impunge_ret_child = impunge_sh->impunge_ret_child; - AFR_STACK_DESTROY (impunge_frame); - sh->impunge_done (frame, this, impunge_ret_child, op_ret, - op_errno); - } + if (call_count == 0) + afr_sh_entry_call_impunge_done (impunge_frame, this, + op_ret, op_errno); return 0; } @@ -1423,19 +1369,12 @@ afr_sh_entry_impunge_readlink_sink_cbk (call_frame_t *impunge_frame, void *cooki afr_local_t *impunge_local = NULL; afr_self_heal_t *impunge_sh = NULL; int child_index = -1; - call_frame_t *frame = NULL; int call_count = -1; int active_src = -1; - afr_local_t *local = NULL; - afr_self_heal_t *sh = NULL; - int32_t impunge_ret_child = 0; priv = this->private; impunge_local = impunge_frame->local; impunge_sh = &impunge_local->self_heal; - frame = impunge_sh->sh_frame; - local = frame->local; - sh = &local->self_heal; active_src = impunge_sh->active_source; child_index = (long) cookie; @@ -1480,12 +1419,9 @@ out: } UNLOCK (&impunge_frame->lock); - if (call_count == 0) { - impunge_ret_child = impunge_sh->impunge_ret_child; - AFR_STACK_DESTROY (impunge_frame); - sh->impunge_done (frame, this, impunge_ret_child, op_ret, - op_errno); - } + if (call_count == 0) + afr_sh_entry_call_impunge_done (impunge_frame, this, + op_ret, op_errno); return 0; } @@ -1525,19 +1461,12 @@ afr_sh_entry_impunge_readlink_cbk (call_frame_t *impunge_frame, void *cookie, afr_local_t *impunge_local = NULL; afr_self_heal_t *impunge_sh = NULL; int child_index = -1; - call_frame_t *frame = NULL; int call_count = -1; int active_src = -1; - afr_local_t *local = NULL; - afr_self_heal_t *sh = NULL; - int32_t impunge_ret_child = 0; priv = this->private; impunge_local = impunge_frame->local; impunge_sh = &impunge_local->self_heal; - frame = impunge_sh->sh_frame; - local = frame->local; - sh = &local->self_heal; active_src = impunge_sh->active_source; child_index = (long) cookie; @@ -1563,12 +1492,9 @@ out: } UNLOCK (&impunge_frame->lock); - if (call_count == 0) { - impunge_ret_child = impunge_sh->impunge_ret_child; - AFR_STACK_DESTROY (impunge_frame); - sh->impunge_done (frame, this, impunge_ret_child, op_ret, - op_errno); - } + if (call_count == 0) + afr_sh_entry_call_impunge_done (impunge_frame, this, + op_ret, op_errno); return 0; } @@ -1648,175 +1574,162 @@ afr_sh_entry_impunge_create (call_frame_t *impunge_frame, xlator_t *this, return ret; } -int -afr_sh_entry_impunge_recreate_lookup_cbk (call_frame_t *impunge_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) +gf_boolean_t +afr_sh_need_recreate (afr_self_heal_t *impunge_sh, int *sources, + unsigned int child, unsigned int child_count) { - afr_private_t *priv = NULL; - afr_local_t *impunge_local = NULL; - afr_local_t *local = NULL; - afr_self_heal_t *impunge_sh = NULL; - afr_self_heal_t *sh = NULL; - int active_src = 0; - int child_index = 0; - call_frame_t *frame = NULL; - int call_count = 0; - int ret = 0; - int32_t impunge_ret_child = 0; + int32_t *success_children = NULL; + gf_boolean_t recreate = _gf_false; - priv = this->private; - impunge_local = impunge_frame->local; - impunge_sh = &impunge_local->self_heal; - frame = impunge_sh->sh_frame; - local = frame->local; - sh = &local->self_heal; - - child_index = (long) cookie; + GF_ASSERT (impunge_sh->impunging_entry_mode); + GF_ASSERT (impunge_sh->child_errno); + GF_ASSERT (sources); - active_src = impunge_sh->active_source; - - if (op_ret != 0) { - gf_log (this->name, GF_LOG_DEBUG, - "looking up %s on %s (for %s) failed (%s)", - impunge_local->loc.path, - priv->children[active_src]->name, - priv->children[child_index]->name, - strerror (op_errno)); + success_children = impunge_sh->success_children; + if (sources[child] || (child == impunge_sh->active_source)) { + GF_ASSERT (afr_is_child_present (success_children, + child_count, child)); goto out; } - ret = afr_sh_entry_impunge_create (impunge_frame, this, child_index, buf, - postparent); - if (ret) + if (IA_ISLNK (impunge_sh->impunging_entry_mode)) { + recreate = _gf_true; goto out; + } - return 0; - + if (impunge_sh->child_errno[child] == ENOENT) + recreate = _gf_true; out: - LOCK (&impunge_frame->lock); - { - call_count = --impunge_local->call_count; - } - UNLOCK (&impunge_frame->lock); + return recreate; +} - if (call_count == 0) { - impunge_ret_child = impunge_sh->impunge_ret_child; - AFR_STACK_DESTROY (impunge_frame); - sh->impunge_done (frame, this, impunge_ret_child, op_ret, - op_errno); +unsigned int +afr_sh_recreate_count (afr_self_heal_t *impunge_sh, int *sources, + unsigned int child_count) +{ + int count = 0; + int i = 0; + + for (i = 0; i < child_count; i++) { + if (afr_sh_need_recreate (impunge_sh, sources, i, child_count)) + count++; } - return 0; + return count; } - int -afr_sh_entry_impunge_recreate (call_frame_t *impunge_frame, xlator_t *this, - int child_index) +afr_sh_entry_call_impunge_recreate (call_frame_t *impunge_frame, + xlator_t *this) { afr_private_t *priv = NULL; afr_local_t *impunge_local = NULL; afr_self_heal_t *impunge_sh = NULL; + call_frame_t *frame = NULL; + afr_local_t *local = NULL; + afr_self_heal_t *sh = NULL; + struct iatt *buf = NULL; + struct iatt *postparent = NULL; + unsigned int recreate_count = 0; + int i = 0; int active_src = 0; + priv = this->private; + AFR_INIT_SH_FRAME_VALS (impunge_frame, impunge_local, impunge_sh, + frame, local, sh); + active_src = impunge_sh->active_source; + buf = &impunge_sh->buf[active_src]; + postparent = &impunge_sh->parentbufs[active_src]; - priv = this->private; - impunge_local = impunge_frame->local; - impunge_sh = &impunge_local->self_heal; - - active_src = impunge_sh->active_source; - - STACK_WIND_COOKIE (impunge_frame, - afr_sh_entry_impunge_recreate_lookup_cbk, - (void *) (long) child_index, - priv->children[active_src], - priv->children[active_src]->fops->lookup, - &impunge_local->loc, 0); - + recreate_count = afr_sh_recreate_count (impunge_sh, sh->sources, + priv->child_count); + GF_ASSERT (recreate_count); + impunge_local->call_count = recreate_count; + for (i = 0; i < priv->child_count; i++) { + if (afr_sh_need_recreate (impunge_sh, sh->sources, i, + priv->child_count)) { + (void)afr_sh_entry_impunge_create (impunge_frame, this, + i, buf, + postparent); + recreate_count--; + } + } + GF_ASSERT (!recreate_count); return 0; } - -int -afr_sh_entry_impunge_entry_cbk (call_frame_t *impunge_frame, void *cookie, - xlator_t *this, - int32_t op_ret, int32_t op_errno, - inode_t *inode, struct iatt *buf, dict_t *x, - struct iatt *postparent) +void +afr_sh_entry_common_lookup_done (call_frame_t *impunge_frame, xlator_t *this, + int32_t op_ret, int32_t op_errno) { afr_private_t *priv = NULL; afr_local_t *impunge_local = NULL; afr_self_heal_t *impunge_sh = NULL; - int call_count = 0; - int child_index = 0; call_frame_t *frame = NULL; afr_local_t *local = NULL; afr_self_heal_t *sh = NULL; - int32_t impunge_ret_child = 0; - - priv = this->private; - impunge_local = impunge_frame->local; - impunge_sh = &impunge_local->self_heal; - frame = impunge_sh->sh_frame; - local = frame->local; - sh = &local->self_heal; - child_index = (long) cookie; - - if ((op_ret == -1 && op_errno == ENOENT) - || (IA_ISLNK (impunge_sh->impunging_entry_mode))) { - - /* - * A symlink's target might have changed, so - * always go down the recreate path for them. - */ - - /* decrease call_count in recreate-callback */ - - gf_log (this->name, GF_LOG_TRACE, - "missing entry %s on %s", - impunge_local->loc.path, - priv->children[child_index]->name); - - afr_sh_entry_impunge_recreate (impunge_frame, this, - child_index); - return 0; - } + unsigned int recreate_count = 0; + unsigned int gfid_miss_count = 0; + unsigned int children_up_count = 0; + uuid_t gfid = {0}; + int active_src = 0; - if (op_ret == 0) { - gf_log (this->name, GF_LOG_TRACE, - "%s exists under %s", - impunge_local->loc.path, - priv->children[child_index]->name); + priv = this->private; + AFR_INIT_SH_FRAME_VALS (impunge_frame, impunge_local, impunge_sh, + frame, local, sh); + active_src = impunge_sh->active_source; - impunge_sh->parentbuf = *postparent; + if (op_ret < 0) + goto done; + if (impunge_sh->child_errno[active_src]) { + op_ret = -1; + op_errno = impunge_sh->child_errno[active_src]; + goto done; + } + + gfid_miss_count = afr_gfid_missing_count (this->name, + impunge_sh->success_children, + impunge_sh->buf, priv->child_count, + impunge_local->loc.path); + children_up_count = afr_up_children_count (impunge_local->child_up, + priv->child_count); + if ((gfid_miss_count == children_up_count) && + (children_up_count < priv->child_count)) { + op_ret = -1; + op_errno = ENODATA; + gf_log (this->name, GF_LOG_ERROR, "Not all children are up, " + "gfid should not be assigned in this state for %s", + impunge_local->loc.path); + goto done; + } + + if (gfid_miss_count) { + afr_update_gfid_from_iatts (gfid, impunge_sh->buf, + impunge_sh->success_children, + priv->child_count); + if (uuid_is_null (gfid)) + uuid_generate (gfid); + afr_sh_common_lookup (impunge_frame, this, &impunge_local->loc, + afr_sh_entry_common_lookup_done, gfid, + AFR_LOOKUP_FAIL_CONFLICTS | + AFR_LOOKUP_FAIL_MISSING_GFIDS); } else { - gf_log (this->name, GF_LOG_WARNING, - "looking up %s under %s failed (%s)", - impunge_local->loc.path, - priv->children[child_index]->name, - strerror (op_errno)); - } - - LOCK (&impunge_frame->lock); - { - call_count = --impunge_local->call_count; - } - UNLOCK (&impunge_frame->lock); - - if (call_count == 0) { - impunge_ret_child = impunge_sh->impunge_ret_child; - AFR_STACK_DESTROY (impunge_frame); - sh->impunge_done (frame, this, impunge_ret_child, op_ret, - op_errno); + recreate_count = afr_sh_recreate_count (impunge_sh, sh->sources, + priv->child_count); + if (!recreate_count) { + op_ret = 0; + op_errno = 0; + goto done; + } + afr_sh_entry_call_impunge_recreate (impunge_frame, this); } - - return 0; + return; +done: + afr_sh_entry_call_impunge_done (impunge_frame, this, + op_ret, op_errno); + return; } - int afr_sh_entry_impunge_entry (call_frame_t *frame, xlator_t *this, gf_dirent_t *entry) @@ -1827,12 +1740,10 @@ afr_sh_entry_impunge_entry (call_frame_t *frame, xlator_t *this, int ret = -1; call_frame_t *impunge_frame = NULL; afr_local_t *impunge_local = NULL; - afr_self_heal_t *impunge_sh = NULL; int active_src = 0; - int i = 0; - int call_count = 0; int op_errno = 0; int op_ret = -1; + mode_t entry_mode = 0; priv = this->private; local = frame->local; @@ -1857,70 +1768,34 @@ afr_sh_entry_impunge_entry (call_frame_t *frame, xlator_t *this, "inspecting existance of %s under %s", entry->d_name, local->loc.path); - impunge_frame = copy_frame (frame); - if (!impunge_frame) { - gf_log (this->name, GF_LOG_ERROR, - "Out of memory."); - op_errno = ENOMEM; + entry_mode = st_mode_from_ia (entry->d_stat.ia_prot, + entry->d_stat.ia_type); + ret = afr_impunge_frame_create (frame, this, active_src, active_src, + entry_mode, &impunge_frame); + if (ret) { + op_errno = -ret; goto out; } - ALLOC_OR_GOTO (impunge_local, afr_local_t, out); - - impunge_frame->local = impunge_local; - impunge_sh = &impunge_local->self_heal; - impunge_sh->sh_frame = frame; - impunge_sh->active_source = active_src; - impunge_sh->impunge_ret_child = active_src; - - impunge_sh->impunging_entry_mode = - st_mode_from_ia (entry->d_stat.ia_prot, entry->d_stat.ia_type); - - ret = build_child_loc (this, &impunge_local->loc, &local->loc, entry->d_name); + impunge_local = impunge_frame->local; + ret = afr_build_child_loc (this, &impunge_local->loc, &local->loc, + entry->d_name); if (ret != 0) { op_errno = ENOMEM; goto out; } - for (i = 0; i < priv->child_count; i++) { - if (i == active_src) - continue; - if (local->child_up[i] == 0) - continue; - if (sh->sources[i] == 1) - continue; - call_count++; - } - - impunge_local->call_count = call_count; - - for (i = 0; i < priv->child_count; i++) { - if (i == active_src) - continue; - if (local->child_up[i] == 0) - continue; - if (sh->sources[i] == 1) - continue; - - gf_log (this->name, GF_LOG_TRACE, - "looking up %s on %s", impunge_local->loc.path, - priv->children[i]->name); - - STACK_WIND_COOKIE (impunge_frame, - afr_sh_entry_impunge_entry_cbk, - (void *) (long) i, - priv->children[i], - priv->children[i]->fops->lookup, - &impunge_local->loc, 0); - - if (!--call_count) - break; - } + afr_sh_common_lookup (impunge_frame, this, &impunge_local->loc, + afr_sh_entry_common_lookup_done, NULL, + AFR_LOOKUP_FAIL_CONFLICTS); - ret = 0; + op_ret = 0; out: - if (ret == -1) + if (ret) { + if (impunge_frame) + AFR_STACK_DESTROY (impunge_frame); sh->impunge_done (frame, this, active_src, op_ret, op_errno); + } return 0; } @@ -2217,8 +2092,9 @@ afr_sh_entry_sync_prepare (call_frame_t *frame, xlator_t *this) } -int -afr_sh_entry_fix (call_frame_t *frame, xlator_t *this) +void +afr_sh_entry_fix (call_frame_t *frame, xlator_t *this, + int32_t op_ret, int32_t op_errno) { afr_local_t *local = NULL; afr_self_heal_t *sh = NULL; @@ -2231,6 +2107,13 @@ afr_sh_entry_fix (call_frame_t *frame, xlator_t *this) sh = &local->self_heal; priv = this->private; + if (op_ret < 0) { + sh->op_failed = 1; + afr_sh_set_error (sh, op_errno); + afr_sh_entry_finish (frame, this); + goto out; + } + if (sh->forced_merge) { sh->source = -1; goto heal; @@ -2246,7 +2129,7 @@ afr_sh_entry_fix (call_frame_t *frame, xlator_t *this) local->loc.path); afr_sh_entry_finish (frame, this); - return 0; + return; } source = afr_sh_select_source (sh->sources, priv->child_count); @@ -2262,33 +2145,8 @@ afr_sh_entry_fix (call_frame_t *frame, xlator_t *this) heal: afr_sh_entry_sync_prepare (frame, this); - - return 0; -} - - - -int -afr_sh_entry_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) -{ - int call_count = 0; - afr_local_t *local = NULL; - - local = frame->local; - afr_sh_common_lookup_resp_handler (frame, cookie, this, op_ret, - op_errno, inode, buf, xattr, - postparent, &local->loc); - - call_count = afr_frame_return (frame); - - if (call_count == 0) { - afr_sh_entry_fix (frame, this); - } - - return 0; +out: + return; } int @@ -2312,7 +2170,9 @@ afr_sh_post_nonblocking_entry_cbk (call_frame_t *frame, xlator_t *this) gf_log (this->name, GF_LOG_DEBUG, "Non Blocking entrylks done " "for %s. Proceeding to FOP", local->loc.path); afr_sh_common_lookup (frame, this, &local->loc, - afr_sh_entry_lookup_cbk, _gf_false); + afr_sh_entry_fix, NULL, + AFR_LOOKUP_FAIL_CONFLICTS | + AFR_LOOKUP_FAIL_MISSING_GFIDS); } return 0; diff --git a/xlators/cluster/afr/src/afr-self-heal-metadata.c b/xlators/cluster/afr/src/afr-self-heal-metadata.c index 9999fdcdb..efc841261 100644 --- a/xlators/cluster/afr/src/afr-self-heal-metadata.c +++ b/xlators/cluster/afr/src/afr-self-heal-metadata.c @@ -459,8 +459,9 @@ afr_sh_metadata_sync_prepare (call_frame_t *frame, xlator_t *this) } -int -afr_sh_metadata_fix (call_frame_t *frame, xlator_t *this) +void +afr_sh_metadata_fix (call_frame_t *frame, xlator_t *this, + int32_t op_ret, int32_t op_errno) { afr_local_t *local = NULL; afr_self_heal_t *sh = NULL; @@ -473,6 +474,12 @@ afr_sh_metadata_fix (call_frame_t *frame, xlator_t *this) sh = &local->self_heal; priv = this->private; + if (op_ret < 0) { + sh->op_failed = 1; + afr_sh_set_error (sh, op_errno); + afr_sh_metadata_finish (frame, this); + goto out; + } nsources = afr_build_sources (this, sh->xattr, sh->buf, sh->pending_matrix, sh->sources, sh->success_children, @@ -483,7 +490,7 @@ afr_sh_metadata_fix (call_frame_t *frame, xlator_t *this) local->loc.path); afr_sh_metadata_finish (frame, this); - return 0; + goto out; } if ((nsources == -1) @@ -510,7 +517,7 @@ afr_sh_metadata_fix (call_frame_t *frame, xlator_t *this) local->govinda_gOvinda = 1; afr_sh_metadata_finish (frame, this); - return 0; + goto out; } source = afr_sh_select_source (sh->sources, priv->child_count); @@ -520,7 +527,7 @@ afr_sh_metadata_fix (call_frame_t *frame, xlator_t *this) "No active sources found."); afr_sh_metadata_finish (frame, this); - return 0; + goto out; } sh->source = source; @@ -547,32 +554,8 @@ afr_sh_metadata_fix (call_frame_t *frame, xlator_t *this) } afr_sh_metadata_sync_prepare (frame, this); - - return 0; -} - - -int -afr_sh_metadata_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; - int call_count = 0; - - local = frame->local; - - afr_sh_common_lookup_resp_handler (frame, cookie, this, op_ret, - op_errno, inode, buf, xattr, - postparent, &local->loc); - - call_count = afr_frame_return (frame); - - if (call_count == 0) - afr_sh_metadata_fix (frame, this); - - return 0; +out: + return; } int @@ -597,7 +580,9 @@ afr_sh_metadata_post_nonblocking_inodelk_cbk (call_frame_t *frame, "inodelks done for %s. Proceeding to FOP", local->loc.path); afr_sh_common_lookup (frame, this, &local->loc, - afr_sh_metadata_lookup_cbk, _gf_false); + afr_sh_metadata_fix, NULL, + AFR_LOOKUP_FAIL_CONFLICTS | + AFR_LOOKUP_FAIL_MISSING_GFIDS); } return 0; diff --git a/xlators/cluster/afr/src/afr-self-heald.c b/xlators/cluster/afr/src/afr-self-heald.c index d27d9e09b..30450d97c 100644 --- a/xlators/cluster/afr/src/afr-self-heald.c +++ b/xlators/cluster/afr/src/afr-self-heald.c @@ -24,7 +24,10 @@ #include "afr.h" #include "syncop.h" #include "afr-self-heald.h" +#include "afr-self-heal-common.h" +static int +_crawl_directory (loc_t *loc, pid_t pid, uuid_t gfid); static int get_pathinfo_host (char *pathinfo, char *hostname, size_t size) { @@ -81,20 +84,99 @@ out: return ret; } +static void +_generate_gfid_on_empty (uuid_t gfid) +{ + if (uuid_is_null (gfid)) + uuid_generate (gfid); +} + +static void +_empty_gfid_on_set (uuid_t gfid, int lookup_status, struct iatt *iatt) +{ + if (lookup_status || !uuid_compare (gfid, iatt->ia_gfid)) + uuid_clear (gfid); +} + +static void +_fill_loc_info (loc_t *loc, struct iatt *iatt, struct iatt *parent) +{ + afr_update_loc_gfids (loc, iatt, parent); + uuid_copy (loc->inode->gfid, iatt->ia_gfid); +} + +static int +_perform_self_heal (xlator_t *this, loc_t *parentloc, gf_dirent_t *entries, + uuid_t gfid, off_t *offset, pid_t pid) +{ + gf_dirent_t *entry = NULL; + gf_dirent_t *tmp = NULL; + struct iatt iatt = {0}; + struct iatt parent = {0};; + int ret = 0; + loc_t entry_loc = {0}; + afr_private_t *priv = NULL; + dict_t *xattr_req = NULL; + + priv = this->private; + + xattr_req = dict_new (); + if (!xattr_req) { + ret = -1; + goto out; + } + + list_for_each_entry_safe (entry, tmp, &entries->list, list) { + *offset = entry->d_off; + if (IS_ENTRY_CWD (entry->d_name) || + IS_ENTRY_PARENT (entry->d_name)) + continue; + + ret = dict_reset (xattr_req); + if (ret) + goto out; + + loc_wipe (&entry_loc); + ret = afr_build_child_loc (this, &entry_loc, + parentloc, entry->d_name); + if (ret) + goto out; + + _generate_gfid_on_empty (gfid); + ret = afr_set_dict_gfid (xattr_req, gfid); + if (ret) + goto out; + gf_log (this->name, GF_LOG_DEBUG, "lookup %s", entry_loc.path); + + ret = syncop_lookup (this, &entry_loc, xattr_req, + &iatt, NULL, &parent); + _empty_gfid_on_set (gfid, ret, &iatt); + //Don't fail the crawl if lookup fails as it + //could be because of split-brain + if (ret || (!IA_ISDIR (iatt.ia_type))) + continue; + _fill_loc_info (&entry_loc, &iatt, &parent); + ret = _crawl_directory (&entry_loc, pid, gfid); + } + ret = 0; +out: + if (xattr_req) + dict_unref (xattr_req); + if (entry_loc.path) + loc_wipe (&entry_loc); + return ret; +} + static int -_crawl_directory (loc_t *loc, pid_t pid) +_crawl_directory (loc_t *loc, pid_t pid, uuid_t gfid) { xlator_t *this = NULL; afr_private_t *priv = NULL; fd_t *fd = NULL; off_t offset = 0; - loc_t entry_loc = {0}; - gf_dirent_t *entry = NULL; - gf_dirent_t *tmp = NULL; gf_dirent_t entries; struct iatt iatt = {0}; struct iatt parent = {0};; - char *file_path = NULL; int ret = 0; gf_boolean_t free_entries = _gf_false; @@ -138,42 +220,14 @@ _crawl_directory (loc_t *loc, pid_t pid) if (list_empty (&entries.list)) goto out; - list_for_each_entry_safe (entry, tmp, &entries.list, list) { - offset = entry->d_off; - if (IS_ENTRY_CWD (entry->d_name) || - IS_ENTRY_PARENT (entry->d_name)) - continue; - - file_path = afr_build_file_path (loc, entry); - if (!file_path) { - ret = -1; - goto out; - } - - loc_wipe (&entry_loc); - afr_build_child_loc (loc, &entry_loc, - file_path, entry->d_name); - - gf_log (this->name, GF_LOG_DEBUG, - "found readdir entry=%s", entry->d_name); - - ret = syncop_lookup (this, &entry_loc, NULL, - &iatt, NULL, &parent); - - //Don't fail the crawl if lookup fails as it - //could be because of split-brain - if (ret || (!IA_ISDIR (iatt.ia_type))) - continue; - ret = _crawl_directory (&entry_loc, pid); - } - + ret = _perform_self_heal (this, loc, &entries, gfid, &offset, pid); gf_dirent_free (&entries); free_entries = _gf_false; } + if (fd) + fd_unref (fd); ret = 0; out: - if (entry_loc.path) - loc_wipe (&entry_loc); if (free_entries) gf_dirent_free (&entries); return ret; @@ -331,6 +385,7 @@ afr_crawl_directory (xlator_t *this, pid_t pid) loc_t loc = {0}; gf_boolean_t crawl = _gf_false; int ret = 0; + uuid_t gfid = {0}; priv = this->private; shd = &priv->shd; @@ -357,7 +412,7 @@ afr_crawl_directory (xlator_t *this, pid_t pid) afr_build_root_loc (priv->root_inode, &loc); while (crawl) { - ret = _crawl_directory (&loc, pid); + ret = _crawl_directory (&loc, pid, gfid); if (ret) gf_log (this->name, GF_LOG_ERROR, "Crawl failed"); else @@ -470,43 +525,3 @@ afr_set_root_gfid (dict_t *dict) return ret; } - -char * -afr_build_file_path (loc_t *loc, gf_dirent_t *entry) -{ - xlator_t *this = NULL; - char *file_path = NULL; - int pathlen = 0; - size_t total_size = 0; - char *fmt = NULL; - - this = THIS; - - pathlen = STRLEN_0 (loc->path); - - if (IS_ROOT_PATH (loc->path)) { - total_size = pathlen + entry->d_len; - fmt = "%s%s"; - } else { - total_size = pathlen + entry->d_len + 1; /* for the extra '/' in the path */ - fmt = "%s/%s"; - } - - file_path = GF_CALLOC (1, total_size + 1, gf_afr_mt_char); - if (!file_path) - goto out; - - snprintf(file_path, total_size, fmt, loc->path, entry->d_name); -out: - return file_path; -} - -void -afr_build_child_loc (loc_t *parent, loc_t *child, char *path, char *name) -{ - child->path = path; - child->name = name; - - child->parent = inode_ref (parent->inode); - child->inode = inode_new (parent->inode->table); -} diff --git a/xlators/cluster/afr/src/afr-self-heald.h b/xlators/cluster/afr/src/afr-self-heald.h index c85c97b25..5d7892fa7 100644 --- a/xlators/cluster/afr/src/afr-self-heald.h +++ b/xlators/cluster/afr/src/afr-self-heald.h @@ -37,8 +37,4 @@ void afr_build_root_loc (inode_t *inode, loc_t *loc); int afr_set_root_gfid (dict_t *dict); -char * afr_build_file_path (loc_t *loc, gf_dirent_t *entry); - -void -afr_build_child_loc (loc_t *parent, loc_t *child, char *path, char *name); #endif /* __AFR_SELF_HEALD_H__ */ diff --git a/xlators/cluster/afr/src/afr.h b/xlators/cluster/afr/src/afr.h index becbd261f..0f4db7d91 100644 --- a/xlators/cluster/afr/src/afr.h +++ b/xlators/cluster/afr/src/afr.h @@ -48,6 +48,8 @@ typedef int (*afr_impunge_done_cbk_t) (call_frame_t *frame, xlator_t *this, typedef int (*afr_post_remove_call_t) (call_frame_t *frame, xlator_t *this); typedef int (*afr_lock_cbk_t) (call_frame_t *frame, xlator_t *this); +typedef void (*afr_lookup_done_cbk_t) (call_frame_t *frame, xlator_t *this, + int32_t op_ret, int32_t op_errno); typedef enum { AFR_POS_UNKNOWN, @@ -204,6 +206,10 @@ typedef struct { int32_t *fresh_parent_dirs; /* array of errno's, one for each child */ int *child_errno; + /*loc used for lookup*/ + loc_t lookup_loc; + int32_t lookup_flags; + afr_lookup_done_cbk_t lookup_done; int32_t **pending_matrix; int32_t **delta_matrix; @@ -979,7 +985,7 @@ gf_boolean_t afr_conflicting_iattrs (struct iatt *bufs, int32_t *success_children, unsigned int child_count, const char *path, const char *xlator_name); -int +unsigned int afr_gfid_missing_count (const char *xlator_name, int32_t *children, struct iatt *bufs, unsigned int child_count, const char *path); diff --git a/xlators/cluster/afr/src/pump.c b/xlators/cluster/afr/src/pump.c index 0623b817a..63c89b3c7 100644 --- a/xlators/cluster/afr/src/pump.c +++ b/xlators/cluster/afr/src/pump.c @@ -332,7 +332,7 @@ pump_save_file_stats (xlator_t *this, const char *path) } static int -gf_pump_traverse_directory (loc_t *loc) +gf_pump_traverse_directory (loc_t *loc, uuid_t gfid) { xlator_t *this = NULL; fd_t *fd = NULL; @@ -346,7 +346,6 @@ gf_pump_traverse_directory (loc_t *loc) struct iatt iatt, parent; dict_t *xattr_rsp; - char *file_path = NULL; int ret = 0; gf_boolean_t is_directory_empty = _gf_true; @@ -385,15 +384,10 @@ gf_pump_traverse_directory (loc_t *loc) gf_log (this->name, GF_LOG_DEBUG, "found readdir entry=%s", entry->d_name); - file_path = afr_build_file_path (loc, entry); - if (!file_path) { - gf_log (this->name, GF_LOG_DEBUG, - "file path construction failed"); + ret = afr_build_child_loc (this, &entry_loc, loc, + entry->d_name); + if (ret) goto out; - } - - afr_build_child_loc (loc, &entry_loc, file_path, - entry->d_name); if (!IS_ENTRY_CWD (entry->d_name) && !IS_ENTRY_PARENT (entry->d_name)) { @@ -401,8 +395,17 @@ gf_pump_traverse_directory (loc_t *loc) is_directory_empty = _gf_false; ret = syncop_lookup (this, &entry_loc, NULL, &iatt, &xattr_rsp, &parent); - - memcpy (entry_loc.inode->gfid, iatt.ia_gfid, 16); + if (ret) + continue; + + if (uuid_is_null (iatt.ia_gfid)) { + uuid_generate (gfid); + uuid_copy (entry_loc.inode->gfid, + gfid); + } else { + uuid_copy (entry_loc.inode->gfid, + iatt.ia_gfid); + } gf_log (this->name, GF_LOG_DEBUG, "lookup %s => %"PRId64, @@ -440,7 +443,7 @@ gf_pump_traverse_directory (loc_t *loc) gf_log (this->name, GF_LOG_TRACE, "entering dir=%s", entry->d_name); - gf_pump_traverse_directory (&entry_loc); + gf_pump_traverse_directory (&entry_loc, gfid); } } } @@ -622,6 +625,7 @@ pump_task (void *data) struct iatt iatt, parent; dict_t *xattr_rsp = NULL; dict_t *xattr_req = NULL; + uuid_t gfid = {0}; int ret = -1; @@ -662,7 +666,7 @@ pump_task (void *data) goto out; } - gf_pump_traverse_directory (&loc); + gf_pump_traverse_directory (&loc, gfid); pump_complete_migration (this); out: -- cgit