3604df
From ae17bd3a90a8c600397545e5f7b8c4950cc0f7e2 Mon Sep 17 00:00:00 2001
3604df
From: Niels de Vos <ndevos@redhat.com>
3604df
Date: Fri, 18 Nov 2016 14:45:35 +0100
3604df
Subject: [PATCH 185/206] gfapi: redesign the public interface for upcall
3604df
 consumers
3604df
3604df
The glfs_callback_arg and glfs_callback_inode_arg were allocated by
3604df
gfapi, and expected to be free()'d by the application. However it is not
3604df
reasonable to expect that applications use the same memory allocator to
3604df
as the compiled libgfapi.so. For instance, it is possible that gfapi
3604df
uses glibc malloc/free, and an application like NFS-Ganesha the versions
3604df
from jemalloc. Mismatching of the malloc() and free() functions causes
3604df
segmentation faults at best.
3604df
3604df
In order to prevent problems like this in the future, the API for
3604df
applications that consume upcalls has been remodeled. Any of the
3604df
structures that gfapi allocates, should be free'd with glfs_free(). The
3604df
members of the structures can not be accessed directly anymore, each
3604df
has its own function to access now.
3604df
3604df
Correcting the naming of the functions, structures and constants is a
3604df
continuation of commit 2775dc64101ed37c8d9809bf9852dbf0746ee2b6. These
3604df
new improvements not only have correct prefixes for the functions and
3604df
structures, the naming also reflects more to the upcall framework and
3604df
does not use "callback" anymore.
3604df
3604df
Cherry picked from commit 4721188a154acd9a0a4c096d8d73e97f3bf1b2a9:
3604df
> Change-Id: I2b8bd5a0a82036d2abea1a217f5e5975a1d4fe93
3604df
> BUG: 1344714
3604df
> Signed-off-by: Niels de Vos <ndevos@redhat.com>
3604df
> Reviewed-on: http://review.gluster.org/14701
3604df
> Smoke: Gluster Build System <jenkins@build.gluster.org>
3604df
> NetBSD-regression: NetBSD Build System <jenkins@build.gluster.org>
3604df
> CentOS-regression: Gluster Build System <jenkins@build.gluster.org>
3604df
> Reviewed-by: Kaleb KEITHLEY <kkeithle@redhat.com>
3604df
> Reviewed-by: soumya k <skoduri@redhat.com>
3604df
> Reviewed-by: jiffin tony Thottan <jthottan@redhat.com>
3604df
3604df
For the ease of backporting, this patch also includes the (mostly
3604df
overwritten) changes from commit 2775dc64.
3604df
3604df
Cherry picked from commit 5bc41576647dd7f0e201e7e2951cf75702d8b623:
3604df
> Change-Id: I2b8bd5a0a82036d2abea1a217f5e5975a1d4fe93
3604df
> BUG: 1347717
3604df
> Signed-off-by: Niels de Vos <ndevos@redhat.com>
3604df
> Reviewed-on: http://review.gluster.org/15640
3604df
> Smoke: Gluster Build System <jenkins@build.gluster.org>
3604df
> NetBSD-regression: NetBSD Build System <jenkins@build.gluster.org>
3604df
> Reviewed-by: Kaleb KEITHLEY <kkeithle@redhat.com>
3604df
> CentOS-regression: Gluster Build System <jenkins@build.gluster.org>
3604df
3604df
Change-Id: I2b8bd5a0a82036d2abea1a217f5e5975a1d4fe93
3604df
BUG: 1386635
3604df
Signed-off-by: Niels de Vos <ndevos@redhat.com>
3604df
Reviewed-on: https://code.engineering.redhat.com/gerrit/90578
3604df
Reviewed-by: Soumya Koduri <skoduri@redhat.com>
3604df
Tested-by: Soumya Koduri <skoduri@redhat.com>
3604df
Reviewed-by: Atin Mukherjee <amukherj@redhat.com>
3604df
---
3604df
 api/src/gfapi.aliases                        |  13 ++
3604df
 api/src/gfapi.map                            |  15 ++
3604df
 api/src/glfs-handleops.c                     | 226 ++++++++++++++++++++-------
3604df
 api/src/glfs-handles.h                       | 107 ++++++++-----
3604df
 api/src/glfs-internal.h                      |  53 ++++++-
3604df
 api/src/glfs-mem-types.h                     |   1 +
3604df
 api/src/glfs.c                               | 104 ++++++++++++
3604df
 tests/basic/gfapi/bug1283983.c               |  32 ++--
3604df
 tests/basic/gfapi/bug1291259.c               |  61 +++++---
3604df
 tests/basic/gfapi/libgfapi-fini-hang.sh      |   4 +-
3604df
 tests/basic/gfapi/upcall-cache-invalidate.c  |  72 +++++----
3604df
 tests/basic/gfapi/upcall-cache-invalidate.sh |   7 -
3604df
 12 files changed, 519 insertions(+), 176 deletions(-)
3604df
3604df
diff --git a/api/src/gfapi.aliases b/api/src/gfapi.aliases
3604df
index 8d43560..b37665f 100644
3604df
--- a/api/src/gfapi.aliases
3604df
+++ b/api/src/gfapi.aliases
3604df
@@ -140,3 +140,16 @@ _priv_glfs_resolve _glfs_resolve$GFAPI_PRIVATE_3.7.0
3604df
 _priv_glfs_process_upcall_event _glfs_process_upcall_event$GFAPI_PRIVATE_3.7.0
3604df
 
3604df
 _pub_glfs_h_lookupat _glfs_h_lookupat$GFAPI_3.7.4
3604df
+
3604df
+_pub_glfs_h_poll_upcall _glfs_h_poll_upcall$GFAPI_3.7.16
3604df
+_pub_glfs_upcall_get_fs _glfs_upcall_get_fs$GFAPI_3.7.16
3604df
+_pub_glfs_upcall_get_reason _glfs_upcall_get_reason$GFAPI_3.7.16
3604df
+_pub_glfs_upcall_inode_get_event _glfs_upcall_inode_get_event$GFAPI_3.7.16
3604df
+_pub_glfs_upcall_inode_get_object _glfs_upcall_inode_get_object$GFAPI_3.7.16
3604df
+_pub_glfs_upcall_inode_get_flags _glfs_upcall_inode_get_flags$GFAPI_3.7.16
3604df
+_pub_glfs_upcall_inode_get_stat _glfs_upcall_inode_get_stat$GFAPI_3.7.16
3604df
+_pub_glfs_upcall_inode_get_expire _glfs_upcall_inode_get_expire$GFAPI_3.7.16
3604df
+_pub_glfs_upcall_inode_get_pobject _glfs_upcall_inode_get_pobject$GFAPI_3.7.16
3604df
+_pub_glfs_upcall_inode_get_pstat _glfs_upcall_inode_get_pstat$GFAPI_3.7.16
3604df
+_pub_glfs_upcall_inode_get_oldpobject _glfs_upcall_inode_get_oldpobject$GFAPI_3.7.16
3604df
+_pub_glfs_upcall_inode_get_oldpstat _glfs_upcall_inode_get_oldpstat$GFAPI_3.7.16
3604df
diff --git a/api/src/gfapi.map b/api/src/gfapi.map
3604df
index 3ee3558..f38ef02 100644
3604df
--- a/api/src/gfapi.map
3604df
+++ b/api/src/gfapi.map
3604df
@@ -171,3 +171,18 @@ GFAPI_3.7.15 {
3604df
 	global:
3604df
 		glfs_truncate;
3604df
 } GFAPI_3.7.4;
