14f8ab
From c2b1c50f06cc59b47c9c834617dff2aed7177a78 Mon Sep 17 00:00:00 2001
14f8ab
From: Ashish Pandey <aspandey@redhat.com>
14f8ab
Date: Mon, 18 Mar 2019 12:54:54 +0530
14f8ab
Subject: [PATCH 164/169] cluster/ec: Fix handling of heal info cases without
14f8ab
 locks
14f8ab
14f8ab
When we use heal info command, it takes lot of time as in
14f8ab
some cases it takes lock on entries to find out if the
14f8ab
entry actually needs heal or not.
14f8ab
14f8ab
There are some cases where we can avoid these locks and
14f8ab
can conclude if the entry needs heal or not.
14f8ab
14f8ab
1 - We do a lookup (without lock) on an entry, which we found in
14f8ab
.glusterfs/indices/xattrop, and find that lock count is
14f8ab
zero. Now if the file contains dirty bit set on all or any
14f8ab
brick, we can say that this entry needs heal.
14f8ab
14f8ab
2 - If the lock count is one and dirty is greater than 1,
14f8ab
then it also means that some fop had left the dirty bit set
14f8ab
which made the dirty count of current fop (which has taken lock)
14f8ab
more than one. At this point also we can definitely say that
14f8ab
this entry needs heal.
14f8ab
14f8ab
This patch is modifying code to take into consideration above two
14f8ab
points.
14f8ab
It is also changing code to not to call ec_heal_inspect if ec_heal_do
14f8ab
was called from client side heal. Client side heal triggeres heal
14f8ab
only when it is sure that it requires heal.
14f8ab
14f8ab
[We have changed the code to not to call heal for lookup]
14f8ab
14f8ab
Upstream patch -
14f8ab
https://review.gluster.org/#/c/glusterfs/+/22372/
14f8ab
14f8ab
Fixes: bz#1716385
14f8ab
Change-Id: I7f09f0ecd12f65a353297aefd57026fd2bebdf9c
14f8ab
Signed-off-by: Ashish Pandey <aspandey@redhat.com>
14f8ab
Reviewed-on: https://code.engineering.redhat.com/gerrit/172579
14f8ab
Reviewed-by: Atin Mukherjee <amukherj@redhat.com>
14f8ab
Tested-by: RHGS Build Bot <nigelb@redhat.com>
14f8ab
---
14f8ab
 xlators/cluster/ec/src/ec-heal.c | 42 ++++++++++++++++------------------------
14f8ab
 1 file changed, 17 insertions(+), 25 deletions(-)
14f8ab
14f8ab
diff --git a/xlators/cluster/ec/src/ec-heal.c b/xlators/cluster/ec/src/ec-heal.c
14f8ab
index 3aa04fb..2fa1f11 100644
14f8ab
--- a/xlators/cluster/ec/src/ec-heal.c
14f8ab
+++ b/xlators/cluster/ec/src/ec-heal.c
14f8ab
@@ -2541,13 +2541,15 @@ ec_heal_do(xlator_t *this, void *data, loc_t *loc, int32_t partial)
14f8ab
 
14f8ab
     /* Mount triggers heal only when it detects that it must need heal, shd
14f8ab
      * triggers heals periodically which need not be thorough*/
