f338ef
From bd553499909d2d57fd05696dc7604901cef3a36a Mon Sep 17 00:00:00 2001
f338ef
From: Soumya Koduri <skoduri@redhat.com>
f338ef
Date: Fri, 7 Jun 2019 17:20:15 +0530
f338ef
Subject: [PATCH 200/221] gfapi: fix incorrect initialization of upcall syncop
f338ef
 arguments
f338ef
f338ef
While sending upcall notifications via synctasks, the argument used to
f338ef
carry relevant data for these tasks is not initialized properly. This patch
f338ef
is to fix the same.
f338ef
f338ef
This is backport of below upstream fix -
f338ef
mainline: https://review.gluster.org/22839
f338ef
release-6: https://review.gluster.org/22871
f338ef
f338ef
Change-Id: I9fa8f841e71d3c37d3819fbd430382928c07176c
f338ef
fixes: bz#1717784
f338ef
Signed-off-by: Soumya Koduri <skoduri@redhat.com>
f338ef
Reviewed-on: https://code.engineering.redhat.com/gerrit/173508
f338ef
Tested-by: RHGS Build Bot <nigelb@redhat.com>
f338ef
Reviewed-by: Kaleb Keithley <kkeithle@redhat.com>
f338ef
---
f338ef
 api/src/glfs-fops.c | 109 ++++++++++++++++++++++++++++++++++------------------
f338ef
 1 file changed, 72 insertions(+), 37 deletions(-)
f338ef
f338ef
diff --git a/api/src/glfs-fops.c b/api/src/glfs-fops.c
f338ef
index 01ba60b..396f18c 100644
f338ef
--- a/api/src/glfs-fops.c
f338ef
+++ b/api/src/glfs-fops.c
f338ef
@@ -34,7 +34,7 @@
f338ef
 
f338ef
 struct upcall_syncop_args {
f338ef
     struct glfs *fs;
f338ef
-    struct gf_upcall *upcall_data;
f338ef
+    struct glfs_upcall *up_arg;
f338ef
 };
f338ef
 
f338ef
 #define READDIRBUF_SIZE (sizeof(struct dirent) + GF_NAME_MAX + 1)
f338ef
@@ -5714,12 +5714,28 @@ out:
f338ef
 }
f338ef
 
f338ef
 static int
f338ef
+upcall_syncop_args_free(struct upcall_syncop_args *args)
f338ef
+{
f338ef
+    if (args && args->up_arg)
f338ef
+        GLFS_FREE(args->up_arg);
f338ef
+    GF_FREE(args);
f338ef
+    return 0;
f338ef
+}
f338ef
+
f338ef
+static int
f338ef
 glfs_upcall_syncop_cbk(int ret, call_frame_t *frame, void *opaque)
f338ef
 {
f338ef
     struct upcall_syncop_args *args = opaque;
f338ef
 
f338ef
-    GF_FREE(args->upcall_data);
f338ef
-    GF_FREE(args);
f338ef
+    /* Here we not using upcall_syncop_args_free as application
f338ef
+     * will be cleaning up the args->up_arg using glfs_free
f338ef
+     * post processing upcall.
f338ef
+     */
f338ef
+    if (ret) {
f338ef
+        upcall_syncop_args_free(args);
f338ef
+    } else
f338ef
+        GF_FREE(args);
f338ef
+
f338ef
     return 0;
f338ef
 }
f338ef
 
f338ef
@@ -5727,13 +5743,29 @@ static int
f338ef
 glfs_cbk_upcall_syncop(void *opaque)
f338ef
 {
f338ef
     struct upcall_syncop_args *args = opaque;
f338ef
-    int ret = -1;
f338ef
     struct glfs_upcall *up_arg = NULL;
f338ef
     struct glfs *fs;
f338ef
-    struct gf_upcall *upcall_data;
f338ef
 
f338ef
     fs = args->fs;
f338ef
-    upcall_data = args->upcall_data;
f338ef
+    up_arg = args->up_arg;
f338ef
+
f338ef
+    if (fs->up_cbk && up_arg) {
f338ef
+        (fs->up_cbk)(up_arg, fs->up_data);
f338ef
+        return 0;
f338ef
+    }
f338ef
+
f338ef
+    return -1;
f338ef
+}
f338ef
+
f338ef
+static struct upcall_syncop_args *
f338ef
+upcall_syncop_args_init(struct glfs *fs, struct gf_upcall *upcall_data)
f338ef
+{
f338ef
+    struct upcall_syncop_args *args = NULL;
f338ef
+    int ret = -1;
f338ef
+    struct glfs_upcall *up_arg = NULL;
f338ef
+
f338ef
+    if (!fs || !upcall_data)
f338ef
+        goto out;
f338ef
 
f338ef
     up_arg = GLFS_CALLOC(1, sizeof(struct gf_upcall), glfs_release_upcall,
f338ef
                          glfs_mt_upcall_entry_t);
f338ef
@@ -5754,33 +5786,51 @@ glfs_cbk_upcall_syncop(void *opaque)
f338ef
             errno = EINVAL;
f338ef
     }
f338ef
 
