3604df
From d1c4817b7c63a7fd94aa11dae5899d6d50e75897 Mon Sep 17 00:00:00 2001
3604df
From: Ashish Pandey <aspandey@redhat.com>
3604df
Date: Tue, 20 Sep 2016 12:32:28 +0530
3604df
Subject: [PATCH 099/141] cluster/ec: Implement heal info with lock
3604df
3604df
Problem: Currently heal info command prints all
3604df
the files/directories if the index for the
3604df
file/directory is present in .glusterfs/indices folder.
3604df
After implementing patch http://review.gluster.org/#/c/13733/
3604df
indices of the file which is going through update fop
3604df
will also be present in .glusterfs/indices even
3604df
if the fop is successful on all the brick. At this time
3604df
if heal info command is being used, it will also display this
3604df
file which is actually healthy and does not require any heal.
3604df
3604df
Solution: Take lock on a file corresponding to the indices
3604df
and inspect xattrs to decide if the file needs heal or not.
3604df
3604df
>Reviewed-on: http://review.gluster.org/15543
3604df
>NetBSD-regression: NetBSD Build System <jenkins@build.gluster.org>
3604df
>Reviewed-by: Pranith Kumar Karampuri <pkarampu@redhat.com>
3604df
>Reviewed-by: Xavier Hernandez <xhernandez@datalab.es>
3604df
>CentOS-regression: Gluster Build System <jenkins@build.gluster.org>
3604df
>Smoke: Gluster Build System <jenkins@build.gluster.org>
3604df
3604df
Change-Id: I6361e2813ece369be12d02e74816df4eddb81cfa
3604df
BUG: 1347257
3604df
Signed-off-by: Ashish Pandey <aspandey@redhat.com>
3604df
Reviewed-on: https://code.engineering.redhat.com/gerrit/87015
3604df
Tested-by: Pranith Kumar Karampuri <pkarampu@redhat.com>
3604df
Reviewed-by: Pranith Kumar Karampuri <pkarampu@redhat.com>
3604df
---
3604df
 libglusterfs/src/syncop-utils.c          |   35 ++++
3604df
 libglusterfs/src/syncop-utils.h          |    4 +
3604df
 tests/afr.rc                             |    5 -
3604df
 tests/basic/ec/ec-background-heals.t     |    5 +-
3604df
 tests/volume.rc                          |    5 +
3604df
 xlators/cluster/afr/src/afr-self-heald.c |   27 +--
3604df
 xlators/cluster/ec/src/ec-common.h       |    3 +
3604df
 xlators/cluster/ec/src/ec-heal.c         |  254 ++++++++++++++++++++++++++++--
3604df
 xlators/cluster/ec/src/ec-heald.c        |   46 +-----
3604df
 xlators/cluster/ec/src/ec.c              |   10 +-
3604df
 10 files changed, 308 insertions(+), 86 deletions(-)
3604df
3604df
diff --git a/libglusterfs/src/syncop-utils.c b/libglusterfs/src/syncop-utils.c
3604df
index 8f25db2..8c25dd1 100644
3604df
--- a/libglusterfs/src/syncop-utils.c
3604df
+++ b/libglusterfs/src/syncop-utils.c
3604df
@@ -591,3 +591,38 @@ out:
3604df
 
3604df
         return ret;
3604df
 }
