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