diff options
Diffstat (limited to 'api')
-rw-r--r-- | api/src/glfs-fops.c | 5 | ||||
-rw-r--r-- | api/src/glfs-handleops.c | 132 | ||||
-rw-r--r-- | api/src/glfs-handles.h | 30 | ||||
-rw-r--r-- | api/src/glfs-internal.h | 6 |
4 files changed, 134 insertions, 39 deletions
diff --git a/api/src/glfs-fops.c b/api/src/glfs-fops.c index ae7bb087af..4aad28005f 100644 --- a/api/src/glfs-fops.c +++ b/api/src/glfs-fops.c @@ -61,8 +61,11 @@ glfs_get_upcall_cache_invalidation (struct gf_upcall *to_up_data, to_up_data->data = ca_data; - ca_data->flags = f_ca_data->flags; + ca_data->flags = f_ca_data->flags; ca_data->expire_time_attr = f_ca_data->expire_time_attr; + ca_data->stat = f_ca_data->stat; + ca_data->p_stat = f_ca_data->p_stat; + ca_data->oldp_stat = f_ca_data->oldp_stat; ret = 0; out: diff --git a/api/src/glfs-handleops.c b/api/src/glfs-handleops.c index c3ac789569..13b47a1b74 100644 --- a/api/src/glfs-handleops.c +++ b/api/src/glfs-handleops.c @@ -1621,6 +1621,76 @@ out: GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_h_rename, 3.4.2); +int +glfs_h_poll_cache_invalidation (struct glfs *fs, + struct callback_arg *up_arg, + struct gf_upcall *upcall_data) +{ + int ret = -1; + struct glfs_object *p_object = NULL; + struct glfs_object *oldp_object = NULL; + struct glfs_object *object = NULL; + struct gf_upcall_cache_invalidation *ca_data = NULL; + struct callback_inode_arg *up_inode_arg = NULL; + + ca_data = upcall_data->data; + 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); + + up_inode_arg = calloc (1, sizeof (struct callback_inode_arg)); + 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; + + /* XXX: Update stat as well incase of UP_*_TIMES. + * This will be addressed as part of INODE_UPDATE */ + if (ca_data->flags & GFAPI_INODE_UPDATE_FLAGS) { + glfs_iatt_to_stat (fs, &ca_data->stat, &up_inode_arg->buf); + } + + 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); + + glfs_iatt_to_stat (fs, &ca_data->p_stat, &up_inode_arg->p_buf); + } + up_inode_arg->p_object = p_object; + + /* 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); + + glfs_iatt_to_stat (fs, &ca_data->oldp_stat, + &up_inode_arg->oldp_buf); + } + up_inode_arg->oldp_object = oldp_object; + + ret = 0; + +out: + return ret; +} + /* * This API is used to poll for upcall events stored in the * upcall list. Current users of this API is NFS-Ganesha. @@ -1628,11 +1698,17 @@ GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_h_rename, 3.4.2); * into 'callback_arg' along with the handle object to be passed * to NFS-Ganesha. * - * On success, applications need to check for 'object' to decide + * On success, applications need to check for 'reason' to decide * if any upcall event is received. * - * After processing the event, they need to free "object" - * using glfs_h_close(..). + * Current supported upcall_events - + * GFAPI_INODE_INVALIDATE - + * 'arg - callback_inode_arg + * + * After processing the event, applications need to free 'event_arg'. + * + * Incase of INODE_INVALIDATE, applications need to free "object", + * "p_object" and "oldp_object" using glfs_h_close(..). * * Also similar to I/Os, the application should ideally stop polling * before calling glfs_fini(..). Hence making an assumption that @@ -1641,8 +1717,6 @@ GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_h_rename, 3.4.2); int pub_glfs_h_poll_upcall (struct glfs *fs, struct callback_arg *up_arg) { - struct glfs_object *object = NULL; - uuid_t gfid; upcall_entry *u_list = NULL; upcall_entry *tmp = NULL; xlator_t *subvol = NULL; @@ -1651,7 +1725,6 @@ pub_glfs_h_poll_upcall (struct glfs *fs, struct callback_arg *up_arg) glusterfs_ctx_t *ctx = NULL; int ret = -1; struct gf_upcall *upcall_data = NULL; - struct gf_upcall_cache_invalidation *ca_data = NULL; if (!fs || !up_arg) { errno = EINVAL; @@ -1668,8 +1741,6 @@ pub_glfs_h_poll_upcall (struct glfs *fs, struct callback_arg *up_arg) goto err; } - up_arg->object = NULL; - /* Ideally applications should stop polling before calling * 'glfs_fini'. Yet cross check if cleanup has started */ @@ -1691,7 +1762,6 @@ pub_glfs_h_poll_upcall (struct glfs *fs, struct callback_arg *up_arg) list_for_each_entry_safe (u_list, tmp, &fs->upcall_list, upcall_list) { - gf_uuid_copy (gfid, u_list->upcall_data.gfid); found = 1; break; } @@ -1700,11 +1770,20 @@ pub_glfs_h_poll_upcall (struct glfs *fs, struct callback_arg *up_arg) pthread_mutex_unlock (&fs->upcall_list_mutex); if (found) { - object = glfs_h_create_from_handle (fs, gfid, - GFAPI_HANDLE_LENGTH, - NULL); + upcall_data = &u_list->upcall_data; - if (!object) { + switch (upcall_data->event_type) { + case GF_UPCALL_CACHE_INVALIDATION: + /* 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, + upcall_data); + if (!ret) { + break; + } /* It could so happen that the file which got * upcall notification may have got deleted * by other thread. Irrespective of the error, @@ -1714,32 +1793,15 @@ pub_glfs_h_poll_upcall (struct glfs *fs, struct callback_arg *up_arg) * as up_arg->object will be NULL */ gf_log (subvol->name, GF_LOG_WARNING, "handle creation of %s failed: %s", - uuid_utoa (gfid), strerror (errno)); + uuid_utoa (upcall_data->gfid), + strerror (errno)); reason = GFAPI_CBK_EVENT_NULL; - } else { - - upcall_data = &u_list->upcall_data; - - switch (upcall_data->event_type) { - case GF_UPCALL_CACHE_INVALIDATION: - /* XXX: Need to revisit this to support - * GFAPI_INODE_UPDATE if required. - */ - ca_data = upcall_data->data; - GF_VALIDATE_OR_GOTO ("glfs_h_poll_upcall", - ca_data, out); - reason = GFAPI_INODE_INVALIDATE; - up_arg->flags = ca_data->flags; - up_arg->expire_time_attr = ca_data->expire_time_attr; - - break; - default: - break; - } + break; + default: + break; } - up_arg->object = object; up_arg->reason = reason; list_del_init (&u_list->upcall_list); diff --git a/api/src/glfs-handles.h b/api/src/glfs-handles.h index 02204a7638..b5813b2344 100644 --- a/api/src/glfs-handles.h +++ b/api/src/glfs-handles.h @@ -71,6 +71,9 @@ permission checking */ #define GFAPI_UP_RENAME 0x00000080 /* this is a rename op - delete the cache entry */ +#define GFAPI_UP_FORGET 0x00000100 /* inode_forget on server side - + invalidate the cache entry */ +#define GFAPI_UP_PARENT_TIMES 0x00000200 /* update parent dir times */ #define GFAPI_INODE_UPDATE_FLAGS (GFAPI_UP_NLINK | GFAPI_UP_MODE | \ GFAPI_UP_OWN | GFAPI_UP_SIZE | \ @@ -102,15 +105,30 @@ typedef struct glfs_object glfs_object_t; * Applications (currently NFS-Ganesha) can make use of this * structure to read upcall notifications sent by server. * - * On success, applications need to check for 'object' to decide + * On success, applications need to check for 'reason' to decide * if any upcall event is received. * - * After processing the event, they need to free "object" - * using glfs_h_close(..). + * Currently supported upcall_events - + * GFAPI_INODE_INVALIDATE - + * 'event_arg' - callback_inode_arg + * + * After processing the event, applications need to free 'event_arg'. + * + * 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 callback_arg { struct glfs *fs; /* glfs object */ int reason; /* Upcall event type */ + void *event_arg; /* changes based in the event type */ +}; + +/* + * After processing upcall event, they need to free "object" , "p_object", + * "oldp_object" using glfs_h_close(..). + */ +struct 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 */ @@ -118,6 +136,12 @@ struct callback_arg { * 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 */ }; /* reason list in callback_arg */ diff --git a/api/src/glfs-internal.h b/api/src/glfs-internal.h index 20fbb5c320..972f2e4cf4 100644 --- a/api/src/glfs-internal.h +++ b/api/src/glfs-internal.h @@ -14,6 +14,8 @@ #include "xlator.h" #include "glusterfs.h" +#include "upcall-utils.h" +#include "glfs-handles.h" #define GLFS_SYMLINK_MAX_FOLLOW 2048 @@ -335,5 +337,9 @@ void glfs_free_from_ctx (struct glfs *fs) 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 callback_arg *up_arg, + struct gf_upcall *upcall_data); #endif /* !_GLFS_INTERNAL_H */ |