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