d2787b
From 5294c82e0528059b10cbaab7805b20e76ffdd66b Mon Sep 17 00:00:00 2001
d2787b
From: mohit84 <moagrawa@redhat.com>
d2787b
Date: Mon, 30 Nov 2020 17:39:53 +0530
d2787b
Subject: [PATCH 510/511] glusterd[brick_mux]: Optimize friend handshake code
d2787b
 to avoid call_bail (#1614)
d2787b
d2787b
During glusterd handshake glusterd received a volume dictionary
d2787b
from peer end to compare the own volume dictionary data.If the options
d2787b
are differ it sets the key to recognize volume options are changed
d2787b
and call import syntask to delete/start the volume.In brick_mux
d2787b
environment while number of volumes are high(5k) the dict api in function
d2787b
glusterd_compare_friend_volume takes time because the function
d2787b
glusterd_handle_friend_req saves all peer volume data in a single dictionary.
d2787b
Due to time taken by the function glusterd_handle_friend RPC requests receives
d2787b
a call_bail from a peer end gluster(CLI) won't be able to show volume status.
d2787b
d2787b
Solution: To optimize the code done below changes
d2787b
1) Populate a new specific dictionary to save the peer end version specific
d2787b
   data so that function won't take much time to take the decision about the
d2787b
   peer end has some volume updates.
d2787b
2) In case of volume has differ version set the key in status_arr instead
d2787b
   of saving in a dictionary to make the operation is faster.
d2787b
d2787b
Note: To validate the changes followed below procedure
d2787b
1) Setup 5100 distributed volumes 3x1
d2787b
2) Enable brick_mux
d2787b
3) Start all the volumes
d2787b
4) Kill all gluster processes on 3rd node
d2787b
5) Run a loop to update volume option on a 1st node
d2787b
   for i in {1..5100}; do gluster v set vol$i performance.open-behind off; done
d2787b
6) Start the glusterd process on the 3rd node
d2787b
7) Wait to finish handshake and check there should not be any call_bail message
d2787b
   in the logs