3604df
+
3604df
+GFAPI_3.7.16 {
3604df
+	global:
3604df
+		glfs_upcall_get_fs;
3604df
+		glfs_upcall_get_reason;
3604df
+		glfs_upcall_inode_get_event;
3604df
+		glfs_upcall_inode_get_object;
3604df
+		glfs_upcall_inode_get_flags;
3604df
+		glfs_upcall_inode_get_stat;
3604df
+		glfs_upcall_inode_get_expire;
3604df
+		glfs_upcall_inode_get_pobject;
3604df
+		glfs_upcall_inode_get_pstat;
3604df
+		glfs_upcall_inode_get_oldpobject;
3604df
+		glfs_upcall_inode_get_oldpstat;
3604df
+} GFAPI_3.7.15;
3604df
diff --git a/api/src/glfs-handleops.c b/api/src/glfs-handleops.c
3604df
index f9b4ee9..a464b2e 100644
3604df
--- a/api/src/glfs-handleops.c
3604df
+++ b/api/src/glfs-handleops.c
3604df
@@ -1856,9 +1856,27 @@ invalid_fs:
3604df
 
3604df
 }
3604df
 
3604df
+static void
3604df
+glfs_free_upcall_inode (void *to_free)
3604df
+{
3604df
+        struct glfs_upcall_inode *arg = to_free;
3604df
+
3604df
+        if (!arg)
3604df
+                return;
3604df
+
3604df
+        if (arg->object)
3604df
+                glfs_h_close (arg->object);
3604df
+        if (arg->p_object)
3604df
+                glfs_h_close (arg->p_object);
3604df
+        if (arg->oldp_object)
3604df
+                glfs_h_close (arg->oldp_object);
3604df
+
3604df
+        GF_FREE (arg);
3604df
+}
3604df
+
3604df
 int
3604df
 glfs_h_poll_cache_invalidation (struct glfs *fs,
3604df
-                                struct callback_arg *up_arg,
3604df
+                                struct glfs_upcall *up_arg,
3604df
                                 struct gf_upcall *upcall_data)
