12a457
From 44ef95f37891c6023dd625b495849673fe8ccece Mon Sep 17 00:00:00 2001
12a457
From: Soumya Koduri <skoduri@redhat.com>
12a457
Date: Sat, 30 Apr 2016 22:01:47 +0530
12a457
Subject: [PATCH 127/139] gfapi/upcall: Ignore handle create failures
12a457
12a457
In "glfs_h_poll_cache_invalidation", we need to send upcall only if there
12a457
is a corresponding inode entry in the gfapi inode table for that handle.
12a457
12a457
That's because the application will have reference to the inode as long as
12a457
it operates on any handle. That means the only case in which we cannot find
12a457
inode is when the application has closed the handle (either as part of unlink
12a457
or for any other purpose). But since it will have no more references and will
12a457
not be interested in any upcall event for that handle, we can safely ignore such
12a457
cases.
12a457
12a457
Note: This will affect only that particular applicaiton process/local libgfapi
12a457
client.
12a457
12a457
This is backport of the below upstream fixes -
12a457
 http://review.gluster.org/14132 (upstream)
12a457
 http://review.gluster.org/#/c/14181/ (release-3.7)
12a457
12a457
Change-Id: I9499cd9c284350d4a271e58f2a0966db65a7a61c
12a457
BUG: 1323424
12a457
Signed-off-by: Soumya Koduri <skoduri@redhat.com>
12a457
Reviewed-on: http://review.gluster.org/14132
12a457
Reviewed-by: jiffin tony Thottan <jthottan@redhat.com>
12a457
Reviewed-by: Kaleb KEITHLEY <kkeithle@redhat.com>
12a457
Reviewed-on: https://code.engineering.redhat.com/gerrit/73590
12a457
Reviewed-by: Jiffin Thottan <jthottan@redhat.com>
12a457
Reviewed-by: Kaleb Keithley <kkeithle@redhat.com>
12a457
Tested-by: Kaleb Keithley <kkeithle@redhat.com>
12a457
---
12a457
 api/src/glfs-handleops.c |  142 ++++++++++++++++++++++++++++++++++++++--------
12a457
 1 files changed, 118 insertions(+), 24 deletions(-)
12a457
12a457
diff --git a/api/src/glfs-handleops.c b/api/src/glfs-handleops.c
12a457
index a230578..72aa7de 100644
12a457
--- a/api/src/glfs-handleops.c
12a457
+++ b/api/src/glfs-handleops.c
12a457
@@ -1805,6 +1805,69 @@ invalid_fs:
12a457
 
12a457
 GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_h_rename, 3.4.2);
12a457
 
12a457
+/*
12a457
+ * Given a handle/gfid, find if the corresponding inode is present in
12a457
+ * the inode table. If yes create and return the corresponding glfs_object.
12a457
+ */
12a457
+struct glfs_object *
12a457
+glfs_h_find_handle (struct glfs *fs, unsigned char *handle, int len)
12a457
+{
12a457
+        int                 ret = -1;
12a457
+        inode_t            *newinode = NULL;
12a457
+        xlator_t           *subvol = NULL;
12a457
+        struct glfs_object *object = NULL;
12a457
+        uuid_t gfid;
12a457
+
12a457
+        /* validate in args */
12a457
+        if ((fs == NULL) || (handle == NULL) || (len != GFAPI_HANDLE_LENGTH)) {
12a457
+                errno = EINVAL;
12a457
+                return NULL;
12a457
+        }
12a457
+
12a457
+        DECLARE_OLD_THIS;
12a457
+        __GLFS_ENTRY_VALIDATE_FS (fs, invalid_fs);
12a457
+
12a457
+        /* get the active volume */
12a457
+        subvol = glfs_active_subvol (fs);
12a457
+        if (!subvol) {
12a457
+                errno = EIO;
12a457
+                goto out;
12a457
+        }
12a457
+
12a457
+        memcpy (gfid, handle, GFAPI_HANDLE_LENGTH);
12a457
+
12a457
+        /* make sure the gfid received is valid */
12a457
+        GF_VALIDATE_OR_GOTO ("glfs_h_find_handle",
12a457
+                             !(gf_uuid_is_null (gfid)), out);
12a457
+
12a457
+        newinode = inode_find (subvol->itable, gfid);
12a457
+        if (!newinode) {
12a457
+                goto out;
12a457
+        }
12a457
+
12a457
+        object = GF_CALLOC (1, sizeof(struct glfs_object),
12a457
+                            glfs_mt_glfs_object_t);
12a457
+        if (object == NULL) {
12a457
+                errno = ENOMEM;
12a457
+                ret = -1;
12a457
+                goto out;
12a457
+        }
12a457
+
12a457
+        /* populate the return object. The ref taken here
12a457
+         * is un'refed when the application does glfs_h_close() */
12a457
+        object->inode = inode_ref(newinode);
12a457
+        gf_uuid_copy (object->gfid, object->inode->gfid);
12a457
+
12a457
+out:
12a457
+        glfs_subvol_done (fs, subvol);
12a457
+
12a457
+        __GLFS_EXIT_FS;
12a457
+
12a457
+invalid_fs:
12a457
+        return object;
12a457
+
12a457
+}
12a457
+
12a457
 int
