e3c68b
From d79cb2cdff6fe8d962c9ac095a7541ddf500302b Mon Sep 17 00:00:00 2001
e3c68b
From: Mohammed Rafi KC <rkavunga@redhat.com>
e3c68b
Date: Mon, 1 Apr 2019 14:44:20 +0530
e3c68b
Subject: [PATCH 099/124] client/fini: return fini after rpc cleanup
e3c68b
e3c68b
There is a race condition in rpc_transport later
e3c68b
and client fini.
e3c68b
e3c68b
Sequence of events to happen the race condition
e3c68b
1) When we want to destroy a graph, we send a parent down
e3c68b
   event first
e3c68b
2) Once parent down received on a client xlator, we will
e3c68b
   initiates a rpc disconnect
e3c68b
3) This will in turn generates a child down event.
e3c68b
4) When we process child down, we first do fini for
e3c68b
   Every xlator
e3c68b
5) On successful return of fini, we delete the graph
e3c68b
e3c68b
Here after the step 5, there is a chance that the fini
e3c68b
on client might not be finished. Because an rpc_tranpsort
e3c68b
ref can race with the above sequence.
e3c68b
e3c68b
So we have to wait till all rpc's are successfully freed
e3c68b
before returning the fini from client
e3c68b
e3c68b
Backport of: https://review.gluster.org/#/c/glusterfs/+/22468/
e3c68b
e3c68b
>Change-Id: I20145662d71fb837e448a4d3210d1fcb2855f2d4
e3c68b
>fixes: bz#1659708
e3c68b
>Signed-off-by: Mohammed Rafi KC <rkavunga@redhat.com>
e3c68b
e3c68b
Change-Id: I848bcfb9443467caed32bae0717244ab01b407fc
e3c68b
BUG: 1471742
e3c68b
Signed-off-by: Mohammed Rafi KC <rkavunga@redhat.com>
e3c68b
Reviewed-on: https://code.engineering.redhat.com/gerrit/167831
e3c68b
Tested-by: RHGS Build Bot <nigelb@redhat.com>
e3c68b
Reviewed-by: Atin Mukherjee <amukherj@redhat.com>
e3c68b
---
e3c68b
 xlators/protocol/client/src/client.c | 25 ++++++++++++++++++++-----
e3c68b
 xlators/protocol/client/src/client.h |  6 ++++++
e3c68b
 2 files changed, 26 insertions(+), 5 deletions(-)
e3c68b
e3c68b
diff --git a/xlators/protocol/client/src/client.c b/xlators/protocol/client/src/client.c
e3c68b
index 19f5175..a372807 100644
e3c68b
--- a/xlators/protocol/client/src/client.c
e3c68b
+++ b/xlators/protocol/client/src/client.c
e3c68b
@@ -49,11 +49,12 @@ client_fini_complete(xlator_t *this)
e3c68b
     if (!conf->destroy)
e3c68b
         return 0;
e3c68b
 
e3c68b
-    this->private = NULL;
e3c68b
-
e3c68b
-    pthread_spin_destroy(&conf->fd_lock);
e3c68b
-    pthread_mutex_destroy(&conf->lock);
e3c68b
-    GF_FREE(conf);
e3c68b
+    pthread_mutex_lock(&conf->lock);
e3c68b
+    {
e3c68b
+        conf->fini_completed = _gf_true;
e3c68b
+        pthread_cond_broadcast(&conf->fini_complete_cond);
e3c68b
+    }
e3c68b
+    pthread_mutex_unlock(&conf->lock);
e3c68b
 
e3c68b
 out:
e3c68b
     return 0;
e3c68b
@@ -2721,6 +2722,7 @@ init(xlator_t *this)
e3c68b
         goto out;
e3c68b
 
e3c68b
     pthread_mutex_init(&conf->lock, NULL);
e3c68b
+    pthread_cond_init(&conf->fini_complete_cond, NULL);
e3c68b
     pthread_spin_init(&conf->fd_lock, 0);
e3c68b
     INIT_LIST_HEAD(&conf->saved_fds);
e3c68b
 
e3c68b
@@ -2779,6 +2781,7 @@ fini(xlator_t *this)
e3c68b
     if (!conf)
e3c68b
         return;
e3c68b
 
e3c68b
+    conf->fini_completed = _gf_false;
e3c68b
     conf->destroy = 1;
e3c68b
     if (conf->rpc) {
e3c68b
         /* cleanup the saved-frames before last unref */
e3c68b
@@ -2786,6 +2789,18 @@ fini(xlator_t *this)
e3c68b
         rpc_clnt_unref(conf->rpc);
e3c68b
     }
e3c68b
 
e3c68b
+    pthread_mutex_lock(&conf->lock);
e3c68b
+    {
e3c68b
+        while (!conf->fini_completed)
e3c68b
+            pthread_cond_wait(&conf->fini_complete_cond, &conf->lock);
e3c68b
+    }
e3c68b
+    pthread_mutex_unlock(&conf->lock);
e3c68b
+
e3c68b
+    pthread_spin_destroy(&conf->fd_lock);
e3c68b
+    pthread_mutex_destroy(&conf->lock);
e3c68b
+    pthread_cond_destroy(&conf->fini_complete_cond);
e3c68b
+    GF_FREE(conf);
e3c68b
+
e3c68b
     /* Saved Fds */
e3c68b
     /* TODO: */
e3c68b
 
e3c68b
diff --git a/xlators/protocol/client/src/client.h b/xlators/protocol/client/src/client.h
e3c68b
index f12fa61..8dcd72f 100644
e3c68b
--- a/xlators/protocol/client/src/client.h
e3c68b
+++ b/xlators/protocol/client/src/client.h
e3c68b
@@ -235,6 +235,12 @@ typedef struct clnt_conf {
e3c68b
                                       * up, disconnects can be
e3c68b
                                       * logged
e3c68b
                                       */
e3c68b
+
e3c68b
+    gf_boolean_t old_protocol;         /* used only for old-protocol testing */
e3c68b
+    pthread_cond_t fini_complete_cond; /* Used to wait till we finsh the fini
e3c68b
+                                          compltely, ie client_fini_complete
e3c68b
+                                          to return*/
e3c68b
+    gf_boolean_t fini_completed;
e3c68b
 } clnt_conf_t;
e3c68b
 
e3c68b
 typedef struct _client_fd_ctx {
e3c68b
-- 
e3c68b
1.8.3.1
e3c68b