14f8ab
-    ec_heal_inspect(frame, ec, loc->inode, up_subvols, _gf_false,
14f8ab
-                    !ec->shd.iamshd, &need_heal);
14f8ab
+    if (ec->shd.iamshd) {
14f8ab
+        ec_heal_inspect(frame, ec, loc->inode, up_subvols, _gf_false, _gf_false,
14f8ab
+                        &need_heal);
14f8ab
 
14f8ab
-    if (need_heal == EC_HEAL_NONEED) {
14f8ab
-        gf_msg(ec->xl->name, GF_LOG_DEBUG, 0, EC_MSG_HEAL_FAIL,
14f8ab
-               "Heal is not required for : %s ", uuid_utoa(loc->gfid));
14f8ab
-        goto out;
14f8ab
+        if (need_heal == EC_HEAL_NONEED) {
14f8ab
+            gf_msg(ec->xl->name, GF_LOG_DEBUG, 0, EC_MSG_HEAL_FAIL,
14f8ab
+                   "Heal is not required for : %s ", uuid_utoa(loc->gfid));
14f8ab
+            goto out;
14f8ab
+        }
14f8ab
     }
14f8ab
     sources = alloca0(ec->nodes);
14f8ab
     healed_sinks = alloca0(ec->nodes);
14f8ab
@@ -2902,7 +2904,7 @@ out:
14f8ab
 static int32_t
14f8ab
 _need_heal_calculate(ec_t *ec, uint64_t *dirty, unsigned char *sources,
14f8ab
                      gf_boolean_t self_locked, int32_t lock_count,
14f8ab
-                     ec_heal_need_t *need_heal)
14f8ab
+                     ec_heal_need_t *need_heal, uint64_t *versions)
14f8ab
 {
14f8ab
     int i = 0;
14f8ab
     int source_count = 0;
14f8ab
@@ -2912,7 +2914,7 @@ _need_heal_calculate(ec_t *ec, uint64_t *dirty, unsigned char *sources,
14f8ab
         *need_heal = EC_HEAL_NONEED;
14f8ab
         if (self_locked || lock_count == 0) {
14f8ab
             for (i = 0; i < ec->nodes; i++) {
14f8ab
-                if (dirty[i]) {
14f8ab
+                if (dirty[i] || (versions[i] != versions[0])) {
14f8ab
                     *need_heal = EC_HEAL_MUST;
14f8ab
                     goto out;
14f8ab
                 }
14f8ab
@@ -2928,6 +2930,9 @@ _need_heal_calculate(ec_t *ec, uint64_t *dirty, unsigned char *sources,
14f8ab
                     *need_heal = EC_HEAL_MUST;
14f8ab
                     goto out;
14f8ab
                 }
14f8ab
+                if (dirty[i] != dirty[0] || (versions[i] != versions[0])) {
14f8ab
+                    *need_heal = EC_HEAL_MAYBE;
14f8ab
+                }
14f8ab
             }
14f8ab
         }
14f8ab
     } else {
14f8ab
@@ -2948,7 +2953,6 @@ ec_need_metadata_heal(ec_t *ec, inode_t *inode, default_args_cbk_t *replies,
14f8ab
     unsigned char *healed_sinks = NULL;
14f8ab
     uint64_t *meta_versions = NULL;
14f8ab
     int ret = 0;
14f8ab
-    int i = 0;
14f8ab
 
14f8ab
     sources = alloca0(ec->nodes);
14f8ab
     healed_sinks = alloca0(ec->nodes);
14f8ab
@@ -2961,15 +2965,7 @@ ec_need_metadata_heal(ec_t *ec, inode_t *inode, default_args_cbk_t *replies,
14f8ab
     }
14f8ab
 
14f8ab
     ret = _need_heal_calculate(ec, dirty, sources, self_locked, lock_count,
14f8ab
-                               need_heal);
14f8ab
-    if (ret == ec->nodes && *need_heal == EC_HEAL_NONEED) {
14f8ab
-        for (i = 1; i < ec->nodes; i++) {
14f8ab
-            if (meta_versions[i] != meta_versions[0]) {
14f8ab
-                *need_heal = EC_HEAL_MUST;
14f8ab
-                goto out;
14f8ab
-            }
14f8ab
-        }
14f8ab
-    }
14f8ab
+                               need_heal, meta_versions);
14f8ab
 out:
14f8ab
     return ret;
14f8ab
 }
14f8ab
@@ -3005,7 +3001,7 @@ ec_need_data_heal(ec_t *ec, inode_t *inode, default_args_cbk_t *replies,
14f8ab
     }
14f8ab
 
14f8ab
     ret = _need_heal_calculate(ec, dirty, sources, self_locked, lock_count,
14f8ab
-                               need_heal);
14f8ab
+                               need_heal, data_versions);
14f8ab
 out:
14f8ab
     return ret;
14f8ab
 }
14f8ab
@@ -3033,7 +3029,7 @@ ec_need_entry_heal(ec_t *ec, inode_t *inode, default_args_cbk_t *replies,
14f8ab
     }
14f8ab
 
14f8ab
     ret = _need_heal_calculate(ec, dirty, sources, self_locked, lock_count,
14f8ab
-                               need_heal);
14f8ab
+                               need_heal, data_versions);
14f8ab
 out:
14f8ab
     return ret;
14f8ab
 }
14f8ab
@@ -3131,10 +3127,6 @@ ec_heal_inspect(call_frame_t *frame, ec_t *ec, inode_t *inode,
14f8ab
 need_heal:
14f8ab
     ret = ec_need_heal(ec, inode, replies, lock_count, self_locked, thorough,
14f8ab
                        need_heal);
14f8ab
-
14f8ab
-    if (!self_locked && *need_heal == EC_HEAL_MUST) {
14f8ab
-        *need_heal = EC_HEAL_MAYBE;
14f8ab
-    }
14f8ab
 out:
14f8ab
     cluster_replies_wipe(replies, ec->nodes);
14f8ab
     loc_wipe(&loc;;
14f8ab
@@ -3220,7 +3212,7 @@ ec_get_heal_info(xlator_t *this, loc_t *entry_loc, dict_t **dict_rsp)
14f8ab
 
14f8ab
     ret = ec_heal_inspect(frame, ec, loc.inode, up_subvols, _gf_false,
14f8ab
                           _gf_false, &need_heal);
14f8ab
-    if (ret == ec->nodes && need_heal == EC_HEAL_NONEED) {
14f8ab
+    if (ret == ec->nodes && need_heal != EC_HEAL_MAYBE) {
14f8ab
         goto set_heal;
14f8ab
     }
14f8ab
     need_heal = EC_HEAL_NONEED;
14f8ab
-- 
14f8ab
1.8.3.1
14f8ab