12a457
 glfs_h_poll_cache_invalidation (struct glfs *fs,
12a457
                                 struct callback_arg *up_arg,
12a457
@@ -1821,11 +1884,24 @@ glfs_h_poll_cache_invalidation (struct glfs *fs,
12a457
         GF_VALIDATE_OR_GOTO ("glfs_h_poll_cache_invalidation",
12a457
                              ca_data, out);
12a457
 
12a457
-        object = glfs_h_create_from_handle (fs, upcall_data->gfid,
12a457
-                                            GFAPI_HANDLE_LENGTH,
12a457
-                                            NULL);
12a457
-        GF_VALIDATE_OR_GOTO ("glfs_h_poll_cache_invalidation",
12a457
-                             object, out);
12a457
+        object = glfs_h_find_handle (fs, upcall_data->gfid,
12a457
+                                     GFAPI_HANDLE_LENGTH);
12a457
+        if (!object) {
12a457
+                /* The reason handle creation will fail is because we
12a457
+                 * couldn't find the inode in the gfapi inode table.
12a457
+                 *
12a457
+                 * But since application would have taken inode_ref, the
12a457
+                 * only case when this can happen is when it has closed
12a457
+                 * the handle and hence will no more be interested in
12a457
+                 * the upcall for this particular gfid.
12a457
+                 */
12a457
+                gf_msg (THIS->name, GF_LOG_DEBUG, errno,
12a457
+                        API_MSG_CREATE_HANDLE_FAILED,
12a457
+                        "handle creation of %s failed",
12a457
+                         uuid_utoa (upcall_data->gfid));
12a457
+                errno = ESTALE;
12a457
+                goto out;
12a457
+        }
12a457
 
12a457
         up_inode_arg = calloc (1, sizeof (struct callback_inode_arg));
12a457
         GF_VALIDATE_OR_GOTO ("glfs_h_poll_cache_invalidation",
12a457
@@ -1844,12 +1920,17 @@ glfs_h_poll_cache_invalidation (struct glfs *fs,
12a457
         }
12a457
 
12a457
         if (ca_data->flags & GFAPI_UP_PARENT_TIMES) {
12a457
-                p_object = glfs_h_create_from_handle (fs,
12a457
-                                                      ca_data->p_stat.ia_gfid,
12a457
-                                                      GFAPI_HANDLE_LENGTH,
12a457
-                                                      NULL);
12a457
-                GF_VALIDATE_OR_GOTO ("glfs_h_poll_cache_invalidation",
12a457
-                                       p_object, out);
12a457
+                p_object = glfs_h_find_handle (fs,
12a457
+                                               ca_data->p_stat.ia_gfid,
12a457
+                                               GFAPI_HANDLE_LENGTH);
12a457
+                if (!p_object) {
12a457
+                        gf_msg (THIS->name, GF_LOG_DEBUG, errno,
12a457
+                                API_MSG_CREATE_HANDLE_FAILED,
12a457
+                                "handle creation of %s failed",
12a457
+                                 uuid_utoa (ca_data->p_stat.ia_gfid));
12a457
+                        errno = ESTALE;
12a457
+                        goto out;
12a457
+                }
12a457
 
12a457
                 glfs_iatt_to_stat (fs, &ca_data->p_stat, &up_inode_arg->p_buf);
12a457
         }
12a457
@@ -1857,12 +1938,21 @@ glfs_h_poll_cache_invalidation (struct glfs *fs,
12a457
 
12a457
         /* In case of RENAME, update old parent as well */
12a457
         if (ca_data->flags & GFAPI_UP_RENAME) {
12a457
-                oldp_object = glfs_h_create_from_handle (fs,
12a457
-                                                     ca_data->oldp_stat.ia_gfid,
12a457
-                                                     GFAPI_HANDLE_LENGTH,
12a457
-                                                     NULL);
12a457
-                GF_VALIDATE_OR_GOTO ("glfs_h_poll_cache_invalidation",
12a457
-                                       oldp_object, out);
12a457
+                oldp_object = glfs_h_find_handle (fs,
12a457
+                                                  ca_data->oldp_stat.ia_gfid,
12a457
+                                                  GFAPI_HANDLE_LENGTH);
12a457
+                if (!oldp_object) {
12a457
+                        gf_msg (THIS->name, GF_LOG_DEBUG, errno,
12a457
+                                API_MSG_CREATE_HANDLE_FAILED,
12a457
+                                "handle creation of %s failed",
12a457
+                                 uuid_utoa (ca_data->oldp_stat.ia_gfid));
12a457
+                        errno = ESTALE;
12a457
+                        /* By the time we receive upcall old parent_dir may
12a457
+                         * have got removed. We still need to send upcall
12a457
+                         * for the file/dir and current parent handles. */
12a457
+                        up_inode_arg->oldp_object = NULL;
12a457
+                        ret = 0;
12a457
+                }
12a457
 
12a457
                 glfs_iatt_to_stat (fs, &ca_data->oldp_stat,
12a457
                                    &up_inode_arg->oldp_buf);
12a457
@@ -1872,6 +1962,15 @@ glfs_h_poll_cache_invalidation (struct glfs *fs,
12a457
         ret = 0;
12a457
 
12a457
 out:
12a457
+        if (ret) {
12a457
+                /* Close p_object and oldp_object as well if being referenced.*/
12a457
+                if (object)
12a457
+                        glfs_h_close (object);
12a457
+
12a457
+                /* Reset event_arg as well*/
12a457
+                up_arg->event_arg = NULL;
12a457
+                GF_FREE (up_inode_arg);
12a457
+        }
12a457
         return ret;
12a457
 }
12a457
 
12a457
@@ -1972,16 +2071,11 @@ pub_glfs_h_poll_upcall (struct glfs *fs, struct callback_arg *up_arg)
12a457
                         }
12a457
                         /* It could so happen that the file which got
12a457
                          * upcall notification may have got deleted
12a457
-                         * by other thread. Irrespective of the error,
12a457
-                         * log it and return with CBK_NULL reason.
12a457
+                         * by the same client. Irrespective of the error,
12a457
+                         * return with CBK_NULL reason.
12a457
                          *
12a457
                          * Applications will ignore this notification
12a457
                          * as up_arg->object will be NULL */
12a457
-                        gf_msg (subvol->name, GF_LOG_WARNING, errno,
12a457
-                                API_MSG_CREATE_HANDLE_FAILED,
12a457
-                                "handle creation of %s failed",
12a457
-                                uuid_utoa (upcall_data->gfid));
12a457
-
12a457
                         reason = GFAPI_CBK_EVENT_NULL;
12a457
                         break;
12a457
                 default:
12a457
-- 
12a457
1.7.1
12a457