diff options
-rw-r--r-- | api/src/gfapi.aliases | 14 | ||||
-rw-r--r-- | api/src/gfapi.map | 17 | ||||
-rw-r--r-- | api/src/glfs-handleops.c | 226 | ||||
-rw-r--r-- | api/src/glfs-handles.h | 107 | ||||
-rw-r--r-- | api/src/glfs-internal.h | 53 | ||||
-rw-r--r-- | api/src/glfs-mem-types.h | 1 | ||||
-rw-r--r-- | api/src/glfs.c | 104 | ||||
-rw-r--r-- | tests/basic/gfapi/bug1283983.c | 32 | ||||
-rw-r--r-- | tests/basic/gfapi/bug1291259.c | 62 | ||||
-rwxr-xr-x | tests/basic/gfapi/libgfapi-fini-hang.t | 4 | ||||
-rw-r--r-- | tests/basic/gfapi/upcall-cache-invalidate.c | 71 | ||||
-rwxr-xr-x | tests/basic/gfapi/upcall-cache-invalidate.t | 7 |
12 files changed, 520 insertions, 178 deletions
diff --git a/api/src/gfapi.aliases b/api/src/gfapi.aliases index 365d170230b..ac89d35df6b 100644 --- a/api/src/gfapi.aliases +++ b/api/src/gfapi.aliases @@ -140,4 +140,18 @@ _priv_glfs_resolve _glfs_resolve$GFAPI_PRIVATE_3.7.0 _priv_glfs_process_upcall_event _glfs_process_upcall_event$GFAPI_PRIVATE_3.7.0 _pub_glfs_h_lookupat _glfs_h_lookupat$GFAPI_3.7.4 + +_pub_glfs_h_poll_upcall _glfs_h_poll_upcall$GFAPI_3.7.16 +_pub_glfs_upcall_get_fs _glfs_upcall_get_fs$GFAPI_3.7.16 +_pub_glfs_upcall_get_reason _glfs_upcall_get_reason$GFAPI_3.7.16 +_pub_glfs_upcall_inode_get_event _glfs_upcall_inode_get_event$GFAPI_3.7.16 +_pub_glfs_upcall_inode_get_object _glfs_upcall_inode_get_object$GFAPI_3.7.16 +_pub_glfs_upcall_inode_get_flags _glfs_upcall_inode_get_flags$GFAPI_3.7.16 +_pub_glfs_upcall_inode_get_stat _glfs_upcall_inode_get_stat$GFAPI_3.7.16 +_pub_glfs_upcall_inode_get_expire _glfs_upcall_inode_get_expire$GFAPI_3.7.16 +_pub_glfs_upcall_inode_get_pobject _glfs_upcall_inode_get_pobject$GFAPI_3.7.16 +_pub_glfs_upcall_inode_get_pstat _glfs_upcall_inode_get_pstat$GFAPI_3.7.16 +_pub_glfs_upcall_inode_get_oldpobject _glfs_upcall_inode_get_oldpobject$GFAPI_3.7.16 +_pub_glfs_upcall_inode_get_oldpstat _glfs_upcall_inode_get_oldpstat$GFAPI_3.7.16 + _pub_glfs_ipc _glfs_ipc$GFAPI_4.0.0 diff --git a/api/src/gfapi.map b/api/src/gfapi.map index b03e6212694..bd7ff13fe41 100644 --- a/api/src/gfapi.map +++ b/api/src/gfapi.map @@ -173,7 +173,22 @@ GFAPI_3.7.15 { glfs_truncate; } GFAPI_3.7.4; +GFAPI_3.7.16 { + global: + glfs_upcall_get_fs; + glfs_upcall_get_reason; + glfs_upcall_inode_get_event; + glfs_upcall_inode_get_object; + glfs_upcall_inode_get_flags; + glfs_upcall_inode_get_stat; + glfs_upcall_inode_get_expire; + glfs_upcall_inode_get_pobject; + glfs_upcall_inode_get_pstat; + glfs_upcall_inode_get_oldpobject; + glfs_upcall_inode_get_oldpstat; +} GFAPI_3.7.15; + GFAPI_4.0.0 { global: glfs_ipc; -} GFAPI_3.7.15; +} GFAPI_3.7.16; diff --git a/api/src/glfs-handleops.c b/api/src/glfs-handleops.c index 47bdbcbec52..84dba5b82c5 100644 --- a/api/src/glfs-handleops.c +++ b/api/src/glfs-handleops.c @@ -1854,9 +1854,27 @@ invalid_fs: } +static void +glfs_free_upcall_inode (void *to_free) +{ + struct glfs_upcall_inode *arg = to_free; + + if (!arg) + return; + + if (arg->object) + glfs_h_close (arg->object); + if (arg->p_object) + glfs_h_close (arg->p_object); + if (arg->oldp_object) + glfs_h_close (arg->oldp_object); + + GF_FREE (arg); +} + int glfs_h_poll_cache_invalidation (struct glfs *fs, - struct glfs_callback_arg *up_arg, + struct glfs_upcall *up_arg, struct gf_upcall *upcall_data) { int ret = -1; @@ -1864,7 +1882,7 @@ glfs_h_poll_cache_invalidation (struct glfs *fs, struct glfs_object *oldp_object = NULL; struct glfs_object *object = NULL; struct gf_upcall_cache_invalidation *ca_data = NULL; - struct glfs_callback_inode_arg *up_inode_arg = NULL; + struct glfs_upcall_inode *up_inode_arg = NULL; ca_data = upcall_data->data; GF_VALIDATE_OR_GOTO ("glfs_h_poll_cache_invalidation", @@ -1889,13 +1907,11 @@ glfs_h_poll_cache_invalidation (struct glfs *fs, goto out; } - up_inode_arg = GF_CALLOC (1, sizeof (struct glfs_callback_inode_arg), - glfs_mt_upcall_entry_t); + up_inode_arg = GF_CALLOC (1, sizeof (struct glfs_upcall_inode), + glfs_mt_upcall_inode_t); GF_VALIDATE_OR_GOTO ("glfs_h_poll_cache_invalidation", up_inode_arg, out); - up_arg->event_arg = up_inode_arg; - up_inode_arg->object = object; up_inode_arg->flags = ca_data->flags; up_inode_arg->expire_time_attr = ca_data->expire_time_attr; @@ -1946,6 +1962,10 @@ glfs_h_poll_cache_invalidation (struct glfs *fs, } up_inode_arg->oldp_object = oldp_object; + up_arg->reason = GLFS_UPCALL_INODE_INVALIDATE; + up_arg->event = up_inode_arg; + up_arg->free_event = glfs_free_upcall_inode; + ret = 0; out: @@ -1954,47 +1974,42 @@ out: if (object) glfs_h_close (object); - /* Reset event_arg as well*/ - up_arg->event_arg = NULL; + /* Set reason to prevent applications from using ->event */ + up_arg->reason = GLFS_UPCALL_EVENT_NULL; GF_FREE (up_inode_arg); } return ret; } /* - * 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 'glfs_callback_arg' along with the handle object to be passed - * to NFS-Ganesha. - * - * On success, applications need to check for 'reason' to decide - * if any upcall event is received. + * 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 'glfs_upcall' along with the handle object + * to be passed to NFS-Ganesha. * - * Current supported upcall_events - - * GFAPI_INODE_INVALIDATE - - * 'arg - glfs_callback_inode_arg + * On success, applications need to check if up_arg is not-NULL or errno is not + * ENOENT. glfs_upcall_get_reason() can be used to decide what kind of event + * has been received. * - * After processing the event, applications need to free 'event_arg'. + * Current supported upcall_events: + * GLFS_UPCALL_INODE_INVALIDATE * - * Incase of INODE_INVALIDATE, applications need to free "object", - * "p_object" and "oldp_object" using glfs_h_close(..). + * After processing the event, applications need to free 'up_arg' by calling + * glfs_free(). * - * 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. + * 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 glfs_callback_arg *up_arg) +pub_glfs_h_poll_upcall (struct glfs *fs, struct glfs_upcall **up_arg) { - 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; - struct gf_upcall *upcall_data = NULL; + upcall_entry *u_list = NULL; + upcall_entry *tmp = NULL; + xlator_t *subvol = NULL; + glusterfs_ctx_t *ctx = NULL; + int ret = -1; + struct gf_upcall *upcall_data = NULL; DECLARE_OLD_THIS; @@ -2007,15 +2022,13 @@ pub_glfs_h_poll_upcall (struct glfs *fs, struct glfs_callback_arg *up_arg) /* get the active volume */ subvol = glfs_active_subvol (fs); - if (!subvol) { errno = EIO; goto restore; } /* Ideally applications should stop polling before calling - * 'glfs_fini'. Yet cross check if cleanup has started - */ + * 'glfs_fini'. Yet cross check if cleanup has started. */ pthread_mutex_lock (&fs->mutex); { ctx = fs->ctx; @@ -2038,46 +2051,55 @@ pub_glfs_h_poll_upcall (struct glfs *fs, struct glfs_callback_arg *up_arg) list_for_each_entry_safe (u_list, tmp, &fs->upcall_list, upcall_list) { - found = 1; list_del_init (&u_list->upcall_list); + upcall_data = &u_list->upcall_data; break; } } /* No other thread can delete this entry. So unlock it */ pthread_mutex_unlock (&fs->upcall_list_mutex); - if (found) { - upcall_data = &u_list->upcall_data; - + if (upcall_data) { switch (upcall_data->event_type) { case GF_UPCALL_CACHE_INVALIDATION: + *up_arg = GF_CALLOC (1, sizeof (struct gf_upcall), + glfs_mt_upcall_entry_t); + if (!*up_arg) { + errno = ENOMEM; + break; /* goto free u_list */ + } + /* XXX: Need to revisit this to support - * GFAPI_INODE_UPDATE if required. - */ - reason = GFAPI_INODE_INVALIDATE; - ret = glfs_h_poll_cache_invalidation (fs, - up_arg, + * GLFS_UPCALL_INODE_UPDATE if required. */ + ret = glfs_h_poll_cache_invalidation (fs, *up_arg, upcall_data); - if (!ret) { - break; + if (ret + || (*up_arg)->reason == GLFS_UPCALL_EVENT_NULL) { + /* It could so happen that the file which got + * upcall notification may have got deleted by + * the same client. Irrespective of the error, + * return with an error or success+ENOENT. */ + if ((*up_arg)->reason == GLFS_UPCALL_EVENT_NULL) + errno = ENOENT; + + GF_FREE (*up_arg); + *up_arg = NULL; } - /* It could so happen that the file which got - * upcall notification may have got deleted - * 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 */ - reason = GFAPI_CBK_EVENT_NULL; break; - default: + case GF_UPCALL_RECALL_LEASE: + gf_log ("glfs_h_poll_upcall", GF_LOG_DEBUG, + "UPCALL_RECALL_LEASE is not implemented yet"); + case GF_UPCALL_EVENT_NULL: + /* no 'default:' label, to force handling all upcall events */ + errno = ENOENT; break; } - up_arg->reason = reason; - GF_FREE (u_list->upcall_data.data); GF_FREE (u_list); + } else { + /* fs->upcall_list was empty, no upcall events cached */ + errno = ENOENT; } ret = 0; @@ -2097,7 +2119,91 @@ err: return ret; } -GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_h_poll_upcall, 3.7.0); +GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_h_poll_upcall, 3.7.16); + +static gf_boolean_t log_upcall370 = _gf_true; /* log once */ + +/* The old glfs_h_poll_upcall interface requires intimite knowledge of the + * structures that are returned to the calling application. This is not + * recommended, as the returned structures need to returned correctly (handles + * closed, memory free'd with the unavailable GF_FREE(), and possibly more.) + * + * To the best of our knowledge, only NFS-Ganesha uses the upcall events + * through gfapi. We keep this backwards compatability function around so that + * applications using the existing implementation do not break. + * + * WARNING: this function will be removed in the future. + */ +int +pub_glfs_h_poll_upcall370 (struct glfs *fs, struct glfs_callback_arg *up_arg) +{ + struct glfs_upcall *upcall = NULL; + int ret = -1; + + if (log_upcall370) { + log_upcall370 = _gf_false; + gf_log (THIS->name, GF_LOG_WARNING, "this application is " + "compiled against an old version of libgfapi, it " + "should use glfs_free() to release the structure " + "returned by glfs_h_poll_upcall() - for more details, " + "see http://review.gluster.org/14701"); + } + + ret = pub_glfs_h_poll_upcall (fs, &upcall); + if (ret == 0) { + up_arg->fs = fs; + if (errno == ENOENT || upcall->event == NULL) { + up_arg->reason = GLFS_UPCALL_EVENT_NULL; + goto out; + } + + up_arg->reason = upcall->reason; + + if (upcall->reason == GLFS_UPCALL_INODE_INVALIDATE) { + struct glfs_callback_inode_arg *cb_inode = NULL; + struct glfs_upcall_inode *up_inode = NULL; + + cb_inode = GF_CALLOC (1, + sizeof (struct glfs_callback_inode_arg), + glfs_mt_upcall_inode_t); + if (!cb_inode) { + errno = ENOMEM; + ret = -1; + goto out; + } + + up_inode = upcall->event; + + /* copy attributes one by one, the memory layout might + * be different between the old glfs_callback_inode_arg + * and new glfs_upcall_inode */ + cb_inode->object = up_inode->object; + cb_inode->flags = up_inode->flags; + memcpy (&cb_inode->buf, &up_inode->buf, + sizeof (struct stat)); + cb_inode->expire_time_attr = up_inode->expire_time_attr; + cb_inode->p_object = up_inode->p_object; + memcpy (&cb_inode->p_buf, &up_inode->p_buf, + sizeof (struct stat)); + cb_inode->oldp_object = up_inode->oldp_object; + memcpy (&cb_inode->oldp_buf, &up_inode->oldp_buf, + sizeof (struct stat)); + + up_arg->event_arg = cb_inode; + } + } + +out: + if (upcall) { + /* we can not use glfs_free() here, objects need to stay */ + GF_FREE (upcall->event); + GF_FREE (upcall); + } + + return ret; +} + +GFAPI_SYMVER_PUBLIC(glfs_h_poll_upcall370, glfs_h_poll_upcall, 3.7.0); #ifdef HAVE_ACL_LIBACL_H #include "glusterfs-acl.h" diff --git a/api/src/glfs-handles.h b/api/src/glfs-handles.h index 557934503d2..740b759d0a0 100644 --- a/api/src/glfs-handles.h +++ b/api/src/glfs-handles.h @@ -12,6 +12,7 @@ #define _GLFS_HANDLES_H #include "glfs.h" +#include <inttypes.h> /* GLFS OBJECT BASED OPERATIONS * @@ -110,45 +111,82 @@ typedef struct glfs_object glfs_object_t; * * Currently supported upcall_events - * GFAPI_INODE_INVALIDATE - - * 'event_arg' - glfs_callback_inode_arg + * 'event_arg' - glfs_upcall_inode * - * After processing the event, applications need to free 'event_arg'. + * After processing the event, applications need to free 'event_arg' with + * glfs_free(). * * 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. */ -struct glfs_callback_arg { - struct glfs *fs; /* glfs object */ - int reason; /* Upcall event type */ - void *event_arg; /* changes based in the event type */ +struct glfs_upcall; + +struct glfs* +glfs_upcall_get_fs (struct glfs_upcall *arg) __THROW + GFAPI_PUBLIC(glfs_upcall_get_fs, 3.7.16); + +enum glfs_upcall_reason { + GLFS_UPCALL_EVENT_NULL = 0, + GLFS_UPCALL_INODE_INVALIDATE, /* invalidate cache entry */ }; +enum glfs_upcall_reason +glfs_upcall_get_reason (struct glfs_upcall *arg) __THROW + GFAPI_PUBLIC(glfs_upcall_get_reason, 3.7.16); + + /* - * After processing upcall event, they need to free "object" , "p_object", - * "oldp_object" using glfs_h_close(..). + * After processing upcall event, glfs_free() should be called on the + * glfs_upcall. */ -struct glfs_callback_inode_arg { - struct glfs_object *object; /* Object which need to be acted upon */ - int flags; /* Cache UPDATE/INVALIDATE flags */ - struct stat buf; /* Latest stat of this entry */ - unsigned int expire_time_attr; /* the amount of time for which - * the application need to cache - * this entry - */ - struct glfs_object *p_object; /* parent Object to be updated */ - struct stat p_buf; /* Latest stat of parent dir handle */ - struct glfs_object *oldp_object; /* Old parent Object - * to be updated */ - struct stat oldp_buf; /* Latest stat of old parent - * dir handle */ -}; +void* +glfs_upcall_get_event (struct glfs_upcall *arg) __THROW + GFAPI_PUBLIC(glfs_upcall_get_event, 3.7.16); + + +/* Functions for getting details about the glfs_upcall_inode + * + * None of the pointers returned by the below functions should be free()'d, + * glfs_free()'d or glfs_h_close()'d by the application. + * + * Releasing of the structures is done by passing the glfs_upcall pointer + * to glfs_free(). + */ +struct glfs_upcall_inode; + +struct glfs_object* +glfs_upcall_inode_get_object (struct glfs_upcall_inode *arg) __THROW + GFAPI_PUBLIC(glfs_upcall_inode_get_object, 3.7.16); + +uint64_t +glfs_upcall_inode_get_flags (struct glfs_upcall_inode *arg) __THROW + GFAPI_PUBLIC(glfs_upcall_inode_get_flags, 3.7.16); + +struct stat* +glfs_upcall_inode_get_stat (struct glfs_upcall_inode *arg) __THROW + GFAPI_PUBLIC(glfs_upcall_inode_get_stat, 3.7.16); + +uint64_t +glfs_upcall_inode_get_expire (struct glfs_upcall_inode *arg) __THROW + GFAPI_PUBLIC(glfs_upcall_inode_get_expire, 3.7.16); + +struct glfs_object* +glfs_upcall_inode_get_pobject (struct glfs_upcall_inode *arg) __THROW + GFAPI_PUBLIC(glfs_upcall_inode_get_pobject, 3.7.16); + +struct stat* +glfs_upcall_inode_get_pstat (struct glfs_upcall_inode *arg) __THROW + GFAPI_PUBLIC(glfs_upcall_inode_get_pstat, 3.7.16); + +struct glfs_object* +glfs_upcall_inode_get_oldpobject (struct glfs_upcall_inode *arg) __THROW + GFAPI_PUBLIC(glfs_upcall_inode_get_oldpobject, 3.7.16); + +struct stat* +glfs_upcall_inode_get_oldpstat (struct glfs_upcall_inode *arg) __THROW + GFAPI_PUBLIC(glfs_upcall_inode_get_oldpstat, 3.7.16); -/* reason list in glfs_callback_arg */ -enum gfapi_callback_type { - GFAPI_CBK_EVENT_NULL, - GFAPI_INODE_INVALIDATE, /* invalidate cache entry */ -}; /* Handle based operations */ /* Operations that generate handles */ @@ -273,7 +311,7 @@ glfs_h_access (struct glfs *fs, struct glfs_object *object, int mask) __THROW 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 'glfs_callback_arg' along with the handle('glfs_object') to be + into 'glfs_upcall' along with the handle('glfs_object') to be passed to NFS-Ganesha. In case of success, applications need to check the value of @@ -283,11 +321,8 @@ glfs_h_access (struct glfs *fs, struct glfs_object *object, int mask) __THROW PARAMETERS @fs: glfs object to poll the upcall events for - @cbk: Structure to store upcall events as desired by the application. - Application is responsible for allocating and passing the - references of all the pointers of this structure except for - "handle". In case of any events received, it needs to free - "handle" + @cbk: Pointer that will contain an upcall event for use by the application. + Application is responsible for free'ing the structure with glfs_free(). RETURN VALUES @@ -297,8 +332,8 @@ glfs_h_access (struct glfs *fs, struct glfs_object *object, int mask) __THROW */ int -glfs_h_poll_upcall (struct glfs *fs, struct glfs_callback_arg *cbk) __THROW - GFAPI_PUBLIC(glfs_h_poll_upcall, 3.7.0); +glfs_h_poll_upcall (struct glfs *fs, struct glfs_upcall **cbk) __THROW + GFAPI_PUBLIC(glfs_h_poll_upcall, 3.7.16); int glfs_h_acl_set (struct glfs *fs, struct glfs_object *object, diff --git a/api/src/glfs-internal.h b/api/src/glfs-internal.h index a10c7289115..fc62bbf027d 100644 --- a/api/src/glfs-internal.h +++ b/api/src/glfs-internal.h @@ -225,6 +225,26 @@ struct glfs_object { uuid_t gfid; }; +struct glfs_upcall { + struct glfs *fs; /* glfs object */ + enum glfs_upcall_reason reason; /* Upcall event type */ + void *event; /* changes based in the event type */ + void (*free_event)(void *); /* free event after the usage */ +}; + +struct glfs_upcall_inode { + struct glfs_object *object; /* Object which need to be acted upon */ + int flags; /* Cache UPDATE/INVALIDATE flags */ + struct stat buf; /* Latest stat of this entry */ + unsigned int expire_time_attr; /* the amount of time for which + * the application need to cache + * this entry */ + struct glfs_object *p_object; /* parent Object to be updated */ + struct stat p_buf; /* Latest stat of parent dir handle */ + struct glfs_object *oldp_object; /* Old parent Object to be updated */ + struct stat oldp_buf; /* Latest stat of old parent dir handle */ +}; + #define DEFAULT_EVENT_POOL_SIZE 16384 #define GF_MEMPOOL_COUNT_OF_DICT_T 4096 #define GF_MEMPOOL_COUNT_OF_DATA_T (GF_MEMPOOL_COUNT_OF_DICT_T * 4) @@ -401,7 +421,7 @@ int glfs_get_upcall_cache_invalidation (struct gf_upcall *to_up_data, struct gf_upcall *from_up_data); int glfs_h_poll_cache_invalidation (struct glfs *fs, - struct glfs_callback_arg *up_arg, + struct glfs_upcall *up_arg, struct gf_upcall *upcall_data); ssize_t @@ -416,4 +436,35 @@ glfs_anonymous_pwritev (struct glfs *fs, struct glfs_object *object, struct glfs_object * glfs_h_resolve_symlink (struct glfs *fs, struct glfs_object *object); + +/* Deprecated structures that were passed to client applications, replaced by + * accessor functions. Do not use these in new applications, and update older + * usage. + * + * See http://review.gluster.org/14701 for more details. + * + * WARNING: These structures will be removed in the future. + */ +struct glfs_callback_arg { + struct glfs *fs; + enum glfs_upcall_reason reason; + void *event_arg; +}; + +struct glfs_callback_inode_arg { + struct glfs_object *object; /* Object which need to be acted upon */ + int flags; /* Cache UPDATE/INVALIDATE flags */ + struct stat buf; /* Latest stat of this entry */ + unsigned int expire_time_attr; /* the amount of time for which + * the application need to cache + * this entry + */ + struct glfs_object *p_object; /* parent Object to be updated */ + struct stat p_buf; /* Latest stat of parent dir handle */ + struct glfs_object *oldp_object; /* Old parent Object + * to be updated */ + struct stat oldp_buf; /* Latest stat of old parent + * dir handle */ +}; + #endif /* !_GLFS_INTERNAL_H */ diff --git a/api/src/glfs-mem-types.h b/api/src/glfs-mem-types.h index cad1ca95d4f..d32d63f0f13 100644 --- a/api/src/glfs-mem-types.h +++ b/api/src/glfs-mem-types.h @@ -27,6 +27,7 @@ enum glfs_mem_types_ { glfs_mt_readdirbuf_t, glfs_mt_upcall_entry_t, glfs_mt_acl_t, + glfs_mt_upcall_inode_t, glfs_mt_end }; #endif diff --git a/api/src/glfs.c b/api/src/glfs.c index e46c875bb79..a9d56071743 100644 --- a/api/src/glfs.c +++ b/api/src/glfs.c @@ -1360,3 +1360,107 @@ pub_glfs_ipc37 (struct glfs *fs, int opcode) } GFAPI_SYMVER_PUBLIC(glfs_ipc37, glfs_ipc, 3.7.0); + + +void +pub_glfs_free (void *ptr) +{ + int mem_type = 0; + + mem_type = gf_get_mem_type (ptr); + + switch (mem_type) { + case glfs_mt_upcall_entry_t: + { + struct glfs_upcall *to_free = ptr; + + if (to_free->event) + to_free->free_event (to_free->event); + + GF_FREE (ptr); + break; + } + default: + GF_FREE (ptr); + } +} + +GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_free, 3.7.16); + + +struct glfs* +pub_glfs_upcall_get_fs (struct glfs_upcall *arg) +{ + return arg->fs; +} +GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_upcall_get_fs, 3.7.16); + +enum glfs_upcall_reason +pub_glfs_upcall_get_reason (struct glfs_upcall *arg) +{ + return arg->reason; +} +GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_upcall_get_reason, 3.7.16); + +void* +pub_glfs_upcall_get_event (struct glfs_upcall *arg) +{ + return arg->event; +} +GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_upcall_get_event, 3.7.16); + +struct glfs_object* +pub_glfs_upcall_inode_get_object (struct glfs_upcall_inode *arg) +{ + return arg->object; +} +GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_upcall_inode_get_object, 3.7.16); + +uint64_t +pub_glfs_upcall_inode_get_flags (struct glfs_upcall_inode *arg) +{ + return arg->flags; +} +GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_upcall_inode_get_flags, 3.7.16); + +struct stat* +pub_glfs_upcall_inode_get_stat (struct glfs_upcall_inode *arg) +{ + return &arg->buf; +} +GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_upcall_inode_get_stat, 3.7.16); + +uint64_t +pub_glfs_upcall_inode_get_expire (struct glfs_upcall_inode *arg) +{ + return arg->expire_time_attr; +} +GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_upcall_inode_get_expire, 3.7.16); + +struct glfs_object* +pub_glfs_upcall_inode_get_pobject (struct glfs_upcall_inode *arg) +{ + return arg->p_object; +} +GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_upcall_inode_get_pobject, 3.7.16); + +struct stat* +pub_glfs_upcall_inode_get_pstat (struct glfs_upcall_inode *arg) +{ + return &arg->p_buf; +} +GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_upcall_get_pstat, 3.7.16); + +struct glfs_object* +pub_glfs_upcall_inode_get_oldpobject (struct glfs_upcall_inode *arg) +{ + return arg->oldp_object; +} +GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_upcall_get_oldpobject, 3.7.16); + +struct stat* +pub_glfs_upcall_inode_get_oldpstat (struct glfs_upcall_inode *arg) +{ + return &arg->oldp_buf; +} +GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_upcall_get_oldpstat, 3.7.16); diff --git a/tests/basic/gfapi/bug1283983.c b/tests/basic/gfapi/bug1283983.c index 6583097697b..3334b290d9e 100644 --- a/tests/basic/gfapi/bug1283983.c +++ b/tests/basic/gfapi/bug1283983.c @@ -31,20 +31,18 @@ int gfapi = 1; int main (int argc, char *argv[]) { - glfs_t *fs = NULL; - int ret = 0, i; - glfs_fd_t *fd = NULL; - char *filename = "/a1"; - char *filename2 = "/a2"; - struct stat sb = {0, }; - struct glfs_callback_arg cbk; - char *logfile = NULL; - char *volname = NULL; - int cnt = 1; - struct glfs_callback_inode_arg *in_arg = NULL; - struct glfs_object *root = NULL, *leaf = NULL; - - cbk.reason = 0; + glfs_t *fs = NULL; + int ret = 0, i; + glfs_fd_t *fd = NULL; + char *filename = "/a1"; + char *filename2 = "/a2"; + struct stat sb = {0, }; + struct glfs_upcall *cbk = NULL; + char *logfile = NULL; + char *volname = NULL; + int cnt = 1; + struct glfs_upcall_inode *in_arg = NULL; + struct glfs_object *root = NULL, *leaf = NULL; fprintf (stderr, "Starting libgfapi_fini\n"); if (argc != 4) { @@ -105,11 +103,13 @@ main (int argc, char *argv[]) LOG_ERR ("glfs_h_poll_upcall", ret); /* There should not be any upcalls sent */ - if (cbk.reason != GFAPI_CBK_EVENT_NULL) { + if (glfs_upcall_get_reason(cbk) != GLFS_UPCALL_EVENT_NULL) { fprintf (stderr, "Error: Upcall received(%d)\n", - cbk.reason); + glfs_upcall_get_reason(cbk)); exit (1); } + + glfs_free (cbk); } ret = glfs_fini(fs); diff --git a/tests/basic/gfapi/bug1291259.c b/tests/basic/gfapi/bug1291259.c index 9fbe02ba34d..78b95c6dcfd 100644 --- a/tests/basic/gfapi/bug1291259.c +++ b/tests/basic/gfapi/bug1291259.c @@ -33,23 +33,22 @@ int gfapi = 1; int main (int argc, char *argv[]) { - glfs_t *fs = NULL; - glfs_t *fs2 = NULL; - int ret = 0, i; - glfs_fd_t *fd = NULL; - char *filename = "/a1"; - char *filename2 = "/a2"; - struct stat sb = {0, }; - struct glfs_callback_arg cbk; - char *logfile = NULL; - char *volname = NULL; - char *hostname = NULL; - int cnt = 1; - int upcall_received = 0; - struct glfs_callback_inode_arg *in_arg = NULL; - struct glfs_object *root = NULL, *leaf = NULL; - unsigned char globjhdl[GFAPI_HANDLE_LENGTH]; - unsigned char globjhdl2[GFAPI_HANDLE_LENGTH]; + glfs_t *fs = NULL; + glfs_t *fs2 = NULL; + int ret = 0, i; + glfs_fd_t *fd = NULL; + char *filename = "/a1"; + char *filename2 = "/a2"; + struct stat sb = {0, }; + char *logfile = NULL; + char *volname = NULL; + char *hostname = NULL; + int cnt = 1; + int upcall_received = 0; + struct glfs_upcall *cbk = NULL; + struct glfs_object *root = NULL, *leaf = NULL; + unsigned char globjhdl[GFAPI_HANDLE_LENGTH]; + unsigned char globjhdl2[GFAPI_HANDLE_LENGTH]; fprintf (stderr, "Starting libgfapi_fini\n"); if (argc != 4) { @@ -82,7 +81,6 @@ main (int argc, char *argv[]) * on the fs (through this instance) happens. */ ret = glfs_h_poll_upcall(fs, &cbk); LOG_ERR ("glfs_h_poll_upcall", ret); - cbk.reason = 0; fs2 = glfs_new (volname); if (!fs) { @@ -123,21 +121,30 @@ main (int argc, char *argv[]) } fprintf (stderr, "glfs_h_create leaf - %p\n", leaf); - while (cnt++ < 5) { + while (cnt++ < 5 && !upcall_received) { + enum glfs_upcall_reason reason = 0; + struct glfs_upcall_inode *in_arg = NULL; + ret = glfs_h_poll_upcall(fs, &cbk); LOG_ERR ("glfs_h_poll_upcall", ret); + if (ret) + goto retry; + + reason = glfs_upcall_get_reason (cbk); + fprintf (stderr, "Upcall received(%d)\n", reason); + + if (reason == GLFS_UPCALL_INODE_INVALIDATE) { + struct glfs_object *object = NULL; - if (cbk.reason == GFAPI_INODE_INVALIDATE) { - fprintf (stderr, "Upcall received(%d)\n", - cbk.reason); - in_arg = (struct glfs_callback_inode_arg *)(cbk.event_arg); + in_arg = glfs_upcall_get_event (cbk); + object = glfs_upcall_inode_get_object (in_arg); ret = glfs_h_extract_handle (root, globjhdl+GLAPI_UUID_LENGTH, GFAPI_HANDLE_LENGTH); LOG_ERR("glfs_h_extract_handle", (ret != 16)); - ret = glfs_h_extract_handle (in_arg->object, + ret = glfs_h_extract_handle (object, globjhdl2+GLAPI_UUID_LENGTH, GFAPI_HANDLE_LENGTH); LOG_ERR("glfs_h_extract_handle", (ret != 16)); @@ -149,6 +156,13 @@ main (int argc, char *argv[]) } upcall_received = 1; } + +retry: + if (!upcall_received) + sleep (1); /* glfs_h_poll_upcall() does not block */ + + glfs_free (cbk); + cbk = NULL; } if (!upcall_received) { diff --git a/tests/basic/gfapi/libgfapi-fini-hang.t b/tests/basic/gfapi/libgfapi-fini-hang.t index 7c939872574..ba262a943ee 100755 --- a/tests/basic/gfapi/libgfapi-fini-hang.t +++ b/tests/basic/gfapi/libgfapi-fini-hang.t @@ -21,9 +21,9 @@ EXPECT 'Created' volinfo_field $V0 'Status'; TEST $CLI volume start $V0; EXPECT 'Started' volinfo_field $V0 'Status'; -logdir=`gluster --print-logdir` +logdir=$(gluster --print-logdir) -TEST build_tester -lgfapi $(dirname $0)/libgfapi-fini-hang.c -o $M0/libgfapi-fini-hang +TEST build_tester $(dirname $0)/libgfapi-fini-hang.c -o $M0/libgfapi-fini-hang -lgfapi TEST cd $M0 ./libgfapi-fini-hang $H0 $V0 $logdir/libgfapi-fini-hang.log & PID=$! diff --git a/tests/basic/gfapi/upcall-cache-invalidate.c b/tests/basic/gfapi/upcall-cache-invalidate.c index 44e186955e7..9add3381278 100644 --- a/tests/basic/gfapi/upcall-cache-invalidate.c +++ b/tests/basic/gfapi/upcall-cache-invalidate.c @@ -8,7 +8,6 @@ #include <errno.h> #include <glusterfs/api/glfs.h> #include <glusterfs/api/glfs-handles.h> -int gfapi = 1; #define LOG_ERR(func, ret) do { \ if (ret != 0) { \ @@ -23,25 +22,24 @@ int gfapi = 1; int main (int argc, char *argv[]) { - glfs_t *fs = NULL; - glfs_t *fs2 = NULL; - glfs_t *fs_tmp = NULL; - glfs_t *fs_tmp2 = NULL; - int ret = 0, i; - glfs_fd_t *fd = NULL; - glfs_fd_t *fd2 = NULL; - glfs_fd_t *fd_tmp = NULL; - glfs_fd_t *fd_tmp2 = NULL; - char readbuf[32]; - char *filename = "file_tmp"; - char *writebuf = NULL; - char *vol_id = NULL; - unsigned int cnt = 1; - struct glfs_callback_arg cbk; - char *logfile = NULL; - char *volname = NULL; - char *hostname = NULL; - struct glfs_callback_inode_arg *in_arg = NULL; + glfs_t *fs = NULL; + glfs_t *fs2 = NULL; + glfs_t *fs_tmp = NULL; + glfs_t *fs_tmp2 = NULL; + int ret = 0, i; + glfs_fd_t *fd = NULL; + glfs_fd_t *fd2 = NULL; + glfs_fd_t *fd_tmp = NULL; + glfs_fd_t *fd_tmp2 = NULL; + char readbuf[32]; + char *filename = "file_tmp"; + char *writebuf = NULL; + char *vol_id = NULL; + unsigned int cnt = 1; + struct glfs_upcall *cbk = NULL; + char *logfile = NULL; + char *volname = NULL; + char *hostname = NULL; if (argc != 4) { fprintf (stderr, "Invalid argument\n"); @@ -72,7 +70,6 @@ main (int argc, char *argv[]) * on the fs (through this instance) happens. */ ret = glfs_h_poll_upcall(fs_tmp, &cbk); LOG_ERR ("glfs_h_poll_upcall", ret); - cbk.reason = 0; fs2 = glfs_new (volname); if (!fs2) { @@ -139,6 +136,7 @@ main (int argc, char *argv[]) ret = glfs_lseek (fd_tmp2, 0, SEEK_SET); LOG_ERR ("glfs_lseek", ret); + memset (readbuf, 0, sizeof(readbuf)); ret = glfs_pread (fd_tmp2, readbuf, 4, 0, 0); if (ret <= 0) { @@ -152,26 +150,37 @@ main (int argc, char *argv[]) * there are I/Os on that fd */ if (cnt > 2) { + struct glfs_upcall_inode *in_arg = NULL; + enum glfs_upcall_reason reason = 0; + struct glfs_object *object = NULL; + uint64_t flags = 0; + uint64_t expire = 0; + ret = glfs_h_poll_upcall(fs_tmp, &cbk); LOG_ERR ("glfs_h_poll_upcall", ret); - /* Expect 'GFAPI_INODE_INVALIDATE' upcall event. */ - if (cbk.reason == GFAPI_INODE_INVALIDATE) { - in_arg = cbk.event_arg; + + reason = glfs_upcall_get_reason (cbk); + + /* Expect 'GLFS_INODE_INVALIDATE' upcall event. */ + if (reason == GLFS_UPCALL_INODE_INVALIDATE) { + in_arg = glfs_upcall_get_event (cbk); + + object = glfs_upcall_inode_get_object (in_arg); + flags = glfs_upcall_inode_get_flags (in_arg); + expire = glfs_upcall_inode_get_expire (in_arg); + fprintf (stderr, " upcall event type - %d," " object(%p), flags(%d), " " expire_time_attr(%d)\n" , - cbk.reason, in_arg->object, - in_arg->flags, - in_arg->expire_time_attr); - ret = glfs_h_close (in_arg->object); - LOG_ERR ("glfs_h_close", ret); - free (in_arg); + reason, object, flags, expire); } else { fprintf (stderr, - "Dint receive upcall notify event"); + "Didnt receive upcall notify event"); ret = -1; goto err; } + + glfs_free (cbk); } sleep(5); diff --git a/tests/basic/gfapi/upcall-cache-invalidate.t b/tests/basic/gfapi/upcall-cache-invalidate.t index 6acbab2c51a..5fd6a3332e7 100755 --- a/tests/basic/gfapi/upcall-cache-invalidate.t +++ b/tests/basic/gfapi/upcall-cache-invalidate.t @@ -5,13 +5,6 @@ cleanup; -# Upcall feature is disable for now. A new xlator option -# will be introduced to turn it on. Skipping this test -# till then. - -SKIP_TESTS; -exit 0 - TEST glusterd TEST $CLI volume create $V0 $H0:$B0/brick1; |