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