f338ef
-    if (!ret && (up_arg->reason != GLFS_UPCALL_EVENT_NULL)) {
f338ef
-        /* It could so happen that the file which got
f338ef
-         * upcall notification may have got deleted by
f338ef
-         * the same client. In such cases up_arg->reason
f338ef
-         * is set to GLFS_UPCALL_EVENT_NULL. No need to
f338ef
-         * send upcall then */
f338ef
-        (fs->up_cbk)(up_arg, fs->up_data);
f338ef
-    } else if (up_arg->reason == GLFS_UPCALL_EVENT_NULL) {
f338ef
+    /* It could so happen that the file which got
f338ef
+     * upcall notification may have got deleted by
f338ef
+     * the same client. In such cases up_arg->reason
f338ef
+     * is set to GLFS_UPCALL_EVENT_NULL. No need to
f338ef
+     * send upcall then
f338ef
+     */
f338ef
+    if (up_arg->reason == GLFS_UPCALL_EVENT_NULL) {
f338ef
         gf_msg(THIS->name, GF_LOG_DEBUG, errno, API_MSG_INVALID_ENTRY,
f338ef
                "Upcall_EVENT_NULL received. Skipping it.");
f338ef
         goto out;
f338ef
-    } else {
f338ef
+    } else if (ret) {
f338ef
         gf_msg(THIS->name, GF_LOG_ERROR, errno, API_MSG_INVALID_ENTRY,
f338ef
                "Upcall entry validation failed.");
f338ef
         goto out;
f338ef
     }
f338ef
 
f338ef
+    args = GF_CALLOC(1, sizeof(struct upcall_syncop_args),
f338ef
+                     glfs_mt_upcall_entry_t);
f338ef
+    if (!args) {
f338ef
+        gf_msg(THIS->name, GF_LOG_ERROR, ENOMEM, API_MSG_ALLOC_FAILED,
f338ef
+               "Upcall syncop args allocation failed.");
f338ef
+        goto out;
f338ef
+    }
f338ef
+
f338ef
+    /* Note: we are not taking any ref on fs here.
f338ef
+     * Ideally applications have to unregister for upcall events
f338ef
+     * or stop polling for upcall events before performing
f338ef
+     * glfs_fini. And as for outstanding synctasks created, we wait
f338ef
+     * for all syncenv threads to finish tasks before cleaning up the
f338ef
+     * fs->ctx. Hence it seems safe to process these callback
f338ef
+     * notification without taking any lock/ref.
f338ef
+     */
f338ef
+    args->fs = fs;
f338ef
+    args->up_arg = up_arg;
f338ef
+
f338ef
     /* application takes care of calling glfs_free on up_arg post
f338ef
      * their processing */
f338ef
-    ret = 0;
f338ef
 
f338ef
+    return args;
f338ef
 out:
f338ef
-    if (ret && up_arg) {
f338ef
+    if (up_arg) {
f338ef
         GLFS_FREE(up_arg);
f338ef
     }
f338ef
 
f338ef
-    return 0;
f338ef
+    return NULL;
f338ef
 }
f338ef
 
f338ef
 static void
f338ef
@@ -5797,24 +5847,10 @@ glfs_cbk_upcall_data(struct glfs *fs, struct gf_upcall *upcall_data)
f338ef
         goto out;
f338ef
     }
f338ef
 
f338ef
-    args = GF_CALLOC(1, sizeof(struct upcall_syncop_args),
f338ef
-                     glfs_mt_upcall_entry_t);
f338ef
-    if (!args) {
f338ef
-        gf_msg(THIS->name, GF_LOG_ERROR, ENOMEM, API_MSG_ALLOC_FAILED,
f338ef
-               "Upcall syncop args allocation failed.");
f338ef
-        goto out;
f338ef
-    }
f338ef
+    args = upcall_syncop_args_init(fs, upcall_data);
f338ef
 
f338ef
-    /* Note: we are not taking any ref on fs here.
f338ef
-     * Ideally applications have to unregister for upcall events
f338ef
-     * or stop polling for upcall events before performing
f338ef
-     * glfs_fini. And as for outstanding synctasks created, we wait
f338ef
-     * for all syncenv threads to finish tasks before cleaning up the
f338ef
-     * fs->ctx. Hence it seems safe to process these callback
f338ef
-     * notification without taking any lock/ref.
f338ef
-     */
f338ef
-    args->fs = fs;
f338ef
-    args->upcall_data = gf_memdup(upcall_data, sizeof(*upcall_data));
f338ef
+    if (!args)
f338ef
+        goto out;
f338ef
 
f338ef
     ret = synctask_new(THIS->ctx->env, glfs_cbk_upcall_syncop,
f338ef
                        glfs_upcall_syncop_cbk, NULL, args);
f338ef
@@ -5823,8 +5859,7 @@ glfs_cbk_upcall_data(struct glfs *fs, struct gf_upcall *upcall_data)
f338ef
         gf_msg(THIS->name, GF_LOG_ERROR, errno, API_MSG_UPCALL_SYNCOP_FAILED,
f338ef
                "Synctak for Upcall event_type(%d) and gfid(%s) failed",
f338ef
                upcall_data->event_type, (char *)(upcall_data->gfid));
f338ef
-        GF_FREE(args->upcall_data);
f338ef
-        GF_FREE(args);
f338ef
+        upcall_syncop_args_free(args);
f338ef
     }
f338ef
 
f338ef
 out:
f338ef
-- 
f338ef
1.8.3.1
f338ef