3604df
 {
3604df
         int                                 ret           = -1;
3604df
@@ -1866,7 +1884,7 @@ glfs_h_poll_cache_invalidation (struct glfs *fs,
3604df
         struct glfs_object                  *oldp_object  = NULL;
3604df
         struct glfs_object                  *object       = NULL;
3604df
         struct gf_upcall_cache_invalidation *ca_data      = NULL;
3604df
-        struct callback_inode_arg           *up_inode_arg = NULL;
3604df
+        struct glfs_upcall_inode            *up_inode_arg = NULL;
3604df
 
3604df
         ca_data = upcall_data->data;
3604df
         GF_VALIDATE_OR_GOTO ("glfs_h_poll_cache_invalidation",
3604df
@@ -1891,13 +1909,11 @@ glfs_h_poll_cache_invalidation (struct glfs *fs,
3604df
                 goto out;
3604df
         }
3604df
 
3604df
-        up_inode_arg = GF_CALLOC (1, sizeof (struct callback_inode_arg),
3604df
-                                  glfs_mt_upcall_entry_t);
3604df
+        up_inode_arg = GF_CALLOC (1, sizeof (struct glfs_upcall_inode),
3604df
+                                  glfs_mt_upcall_inode_t);
3604df
         GF_VALIDATE_OR_GOTO ("glfs_h_poll_cache_invalidation",
3604df
                              up_inode_arg, out);
3604df
 
3604df
-        up_arg->event_arg = up_inode_arg;
3604df
-
3604df
         up_inode_arg->object = object;
3604df
         up_inode_arg->flags = ca_data->flags;
3604df
         up_inode_arg->expire_time_attr = ca_data->expire_time_attr;
3604df
@@ -1948,6 +1964,10 @@ glfs_h_poll_cache_invalidation (struct glfs *fs,
3604df
         }
3604df
         up_inode_arg->oldp_object = oldp_object;
3604df
 
3604df
+        up_arg->reason = GLFS_UPCALL_INODE_INVALIDATE;
3604df
+        up_arg->event = up_inode_arg;
3604df
+        up_arg->free_event = glfs_free_upcall_inode;
3604df
+
3604df
         ret = 0;
3604df
 
3604df
 out:
3604df
@@ -1956,47 +1976,42 @@ out:
3604df
                 if (object)
3604df
                         glfs_h_close (object);
3604df
 
3604df
-                /* Reset event_arg as well*/
3604df
-                up_arg->event_arg = NULL;
3604df
+                /* Set reason to prevent applications from using ->event */
3604df
+                up_arg->reason = GLFS_UPCALL_EVENT_NULL;
3604df
                 GF_FREE (up_inode_arg);
3604df
         }
3604df
         return ret;
3604df
 }
3604df
 
3604df
 /*
3604df
- * This API is used to poll for upcall events stored in the
3604df
- * upcall list. Current users of this API is NFS-Ganesha.
3604df
- * Incase of any event received, it will be mapped appropriately
3604df
- * into 'callback_arg' along with the handle object  to be passed
3604df
- * to NFS-Ganesha.
3604df
- *
3604df
- * On success, applications need to check for 'reason' to decide
3604df
- * if any upcall event is received.
3604df
+ * This API is used to poll for upcall events stored in the upcall list.
3604df
+ * Current users of this API is NFS-Ganesha. Incase of any event received, it
3604df
+ * will be mapped appropriately into 'glfs_upcall' along with the handle object
3604df
+ * to be passed to NFS-Ganesha.
3604df
  *
3604df
- * Current supported upcall_events -
3604df
- *      GFAPI_INODE_INVALIDATE -
3604df
- *              'arg - callback_inode_arg
3604df
+ * On success, applications need to check if up_arg is not-NULL or errno is not
3604df
+ * ENOENT. glfs_upcall_get_reason() can be used to decide what kind of event
3604df
+ * has been received.
3604df
  *
3604df
- * After processing the event, applications need to free 'event_arg'.
3604df
+ * Current supported upcall_events:
3604df
+ *      GLFS_UPCALL_INODE_INVALIDATE
3604df
  *
3604df
- * Incase of INODE_INVALIDATE, applications need to free "object",
3604df
- * "p_object" and "oldp_object" using glfs_h_close(..).
3604df
+ * After processing the event, applications need to free 'up_arg' by calling
3604df
+ * glfs_free().
3604df
  *
3604df
- * Also similar to I/Os, the application should ideally stop polling
3604df
- * before calling glfs_fini(..). Hence making an assumption that
3604df
- * 'fs' & ctx structures cannot be freed while in this routine.
3604df
+ * Also similar to I/Os, the application should ideally stop polling before
3604df
+ * calling glfs_fini(..). Hence making an assumption that 'fs' & ctx structures
3604df
+ * cannot be freed while in this routine.
3604df
  */
3604df
 int
3604df
-pub_glfs_h_poll_upcall (struct glfs *fs, struct callback_arg *up_arg)
3604df
+pub_glfs_h_poll_upcall (struct glfs *fs, struct glfs_upcall **up_arg)
3604df
 {
3604df
-        upcall_entry                        *u_list         = NULL;
3604df
-        upcall_entry                        *tmp            = NULL;
3604df
-        xlator_t                            *subvol         = NULL;
3604df
-        int                                 found           = 0;
3604df
-        int                                 reason          = 0;
3604df
-        glusterfs_ctx_t                     *ctx            = NULL;
3604df
-        int                                 ret             = -1;
3604df
-        struct gf_upcall                    *upcall_data    = NULL;
3604df
+        upcall_entry       *u_list         = NULL;
3604df
+        upcall_entry       *tmp            = NULL;
3604df
+        xlator_t           *subvol         = NULL;
3604df
+        glusterfs_ctx_t    *ctx            = NULL;
3604df
+        int                 ret            = -1;
3604df
+        struct gf_upcall   *upcall_data    = NULL;
3604df
 
3604df
         DECLARE_OLD_THIS;
3604df
 
3604df
@@ -2009,15 +2024,13 @@ pub_glfs_h_poll_upcall (struct glfs *fs, struct callback_arg *up_arg)
3604df
 
3604df
         /* get the active volume */
3604df
         subvol = glfs_active_subvol (fs);
3604df
-
3604df
         if (!subvol) {
3604df
                 errno = EIO;
3604df
                 goto restore;
3604df
         }
3604df
 
3604df
         /* Ideally applications should stop polling before calling
3604df
-         * 'glfs_fini'. Yet cross check if cleanup has started
3604df
-         */
3604df
+         * 'glfs_fini'. Yet cross check if cleanup has started. */
3604df
         pthread_mutex_lock (&fs->mutex);
3604df
         {
3604df
                 ctx = fs->ctx;
3604df
@@ -2040,46 +2053,55 @@ pub_glfs_h_poll_upcall (struct glfs *fs, struct callback_arg *up_arg)
3604df
                 list_for_each_entry_safe (u_list, tmp,
3604df
                                           &fs->upcall_list,
3604df
                                           upcall_list) {
3604df
-                        found = 1;
3604df
                         list_del_init (&u_list->upcall_list);
3604df
+                        upcall_data = &u_list->upcall_data;
3604df
                         break;
3604df
                 }
3604df
         }
3604df
         /* No other thread can delete this entry. So unlock it */
3604df
         pthread_mutex_unlock (&fs->upcall_list_mutex);
3604df
 
3604df
-        if (found) {
3604df
-                upcall_data = &u_list->upcall_data;
3604df
-
3604df
+        if (upcall_data) {
3604df
                 switch (upcall_data->event_type) {
3604df
                 case GF_UPCALL_CACHE_INVALIDATION:
3604df
+                        *up_arg = GF_CALLOC (1, sizeof (struct gf_upcall),
3604df
+                                             glfs_mt_upcall_entry_t);
3604df
+                        if (!*up_arg) {
3604df
+                                errno = ENOMEM;
3604df
+                                break; /* goto free u_list */
3604df
+                        }
3604df
+
3604df
                         /* XXX: Need to revisit this to support
3604df
-                         * GFAPI_INODE_UPDATE if required.
3604df
-                         */
3604df
-                        reason = GFAPI_INODE_INVALIDATE;
3604df
-                        ret = glfs_h_poll_cache_invalidation (fs,
3604df
-                                                              up_arg,
3604df
+                         * GLFS_UPCALL_INODE_UPDATE if required. */
3604df
+                        ret = glfs_h_poll_cache_invalidation (fs, *up_arg,
3604df
                                                               upcall_data);
3604df
-                        if (!ret) {
3604df
-                                break;
3604df
+                        if (ret
3604df
+                            || (*up_arg)->reason == GLFS_UPCALL_EVENT_NULL) {
3604df
+                                /* It could so happen that the file which got
3604df
+                                 * upcall notification may have got deleted by
3604df
+                                 * the same client. Irrespective of the error,
3604df
+                                 * return with an error or success+ENOENT. */
3604df
+                                if ((*up_arg)->reason == GLFS_UPCALL_EVENT_NULL)
3604df
+                                        errno = ENOENT;
3604df
+
3604df
+                                GF_FREE (*up_arg);
3604df
+                                *up_arg = NULL;
3604df
                         }
3604df
-                        /* It could so happen that the file which got
3604df
-                         * upcall notification may have got deleted
3604df
-                         * by the same client. Irrespective of the error,
3604df
-                         * return with CBK_NULL reason.
3604df
-                         *
3604df
-                         * Applications will ignore this notification
3604df
-                         * as up_arg->object will be NULL */
3604df
-                        reason = GFAPI_CBK_EVENT_NULL;
3604df
                         break;
3604df
-                default:
3604df
+                case GF_UPCALL_RECALL_LEASE:
3604df
+                        gf_log ("glfs_h_poll_upcall", GF_LOG_DEBUG,
3604df
+                                "UPCALL_RECALL_LEASE is not implemented yet");
3604df
+                case GF_UPCALL_EVENT_NULL:
3604df
+                /* no 'default:' label, to force handling all upcall events */
3604df
+                        errno = ENOENT;
3604df
                         break;
3604df
                 }
3604df
 
3604df
-                up_arg->reason = reason;
3604df
-
3604df
                 GF_FREE (u_list->upcall_data.data);
3604df
                 GF_FREE (u_list);
3604df
+        } else {
3604df
+                /* fs->upcall_list was empty, no upcall events cached */
3604df
+                errno = ENOENT;
3604df
         }
3604df
 
3604df
         ret = 0;
3604df
@@ -2099,7 +2121,91 @@ err:
3604df
         return ret;
3604df
 }
3604df
 
3604df
-GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_h_poll_upcall, 3.7.0);
3604df
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_h_poll_upcall, 3.7.16);
3604df
+
3604df
+static gf_boolean_t log_upcall370 = _gf_true; /* log once */
3604df
+
3604df
+/* The old glfs_h_poll_upcall interface requires intimite knowledge of the
3604df
+ * structures that are returned to the calling application. This is not
3604df
+ * recommended, as the returned structures need to returned correctly (handles
3604df
+ * closed, memory free'd with the unavailable GF_FREE(), and possibly more.)
3604df
+ *
3604df
+ * To the best of our knowledge, only NFS-Ganesha uses the upcall events
3604df
+ * through gfapi. We keep this backwards compatability function around so that
3604df
+ * applications using the existing implementation do not break.
3604df
+ *
3604df
+ * WARNING: this function will be removed in the future.
3604df
+ */
3604df
+int
3604df
+pub_glfs_h_poll_upcall370 (struct glfs *fs, struct glfs_callback_arg *up_arg)
3604df
+{
3604df
+        struct glfs_upcall    *upcall        = NULL;
3604df
+        int                    ret           = -1;
3604df
+
3604df
+        if (log_upcall370) {
3604df
+                log_upcall370 = _gf_false;
3604df
+                gf_log (THIS->name, GF_LOG_WARNING, "this application is "
3604df
+                        "compiled against an old version of libgfapi, it "
3604df
+                        "should use glfs_free() to release the structure "
3604df
+                        "returned by glfs_h_poll_upcall() - for more details, "
3604df
+                        "see http://review.gluster.org/14701");
3604df
+        }
3604df
+
3604df
+        ret = pub_glfs_h_poll_upcall (fs, &upcall);
3604df
+        if (ret == 0) {
3604df
+                up_arg->fs = fs;
3604df
+                if (errno == ENOENT || upcall->event == NULL) {
3604df
+                        up_arg->reason = GLFS_UPCALL_EVENT_NULL;
3604df
+                        goto out;
3604df
+                }
3604df
+
3604df
+                up_arg->reason = upcall->reason;
3604df
+
3604df
+                if (upcall->reason == GLFS_UPCALL_INODE_INVALIDATE) {
3604df
+                        struct glfs_callback_inode_arg *cb_inode = NULL;
3604df
+                        struct glfs_upcall_inode       *up_inode = NULL;
3604df
+
3604df
+                        cb_inode = GF_CALLOC (1,
3604df
+                                              sizeof (struct glfs_callback_inode_arg),
3604df
+                                              glfs_mt_upcall_inode_t);
3604df
+                        if (!cb_inode) {
3604df
+                                errno = ENOMEM;
3604df
+                                ret = -1;
3604df
+                                goto out;
3604df
+                        }
3604df
+
3604df
+                        up_inode = upcall->event;
3604df
+
3604df
+                        /* copy attributes one by one, the memory layout might
3604df
+                         * be different between the old glfs_callback_inode_arg
3604df
+                         * and new glfs_upcall_inode */
3604df
+                        cb_inode->object = up_inode->object;
3604df
+                        cb_inode->flags = up_inode->flags;
3604df
+                        memcpy (&cb_inode->buf, &up_inode->buf,
3604df
+                                sizeof (struct stat));
3604df
+                        cb_inode->expire_time_attr = up_inode->expire_time_attr;
3604df
+                        cb_inode->p_object = up_inode->p_object;
3604df
+                        memcpy (&cb_inode->p_buf, &up_inode->p_buf,
3604df
+                                sizeof (struct stat));
3604df
+                        cb_inode->oldp_object = up_inode->oldp_object;
3604df
+                        memcpy (&cb_inode->oldp_buf, &up_inode->oldp_buf,
3604df
+                                sizeof (struct stat));
3604df
+
3604df
+                        up_arg->event_arg = cb_inode;
3604df
+                }
3604df
+        }
3604df
+
3604df
+out:
3604df
+        if (upcall) {
3604df
+                /* we can not use glfs_free() here, objects need to stay */
3604df
+                GF_FREE (upcall->event);
3604df
+                GF_FREE (upcall);
3604df
+        }
3604df
+
3604df
+        return ret;
3604df
+}
3604df
+
3604df
+GFAPI_SYMVER_PUBLIC(glfs_h_poll_upcall370, glfs_h_poll_upcall, 3.7.0);
3604df
 
3604df
 #ifdef HAVE_ACL_LIBACL_H
3604df
 #include "glusterfs-acl.h"
3604df
diff --git a/api/src/glfs-handles.h b/api/src/glfs-handles.h
3604df
index 6446cc3..740b759 100644
3604df
--- a/api/src/glfs-handles.h
3604df
+++ b/api/src/glfs-handles.h
3604df
@@ -12,6 +12,7 @@
3604df
 #define _GLFS_HANDLES_H
3604df
 
3604df
 #include "glfs.h"
3604df
+#include <inttypes.h>
3604df
 
3604df
 /* GLFS OBJECT BASED OPERATIONS
3604df
  *
3604df
@@ -110,45 +111,82 @@ typedef struct glfs_object glfs_object_t;
3604df
  *
3604df
  * Currently supported upcall_events -
3604df
  *      GFAPI_INODE_INVALIDATE -
3604df
- *              'event_arg' - callback_inode_arg
3604df
+ *              'event_arg' - glfs_upcall_inode
3604df
  *
3604df
- * After processing the event, applications need to free 'event_arg'.
3604df
+ * After processing the event, applications need to free 'event_arg' with
3604df
+ * glfs_free().
3604df
  *
3604df
  * Also similar to I/Os, the application should ideally stop polling
3604df
  * before calling glfs_fini(..). Hence making an assumption that
3604df
  * 'fs' & ctx structures cannot be freed while in this routine.
3604df
  */
3604df
-struct callback_arg {
3604df
-        struct glfs             *fs; /* glfs object */
3604df
-        int                     reason;  /* Upcall event type */
3604df
-        void                    *event_arg; /* changes based in the event type */
3604df
+struct glfs_upcall;
3604df
+
3604df
+struct glfs*
3604df
+glfs_upcall_get_fs (struct glfs_upcall *arg) __THROW
3604df
+        GFAPI_PUBLIC(glfs_upcall_get_fs, 3.7.16);
3604df
+
3604df
+enum glfs_upcall_reason {
3604df
+        GLFS_UPCALL_EVENT_NULL = 0,
3604df
+        GLFS_UPCALL_INODE_INVALIDATE,    /* invalidate cache entry */
3604df
 };
3604df
 
3604df
+enum glfs_upcall_reason
3604df
+glfs_upcall_get_reason (struct glfs_upcall *arg) __THROW
3604df
+        GFAPI_PUBLIC(glfs_upcall_get_reason, 3.7.16);
3604df
+
3604df
+
3604df
 /*
3604df
- * After processing upcall event, they need to free "object" , "p_object",
3604df
- * "oldp_object" using glfs_h_close(..).
3604df
+ * After processing upcall event, glfs_free() should be called on the
3604df
+ * glfs_upcall.
3604df
  */
3604df
-struct callback_inode_arg {
3604df
-        struct glfs_object      *object; /* Object which need to be acted upon */
3604df
-        int                     flags; /* Cache UPDATE/INVALIDATE flags */
3604df
-        struct stat             buf; /* Latest stat of this entry */
3604df
-        unsigned int            expire_time_attr; /* the amount of time for which
3604df
-                                                   * the application need to cache
3604df
-                                                   * this entry
3604df
-                                                   */
3604df
-        struct glfs_object      *p_object; /* parent Object to be updated */
3604df
-        struct stat             p_buf; /* Latest stat of parent dir handle */
3604df
-        struct glfs_object      *oldp_object; /* Old parent Object
3604df
-                                               * to be updated */
3604df
-        struct stat             oldp_buf; /* Latest stat of old parent
3604df
-                                           * dir handle */
3604df
-};
3604df
+void*
3604df
+glfs_upcall_get_event (struct glfs_upcall *arg) __THROW
3604df
+        GFAPI_PUBLIC(glfs_upcall_get_event, 3.7.16);
3604df
+
3604df
+
3604df
+/* Functions for getting details about the glfs_upcall_inode
3604df
+ *
3604df
+ * None of the pointers returned by the below functions should be free()'d,
3604df
+ * glfs_free()'d or glfs_h_close()'d by the application.
3604df
+ *
3604df
+ * Releasing of the structures is done by passing the glfs_upcall pointer
3604df
+ * to glfs_free().
3604df
+ */
3604df
+struct glfs_upcall_inode;
3604df
+
3604df
+struct glfs_object*
3604df
+glfs_upcall_inode_get_object (struct glfs_upcall_inode *arg) __THROW
3604df
+        GFAPI_PUBLIC(glfs_upcall_inode_get_object, 3.7.16);
3604df
+
3604df
+uint64_t
3604df
+glfs_upcall_inode_get_flags (struct glfs_upcall_inode *arg) __THROW
3604df
+        GFAPI_PUBLIC(glfs_upcall_inode_get_flags, 3.7.16);
3604df
+
3604df
+struct stat*
3604df
+glfs_upcall_inode_get_stat (struct glfs_upcall_inode *arg) __THROW
3604df
+        GFAPI_PUBLIC(glfs_upcall_inode_get_stat, 3.7.16);
3604df
+
3604df
+uint64_t
3604df
+glfs_upcall_inode_get_expire (struct glfs_upcall_inode *arg) __THROW
3604df
+        GFAPI_PUBLIC(glfs_upcall_inode_get_expire, 3.7.16);
3604df
+
3604df
+struct glfs_object*
3604df
+glfs_upcall_inode_get_pobject (struct glfs_upcall_inode *arg) __THROW
3604df
+        GFAPI_PUBLIC(glfs_upcall_inode_get_pobject, 3.7.16);
3604df
+
3604df
+struct stat*
3604df
+glfs_upcall_inode_get_pstat (struct glfs_upcall_inode *arg) __THROW
3604df
+        GFAPI_PUBLIC(glfs_upcall_inode_get_pstat, 3.7.16);
3604df
+
3604df
+struct glfs_object*
3604df
+glfs_upcall_inode_get_oldpobject (struct glfs_upcall_inode *arg) __THROW
3604df
+        GFAPI_PUBLIC(glfs_upcall_inode_get_oldpobject, 3.7.16);
3604df
+
3604df
+struct stat*
3604df
+glfs_upcall_inode_get_oldpstat (struct glfs_upcall_inode *arg) __THROW
3604df
+        GFAPI_PUBLIC(glfs_upcall_inode_get_oldpstat, 3.7.16);
3604df
 
3604df
-/* reason list in callback_arg */
3604df
-enum gfapi_callback_type {
3604df
-        GFAPI_CBK_EVENT_NULL,
3604df
-        GFAPI_INODE_INVALIDATE, /* invalidate cache entry */
3604df
-};
3604df
 
3604df
 /* Handle based operations */
3604df
 /* Operations that generate handles */
3604df
@@ -273,7 +311,7 @@ glfs_h_access (struct glfs *fs, struct glfs_object *object, int mask) __THROW
3604df
   This API is used to poll for upcall events stored in the
3604df
   upcall list. Current users of this API is NFS-Ganesha.
3604df
   Incase of any event received, it will be mapped appropriately
3604df
-  into 'callback_arg' along with the handle('glfs_object') to be
3604df
+  into 'glfs_upcall' along with the handle('glfs_object') to be
3604df
   passed to NFS-Ganesha.
3604df
 
3604df
   In case of success, applications need to check the value of
3604df
@@ -283,11 +321,8 @@ glfs_h_access (struct glfs *fs, struct glfs_object *object, int mask) __THROW
3604df
   PARAMETERS
3604df
 
3604df
   @fs: glfs object to poll the upcall events for
3604df
-  @cbk: Structure to store upcall events as desired by the application.
3604df
-        Application is responsible for allocating and passing the
3604df
-        references of all the pointers of this structure except for
3604df
-        "handle". In case of any events received, it needs to free
3604df
-        "handle"
3604df
+  @cbk: Pointer that will contain an upcall event for use by the application.
3604df
+        Application is responsible for free'ing the structure with glfs_free().
3604df
 
3604df
   RETURN VALUES
3604df
 
3604df
@@ -297,8 +332,8 @@ glfs_h_access (struct glfs *fs, struct glfs_object *object, int mask) __THROW
3604df
 */
3604df
 
3604df
 int
3604df
-glfs_h_poll_upcall (struct glfs *fs, struct callback_arg *cbk) __THROW
3604df
-        GFAPI_PUBLIC(glfs_h_poll_upcall, 3.7.0);
3604df
+glfs_h_poll_upcall (struct glfs *fs, struct glfs_upcall **cbk) __THROW
3604df
+        GFAPI_PUBLIC(glfs_h_poll_upcall, 3.7.16);
3604df
 
3604df
 int
3604df
 glfs_h_acl_set (struct glfs *fs, struct glfs_object *object,
3604df
diff --git a/api/src/glfs-internal.h b/api/src/glfs-internal.h
3604df
index 458702e..fc62bbf 100644
3604df
--- a/api/src/glfs-internal.h
3604df
+++ b/api/src/glfs-internal.h
3604df
@@ -225,6 +225,26 @@ struct glfs_object {
3604df
         uuid_t          gfid;
3604df
 };
3604df
 
3604df
+struct glfs_upcall {
3604df
+        struct glfs             *fs;     /* glfs object */
3604df
+        enum glfs_upcall_reason  reason; /* Upcall event type */
3604df
+        void                    *event;  /* changes based in the event type */
3604df
+        void (*free_event)(void *);      /* free event after the usage */
3604df
+};
3604df
+
3604df
+struct glfs_upcall_inode {
3604df
+        struct glfs_object   *object;  /* Object which need to be acted upon */
3604df
+        int                   flags;   /* Cache UPDATE/INVALIDATE flags */
3604df
+        struct stat           buf;     /* Latest stat of this entry */
3604df
+        unsigned int          expire_time_attr; /* the amount of time for which
3604df
+                                                 * the application need to cache
3604df
+                                                 * this entry */
3604df
+        struct glfs_object   *p_object; /* parent Object to be updated */
3604df
+        struct stat           p_buf;    /* Latest stat of parent dir handle */
3604df
+        struct glfs_object   *oldp_object; /* Old parent Object to be updated */
3604df
+        struct stat           oldp_buf; /* Latest stat of old parent dir handle */
3604df
+};
3604df
+
3604df
 #define DEFAULT_EVENT_POOL_SIZE           16384
3604df
 #define GF_MEMPOOL_COUNT_OF_DICT_T        4096
3604df
 #define GF_MEMPOOL_COUNT_OF_DATA_T        (GF_MEMPOOL_COUNT_OF_DICT_T * 4)
3604df
@@ -401,7 +421,7 @@ int glfs_get_upcall_cache_invalidation (struct gf_upcall *to_up_data,
3604df
                                         struct gf_upcall *from_up_data);
3604df
 int
3604df
 glfs_h_poll_cache_invalidation (struct glfs *fs,
3604df
-                                struct callback_arg *up_arg,
3604df
+                                struct glfs_upcall *up_arg,
3604df
                                 struct gf_upcall *upcall_data);
3604df
 
3604df
 ssize_t
3604df
@@ -416,4 +436,35 @@ glfs_anonymous_pwritev (struct glfs *fs, struct glfs_object *object,
3604df
 struct glfs_object *
3604df
 glfs_h_resolve_symlink (struct glfs *fs, struct glfs_object *object);
3604df
 
3604df
+
3604df
+/* Deprecated structures that were passed to client applications, replaced by
3604df
+ * accessor functions. Do not use these in new applications, and update older
3604df
+ * usage.
3604df
+ *
3604df
+ * See http://review.gluster.org/14701 for more details.
3604df
+ *
3604df
+ * WARNING: These structures will be removed in the future.
3604df
+ */
3604df
+struct glfs_callback_arg {
3604df
+        struct glfs             *fs;
3604df
+        enum glfs_upcall_reason  reason;
3604df
+        void                    *event_arg;
3604df
+};
3604df
+
3604df
+struct glfs_callback_inode_arg {
3604df
+        struct glfs_object      *object; /* Object which need to be acted upon */
3604df
+        int                     flags; /* Cache UPDATE/INVALIDATE flags */
3604df
+        struct stat             buf; /* Latest stat of this entry */
3604df
+        unsigned int            expire_time_attr; /* the amount of time for which
3604df
+                                                   * the application need to cache
3604df
+                                                   * this entry
3604df
+                                                   */
3604df
+        struct glfs_object      *p_object; /* parent Object to be updated */
3604df
+        struct stat             p_buf; /* Latest stat of parent dir handle */
3604df
+        struct glfs_object      *oldp_object; /* Old parent Object
3604df
+                                               * to be updated */
3604df
+        struct stat             oldp_buf; /* Latest stat of old parent
3604df
+                                           * dir handle */
3604df
+};
3604df
+
3604df
 #endif /* !_GLFS_INTERNAL_H */
3604df
diff --git a/api/src/glfs-mem-types.h b/api/src/glfs-mem-types.h
3604df
index cad1ca9..d32d63f 100644
3604df
--- a/api/src/glfs-mem-types.h
3604df
+++ b/api/src/glfs-mem-types.h
3604df
@@ -27,6 +27,7 @@ enum glfs_mem_types_ {
3604df
 	glfs_mt_readdirbuf_t,
3604df
         glfs_mt_upcall_entry_t,
3604df
 	glfs_mt_acl_t,
3604df
+        glfs_mt_upcall_inode_t,
3604df
 	glfs_mt_end
3604df
 };
3604df
 #endif
3604df
diff --git a/api/src/glfs.c b/api/src/glfs.c
3604df
index 3aec115..1f394a2 100644
3604df
--- a/api/src/glfs.c
3604df
+++ b/api/src/glfs.c
3604df
@@ -1306,3 +1306,107 @@ invalid_fs:
3604df
 }
3604df
 
3604df
 GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_ipc, 3.7.0);
3604df
+
3604df
+
3604df
+void
3604df
+pub_glfs_free (void *ptr)
3604df
+{
3604df
+        int mem_type = 0;
3604df
+
3604df
+        mem_type = gf_get_mem_type (ptr);
3604df
+
3604df
+        switch (mem_type) {
3604df
+        case glfs_mt_upcall_entry_t:
3604df
+        {
3604df
+                struct glfs_upcall *to_free = ptr;
3604df
+
3604df
+                if (to_free->event)
3604df
+                        to_free->free_event (to_free->event);
3604df
+
3604df
+                GF_FREE (ptr);
3604df
+                break;
3604df
+        }
3604df
+        default:
3604df
+                GF_FREE (ptr);
3604df
+        }
3604df
+}
3604df
+
3604df
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_free, 3.7.16);
3604df
+
3604df
+
3604df
+struct glfs*
3604df
+pub_glfs_upcall_get_fs (struct glfs_upcall *arg)
3604df
+{
3604df
+        return arg->fs;
3604df
+}
3604df
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_upcall_get_fs, 3.7.16);
3604df
+
3604df
+enum glfs_upcall_reason
3604df
+pub_glfs_upcall_get_reason (struct glfs_upcall *arg)
3604df
+{
3604df
+        return arg->reason;
3604df
+}
3604df
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_upcall_get_reason, 3.7.16);
3604df
+
3604df
+void*
3604df
+pub_glfs_upcall_get_event (struct glfs_upcall *arg)
3604df
+{
3604df
+        return arg->event;
3604df
+}
3604df
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_upcall_get_event, 3.7.16);
3604df
+
3604df
+struct glfs_object*
3604df
+pub_glfs_upcall_inode_get_object (struct glfs_upcall_inode *arg)
3604df
+{
3604df
+        return arg->object;
3604df
+}
3604df
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_upcall_inode_get_object, 3.7.16);
3604df
+
3604df
+uint64_t
3604df
+pub_glfs_upcall_inode_get_flags (struct glfs_upcall_inode *arg)
3604df
+{
3604df
+        return arg->flags;
3604df
+}
3604df
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_upcall_inode_get_flags, 3.7.16);
3604df
+
3604df
+struct stat*
3604df
+pub_glfs_upcall_inode_get_stat (struct glfs_upcall_inode *arg)
3604df
+{
3604df
+        return &arg->buf;
3604df
+}
3604df
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_upcall_inode_get_stat, 3.7.16);
3604df
+
3604df
+uint64_t
3604df
+pub_glfs_upcall_inode_get_expire (struct glfs_upcall_inode *arg)
3604df
+{
3604df
+        return arg->expire_time_attr;
3604df
+}
3604df
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_upcall_inode_get_expire, 3.7.16);
3604df
+
3604df
+struct glfs_object*
3604df
+pub_glfs_upcall_inode_get_pobject (struct glfs_upcall_inode *arg)
3604df
+{
3604df
+        return arg->p_object;
3604df
+}
3604df
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_upcall_inode_get_pobject, 3.7.16);
3604df
+
3604df
+struct stat*
3604df
+pub_glfs_upcall_inode_get_pstat (struct glfs_upcall_inode *arg)
3604df
+{
3604df
+        return &arg->p_buf;
3604df
+}
3604df
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_upcall_get_pstat, 3.7.16);
3604df
+
3604df
+struct glfs_object*
3604df
+pub_glfs_upcall_inode_get_oldpobject (struct glfs_upcall_inode *arg)
3604df
+{
3604df
+        return arg->oldp_object;
3604df
+}
3604df
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_upcall_get_oldpobject, 3.7.16);
3604df
+
3604df
+struct stat*
3604df
+pub_glfs_upcall_inode_get_oldpstat (struct glfs_upcall_inode *arg)
3604df
+{
3604df
+        return &arg->oldp_buf;
3604df
+}
3604df
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_upcall_get_oldpstat, 3.7.16);
3604df
diff --git a/tests/basic/gfapi/bug1283983.c b/tests/basic/gfapi/bug1283983.c
3604df
index 76db8d5..19354eb 100644
3604df
--- a/tests/basic/gfapi/bug1283983.c
3604df
+++ b/tests/basic/gfapi/bug1283983.c
3604df
@@ -32,20 +32,18 @@ int gfapi = 1;
3604df
 int
