diff options
Diffstat (limited to 'api')
| -rw-r--r-- | api/src/glfs-handleops.c | 142 | 
1 files changed, 118 insertions, 24 deletions
diff --git a/api/src/glfs-handleops.c b/api/src/glfs-handleops.c index a230578b615..72aa7de146e 100644 --- a/api/src/glfs-handleops.c +++ b/api/src/glfs-handleops.c @@ -1805,6 +1805,69 @@ invalid_fs:  GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_h_rename, 3.4.2); +/* + * Given a handle/gfid, find if the corresponding inode is present in + * the inode table. If yes create and return the corresponding glfs_object. + */ +struct glfs_object * +glfs_h_find_handle (struct glfs *fs, unsigned char *handle, int len) +{ +        int                 ret = -1; +        inode_t            *newinode = NULL; +        xlator_t           *subvol = NULL; +        struct glfs_object *object = NULL; +        uuid_t gfid; + +        /* validate in args */ +        if ((fs == NULL) || (handle == NULL) || (len != GFAPI_HANDLE_LENGTH)) { +                errno = EINVAL; +                return NULL; +        } + +        DECLARE_OLD_THIS; +        __GLFS_ENTRY_VALIDATE_FS (fs, invalid_fs); + +        /* get the active volume */ +        subvol = glfs_active_subvol (fs); +        if (!subvol) { +                errno = EIO; +                goto out; +        } + +        memcpy (gfid, handle, GFAPI_HANDLE_LENGTH); + +        /* make sure the gfid received is valid */ +        GF_VALIDATE_OR_GOTO ("glfs_h_find_handle", +                             !(gf_uuid_is_null (gfid)), out); + +        newinode = inode_find (subvol->itable, gfid); +        if (!newinode) { +                goto out; +        } + +        object = GF_CALLOC (1, sizeof(struct glfs_object), +                            glfs_mt_glfs_object_t); +        if (object == NULL) { +                errno = ENOMEM; +                ret = -1; +                goto out; +        } + +        /* populate the return object. The ref taken here +         * is un'refed when the application does glfs_h_close() */ +        object->inode = inode_ref(newinode); +        gf_uuid_copy (object->gfid, object->inode->gfid); + +out: +        glfs_subvol_done (fs, subvol); + +        __GLFS_EXIT_FS; + +invalid_fs: +        return object; + +} +  int  glfs_h_poll_cache_invalidation (struct glfs *fs,                                  struct callback_arg *up_arg, @@ -1821,11 +1884,24 @@ glfs_h_poll_cache_invalidation (struct glfs *fs,          GF_VALIDATE_OR_GOTO ("glfs_h_poll_cache_invalidation",                               ca_data, out); -        object = glfs_h_create_from_handle (fs, upcall_data->gfid, -                                            GFAPI_HANDLE_LENGTH, -                                            NULL); -        GF_VALIDATE_OR_GOTO ("glfs_h_poll_cache_invalidation", -                             object, out); +        object = glfs_h_find_handle (fs, upcall_data->gfid, +                                     GFAPI_HANDLE_LENGTH); +        if (!object) { +                /* The reason handle creation will fail is because we +                 * couldn't find the inode in the gfapi inode table. +                 * +                 * But since application would have taken inode_ref, the +                 * only case when this can happen is when it has closed +                 * the handle and hence will no more be interested in +                 * the upcall for this particular gfid. +                 */ +                gf_msg (THIS->name, GF_LOG_DEBUG, errno, +                        API_MSG_CREATE_HANDLE_FAILED, +                        "handle creation of %s failed", +                         uuid_utoa (upcall_data->gfid)); +                errno = ESTALE; +                goto out; +        }          up_inode_arg = calloc (1, sizeof (struct callback_inode_arg));          GF_VALIDATE_OR_GOTO ("glfs_h_poll_cache_invalidation", @@ -1844,12 +1920,17 @@ glfs_h_poll_cache_invalidation (struct glfs *fs,          }          if (ca_data->flags & GFAPI_UP_PARENT_TIMES) { -                p_object = glfs_h_create_from_handle (fs, -                                                      ca_data->p_stat.ia_gfid, -                                                      GFAPI_HANDLE_LENGTH, -                                                      NULL); -                GF_VALIDATE_OR_GOTO ("glfs_h_poll_cache_invalidation", -                                       p_object, out); +                p_object = glfs_h_find_handle (fs, +                                               ca_data->p_stat.ia_gfid, +                                               GFAPI_HANDLE_LENGTH); +                if (!p_object) { +                        gf_msg (THIS->name, GF_LOG_DEBUG, errno, +                                API_MSG_CREATE_HANDLE_FAILED, +                                "handle creation of %s failed", +                                 uuid_utoa (ca_data->p_stat.ia_gfid)); +                        errno = ESTALE; +                        goto out; +                }                  glfs_iatt_to_stat (fs, &ca_data->p_stat, &up_inode_arg->p_buf);          } @@ -1857,12 +1938,21 @@ glfs_h_poll_cache_invalidation (struct glfs *fs,          /* In case of RENAME, update old parent as well */          if (ca_data->flags & GFAPI_UP_RENAME) { -                oldp_object = glfs_h_create_from_handle (fs, -                                                     ca_data->oldp_stat.ia_gfid, -                                                     GFAPI_HANDLE_LENGTH, -                                                     NULL); -                GF_VALIDATE_OR_GOTO ("glfs_h_poll_cache_invalidation", -                                       oldp_object, out); +                oldp_object = glfs_h_find_handle (fs, +                                                  ca_data->oldp_stat.ia_gfid, +                                                  GFAPI_HANDLE_LENGTH); +                if (!oldp_object) { +                        gf_msg (THIS->name, GF_LOG_DEBUG, errno, +                                API_MSG_CREATE_HANDLE_FAILED, +                                "handle creation of %s failed", +                                 uuid_utoa (ca_data->oldp_stat.ia_gfid)); +                        errno = ESTALE; +                        /* By the time we receive upcall old parent_dir may +                         * have got removed. We still need to send upcall +                         * for the file/dir and current parent handles. */ +                        up_inode_arg->oldp_object = NULL; +                        ret = 0; +                }                  glfs_iatt_to_stat (fs, &ca_data->oldp_stat,                                     &up_inode_arg->oldp_buf); @@ -1872,6 +1962,15 @@ glfs_h_poll_cache_invalidation (struct glfs *fs,          ret = 0;  out: +        if (ret) { +                /* Close p_object and oldp_object as well if being referenced.*/ +                if (object) +                        glfs_h_close (object); + +                /* Reset event_arg as well*/ +                up_arg->event_arg = NULL; +                GF_FREE (up_inode_arg); +        }          return ret;  } @@ -1972,16 +2071,11 @@ pub_glfs_h_poll_upcall (struct glfs *fs, struct callback_arg *up_arg)                          }                          /* It could so happen that the file which got                           * upcall notification may have got deleted -                         * by other thread. Irrespective of the error, -                         * log it and return with CBK_NULL reason. +                         * by the same client. Irrespective of the error, +                         * return with CBK_NULL reason.                           *                           * Applications will ignore this notification                           * as up_arg->object will be NULL */ -                        gf_msg (subvol->name, GF_LOG_WARNING, errno, -                                API_MSG_CREATE_HANDLE_FAILED, -                                "handle creation of %s failed", -                                uuid_utoa (upcall_data->gfid)); -                          reason = GFAPI_CBK_EVENT_NULL;                          break;                  default:  | 