d2787b
d2787b
> Change-Id: Ibad7c23988539cc369ecc39dea2ea6985470bee1
d2787b
> Fixes: #1613
d2787b
> Signed-off-by: Mohit Agrawal <moagrawa@redhat.com>
d2787b
> (Cherry pick from commit 12545d91eed27ff9abb0505a12c7d4e75b45a53e)
d2787b
> (Reviewed on upstream link https://github.com/gluster/glusterfs/issues/1613)
d2787b
d2787b
Change-Id: Ibad7c23988539cc369ecc39dea2ea6985470bee1
d2787b
BUG: 1898784
d2787b
Signed-off-by: Mohit Agrawal <moagrawa@redhat.com>
d2787b
Reviewed-on: https://code.engineering.redhat.com/gerrit/221193
d2787b
Tested-by: RHGS Build Bot <nigelb@redhat.com>
d2787b
Reviewed-by: Sunil Kumar Heggodu Gopala Acharya <sheggodu@redhat.com>
d2787b
---
d2787b
 libglusterfs/src/ctx.c                       |   4 +
d2787b
 libglusterfs/src/dict.c                      | 166 ++++++++++++++++++++++++++-
d2787b
 libglusterfs/src/globals.c                   |   2 -
d2787b
 libglusterfs/src/glusterfs/dict.h            |   5 +
d2787b
 libglusterfs/src/glusterfs/globals.h         |   2 +
d2787b
 libglusterfs/src/libglusterfs.sym            |   1 +
d2787b
 xlators/mgmt/glusterd/src/glusterd-handler.c |  39 ++++---
d2787b
 xlators/mgmt/glusterd/src/glusterd-sm.c      |   6 +-
d2787b
 xlators/mgmt/glusterd/src/glusterd-sm.h      |   1 +
d2787b
 xlators/mgmt/glusterd/src/glusterd-utils.c   | 148 ++++++++++++++----------
d2787b
 xlators/mgmt/glusterd/src/glusterd-utils.h   |   2 +-
d2787b
 xlators/mgmt/glusterd/src/glusterd.h         |   8 +-
d2787b
 12 files changed, 301 insertions(+), 83 deletions(-)
d2787b
d2787b
diff --git a/libglusterfs/src/ctx.c b/libglusterfs/src/ctx.c
d2787b
index 4a001c2..ae1a77a 100644
d2787b
--- a/libglusterfs/src/ctx.c
d2787b
+++ b/libglusterfs/src/ctx.c
d2787b
@@ -14,6 +14,7 @@
d2787b
 #include "glusterfs/glusterfs.h"
d2787b
 #include "timer-wheel.h"
d2787b
 
d2787b
+glusterfs_ctx_t *global_ctx = NULL;
d2787b
 glusterfs_ctx_t *
d2787b
 glusterfs_ctx_new()
d2787b
 {
d2787b
@@ -51,6 +52,9 @@ glusterfs_ctx_new()
d2787b
     GF_ATOMIC_INIT(ctx->stats.max_dict_pairs, 0);
d2787b
     GF_ATOMIC_INIT(ctx->stats.total_pairs_used, 0);
d2787b
     GF_ATOMIC_INIT(ctx->stats.total_dicts_used, 0);
d2787b
+
d2787b
+    if (!global_ctx)
d2787b
+        global_ctx = ctx;
d2787b
 out:
d2787b
     return ctx;
d2787b
 }
d2787b
diff --git a/libglusterfs/src/dict.c b/libglusterfs/src/dict.c
d2787b
index d8cdda4..e5f619c 100644
d2787b
--- a/libglusterfs/src/dict.c
d2787b
+++ b/libglusterfs/src/dict.c
d2787b
@@ -56,7 +56,13 @@ struct dict_cmp {
d2787b
 static data_t *
d2787b
 get_new_data()
d2787b
 {
d2787b
-    data_t *data = mem_get(THIS->ctx->dict_data_pool);
d2787b
+    data_t *data = NULL;
d2787b
+
d2787b
+    if (global_ctx) {
d2787b
+        data = mem_get(global_ctx->dict_data_pool);
d2787b
+    } else {
d2787b
+        data = mem_get(THIS->ctx->dict_data_pool);
d2787b
+    }
d2787b
 
d2787b
     if (!data)
d2787b
         return NULL;
d2787b
@@ -3503,3 +3509,161 @@ unlock:
d2787b
     UNLOCK(&dict->lock);
d2787b
     return 0;
d2787b
 }
d2787b
+
d2787b
+/* Popluate specific dictionary on the basis of passed key array at the
d2787b
+   time of unserialize buffer
d2787b
+*/
d2787b
+int32_t
d2787b
+dict_unserialize_specific_keys(char *orig_buf, int32_t size, dict_t **fill,
d2787b
+                               char **suffix_key_arr, dict_t **specific_dict,
d2787b
+                               int totkeycount)
d2787b
+{
d2787b
+    char *buf = orig_buf;
d2787b
+    int ret = -1;
d2787b
+    int32_t count = 0;
d2787b
+    int i = 0;
d2787b
+    int j = 0;
d2787b
+
d2787b
+    data_t *value = NULL;
d2787b
+    char *key = NULL;
d2787b
+    int32_t keylen = 0;
d2787b
+    int32_t vallen = 0;
d2787b
+    int32_t hostord = 0;
d2787b
+    xlator_t *this = NULL;
d2787b
+    int32_t keylenarr[totkeycount];
d2787b
+
d2787b
+    this = THIS;
d2787b
+    GF_ASSERT(this);
d2787b
+
d2787b
+    if (!buf) {
d2787b
+        gf_msg_callingfn("dict", GF_LOG_WARNING, EINVAL, LG_MSG_INVALID_ARG,
d2787b
+                         "buf is null!");
d2787b
+        goto out;
d2787b
+    }
d2787b
+
d2787b
+    if (size == 0) {
d2787b
+        gf_msg_callingfn("dict", GF_LOG_ERROR, EINVAL, LG_MSG_INVALID_ARG,
d2787b
+                         "size is 0!");
d2787b
+        goto out;
d2787b
+    }
d2787b
+
d2787b
+    if (!fill) {
d2787b
+        gf_msg_callingfn("dict", GF_LOG_ERROR, EINVAL, LG_MSG_INVALID_ARG,
d2787b
+                         "fill is null!");
d2787b
+        goto out;
d2787b
+    }
d2787b
+
d2787b
+    if (!*fill) {
d2787b
+        gf_msg_callingfn("dict", GF_LOG_ERROR, EINVAL, LG_MSG_INVALID_ARG,
d2787b
+                         "*fill is null!");
d2787b
+        goto out;
d2787b
+    }
d2787b
+
d2787b
+    if ((buf + DICT_HDR_LEN) > (orig_buf + size)) {
d2787b
+        gf_msg_callingfn("dict", GF_LOG_ERROR, 0, LG_MSG_UNDERSIZED_BUF,
d2787b
+                         "undersized buffer "
d2787b
+                         "passed. available (%lu) < required (%lu)",
d2787b
+                         (long)(orig_buf + size), (long)(buf + DICT_HDR_LEN));
d2787b
+        goto out;
d2787b
+    }
d2787b
+
d2787b
+    memcpy(&hostord, buf, sizeof(hostord));
d2787b
+    count = ntoh32(hostord);
d2787b
+    buf += DICT_HDR_LEN;
d2787b
+
d2787b
+    if (count < 0) {
d2787b
+        gf_smsg("dict", GF_LOG_ERROR, 0, LG_MSG_COUNT_LESS_THAN_ZERO,
d2787b
+                "count=%d", count, NULL);
d2787b
+        goto out;
d2787b
+    }
d2787b
+
d2787b
+    /* Compute specific key length and save in array */
d2787b
+    for (i = 0; i < totkeycount; i++) {
d2787b
+        keylenarr[i] = strlen(suffix_key_arr[i]);
d2787b
+    }
d2787b
+
d2787b
+    for (i = 0; i < count; i++) {
d2787b
+        if ((buf + DICT_DATA_HDR_KEY_LEN) > (orig_buf + size)) {
d2787b
+            gf_msg_callingfn("dict", GF_LOG_ERROR, 0, LG_MSG_UNDERSIZED_BUF,
d2787b
+                             "undersized "
d2787b
+                             "buffer passed. available (%lu) < "
d2787b
+                             "required (%lu)",
d2787b
+                             (long)(orig_buf + size),
d2787b
+                             (long)(buf + DICT_DATA_HDR_KEY_LEN));
d2787b
+            goto out;
d2787b
+        }
d2787b
+        memcpy(&hostord, buf, sizeof(hostord));
d2787b
+        keylen = ntoh32(hostord);
d2787b
+        buf += DICT_DATA_HDR_KEY_LEN;
d2787b
+
d2787b
+        if ((buf + DICT_DATA_HDR_VAL_LEN) > (orig_buf + size)) {
d2787b
+            gf_msg_callingfn("dict", GF_LOG_ERROR, 0, LG_MSG_UNDERSIZED_BUF,
d2787b
+                             "undersized "
d2787b
+                             "buffer passed. available (%lu) < "
d2787b
+                             "required (%lu)",
d2787b
+                             (long)(orig_buf + size),
d2787b
+                             (long)(buf + DICT_DATA_HDR_VAL_LEN));
d2787b
+            goto out;
d2787b
+        }
d2787b
+        memcpy(&hostord, buf, sizeof(hostord));
d2787b
+        vallen = ntoh32(hostord);
d2787b
+        buf += DICT_DATA_HDR_VAL_LEN;
d2787b
+
d2787b
+        if ((keylen < 0) || (vallen < 0)) {
d2787b
+            gf_msg_callingfn("dict", GF_LOG_ERROR, 0, LG_MSG_UNDERSIZED_BUF,
d2787b
+                             "undersized length passed "
d2787b
+                             "key:%d val:%d",
d2787b
+                             keylen, vallen);
d2787b
+            goto out;
d2787b
+        }
d2787b
+        if ((buf + keylen) > (orig_buf + size)) {
d2787b
+            gf_msg_callingfn("dict", GF_LOG_ERROR, 0, LG_MSG_UNDERSIZED_BUF,
d2787b
+                             "undersized buffer passed. "
d2787b
+                             "available (%lu) < required (%lu)",
d2787b
+                             (long)(orig_buf + size), (long)(buf + keylen));
d2787b
+            goto out;
d2787b
+        }
d2787b
+        key = buf;
d2787b
+        buf += keylen + 1; /* for '\0' */
d2787b
+
d2787b
+        if ((buf + vallen) > (orig_buf + size)) {
d2787b
+            gf_msg_callingfn("dict", GF_LOG_ERROR, 0, LG_MSG_UNDERSIZED_BUF,
d2787b
+                             "undersized buffer passed. "
d2787b
+                             "available (%lu) < required (%lu)",
d2787b
+                             (long)(orig_buf + size), (long)(buf + vallen));
d2787b
+            goto out;
d2787b
+        }
d2787b
+        value = get_new_data();
d2787b
+
d2787b
+        if (!value) {
d2787b
+            ret = -1;
d2787b
+            goto out;
d2787b
+        }
d2787b
+        value->len = vallen;
d2787b
+        value->data = gf_memdup(buf, vallen);
d2787b
+        value->data_type = GF_DATA_TYPE_STR_OLD;
d2787b
+        value->is_static = _gf_false;
d2787b
+        buf += vallen;
d2787b
+
d2787b
+        ret = dict_addn(*fill, key, keylen, value);
d2787b
+        if (ret < 0) {
d2787b
+            data_destroy(value);
d2787b
+            goto out;
d2787b
+        }
d2787b
+        for (j = 0; j < totkeycount; j++) {
d2787b
+            if (keylen > keylenarr[j]) {
d2787b
+                if (!strcmp(key + keylen - keylenarr[j], suffix_key_arr[j])) {
d2787b
+                    ret = dict_addn(*specific_dict, key, keylen, value);
d2787b
+                    break;
d2787b
+                }
d2787b
+            }
d2787b
+        }
d2787b
+
d2787b
+        if (ret < 0)
d2787b
+            goto out;
d2787b
+    }
d2787b
+
d2787b
+    ret = 0;
d2787b
+out:
d2787b
+    return ret;
d2787b
+}
d2787b
diff --git a/libglusterfs/src/globals.c b/libglusterfs/src/globals.c
d2787b
index e433ee8..30c15b6 100644
d2787b
--- a/libglusterfs/src/globals.c
d2787b
+++ b/libglusterfs/src/globals.c
d2787b
@@ -96,7 +96,6 @@ const char *gf_upcall_list[GF_UPCALL_FLAGS_MAXVALUE] = {
d2787b
 /* This global ctx is a bad hack to prevent some of the libgfapi crashes.
d2787b
  * This should be removed once the patch on resource pool is accepted
d2787b
  */
d2787b
-glusterfs_ctx_t *global_ctx = NULL;
d2787b
 pthread_mutex_t global_ctx_mutex = PTHREAD_MUTEX_INITIALIZER;
d2787b
 xlator_t global_xlator;
d2787b
 static int gf_global_mem_acct_enable = 1;
d2787b
@@ -236,7 +235,6 @@ __glusterfs_this_location()
d2787b
     if (*this_location == NULL) {
d2787b
         thread_xlator = &global_xlator;
d2787b
     }
d2787b
-
d2787b
     return this_location;
d2787b
 }
d2787b
 
d2787b
diff --git a/libglusterfs/src/glusterfs/dict.h b/libglusterfs/src/glusterfs/dict.h
d2787b
index 8239c7a..6e469c7 100644
d2787b
--- a/libglusterfs/src/glusterfs/dict.h
d2787b
+++ b/libglusterfs/src/glusterfs/dict.h
d2787b
@@ -423,4 +423,9 @@ dict_has_key_from_array(dict_t *dict, char **strings, gf_boolean_t *result);
d2787b
 
d2787b
 int
d2787b
 dict_serialized_length_lk(dict_t *this);
d2787b
+
d2787b
+int32_t
d2787b
+dict_unserialize_specific_keys(char *orig_buf, int32_t size, dict_t **fill,
d2787b
+                               char **specific_key_arr, dict_t **specific_dict,
d2787b
+                               int totkeycount);
d2787b
 #endif
d2787b
diff --git a/libglusterfs/src/glusterfs/globals.h b/libglusterfs/src/glusterfs/globals.h
d2787b
index cc145cd..33fb023 100644
d2787b
--- a/libglusterfs/src/glusterfs/globals.h
d2787b
+++ b/libglusterfs/src/glusterfs/globals.h
d2787b
@@ -199,4 +199,6 @@ int
d2787b
 gf_global_mem_acct_enable_get(void);
d2787b
 int
d2787b
 gf_global_mem_acct_enable_set(int val);
d2787b
+
d2787b
+extern glusterfs_ctx_t *global_ctx;
d2787b
 #endif /* !_GLOBALS_H */
d2787b
diff --git a/libglusterfs/src/libglusterfs.sym b/libglusterfs/src/libglusterfs.sym
d2787b
index d060292..bc770e2 100644
d2787b
--- a/libglusterfs/src/libglusterfs.sym
d2787b
+++ b/libglusterfs/src/libglusterfs.sym
d2787b
@@ -436,6 +436,7 @@ dict_clear_flag
d2787b
 dict_check_flag
d2787b
 dict_unref
d2787b
 dict_unserialize
d2787b
+dict_unserialize_specific_keys
d2787b
 drop_token
d2787b
 eh_destroy
d2787b
 eh_dump
d2787b
diff --git a/xlators/mgmt/glusterd/src/glusterd-handler.c b/xlators/mgmt/glusterd/src/glusterd-handler.c
d2787b
index b8799ab..908361c 100644
d2787b
--- a/xlators/mgmt/glusterd/src/glusterd-handler.c
d2787b
+++ b/xlators/mgmt/glusterd/src/glusterd-handler.c
d2787b
@@ -86,6 +86,9 @@ glusterd_big_locked_handler(rpcsvc_request_t *req, rpcsvc_actor actor_fn)
d2787b
     return ret;
d2787b
 }
d2787b
 
d2787b
+static char *specific_key_suffix[] = {".quota-cksum", ".ckusm", ".version",
d2787b
+                                      ".quota-version", ".name"};
d2787b
+
d2787b
 static int
d2787b
 glusterd_handle_friend_req(rpcsvc_request_t *req, uuid_t uuid, char *hostname,
d2787b
                            int port, gd1_mgmt_friend_req *friend_req)
d2787b
@@ -97,6 +100,8 @@ glusterd_handle_friend_req(rpcsvc_request_t *req, uuid_t uuid, char *hostname,
d2787b
     char rhost[UNIX_PATH_MAX + 1] = {0};
d2787b
     uuid_t friend_uuid = {0};
d2787b
     dict_t *dict = NULL;
d2787b
+    dict_t *peer_ver = NULL;
d2787b
+    int totcount = sizeof(specific_key_suffix) / sizeof(specific_key_suffix[0]);
d2787b
 
d2787b
     gf_uuid_parse(uuid_utoa(uuid), friend_uuid);
d2787b
     if (!port)
d2787b
@@ -104,8 +109,19 @@ glusterd_handle_friend_req(rpcsvc_request_t *req, uuid_t uuid, char *hostname,
d2787b
 
d2787b
     ret = glusterd_remote_hostname_get(req, rhost, sizeof(rhost));
d2787b
 
d2787b
+    ctx = GF_CALLOC(1, sizeof(*ctx), gf_gld_mt_friend_req_ctx_t);
d2787b
+    dict = dict_new();
d2787b
+    peer_ver = dict_new();
d2787b
+
d2787b
     RCU_READ_LOCK;
d2787b
 
d2787b
+    if (!ctx || !dict || !peer_ver) {
d2787b
+        gf_msg("glusterd", GF_LOG_ERROR, ENOMEM, GD_MSG_NO_MEMORY,
d2787b
+               "Unable to allocate memory");
d2787b
+        ret = -1;
d2787b
+        goto out;
d2787b
+    }
d2787b
+
d2787b
     peerinfo = glusterd_peerinfo_find(uuid, rhost);
d2787b
 
d2787b
     if (peerinfo == NULL) {
d2787b
@@ -130,28 +146,14 @@ glusterd_handle_friend_req(rpcsvc_request_t *req, uuid_t uuid, char *hostname,
d2787b
     event->peername = gf_strdup(peerinfo->hostname);
d2787b
     gf_uuid_copy(event->peerid, peerinfo->uuid);
d2787b
 
d2787b
-    ctx = GF_CALLOC(1, sizeof(*ctx), gf_gld_mt_friend_req_ctx_t);
d2787b
-
d2787b
-    if (!ctx) {
d2787b
-        gf_msg("glusterd", GF_LOG_ERROR, ENOMEM, GD_MSG_NO_MEMORY,
d2787b
-               "Unable to allocate memory");
d2787b
-        ret = -1;
d2787b
-        goto out;
d2787b
-    }
d2787b
-
d2787b
     gf_uuid_copy(ctx->uuid, uuid);
d2787b
     if (hostname)
d2787b
         ctx->hostname = gf_strdup(hostname);
d2787b
     ctx->req = req;
d2787b
 
d2787b
-    dict = dict_new();
d2787b
-    if (!dict) {
d2787b
-        ret = -1;
d2787b
-        goto out;
d2787b
-    }
d2787b
-
d2787b
-    ret = dict_unserialize(friend_req->vols.vols_val, friend_req->vols.vols_len,
d2787b
-                           &dict);
d2787b
+    ret = dict_unserialize_specific_keys(
d2787b
+        friend_req->vols.vols_val, friend_req->vols.vols_len, &dict,
d2787b
+        specific_key_suffix, &peer_ver, totcount);
d2787b
 
d2787b
     if (ret)
d2787b
         goto out;
d2787b
@@ -159,6 +161,7 @@ glusterd_handle_friend_req(rpcsvc_request_t *req, uuid_t uuid, char *hostname,
d2787b
         dict->extra_stdfree = friend_req->vols.vols_val;
d2787b
 
d2787b
     ctx->vols = dict;
d2787b
+    ctx->peer_ver = peer_ver;
d2787b
     event->ctx = ctx;
d2787b
 
d2787b
     ret = glusterd_friend_sm_inject_event(event);
d2787b
@@ -188,6 +191,8 @@ out:
d2787b
         } else {
d2787b
             free(friend_req->vols.vols_val);
d2787b
         }
d2787b
+        if (peer_ver)
d2787b
+            dict_unref(peer_ver);
d2787b
         if (event)
d2787b
             GF_FREE(event->peername);
d2787b
         GF_FREE(event);
d2787b
diff --git a/xlators/mgmt/glusterd/src/glusterd-sm.c b/xlators/mgmt/glusterd/src/glusterd-sm.c
d2787b
index 044da3d..d10a792 100644
d2787b
--- a/xlators/mgmt/glusterd/src/glusterd-sm.c
d2787b
+++ b/xlators/mgmt/glusterd/src/glusterd-sm.c
d2787b
@@ -106,6 +106,8 @@ glusterd_destroy_friend_req_ctx(glusterd_friend_req_ctx_t *ctx)
d2787b
 
d2787b
     if (ctx->vols)
d2787b
         dict_unref(ctx->vols);
d2787b
+    if (ctx->peer_ver)
d2787b
+        dict_unref(ctx->peer_ver);
d2787b
     GF_FREE(ctx->hostname);
d2787b
     GF_FREE(ctx);
d2787b
 }
d2787b
@@ -936,8 +938,8 @@ glusterd_ac_handle_friend_add_req(glusterd_friend_sm_event_t *event, void *ctx)
d2787b
     // Build comparison logic here.
d2787b
     pthread_mutex_lock(&conf->import_volumes);
d2787b
     {
d2787b
-        ret = glusterd_compare_friend_data(ev_ctx->vols, &status,
d2787b
-                                           event->peername);
d2787b
+        ret = glusterd_compare_friend_data(ev_ctx->vols, ev_ctx->peer_ver,
d2787b
+                                           &status, event->peername);
d2787b
         if (ret) {
d2787b
             pthread_mutex_unlock(&conf->import_volumes);
d2787b
             goto out;
d2787b
diff --git a/xlators/mgmt/glusterd/src/glusterd-sm.h b/xlators/mgmt/glusterd/src/glusterd-sm.h
d2787b
index ce008ac..efdf68e 100644
d2787b
--- a/xlators/mgmt/glusterd/src/glusterd-sm.h
d2787b
+++ b/xlators/mgmt/glusterd/src/glusterd-sm.h
d2787b
@@ -174,6 +174,7 @@ typedef struct glusterd_friend_req_ctx_ {
d2787b
     rpcsvc_request_t *req;
d2787b
     int port;
d2787b
     dict_t *vols;
d2787b
+    dict_t *peer_ver;  // Dictionary to save peer ver data
d2787b
 } glusterd_friend_req_ctx_t;
d2787b
 
d2787b
 typedef struct glusterd_friend_update_ctx_ {
d2787b
diff --git a/xlators/mgmt/glusterd/src/glusterd-utils.c b/xlators/mgmt/glusterd/src/glusterd-utils.c
d2787b
index f7030fb..cf32bd9 100644
d2787b
--- a/xlators/mgmt/glusterd/src/glusterd-utils.c
d2787b
+++ b/xlators/mgmt/glusterd/src/glusterd-utils.c
d2787b
@@ -3709,12 +3709,14 @@ out:
d2787b
     return ret;
d2787b
 }
d2787b
 
d2787b
-int32_t
d2787b
-glusterd_compare_friend_volume(dict_t *peer_data, int32_t count,
d2787b
-                               int32_t *status, char *hostname)
d2787b
+static int32_t
d2787b
+glusterd_compare_friend_volume(dict_t *peer_data,
d2787b
+                               glusterd_friend_synctask_args_t *arg,
d2787b
+                               int32_t count, int32_t *status, char *hostname)
d2787b
 {
d2787b
     int32_t ret = -1;
d2787b
     char key[64] = "";
d2787b
+    char key_prefix[32];
d2787b
     int keylen;
d2787b
     glusterd_volinfo_t *volinfo = NULL;
d2787b
     char *volname = NULL;
d2787b
@@ -3726,15 +3728,20 @@ glusterd_compare_friend_volume(dict_t *peer_data, int32_t count,
d2787b
     xlator_t *this = NULL;
d2787b
 
d2787b
     GF_ASSERT(peer_data);
d2787b
+    GF_ASSERT(arg);
d2787b
     GF_ASSERT(status);
d2787b
 
d2787b
     this = THIS;
d2787b
     GF_ASSERT(this);
d2787b
 
d2787b
-    keylen = snprintf(key, sizeof(key), "volume%d.name", count);
d2787b
-    ret = dict_get_strn(peer_data, key, keylen, &volname);
d2787b
-    if (ret)
d2787b
+    snprintf(key_prefix, sizeof(key_prefix), "volume%d", count);
d2787b
+    keylen = snprintf(key, sizeof(key), "%s.name", key_prefix);
d2787b
+    ret = dict_get_strn(arg->peer_ver_data, key, keylen, &volname);
d2787b
+    if (ret) {
d2787b
+        gf_smsg(this->name, GF_LOG_ERROR, errno, GD_MSG_DICT_GET_FAILED,
d2787b
+                "Key=%s is NULL in peer_ver_data", key, NULL);
d2787b
         goto out;
d2787b
+    }
d2787b
 
d2787b
     ret = glusterd_volinfo_find(volname, &volinfo);
d2787b
     if (ret) {
d2787b
@@ -3750,10 +3757,13 @@ glusterd_compare_friend_volume(dict_t *peer_data, int32_t count,
d2787b
         goto out;
d2787b
     }
d2787b
 
d2787b
-    keylen = snprintf(key, sizeof(key), "volume%d.version", count);
d2787b
-    ret = dict_get_int32n(peer_data, key, keylen, &version);
d2787b
-    if (ret)
d2787b
+    keylen = snprintf(key, sizeof(key), "%s.version", key_prefix);
d2787b
+    ret = dict_get_int32n(arg->peer_ver_data, key, keylen, &version);
d2787b
+    if (ret) {
d2787b
+        gf_smsg(this->name, GF_LOG_ERROR, errno, GD_MSG_DICT_GET_FAILED,
d2787b
+                "Key=%s is NULL in peer_ver_data", key, NULL);
d2787b
         goto out;
d2787b
+    }
d2787b
 
d2787b
     if (version > volinfo->version) {
d2787b
         // Mismatch detected
d2787b
@@ -3772,10 +3782,13 @@ glusterd_compare_friend_volume(dict_t *peer_data, int32_t count,
d2787b
 
d2787b
     // Now, versions are same, compare cksums.
d2787b
     //
d2787b
-    snprintf(key, sizeof(key), "volume%d.ckusm", count);
d2787b
-    ret = dict_get_uint32(peer_data, key, &cksum);
d2787b
-    if (ret)
d2787b
+    snprintf(key, sizeof(key), "%s.ckusm", key_prefix);
d2787b
+    ret = dict_get_uint32(arg->peer_ver_data, key, &cksum);
d2787b
+    if (ret) {
d2787b
+        gf_smsg(this->name, GF_LOG_ERROR, errno, GD_MSG_DICT_GET_FAILED,
d2787b
+                "Key=%s is NULL in peer_ver_data", key, NULL);
d2787b
         goto out;
d2787b
+    }
d2787b
 
d2787b
     if (cksum != volinfo->cksum) {
d2787b
         ret = 0;
d2787b
@@ -3790,8 +3803,8 @@ glusterd_compare_friend_volume(dict_t *peer_data, int32_t count,
d2787b
     if (!dict_get_sizen(volinfo->dict, VKEY_FEATURES_QUOTA))
d2787b
         goto skip_quota;
d2787b
 
d2787b
-    snprintf(key, sizeof(key), "volume%d.quota-version", count);
d2787b
-    ret = dict_get_uint32(peer_data, key, &quota_version);
d2787b
+    snprintf(key, sizeof(key), "%s.quota-version", key_prefix);
d2787b
+    ret = dict_get_uint32(arg->peer_ver_data, key, &quota_version);
d2787b
     if (ret) {
d2787b
         gf_msg_debug(this->name, 0,
d2787b
                      "quota-version key absent for"
d2787b
@@ -3809,6 +3822,7 @@ glusterd_compare_friend_volume(dict_t *peer_data, int32_t count,
d2787b
                    "%d on peer %s",
d2787b
                    volinfo->volname, volinfo->quota_conf_version, quota_version,
d2787b
                    hostname);
d2787b
+            GF_ATOMIC_INIT(volinfo->volpeerupdate, 1);
d2787b
             *status = GLUSTERD_VOL_COMP_UPDATE_REQ;
d2787b
             goto out;
d2787b
         } else if (quota_version < volinfo->quota_conf_version) {
d2787b
@@ -3819,8 +3833,8 @@ glusterd_compare_friend_volume(dict_t *peer_data, int32_t count,
d2787b
 
d2787b
     // Now, versions are same, compare cksums.
d2787b
     //
d2787b
-    snprintf(key, sizeof(key), "volume%d.quota-cksum", count);
d2787b
-    ret = dict_get_uint32(peer_data, key, &quota_cksum);
d2787b
+    snprintf(key, sizeof(key), "%s.quota-cksum", key_prefix);
d2787b
+    ret = dict_get_uint32(arg->peer_ver_data, key, &quota_cksum);
d2787b
     if (ret) {
d2787b
         gf_msg_debug(this->name, 0,
d2787b
                      "quota checksum absent for "
d2787b
@@ -3846,13 +3860,12 @@ skip_quota:
d2787b
     *status = GLUSTERD_VOL_COMP_SCS;
d2787b
 
d2787b
 out:
d2787b
-    keylen = snprintf(key, sizeof(key), "volume%d.update", count);
d2787b
-
d2787b
     if (*status == GLUSTERD_VOL_COMP_UPDATE_REQ) {
d2787b
-        ret = dict_set_int32n(peer_data, key, keylen, 1);
d2787b
-    } else {
d2787b
-        ret = dict_set_int32n(peer_data, key, keylen, 0);
d2787b
+        /*Set the status to ensure volume is updated on the peer
d2787b
+         */
d2787b
+        arg->status_arr[(count / 64)] ^= 1UL << (count % 64);
d2787b
     }
d2787b
+
d2787b
     if (*status == GLUSTERD_VOL_COMP_RJT) {
d2787b
         gf_event(EVENT_COMPARE_FRIEND_VOLUME_FAILED, "volume=%s",
d2787b
                  volinfo->volname);
d2787b
@@ -4935,8 +4948,9 @@ out:
d2787b
     return ret;
d2787b
 }
d2787b
 
d2787b
-int32_t
d2787b
-glusterd_import_friend_volume(dict_t *peer_data, int count)
d2787b
+static int32_t
d2787b
+glusterd_import_friend_volume(dict_t *peer_data, int count,
d2787b
+                              glusterd_friend_synctask_args_t *arg)
d2787b
 {
d2787b
     int32_t ret = -1;
d2787b
     glusterd_conf_t *priv = NULL;
d2787b
@@ -4954,10 +4968,27 @@ glusterd_import_friend_volume(dict_t *peer_data, int count)
d2787b
     priv = this->private;
d2787b
     GF_ASSERT(priv);
d2787b
 
d2787b
-    ret = snprintf(key, sizeof(key), "volume%d.update", count);
d2787b
-    ret = dict_get_int32n(peer_data, key, ret, &update);
d2787b
-    if (ret || !update) {
d2787b
+    if (arg) {
d2787b
+        /*Check if the volume options are updated on the other peers
d2787b
+         */
d2787b
+        update = (1UL & (arg->status_arr[(count / 64)] >> (count % 64)));
d2787b
+    } else {
d2787b
+        ret = snprintf(key, sizeof(key), "volume%d.update", count);
d2787b
+        ret = dict_get_int32n(peer_data, key, ret, &update);
d2787b
+        if (ret) {
d2787b
+            gf_smsg(this->name, GF_LOG_ERROR, errno, GD_MSG_DICT_GET_FAILED,
d2787b
+                    "Key=%s", key, NULL);
d2787b
+            goto out;
d2787b
+        }
d2787b
+    }
d2787b
+
d2787b
+    if (!update) {
d2787b
         /* if update is 0 that means the volume is not imported */
d2787b
+        gf_log(this->name, GF_LOG_DEBUG,
d2787b
+               "The volume%d does"
d2787b
+               " not have any peer change",
d2787b
+               count);
d2787b
+        ret = 0;
d2787b
         goto out;
d2787b
     }
d2787b
 
d2787b
@@ -5045,6 +5076,8 @@ glusterd_import_friend_volumes_synctask(void *opaque)
d2787b
     glusterd_conf_t *conf = NULL;
d2787b
     dict_t *peer_data = NULL;
d2787b
     glusterd_friend_synctask_args_t *arg = NULL;
d2787b
+    uint64_t bm = 0;
d2787b
+    uint64_t mask = 0;
d2787b
 
d2787b
     this = THIS;
d2787b
     GF_ASSERT(this);
d2787b
@@ -5056,17 +5089,7 @@ glusterd_import_friend_volumes_synctask(void *opaque)
d2787b
     if (!arg)
d2787b
         goto out;
d2787b
 
d2787b
-    peer_data = dict_new();
d2787b
-    if (!peer_data) {
d2787b
-        goto out;
d2787b
-    }
d2787b
-
d2787b
-    ret = dict_unserialize(arg->dict_buf, arg->dictlen, &peer_data);
d2787b
-    if (ret) {
d2787b
-        errno = ENOMEM;
d2787b
-        goto out;
d2787b
-    }
d2787b
-
d2787b
+    peer_data = arg->peer_data;
d2787b
     ret = dict_get_int32n(peer_data, "count", SLEN("count"), &count);
d2787b
     if (ret)
d2787b
         goto out;
d2787b
@@ -5083,11 +5106,18 @@ glusterd_import_friend_volumes_synctask(void *opaque)
d2787b
     conf->restart_bricks = _gf_true;
d2787b
 
d2787b
     while (i <= count) {
d2787b
-        ret = glusterd_import_friend_volume(peer_data, i);
d2787b
-        if (ret) {
d2787b
-            break;
d2787b
+        bm = arg->status_arr[i / 64];
d2787b
+        while (bm != 0) {
d2787b
+            /* mask will contain the lowest bit set from bm. */
d2787b
+            mask = bm & (-bm);
d2787b
+            bm ^= mask;
d2787b
+            ret = glusterd_import_friend_volume(peer_data, i + ffsll(mask) - 2,
d2787b
+                                                arg);
d2787b
+            if (ret < 0) {
d2787b
+                break;
d2787b
+            }
d2787b
         }
d2787b
-        i++;
d2787b
+        i += 64;
d2787b
     }
d2787b
     if (i > count) {
d2787b
         glusterd_svcs_manager(NULL);
d2787b
@@ -5095,11 +5125,9 @@ glusterd_import_friend_volumes_synctask(void *opaque)
d2787b
     conf->restart_bricks = _gf_false;
d2787b
     synccond_broadcast(&conf->cond_restart_bricks);
d2787b
 out:
d2787b
-    if (peer_data)
d2787b
-        dict_unref(peer_data);
d2787b
     if (arg) {
d2787b
-        if (arg->dict_buf)
d2787b
-            GF_FREE(arg->dict_buf);
d2787b
+        dict_unref(arg->peer_data);
d2787b
+        dict_unref(arg->peer_ver_data);
d2787b
         GF_FREE(arg);
d2787b
     }
d2787b
 
d2787b
@@ -5121,7 +5149,7 @@ glusterd_import_friend_volumes(dict_t *peer_data)
d2787b
         goto out;
d2787b
 
d2787b
     while (i <= count) {
d2787b
-        ret = glusterd_import_friend_volume(peer_data, i);
d2787b
+        ret = glusterd_import_friend_volume(peer_data, i, NULL);
d2787b
         if (ret)
d2787b
             goto out;
d2787b
         i++;
d2787b
@@ -5260,7 +5288,8 @@ out:
d2787b
 }
d2787b
 
d2787b
 int32_t
d2787b
-glusterd_compare_friend_data(dict_t *peer_data, int32_t *status, char *hostname)
d2787b
+glusterd_compare_friend_data(dict_t *peer_data, dict_t *cmp, int32_t *status,
d2787b
+                             char *hostname)
d2787b
 {
d2787b
     int32_t ret = -1;
d2787b
     int32_t count = 0;
d2787b
@@ -5289,8 +5318,19 @@ glusterd_compare_friend_data(dict_t *peer_data, int32_t *status, char *hostname)
d2787b
     if (ret)
d2787b
         goto out;
d2787b
 
d2787b
+    arg = GF_CALLOC(1, sizeof(*arg) + sizeof(uint64_t) * (count / 64),
d2787b
+                    gf_common_mt_char);
d2787b
+    if (!arg) {
d2787b
+        ret = -1;
d2787b
+        gf_msg("glusterd", GF_LOG_ERROR, ENOMEM, GD_MSG_NO_MEMORY,
d2787b
+               "Out Of Memory");
d2787b
+        goto out;
d2787b
+    }
d2787b
+    arg->peer_data = dict_ref(peer_data);
d2787b
+    arg->peer_ver_data = dict_ref(cmp);
d2787b
     while (i <= count) {
d2787b
-        ret = glusterd_compare_friend_volume(peer_data, i, status, hostname);
d2787b
+        ret = glusterd_compare_friend_volume(peer_data, arg, i, status,
d2787b
+                                             hostname);
d2787b
         if (ret)
d2787b
             goto out;
d2787b
 
d2787b
@@ -5310,21 +5350,13 @@ glusterd_compare_friend_data(dict_t *peer_data, int32_t *status, char *hostname)
d2787b
          * first brick to come up before attaching the subsequent bricks
d2787b
          * in case brick multiplexing is enabled
d2787b
          */
d2787b
-        arg = GF_CALLOC(1, sizeof(*arg), gf_common_mt_char);
d2787b
-        ret = dict_allocate_and_serialize(peer_data, &arg->dict_buf,
d2787b
-                                          &arg->dictlen);
d2787b
-        if (ret < 0) {
d2787b
-            gf_log(this->name, GF_LOG_ERROR,
d2787b
-                   "dict_serialize failed while handling "
d2787b
-                   " import friend volume request");
d2787b
-            goto out;
d2787b
-        }
d2787b
-
d2787b
         glusterd_launch_synctask(glusterd_import_friend_volumes_synctask, arg);
d2787b
     }
d2787b
 
d2787b
 out:
d2787b
     if (ret && arg) {
d2787b
+        dict_unref(arg->peer_data);
d2787b
+        dict_unref(arg->peer_ver_data);
d2787b
         GF_FREE(arg);
d2787b
     }
d2787b
     gf_msg_debug(this->name, 0, "Returning with ret: %d, status: %d", ret,
d2787b
diff --git a/xlators/mgmt/glusterd/src/glusterd-utils.h b/xlators/mgmt/glusterd/src/glusterd-utils.h
d2787b
index 5f5de82..02d85d2 100644
d2787b
--- a/xlators/mgmt/glusterd/src/glusterd-utils.h
d2787b
+++ b/xlators/mgmt/glusterd/src/glusterd-utils.h
d2787b
@@ -231,7 +231,7 @@ glusterd_add_volumes_to_export_dict(dict_t *peer_data, char **buf,
d2787b
                                     u_int *length);
d2787b
 
d2787b
 int32_t
d2787b
-glusterd_compare_friend_data(dict_t *peer_data, int32_t *status,
d2787b
+glusterd_compare_friend_data(dict_t *peer_data, dict_t *cmp, int32_t *status,
d2787b
                              char *hostname);
d2787b
 
d2787b
 int
d2787b
diff --git a/xlators/mgmt/glusterd/src/glusterd.h b/xlators/mgmt/glusterd/src/glusterd.h
d2787b
index f739b5d..efe4d0e 100644
d2787b
--- a/xlators/mgmt/glusterd/src/glusterd.h
d2787b
+++ b/xlators/mgmt/glusterd/src/glusterd.h
d2787b
@@ -234,8 +234,12 @@ typedef struct glusterd_add_dict_args {
d2787b
 } glusterd_add_dict_args_t;
d2787b
 
d2787b
 typedef struct glusterd_friend_synctask_args {
d2787b
-    char *dict_buf;
d2787b
-    u_int dictlen;
d2787b
+    dict_t *peer_data;
d2787b
+    dict_t *peer_ver_data;  // Dictionary to save peer version data
d2787b
+    /* This status_arr[1] is not a real size, real size of the array
d2787b
+       is dynamically allocated
d2787b
+    */
d2787b
+    uint64_t status_arr[1];
d2787b
 } glusterd_friend_synctask_args_t;
d2787b
 
d2787b
 typedef enum gf_brick_status {
d2787b
-- 
d2787b
1.8.3.1
d2787b