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