3604df
+
3604df
+int
3604df
+syncop_inode_find (xlator_t *this, xlator_t *subvol,
3604df
+                   uuid_t gfid, inode_t **inode,
3604df
+                   dict_t *xdata, dict_t **rsp_dict)
3604df
+{
3604df
+        int         ret    = 0;
3604df
+        loc_t       loc    = {0, };
3604df
+        struct iatt iatt   = {0, };
3604df
+	*inode =  NULL;
3604df
+
3604df
+        *inode = inode_find (this->itable, gfid);
3604df
+        if (*inode)
3604df
+                goto out;
3604df
+
3604df
+        loc.inode = inode_new (this->itable);
3604df
+        if (!loc.inode) {
3604df
+                ret = -ENOMEM;
3604df
+                goto out;
3604df
+        }
3604df
+        gf_uuid_copy (loc.gfid, gfid);
3604df
+
3604df
+	ret = syncop_lookup (subvol, &loc, &iatt, NULL, xdata, rsp_dict);
3604df
+        if (ret < 0)
3604df
+                goto out;
3604df
+
3604df
+        *inode = inode_link (loc.inode, NULL, NULL, &iatt);
3604df
+        if (!*inode) {
3604df
+                ret = -ENOMEM;
3604df
+                goto out;
3604df
+        }
3604df
+out:
3604df
+        loc_wipe (&loc;;
3604df
+        return ret;
3604df
+}
3604df
diff --git a/libglusterfs/src/syncop-utils.h b/libglusterfs/src/syncop-utils.h
3604df
index 3968d75..4761371 100644
3604df
--- a/libglusterfs/src/syncop-utils.h
3604df
+++ b/libglusterfs/src/syncop-utils.h
3604df
@@ -43,4 +43,8 @@ syncop_ftw_throttle (xlator_t *subvol, loc_t *loc, int pid, void *data,
3604df
                      int (*fn) (xlator_t *subvol, gf_dirent_t *entry,
3604df
                                 loc_t *parent, void *data),
3604df
                      int count, int sleep_time);
3604df
+int
3604df
+syncop_inode_find (xlator_t *this, xlator_t *subvol,
3604df
+                   uuid_t gfid, inode_t **inode,
3604df
+                   dict_t *xdata, dict_t **rsp_dict);
3604df
 #endif /* _SYNCOP_H */
3604df
diff --git a/tests/afr.rc b/tests/afr.rc
3604df
index ed376f0..bdf4075 100644
3604df
--- a/tests/afr.rc
3604df
+++ b/tests/afr.rc
3604df
@@ -85,11 +85,6 @@ function is_file_heal_done {
3604df
 #count the number of entries marked for self-heal
3604df
 #in brick $1's index
3604df
 
3604df
-function count_sh_entries()
3604df
-{
3604df
-    ls $1/.glusterfs/indices/xattrop | grep -v "xattrop-" | wc -l
3604df
-}
3604df
-
3604df
 function count_index_entries()
3604df
 {
3604df
     ls $1/.glusterfs/indices/xattrop | wc -l
3604df
diff --git a/tests/basic/ec/ec-background-heals.t b/tests/basic/ec/ec-background-heals.t
3604df
index 7ac6c0e..28efc83 100644
3604df
--- a/tests/basic/ec/ec-background-heals.t
3604df
+++ b/tests/basic/ec/ec-background-heals.t
3604df
@@ -23,7 +23,9 @@ EXPECT_WITHIN $CHILD_UP_TIMEOUT "3" ec_child_up_count $V0 0
3604df
 EXPECT_WITHIN $CONFIG_UPDATE_TIMEOUT "0" mount_get_option_value $M0 $V0-disperse-0 background-heals
3604df
 EXPECT_WITHIN $CONFIG_UPDATE_TIMEOUT "0" mount_get_option_value $M0 $V0-disperse-0 heal-wait-qlength
3604df
 TEST touch $M0/a
3604df
-EXPECT_WITHIN $CHILD_UP_TIMEOUT "0" get_pending_heal_count $V0 #One for each active brick
3604df
+EXPECT_WITHIN $HEAL_TIMEOUT "^0$" count_sh_entries $B0/${V0}0
3604df
+EXPECT_WITHIN $HEAL_TIMEOUT "^0$" count_sh_entries $B0/${V0}1
3604df
+EXPECT_WITHIN $HEAL_TIMEOUT "^0$" count_sh_entries $B0/${V0}2
3604df
 TEST kill_brick $V0 $H0 $B0/${V0}2
3604df
 echo abc > $M0/a
3604df
 EXPECT 2 get_pending_heal_count $V0 #One for each active brick
3604df
@@ -31,7 +33,6 @@ $CLI volume start $V0 force
3604df
 EXPECT_WITHIN $CHILD_UP_TIMEOUT "3" ec_child_up_count $V0 0
3604df
 #Accessing file shouldn't heal the file
3604df
 EXPECT "abc" cat $M0/a
3604df
-sleep 3
3604df
 EXPECT 2 get_pending_heal_count $V0 #One for each active brick
3604df
 TEST $CLI volume set $V0 disperse.background-heals 1
3604df
 EXPECT_WITHIN $CONFIG_UPDATE_TIMEOUT "1" mount_get_option_value $M0 $V0-disperse-0 background-heals
3604df
diff --git a/tests/volume.rc b/tests/volume.rc
3604df
index 989538d..b7fd20a 100644
3604df
--- a/tests/volume.rc
3604df
+++ b/tests/volume.rc
3604df
@@ -686,3 +686,8 @@ function get_hard_link_count {
3604df
         local path=$1;
3604df
         stat -c %h $path
3604df
 }
3604df
+
3604df
+function count_sh_entries()
3604df
+{
3604df
+    ls $1/.glusterfs/indices/xattrop | grep -v "xattrop-" | wc -l
3604df
+}
3604df
diff --git a/xlators/cluster/afr/src/afr-self-heald.c b/xlators/cluster/afr/src/afr-self-heald.c
3604df
index 26f4a80..f54a1c4 100644
3604df
--- a/xlators/cluster/afr/src/afr-self-heald.c
3604df
+++ b/xlators/cluster/afr/src/afr-self-heald.c
3604df
@@ -153,22 +153,11 @@ unlock:
3604df
 inode_t *
3604df
 afr_shd_inode_find (xlator_t *this, xlator_t *subvol, uuid_t gfid)
3604df
 {
3604df
-	int           ret      = 0;
3604df
-        uint64_t       val     = IA_INVAL;
3604df
-	loc_t         loc      = {0, };
3604df
+        int          ret       = 0;
3604df
+        uint64_t     val       = IA_INVAL;
3604df
         dict_t       *xdata    = NULL;
3604df
         dict_t       *rsp_dict = NULL;
3604df
-	inode_t      *inode    = NULL;
3604df
-	struct iatt   iatt     = {0, };
3604df
-
3604df
-	inode = inode_find (this->itable, gfid);
3604df
-	if (inode)
3604df
-		goto out;
3604df
-
3604df
-	loc.inode = inode_new (this->itable);
3604df
-	if (!loc.inode)
3604df
-		goto out;
3604df
-	gf_uuid_copy (loc.gfid, gfid);
3604df
+        inode_t      *inode    = NULL;
3604df
 
3604df
         xdata = dict_new ();
3604df
         if (!xdata)
3604df
@@ -178,7 +167,8 @@ afr_shd_inode_find (xlator_t *this, xlator_t *subvol, uuid_t gfid)
3604df
         if (ret)
3604df
                 goto out;
3604df
 
3604df
-	ret = syncop_lookup (subvol, &loc, &iatt, NULL, xdata, &rsp_dict);
3604df
+	ret = syncop_inode_find (this, subvol, gfid, &inode,
3604df
+                                 xdata, &rsp_dict);
3604df
 	if (ret < 0)
3604df
 		goto out;
3604df
 
3604df
@@ -188,15 +178,16 @@ afr_shd_inode_find (xlator_t *this, xlator_t *subvol, uuid_t gfid)
3604df
                 if (ret)
3604df
                         goto out;
3604df
         }
3604df
-
3604df
-	inode = inode_link (loc.inode, NULL, NULL, &iatt);
3604df
         ret = inode_ctx_set2 (inode, subvol, 0, &val;;
3604df
 out:
3604df
+        if (ret && inode) {
3604df
+                inode_unref (inode);
3604df
+                inode = NULL;
3604df
+        }
3604df
         if (xdata)
3604df
                 dict_unref (xdata);
3604df
         if (rsp_dict)
3604df
                 dict_unref (rsp_dict);
3604df
-	loc_wipe (&loc;;
3604df
 	return inode;
3604df
 }
3604df
 
3604df
diff --git a/xlators/cluster/ec/src/ec-common.h b/xlators/cluster/ec/src/ec-common.h
3604df
index d720d24..5851b5d 100644
3604df
--- a/xlators/cluster/ec/src/ec-common.h
3604df
+++ b/xlators/cluster/ec/src/ec-common.h
3604df
@@ -118,4 +118,7 @@ void ec_manager(ec_fop_data_t * fop, int32_t error);
3604df
 gf_boolean_t ec_is_recoverable_error (int32_t op_errno);
3604df
 void ec_handle_healers_done (ec_fop_data_t *fop);
3604df
 
3604df
+int32_t
3604df
+ec_get_heal_info (xlator_t *this, loc_t *loc, dict_t **dict);
3604df
+
3604df
 #endif /* __EC_COMMON_H__ */
3604df
diff --git a/xlators/cluster/ec/src/ec-heal.c b/xlators/cluster/ec/src/ec-heal.c
3604df
index 94ff475..39cce19 100644
3604df
--- a/xlators/cluster/ec/src/ec-heal.c
3604df
+++ b/xlators/cluster/ec/src/ec-heal.c
3604df
@@ -1489,22 +1489,29 @@ unlock:
3604df
         return ret;
3604df
 }
3604df
 
3604df
-/*Data heal*/
3604df
+/*Find direction for data heal and heal info*/
3604df
 int
3604df
 ec_heal_data_find_direction (ec_t *ec, default_args_cbk_t *replies,
3604df
-                             uint64_t *versions, uint64_t *dirty,
3604df
-                             uint64_t *size, unsigned char *sources,
3604df
-                             unsigned char *healed_sinks)
3604df
+                       uint64_t *data_versions,  uint64_t *meta_versions,
3604df
+                       uint64_t *dirty, uint64_t *size, unsigned char *sources,
3604df
+                       unsigned char *healed_sinks, int which)
3604df
 {
3604df
         uint64_t        xattr[EC_VERSION_SIZE] = {0};
3604df
-        char            version_size[64] = {0};
3604df
+        char            version_size[128] = {0};
3604df
         dict_t          *version_size_db = NULL;
3604df
+        uint64_t        *m_versions      = NULL;
3604df
         unsigned char   *same            = NULL;
3604df
         int             max_same_count   = 0;
3604df
         int             source           = 0;
3604df
         int             i                = 0;
3604df
         int             ret              = 0;
3604df
+        dict_t          *dict            = NULL;
3604df
 
3604df
+        if (!meta_versions) {
3604df
+                m_versions = alloca0 (ec->nodes * sizeof (*m_versions));
3604df
+        } else {
3604df
+                m_versions = meta_versions;
3604df
+        }
3604df
         version_size_db = dict_new ();
3604df
         if (!version_size_db) {
3604df
                 ret = -ENOMEM;
3604df
@@ -1516,23 +1523,31 @@ ec_heal_data_find_direction (ec_t *ec, default_args_cbk_t *replies,
3604df
                         continue;
3604df
                 if (replies[i].op_ret < 0)
3604df
                         continue;
3604df
-                ret = ec_dict_del_array (replies[i].xattr, EC_XATTR_VERSION,
3604df
+                dict = (which == EC_COMBINE_XDATA) ? replies[i].xdata :
3604df
+                                                     replies[i].xattr;
3604df
+
3604df
+                ret = ec_dict_del_array (dict, EC_XATTR_VERSION,
3604df
                                          xattr, EC_VERSION_SIZE);
3604df
                 if (ret == 0) {
3604df
-                        versions[i] = xattr[EC_DATA_TXN];
3604df
+                        data_versions[i] = xattr[EC_DATA_TXN];
3604df
+                        if (meta_versions) {
3604df
+                                m_versions[i] = xattr[EC_METADATA_TXN];
3604df
+                        }
3604df
                 }
3604df
 
3604df
                 memset (xattr, 0, sizeof (xattr));
3604df
-                ret = ec_dict_del_array (replies[i].xattr, EC_XATTR_DIRTY,
3604df
+                ret = ec_dict_del_array (dict, EC_XATTR_DIRTY,
3604df
                                          xattr, EC_VERSION_SIZE);
3604df
                 if (ret == 0) {
3604df
                         dirty[i] = xattr[EC_DATA_TXN];
3604df
                 }
3604df
-                ret = ec_dict_del_number (replies[i].xattr, EC_XATTR_SIZE,
3604df
+                ret = ec_dict_del_number (dict, EC_XATTR_SIZE,
3604df
                                           &size[i]);
3604df
-                /*Build a db of same version, size*/
3604df
+                /*Build a db of same metadata and data version and size*/
3604df
                 snprintf (version_size, sizeof (version_size),
3604df
-                          "%"PRIu64"-%"PRIu64, versions[i], size[i]);
3604df
+                          "%"PRIu64"-%"PRIu64"-%"PRIu64, data_versions[i],
3604df
+                          m_versions[i], size[i]);
3604df
+
3604df
                 ret = dict_get_bin (version_size_db, version_size,
3604df
                                     (void **)&same);
3604df
                 if (ret < 0) {
3604df
@@ -1562,7 +1577,11 @@ ec_heal_data_find_direction (ec_t *ec, default_args_cbk_t *replies,
3604df
                 goto out;
3604df
         } else {
3604df
                 snprintf (version_size, sizeof (version_size),
3604df
-                          "%"PRIu64"-%"PRIu64, versions[source], size[source]);
3604df
+                          "%"PRIu64"-%"PRIu64"-%"PRIu64,
3604df
+                          data_versions[source],
3604df
+                          m_versions[source],
3604df
+                          size[source]);
3604df
+
3604df
                 ret = dict_get_bin (version_size_db, version_size,
3604df
                                     (void **)&same);
3604df
                 if (ret < 0)
3604df
@@ -1621,8 +1640,9 @@ __ec_heal_data_prepare (call_frame_t *frame, ec_t *ec, fd_t *fd,
3604df
                 goto out;
3604df
         }
3604df
 
3604df
-        source = ec_heal_data_find_direction (ec, replies, versions, dirty,
3604df
-                                              size, sources, healed_sinks);
3604df
+        source = ec_heal_data_find_direction (ec, replies, versions, NULL,
3604df
+                                              dirty, size, sources,
3604df
+                                              healed_sinks, EC_COMBINE_DICT);
3604df
         ret = source;
3604df
         if (ret < 0)
3604df
                 goto out;
3604df
@@ -2602,7 +2622,7 @@ out:
3604df
 int32_t
3604df
 ec_launch_replace_heal (ec_t *ec)
3604df
 {
3604df
-	int ret = -1;
3604df
+        int ret = -1;
3604df
 
3604df
         if (!ec)
3604df
                 return ret;
3604df
@@ -2614,3 +2634,207 @@ ec_launch_replace_heal (ec_t *ec)
3604df
         }
3604df
         return ret;
3604df
 }
3604df
+
3604df
+int32_t
3604df
+ec_set_heal_info(dict_t **dict_rsp, char *status)
3604df
+{
3604df
+        dict_t *dict = NULL;
3604df
+        int    ret   = 0;
3604df
+
3604df
+        dict = dict_new ();
3604df
+        if (!dict) {
3604df
+                ret = -ENOMEM;
3604df
+                goto out;
3604df
+        }
3604df
+        ret = dict_set_str (dict, "heal-info", status);
3604df
+        if (ret) {
3604df
+                gf_msg (THIS->name, GF_LOG_WARNING, -ret,
3604df
+                        EC_MSG_HEAL_FAIL,
3604df
+                        "Failed to set heal-info key to "
3604df
+                        "%s", status);
3604df
+                dict_unref(dict);
3604df
+                dict = NULL;
3604df
+        }
3604df
+        *dict_rsp = dict;
3604df
+out:
3604df
+        return ret;
3604df
+}
3604df
+
3604df
+int32_t
3604df
+ec_need_heal (ec_t *ec, default_args_cbk_t *replies, gf_boolean_t *need_heal)
3604df
+{
3604df
+        uint64_t           *dirty         = NULL;
3604df
+        unsigned char      *sources       = NULL;
3604df
+        unsigned char      *healed_sinks  = NULL;
3604df
+        uint64_t           *data_versions = NULL;
3604df
+        uint64_t           *meta_versions = NULL;
3604df
+        uint64_t           *size          = NULL;
3604df
+        int                ret            = 0;
3604df
+        int                source_count   = 0;
3604df
+
3604df
+        sources = alloca0(ec->nodes);
3604df
+        healed_sinks = alloca0(ec->nodes);
3604df
+        dirty = alloca0 (ec->nodes * sizeof (*dirty));
3604df
+        size = alloca0 (ec->nodes * sizeof (*size));
3604df
+        data_versions = alloca0 (ec->nodes * sizeof (*data_versions));
3604df
+        meta_versions = alloca0 (ec->nodes * sizeof (*meta_versions));
3604df
+
3604df
+        ret = ec_heal_data_find_direction (ec, replies, data_versions,
3604df
+                                           meta_versions, dirty, size,
3604df
+                                           sources, healed_sinks,
3604df
+                                           EC_COMBINE_XDATA);
3604df
+        if (ret < 0 && ret != -EIO) {
3604df
+                goto out;
3604df
+        }
3604df
+        source_count = EC_COUNT (sources, ec->nodes);
3604df
+        if (source_count != ec->nodes) {
3604df
+                *need_heal = _gf_true;
3604df
+        }
3604df
+        ret = source_count;
3604df
+out:
3604df
+        return ret;
3604df
+}
3604df
+
3604df
+int32_t
3604df
+ec_heal_inspect (call_frame_t *frame, ec_t *ec,
3604df
+                 inode_t *inode, unsigned char *locked_on,
3604df
+                 gf_boolean_t *need_heal)
3604df
+{
3604df
+        loc_t              loc           = {0};
3604df
+        int                ret           = 0;
3604df
+        dict_t             *xdata        = NULL;
3604df
+        uint64_t           zero_array[2] = {0};
3604df
+        uint64_t           zero_value    = 0;
3604df
+        unsigned char      *output       = NULL;
3604df
+        default_args_cbk_t *replies      = NULL;
3604df
+
3604df
+        EC_REPLIES_ALLOC (replies, ec->nodes);
3604df
+        output = alloca0 (ec->nodes);
3604df
+
3604df
+        loc.inode = inode_ref (inode);
3604df
+        gf_uuid_copy (loc.gfid, inode->gfid);
3604df
+
3604df
+        xdata = dict_new ();
3604df
+        if (!xdata ||
3604df
+            dict_set_static_bin (xdata, EC_XATTR_VERSION, zero_array,
3604df
+                                 sizeof (zero_array)) ||
3604df
+            dict_set_static_bin (xdata, EC_XATTR_DIRTY, zero_array,
3604df
+                                 sizeof (zero_array)) ||
3604df
+            dict_set_static_bin (xdata, EC_XATTR_SIZE, &zero_value,
3604df
+                                 sizeof (zero_value))) {
3604df
+                ret = -ENOMEM;
3604df
+                goto out;
3604df
+        }
3604df
+        ret = cluster_lookup (ec->xl_list, locked_on, ec->nodes, replies,
3604df
+                              output, frame, ec->xl, &loc, xdata);
3604df
+        if (ret != ec->nodes) {
3604df
+                ret = ec->nodes;
3604df
+                *need_heal = _gf_true;
3604df
+                goto out;
3604df
+        }
3604df
+        ret = ec_need_heal (ec, replies, need_heal);
3604df
+
3604df
+out:
3604df
+        cluster_replies_wipe (replies, ec->nodes);
3604df
+        loc_wipe (&loc;;
3604df
+        if (xdata) {
3604df
+                dict_unref(xdata);
3604df
+        }
3604df
+        return ret;
3604df
+}
3604df
+
3604df
+int32_t
3604df
+ec_heal_locked_inspect (call_frame_t *frame, ec_t *ec, inode_t *inode,
3604df
+                        gf_boolean_t *need_heal)
3604df
+{
3604df
+        unsigned char      *locked_on  = NULL;
3604df
+        unsigned char      *up_subvols = NULL;
3604df
+        unsigned char      *output     = NULL;
3604df
+        default_args_cbk_t *replies    = NULL;
3604df
+        int                ret         = 0;
3604df
+
3604df
+        EC_REPLIES_ALLOC (replies, ec->nodes);
3604df
+        locked_on = alloca0(ec->nodes);
3604df
+        output = alloca0(ec->nodes);
3604df
+        up_subvols = alloca0(ec->nodes);
3604df
+        ec_mask_to_char_array (ec->xl_up, up_subvols, ec->nodes);
3604df
+
3604df
+        ret = cluster_inodelk (ec->xl_list, up_subvols, ec->nodes,
3604df
+                               replies, locked_on, frame, ec->xl,
3604df
+                               ec->xl->name, inode, 0, 0);
3604df
+        if (ret != ec->nodes) {
3604df
+                *need_heal = _gf_true;
3604df
+                goto unlock;
3604df
+        }
3604df
+        ret = ec_heal_inspect (frame, ec, inode,
3604df
+                               locked_on, need_heal);
3604df
+unlock:
3604df
+        cluster_uninodelk (ec->xl_list, locked_on, ec->nodes,
3604df
+                           replies, output, frame, ec->xl,
3604df
+                           ec->xl->name, inode, 0, 0);
3604df
+        cluster_replies_wipe (replies, ec->nodes);
3604df
+        return ret;
3604df
+}
3604df
+
3604df
+int32_t
3604df
+ec_get_heal_info (xlator_t *this, loc_t *entry_loc, dict_t **dict_rsp)
3604df
+{
3604df
+        int             ret             = -ENOMEM;
3604df
+        gf_boolean_t    need_heal       = _gf_false;
3604df
+        call_frame_t    *frame          = NULL;
3604df
+        ec_t            *ec             = NULL;
3604df
+        unsigned char   *up_subvols     = NULL;
3604df
+        loc_t           loc             = {0, };
3604df
+
3604df
+        VALIDATE_OR_GOTO(this, out);
3604df
+        GF_VALIDATE_OR_GOTO(this->name, entry_loc, out);
3604df
+
3604df
+        ec = this->private;
3604df
+        up_subvols = alloca0(ec->nodes);
3604df
+        ec_mask_to_char_array (ec->xl_up, up_subvols, ec->nodes);
3604df
+
3604df
+        frame = create_frame (this, this->ctx->pool);
3604df
+        if (!frame) {
3604df
+                goto out;
3604df
+        }
3604df
+        ec_owner_set(frame, frame->root);
3604df
+        frame->root->uid = 0;
3604df
+        frame->root->gid = 0;
3604df
+        frame->root->pid = GF_CLIENT_PID_SELF_HEALD;
3604df
+
3604df
+        if (loc_copy(&loc, entry_loc) != 0) {
3604df
+                gf_msg (this->name, GF_LOG_ERROR,
3604df
+                        ENOMEM, EC_MSG_LOC_COPY_FAIL,
3604df
+                        "Failed to copy a location.");
3604df
+                goto out;
3604df
+        }
3604df
+        if (!loc.inode) {
3604df
+                ret = syncop_inode_find (this, this, loc.gfid,
3604df
+                                         &loc.inode, NULL, NULL);
3604df
+                if (ret < 0)
3604df
+                        goto out;
3604df
+        }
3604df
+
3604df
+        ret = ec_heal_inspect (frame, ec, loc.inode, up_subvols,
3604df
+                               &need_heal);
3604df
+        if (ret == ec->nodes) {
3604df
+                goto set_heal;
3604df
+        }
3604df
+        need_heal = _gf_false;
3604df
+        ret = ec_heal_locked_inspect (frame, ec, loc.inode,
3604df
+                                      &need_heal);
3604df
+        if (ret < 0)
3604df
+                goto out;
3604df
+set_heal:
3604df
+        if (need_heal) {
3604df
+                ret =  ec_set_heal_info (dict_rsp, "heal");
3604df
+        } else {
3604df
+                ret =  ec_set_heal_info (dict_rsp, "no-heal");
3604df
+        }
3604df
+out:
3604df
+        if (frame) {
3604df
+                STACK_DESTROY (frame->root);
3604df
+        }
3604df
+        loc_wipe (&loc;;
3604df
+        return ret;
3604df
+}
3604df
diff --git a/xlators/cluster/ec/src/ec-heald.c b/xlators/cluster/ec/src/ec-heald.c
3604df
index 0e80768..0f63ab1 100644
3604df
--- a/xlators/cluster/ec/src/ec-heald.c
3604df
+++ b/xlators/cluster/ec/src/ec-heald.c
3604df
@@ -126,42 +126,6 @@ unlock:
3604df
         return ret;
3604df
 }
3604df
 
3604df
-
3604df
-int
3604df
-ec_shd_inode_find (xlator_t *this, xlator_t *subvol,
3604df
-                   uuid_t gfid, inode_t **inode)
3604df
-{
3604df
-        int         ret    = 0;
3604df
-        loc_t       loc    = {0, };
3604df
-        struct iatt iatt   = {0, };
3604df
-	*inode =  NULL;
3604df
-
3604df
-        *inode = inode_find (this->itable, gfid);
3604df
-        if (*inode)
3604df
-                goto out;
3604df
-
3604df
-        loc.inode = inode_new (this->itable);
3604df
-        if (!loc.inode) {
3604df
-                ret = -ENOMEM;
3604df
-                goto out;
3604df
-        }
3604df
-        gf_uuid_copy (loc.gfid, gfid);
3604df
-
3604df
-        ret = syncop_lookup (subvol, &loc, &iatt, NULL, NULL, NULL);
3604df
-        if (ret < 0)
3604df
-                goto out;
3604df
-
3604df
-        *inode = inode_link (loc.inode, NULL, NULL, &iatt);
3604df
-        if (!*inode) {
3604df
-                ret = -ENOMEM;
3604df
-                goto out;
3604df
-        }
3604df
-out:
3604df
-        loc_wipe (&loc;;
3604df
-        return ret;
3604df
-}
3604df
-
3604df
-
3604df
 int
3604df
 ec_shd_index_inode (xlator_t *this, xlator_t *subvol, inode_t **inode)
3604df
 {
3604df
@@ -190,7 +154,8 @@ ec_shd_index_inode (xlator_t *this, xlator_t *subvol, inode_t **inode)
3604df
         gf_msg_debug (this->name, 0, "index-dir gfid for %s: %s",
3604df
                 subvol->name, uuid_utoa (index_gfid));
3604df
 
3604df
-        ret = ec_shd_inode_find (this, subvol, index_gfid, inode);
3604df
+        ret = syncop_inode_find (this, subvol, index_gfid,
3604df
+                                 inode, NULL, NULL);
3604df
 
3604df
 out:
3604df
         loc_wipe (&rootloc);
3604df
@@ -250,8 +215,8 @@ ec_shd_index_heal (xlator_t *subvol, gf_dirent_t *entry, loc_t *parent,
3604df
         if (ret < 0)
3604df
                 goto out;
3604df
 
3604df
-        ret = ec_shd_inode_find (healer->this, healer->this, loc.gfid,
3604df
-                                  &loc.inode);
3604df
+        ret = syncop_inode_find (healer->this, healer->this, loc.gfid,
3604df
+                                 &loc.inode, NULL, NULL);
3604df
         if (ret < 0)
3604df
                 goto out;
3604df
 
3604df
@@ -319,7 +284,8 @@ ec_shd_full_heal (xlator_t *subvol, gf_dirent_t *entry, loc_t *parent,
3604df
         if (ret < 0)
3604df
                 goto out;
3604df
 
3604df
-        ret = ec_shd_inode_find (this, this, loc.gfid, &loc.inode);
3604df
+        ret = syncop_inode_find (this, this, loc.gfid,
3604df
+                                 &loc.inode, NULL, NULL);
3604df
         if (ret < 0)
3604df
                 goto out;
3604df
 
3604df
diff --git a/xlators/cluster/ec/src/ec.c b/xlators/cluster/ec/src/ec.c
3604df
index 591ab25..7e295ca 100644
3604df
--- a/xlators/cluster/ec/src/ec.c
3604df
+++ b/xlators/cluster/ec/src/ec.c
3604df
@@ -772,13 +772,11 @@ ec_handle_heal_commands (call_frame_t *frame, xlator_t *this, loc_t *loc,
3604df
         if (!name || strcmp (name, GF_HEAL_INFO))
3604df
                 return -1;
3604df
 
3604df
-        dict_rsp = dict_new ();
3604df
-        if (dict_rsp == NULL)
3604df
-                goto out;
3604df
+        op_errno = -ec_get_heal_info (this, loc, &dict_rsp);
3604df
+        if (op_errno <= 0) {
3604df
+                op_errno = op_ret = 0;
3604df
+        }
3604df
 
3604df
-        if (dict_set_str (dict_rsp, "heal-info", "heal") == 0)
3604df
-                op_ret = 0;
3604df
-out:
3604df
         STACK_UNWIND_STRICT (getxattr, frame, op_ret, op_errno, dict_rsp, NULL);
3604df
         if (dict_rsp)
3604df
                 dict_unref (dict_rsp);
3604df
-- 
3604df
1.7.1
3604df