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