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