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