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