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