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