diff options
| author | Soumya Koduri <skoduri@redhat.com> | 2015-02-16 11:47:58 +0530 | 
|---|---|---|
| committer | Kaleb KEITHLEY <kkeithle@redhat.com> | 2015-03-17 14:01:21 -0700 | 
| commit | 2a4561ef08b8be3b7d79b951252e87ba8f987120 (patch) | |
| tree | ed5cc0c87f6532b167ebb2b775389a9a391a3cf4 /api/src/glfs-handleops.c | |
| parent | d81182cf69a4f188f304fcce6d651ffd56b67aac (diff) | |
gfapi: APIs to store and process upcall notifications received
In case of any upcall cbk events received by the protocol/client,
gfapi will be notified which queues them up in a list (<gfapi_cbk_upcall>).
Applicatons are responsible to provide APIs to process & notify them in case
of any such upcall events queued.
Added a new API which will be used by Ganesha to repeatedly poll for any
such upcall event notified (<glfs_h_poll_upcall>).
A new test-file has been added to test the cache_invalidation upcall events.
Below link has a writeup which explains the code changes done -
        URL: https://soumyakoduri.wordpress.com/2015/02/25/glusterfs-understanding-upcall-infrastructure-and-cache-invalidation-support/
Change-Id: Iafc6880000c865fd4da22d0cfc388ec135b5a1c5
BUG: 1200262
Signed-off-by: Soumya Koduri <skoduri@redhat.com>
Reviewed-on: http://review.gluster.org/9536
Tested-by: Gluster Build System <jenkins@build.gluster.com>
Reviewed-by: Kaleb KEITHLEY <kkeithle@redhat.com>
Diffstat (limited to 'api/src/glfs-handleops.c')
| -rw-r--r-- | api/src/glfs-handleops.c | 129 | 
1 files changed, 129 insertions, 0 deletions
diff --git a/api/src/glfs-handleops.c b/api/src/glfs-handleops.c index 631af01d97b..037315a518d 100644 --- a/api/src/glfs-handleops.c +++ b/api/src/glfs-handleops.c @@ -1594,3 +1594,132 @@ out:  GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_h_rename, 3.4.2); +/* + * This API is used to poll for upcall events stored in the + * upcall list. Current users of this API is NFS-Ganesha. + * Incase of any event received, it will be mapped appropriately + * into 'callback_arg' along with the handle to be passed to + * NFS-Ganesha. + * + * Application is responsible for allocating and passing the + * references of all the pointers except for "glhandle". + * After processing the event, it needs to free "glhandle" + * + * TODO: there should be a glfs api to destroy these handles, + * maybe "glfs_destroy_object" to free the object. + * + * Also similar to I/Os, the application should ideally stop polling + * before calling glfs_fini(..). Hence making an assumption that + * 'fs' & ctx structures cannot be freed while in this routine. + */ +int +pub_glfs_h_poll_upcall (struct glfs *fs, struct callback_arg *up_arg) +{ +        struct glfs_object  *handle   = NULL; +        uuid_t              gfid; +        upcall_entry        *u_list   = NULL; +        upcall_entry        *tmp      = NULL; +        xlator_t            *subvol   = NULL; +        int                 found     = 0; +        int                 reason    = 0; +        glusterfs_ctx_t     *ctx      = NULL; +        int                 ret       = -1; + +        if (!fs || !up_arg) { +                errno = EINVAL; +                goto err; +        } + +        __glfs_entry_fs (fs); + +        /* get the active volume */ +        subvol = glfs_active_subvol (fs); + +        if (!subvol) { +                errno = EIO; +                goto err; +        } + +        up_arg->handle = NULL; + +        /* Ideally applications should stop polling before calling +         * 'glfs_fini'. Yet cross check if cleanup has started +         */ +        pthread_mutex_lock (&fs->mutex); +        { +                ctx = fs->ctx; + +                if (ctx->cleanup_started) { +                        pthread_mutex_unlock (&fs->mutex); +                        goto out; +                } + +                fs->pin_refcnt++; +        } +        pthread_mutex_unlock (&fs->mutex); + +        pthread_mutex_lock (&fs->upcall_list_mutex); +        { +                list_for_each_entry_safe (u_list, tmp, +                                          &fs->upcall_list, +                                          upcall_list) { +                        uuid_copy (gfid, u_list->gfid); +                        found = 1; +                        break; +                } +        } +        /* No other thread can delete this entry. So unlock it */ +        pthread_mutex_unlock (&fs->upcall_list_mutex); + +        if (found) { +                handle = glfs_h_create_from_handle (fs, gfid, +                                                    GFAPI_HANDLE_LENGTH, +                                                    &up_arg->buf); + +                if (!handle) { +                        errno = ENOMEM; +                        goto out; +                } + +                switch (u_list->event_type) { +                case CACHE_INVALIDATION: +                        if (u_list->flags & (~(INODE_UPDATE_FLAGS))) { +                                /* Invalidate CACHE */ +                                reason = INODE_INVALIDATE; +                                gf_log (subvol->name, GF_LOG_DEBUG, +                                        "Reason - INODE_INVALIDATION"); +                        } else { +                                reason = INODE_UPDATE; +                                gf_log (subvol->name, GF_LOG_DEBUG, +                                        "Reason - INODE_UPDATE"); +                        } +                        break; +                default: +                        break; +                } + +                up_arg->handle = handle; +                up_arg->reason = reason; +                up_arg->flags = u_list->flags; +                up_arg->expire_time_attr = u_list->expire_time_attr; + +                list_del_init (&u_list->upcall_list); +                GF_FREE (u_list); +        } + +        ret = 0; + +out: +        pthread_mutex_lock (&fs->mutex); +        { +                fs->pin_refcnt--; +        } +        pthread_mutex_unlock (&fs->mutex); + +        glfs_subvol_done (fs, subvol); + +err: +        return ret; +} + +GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_h_poll_upcall, 3.7.0);  | 