3604df
 main (int argc, char *argv[])
3604df
 {
3604df
-        glfs_t    *fs = NULL;
3604df
-        int        ret = 0, i;
3604df
-        glfs_fd_t *fd = NULL;
3604df
-        char      *filename = "/a1";
3604df
-        char      *filename2 = "/a2";
3604df
-        struct     stat sb = {0, };
3604df
-        struct    callback_arg cbk;
3604df
-        char      *logfile = NULL;
3604df
-        char      *volname = NULL;
3604df
-        int       cnt = 1;
3604df
-        struct callback_inode_arg *in_arg = NULL;
3604df
-        struct glfs_object *root = NULL, *leaf = NULL;
3604df
-
3604df
-        cbk.reason = 0;
3604df
+        glfs_t                   *fs = NULL;
3604df
+        int                       ret = 0, i;
3604df
+        glfs_fd_t                *fd = NULL;
3604df
+        char                     *filename = "/a1";
3604df
+        char                     *filename2 = "/a2";
3604df
+        struct stat               sb = {0, };
3604df
+        struct glfs_upcall       *cbk = NULL;
3604df
+        char                     *logfile = NULL;
3604df
+        char                     *volname = NULL;
3604df
+        int                       cnt = 1;
3604df
+        struct glfs_upcall_inode *in_arg = NULL;
3604df
+        struct glfs_object       *root = NULL, *leaf = NULL;
3604df
 
3604df
         fprintf (stderr, "Starting libgfapi_fini\n");
3604df
         if (argc != 3) {
3604df
@@ -105,11 +103,13 @@ main (int argc, char *argv[])
3604df
                 LOG_ERR ("glfs_h_poll_upcall", ret);
3604df
 
3604df
                 /* There should not be any upcalls sent */
3604df
-                if (cbk.reason != GFAPI_CBK_EVENT_NULL) {
3604df
+                if (glfs_upcall_get_reason(cbk) != GLFS_UPCALL_EVENT_NULL) {
3604df
                         fprintf (stderr, "Error: Upcall received(%d)\n",
3604df
-                                 cbk.reason);
3604df
+                                 glfs_upcall_get_reason(cbk));
3604df
                         exit (1);
3604df
                 }
3604df
+
3604df
+                glfs_free (cbk);
3604df
         }
3604df
 
3604df
         ret = glfs_fini(fs);
3604df
diff --git a/tests/basic/gfapi/bug1291259.c b/tests/basic/gfapi/bug1291259.c
3604df
index a0cd821..2074113 100644
3604df
--- a/tests/basic/gfapi/bug1291259.c
3604df
+++ b/tests/basic/gfapi/bug1291259.c
3604df
@@ -34,22 +34,22 @@ int gfapi = 1;
3604df
 int
3604df
 main (int argc, char *argv[])
3604df
 {
3604df
-        glfs_t    *fs = NULL;
3604df
-        glfs_t    *fs2 = NULL;
3604df
-        int        ret = 0, i;
3604df
-        glfs_fd_t *fd = NULL;
3604df
-        char      *filename = "/a1";
3604df
-        char      *filename2 = "/a2";
3604df
-        struct     stat sb = {0, };
3604df
-        struct    callback_arg cbk;
3604df
-        char      *logfile = NULL;
3604df
-        char      *volname = NULL;
3604df
-        int        cnt = 1;
3604df
-        int       upcall_received = 0;
3604df
-        struct callback_inode_arg *in_arg = NULL;
3604df
-        struct glfs_object *root = NULL, *leaf = NULL;
3604df
-        unsigned char   globjhdl[GFAPI_HANDLE_LENGTH];
3604df
-        unsigned char   globjhdl2[GFAPI_HANDLE_LENGTH];
3604df
+        glfs_t                     *fs = NULL;
3604df
+        glfs_t                     *fs2 = NULL;
3604df
+        int                         ret = 0, i;
3604df
+        glfs_fd_t                  *fd = NULL;
3604df
+        char                       *filename = "/a1";
3604df
+        char                       *filename2 = "/a2";
3604df
+        struct                      stat sb = {0, };
3604df
+        char                       *logfile = NULL;
3604df
+        char                       *volname = NULL;
3604df
+        char                       *hostname = NULL;
3604df
+        int                         cnt = 1;
3604df
+        int                         upcall_received = 0;
3604df
+        struct glfs_upcall         *cbk = NULL;
3604df
+        struct glfs_object         *root = NULL, *leaf = NULL;
3604df
+        unsigned char               globjhdl[GFAPI_HANDLE_LENGTH];
3604df
+        unsigned char               globjhdl2[GFAPI_HANDLE_LENGTH];
3604df
 
3604df
         fprintf (stderr, "Starting libgfapi_fini\n");
3604df
         if (argc != 3) {
3604df
@@ -81,7 +81,6 @@ main (int argc, char *argv[])
3604df
          * on the fs (through this instance) happens. */
3604df
         ret = glfs_h_poll_upcall(fs, &cbk);
3604df
         LOG_ERR ("glfs_h_poll_upcall", ret);
3604df
-        cbk.reason = 0;
3604df
 
3604df
         fs2 = glfs_new (volname);
3604df
         if (!fs) {
3604df
@@ -122,21 +121,30 @@ main (int argc, char *argv[])
3604df
         }
3604df
         fprintf (stderr, "glfs_h_create leaf - %p\n", leaf);
3604df
 
3604df
-        while (cnt++ < 5) {
3604df
+        while (cnt++ < 5 && !upcall_received) {
3604df
+                enum glfs_upcall_reason     reason = 0;
3604df
+                struct glfs_upcall_inode   *in_arg = NULL;
3604df
+
3604df
                 ret = glfs_h_poll_upcall(fs, &cbk);
3604df
                 LOG_ERR ("glfs_h_poll_upcall", ret);
3604df
+                if (ret)
3604df
+                        goto retry;
3604df
+
3604df
+                reason = glfs_upcall_get_reason (cbk);
3604df
+                fprintf (stderr, "Upcall received(%d)\n", reason);
3604df
+
3604df
+                if (reason == GLFS_UPCALL_INODE_INVALIDATE) {
3604df
+                        struct glfs_object *object = NULL;
3604df
 
3604df
-                if (cbk.reason == GFAPI_INODE_INVALIDATE) {
3604df
-                        fprintf (stderr, "Upcall received(%d)\n",
3604df
-                                 cbk.reason);
3604df
-                        in_arg = (struct callback_inode_arg *)(cbk.event_arg);
3604df
+                        in_arg = glfs_upcall_get_event (cbk);
3604df
+                        object = glfs_upcall_inode_get_object (in_arg);
3604df
 
3604df
                         ret = glfs_h_extract_handle (root,
3604df
                                                      globjhdl+GLAPI_UUID_LENGTH,
3604df
                                                      GFAPI_HANDLE_LENGTH);
3604df
                         LOG_ERR("glfs_h_extract_handle", (ret != 16));
3604df
 
3604df
-                        ret = glfs_h_extract_handle (in_arg->object,
3604df
+                        ret = glfs_h_extract_handle (object,
3604df
                                                   globjhdl2+GLAPI_UUID_LENGTH,
3604df
                                                   GFAPI_HANDLE_LENGTH);
3604df
                         LOG_ERR("glfs_h_extract_handle", (ret != 16));
3604df
@@ -148,6 +156,13 @@ main (int argc, char *argv[])
3604df
                         }
3604df
                         upcall_received = 1;
3604df
                 }
3604df
+
3604df
+retry:
3604df
+                if (!upcall_received)
3604df
+                        sleep (1); /* glfs_h_poll_upcall() does not block */
3604df
+
3604df
+                glfs_free (cbk);
3604df
+                cbk = NULL;
3604df
         }
3604df
 
3604df
         if (!upcall_received) {
3604df
diff --git a/tests/basic/gfapi/libgfapi-fini-hang.sh b/tests/basic/gfapi/libgfapi-fini-hang.sh
3604df
index 5663328..0fa81aa 100755
3604df
--- a/tests/basic/gfapi/libgfapi-fini-hang.sh
3604df
+++ b/tests/basic/gfapi/libgfapi-fini-hang.sh
3604df
@@ -21,7 +21,9 @@ EXPECT 'Created' volinfo_field $V0 'Status';
3604df
 TEST $CLI volume start $V0;
3604df
 EXPECT 'Started' volinfo_field $V0 'Status';
3604df
 
3604df
-build_tester -lgfapi $(dirname $0)/libgfapi-fini-hang.c -o $M0/libgfapi-fini-hang
3604df
+logdir=$(gluster --print-logdir)
3604df
+
3604df
+TEST build_tester $(dirname $0)/libgfapi-fini-hang.c -o $M0/libgfapi-fini-hang -lgfapi
3604df
 TEST cd $M0
3604df
  ./libgfapi-fini-hang $V0 &
3604df
 lpid=$!
3604df
diff --git a/tests/basic/gfapi/upcall-cache-invalidate.c b/tests/basic/gfapi/upcall-cache-invalidate.c
3604df
index 13cca69..4d355e6 100644
3604df
--- a/tests/basic/gfapi/upcall-cache-invalidate.c
3604df
+++ b/tests/basic/gfapi/upcall-cache-invalidate.c
3604df
@@ -9,7 +9,6 @@
3604df
 #include <errno.h>
3604df
 #include <glusterfs/api/glfs.h>
3604df
 #include <glusterfs/api/glfs-handles.h>
3604df
-int gfapi = 1;
3604df
 
3604df
 #define LOG_ERR(func, ret) do { \
3604df
         if (ret != 0) {            \
3604df
@@ -24,26 +23,24 @@ int gfapi = 1;
3604df
 int
3604df
 main (int argc, char *argv[])
3604df
 {
3604df
-        glfs_t    *fs = NULL;
3604df
-        glfs_t    *fs2 = NULL;
3604df
-        glfs_t    *fs_tmp = NULL;
3604df
-        glfs_t    *fs_tmp2 = NULL;
3604df
-        int        ret = 0, i;
3604df
-        glfs_fd_t *fd = NULL;
3604df
-        glfs_fd_t *fd2 = NULL;
3604df
-        glfs_fd_t *fd_tmp = NULL;
3604df
-        glfs_fd_t *fd_tmp2 = NULL;
3604df
-        char       readbuf[32];
3604df
-        char      *filename = "file_tmp";
3604df
-        char      *writebuf = NULL;
3604df
-        char      *vol_id  = NULL;
3604df
-        unsigned int       cnt = 1;
3604df
-        struct    callback_arg cbk;
3604df
-        char      *logfile = NULL;
3604df
-        char      *volname = NULL;
3604df
-        struct callback_inode_arg *in_arg = NULL;
3604df
-
3604df
-        cbk.reason = 0;
3604df
+        glfs_t                   *fs = NULL;
3604df
+        glfs_t                   *fs2 = NULL;
3604df
+        glfs_t                   *fs_tmp = NULL;
3604df
+        glfs_t                   *fs_tmp2 = NULL;
3604df
+        int                       ret = 0, i;
3604df
+        glfs_fd_t                *fd = NULL;
3604df
+        glfs_fd_t                *fd2 = NULL;
3604df
+        glfs_fd_t                *fd_tmp = NULL;
3604df
+        glfs_fd_t                *fd_tmp2 = NULL;
3604df
+        char                      readbuf[32];
3604df
+        char                     *filename = "file_tmp";
3604df
+        char                     *writebuf = NULL;
3604df
+        char                     *vol_id  = NULL;
3604df
+        unsigned int              cnt = 1;
3604df
+        struct glfs_upcall       *cbk = NULL;
3604df
+        char                     *logfile = NULL;
3604df
+        char                     *volname = NULL;
3604df
+        char                     *hostname = NULL;
3604df
 
3604df
         if (argc != 3) {
3604df
                 fprintf (stderr, "Invalid argument\n");
3604df
@@ -73,7 +70,6 @@ main (int argc, char *argv[])
3604df
          * on the fs (through this instance) happens. */
3604df
         ret = glfs_h_poll_upcall(fs_tmp, &cbk);
3604df
         LOG_ERR ("glfs_h_poll_upcall", ret);
3604df
-        cbk.reason = 0;
3604df
 
3604df
         fs2 = glfs_new (volname);
3604df
         if (!fs2) {
3604df
@@ -140,6 +136,7 @@ main (int argc, char *argv[])
3604df
                 ret = glfs_lseek (fd_tmp2, 0, SEEK_SET);
3604df
                 LOG_ERR ("glfs_lseek", ret);
3604df
 
3604df
+                memset (readbuf, 0, sizeof(readbuf));
3604df
                 ret = glfs_pread (fd_tmp2, readbuf, 4, 0, 0);
3604df
 
3604df
                 if (ret <= 0) {
3604df
@@ -153,26 +150,37 @@ main (int argc, char *argv[])
3604df
                  * there are I/Os on that fd
3604df
                  */
3604df
                 if (cnt > 2) {
3604df
+                        struct glfs_upcall_inode *in_arg = NULL;
3604df
+                        enum glfs_upcall_reason   reason = 0;
3604df
+                        struct glfs_object       *object = NULL;
3604df
+                        uint64_t                  flags = 0;
3604df
+                        uint64_t                  expire = 0;
3604df
+
3604df
                         ret = glfs_h_poll_upcall(fs_tmp, &cbk);
3604df
                         LOG_ERR ("glfs_h_poll_upcall", ret);
3604df
-                        /* Expect 'GFAPI_INODE_INVALIDATE' upcall event. */
3604df
-                        if (cbk.reason == GFAPI_INODE_INVALIDATE) {
3604df
-                                in_arg = cbk.event_arg;
3604df
+
3604df
+                        reason = glfs_upcall_get_reason (cbk);
3604df
+
3604df
+                        /* Expect 'GLFS_INODE_INVALIDATE' upcall event. */
3604df
+                        if (reason == GLFS_UPCALL_INODE_INVALIDATE) {
3604df
+                                in_arg = glfs_upcall_get_event (cbk);
3604df
+
3604df
+                                object = glfs_upcall_inode_get_object (in_arg);
3604df
+                                flags = glfs_upcall_inode_get_flags (in_arg);
3604df
+                                expire = glfs_upcall_inode_get_expire (in_arg);
3604df
+
3604df
                                 fprintf (stderr, " upcall event type - %d,"
3604df
                                          " object(%p), flags(%d), "
3604df
                                          " expire_time_attr(%d)\n" ,
3604df
-                                         cbk.reason, in_arg->object,
3604df
-                                         in_arg->flags,
3604df
-                                         in_arg->expire_time_attr);
3604df
-                                ret = glfs_h_close (in_arg->object);
3604df
-                                LOG_ERR ("glfs_h_close", ret);
3604df
-                                free (in_arg);
3604df
+                                         reason, object, flags, expire);
3604df
                         } else {
3604df
                                 fprintf (stderr,
3604df
-                                         "Dint receive upcall notify event");
3604df
+                                         "Didnt receive upcall notify event");
3604df
                                 ret = -1;
3604df
                                 goto err;
3604df
                         }
3604df
+
3604df
+                        glfs_free (cbk);
3604df
                 }
3604df
 
3604df
                 sleep(5);
3604df
diff --git a/tests/basic/gfapi/upcall-cache-invalidate.sh b/tests/basic/gfapi/upcall-cache-invalidate.sh
3604df
index f6f59be..114074d 100755
3604df
--- a/tests/basic/gfapi/upcall-cache-invalidate.sh
3604df
+++ b/tests/basic/gfapi/upcall-cache-invalidate.sh
3604df
@@ -5,13 +5,6 @@
3604df
 
3604df
 cleanup;
3604df
 
3604df
-# Upcall feature is disable for now. A new xlator option
3604df
-# will be introduced to turn it on. Skipping this test
3604df
-# till then.
3604df
-
3604df
-SKIP_TESTS;
3604df
-exit 0
3604df
-
3604df
 TEST glusterd
3604df
 
3604df
 TEST $CLI volume create $V0 localhost:$B0/brick1;
3604df
-- 
3604df
2.9.3
3604df