14f8ab
From 2449a1824c6f7b57889335caaeb09f4c5cb3efce Mon Sep 17 00:00:00 2001
14f8ab
From: Soumya Koduri <skoduri@redhat.com>
14f8ab
Date: Thu, 28 Mar 2019 14:59:00 +0530
14f8ab
Subject: [PATCH 48/52] gfapi: Unblock epoll thread for upcall processing
14f8ab
14f8ab
With commit#ad35193,we have made changes to offload
14f8ab
processing upcall notifications to synctask so as not
14f8ab
to block epoll threads. However seems like the issue wasnt
14f8ab
fully addressed.
14f8ab
14f8ab
In "glfs_cbk_upcall_data" -> "synctask_new1" after creating synctask
14f8ab
if there is no callback defined, the thread waits on synctask_join
14f8ab
till the syncfn is finished. So that way even with those changes,
14f8ab
epoll threads are blocked till the upcalls are processed.
14f8ab
14f8ab
Hence the right fix now is to define a callback function for that
14f8ab
synctask "glfs_cbk_upcall_syncop" so as to unblock epoll/notify threads
14f8ab
completely and the upcall processing can happen in parallel by synctask
14f8ab
threads.
14f8ab
14f8ab
Upstream references-
14f8ab
mainline : https://review.gluster.org/22436
14f8ab
release-6.0 : https://review.gluster.org/22459
14f8ab
14f8ab
Change-Id: I4d8645e3588fab2c3ca534e0112773aaab68a5dd
14f8ab
fixes: bz#1694565
14f8ab
Signed-off-by: Soumya Koduri <skoduri@redhat.com>
14f8ab
Reviewed-on: https://code.engineering.redhat.com/gerrit/166586
14f8ab
Tested-by: RHGS Build Bot <nigelb@redhat.com>
14f8ab
Reviewed-by: Sunil Kumar Heggodu Gopala Acharya <sheggodu@redhat.com>
14f8ab
---
14f8ab
 api/src/glfs-fops.c | 42 ++++++++++++++++++++++++++++++++++--------
14f8ab
 1 file changed, 34 insertions(+), 8 deletions(-)
14f8ab
14f8ab
diff --git a/api/src/glfs-fops.c b/api/src/glfs-fops.c
14f8ab
index 88cd32b..01ba60b 100644
14f8ab
--- a/api/src/glfs-fops.c
14f8ab
+++ b/api/src/glfs-fops.c
14f8ab
@@ -5714,6 +5714,16 @@ out:
14f8ab
 }
14f8ab
 
14f8ab
 static int
14f8ab
+glfs_upcall_syncop_cbk(int ret, call_frame_t *frame, void *opaque)
14f8ab
+{
14f8ab
+    struct upcall_syncop_args *args = opaque;
14f8ab
+
14f8ab
+    GF_FREE(args->upcall_data);
14f8ab
+    GF_FREE(args);
14f8ab
+    return 0;
14f8ab
+}
14f8ab
+
14f8ab
+static int
14f8ab
 glfs_cbk_upcall_syncop(void *opaque)
14f8ab
 {
14f8ab
     struct upcall_syncop_args *args = opaque;
14f8ab
@@ -5770,15 +5780,13 @@ out:
14f8ab
         GLFS_FREE(up_arg);
14f8ab
     }
14f8ab
 
14f8ab
-    return ret;
14f8ab
+    return 0;
14f8ab
 }
14f8ab
 
14f8ab
 static void
14f8ab
 glfs_cbk_upcall_data(struct glfs *fs, struct gf_upcall *upcall_data)
14f8ab
 {
14f8ab
-    struct upcall_syncop_args args = {
14f8ab
-        0,
14f8ab
-    };
14f8ab
+    struct upcall_syncop_args *args = NULL;
14f8ab
     int ret = -1;
14f8ab
 
14f8ab
     if (!fs || !upcall_data)
14f8ab
@@ -5789,16 +5797,34 @@ glfs_cbk_upcall_data(struct glfs *fs, struct gf_upcall *upcall_data)
14f8ab
         goto out;
14f8ab
     }
14f8ab
 
14f8ab
-    args.fs = fs;
14f8ab
-    args.upcall_data = upcall_data;
14f8ab
+    args = GF_CALLOC(1, sizeof(struct upcall_syncop_args),
14f8ab
+                     glfs_mt_upcall_entry_t);
14f8ab
+    if (!args) {
14f8ab
+        gf_msg(THIS->name, GF_LOG_ERROR, ENOMEM, API_MSG_ALLOC_FAILED,
14f8ab
+               "Upcall syncop args allocation failed.");
14f8ab
+        goto out;
14f8ab
+    }
14f8ab
+
14f8ab
+    /* Note: we are not taking any ref on fs here.
14f8ab
+     * Ideally applications have to unregister for upcall events
14f8ab
+     * or stop polling for upcall events before performing
14f8ab
+     * glfs_fini. And as for outstanding synctasks created, we wait
14f8ab
+     * for all syncenv threads to finish tasks before cleaning up the
14f8ab
+     * fs->ctx. Hence it seems safe to process these callback
14f8ab
+     * notification without taking any lock/ref.
14f8ab
+     */
14f8ab
+    args->fs = fs;
14f8ab
+    args->upcall_data = gf_memdup(upcall_data, sizeof(*upcall_data));
14f8ab
 
14f8ab
-    ret = synctask_new(THIS->ctx->env, glfs_cbk_upcall_syncop, NULL, NULL,
14f8ab
-                       &args);
14f8ab
+    ret = synctask_new(THIS->ctx->env, glfs_cbk_upcall_syncop,
14f8ab
+                       glfs_upcall_syncop_cbk, NULL, args);
14f8ab
     /* should we retry incase of failure? */
14f8ab
     if (ret) {
14f8ab
         gf_msg(THIS->name, GF_LOG_ERROR, errno, API_MSG_UPCALL_SYNCOP_FAILED,
14f8ab
                "Synctak for Upcall event_type(%d) and gfid(%s) failed",
14f8ab
                upcall_data->event_type, (char *)(upcall_data->gfid));
14f8ab
+        GF_FREE(args->upcall_data);
14f8ab
+        GF_FREE(args);
14f8ab
     }
14f8ab
 
14f8ab
 out:
14f8ab
-- 
14f8ab
1.8.3.1
14f8ab