diff options
author | Soumya Koduri <skoduri@redhat.com> | 2015-04-30 13:28:44 +0530 |
---|---|---|
committer | Kaleb KEITHLEY <kkeithle@redhat.com> | 2015-05-05 06:57:43 -0700 |
commit | 170cc4ea08aa48e69c2df6be5841076c9a119d5a (patch) | |
tree | a1afb1e9efc19225a4f37a1cb08deb6b4aaffebf /api/src | |
parent | 08107796c89f5f201b24d689ab6757237c743c0d (diff) |
Upcall: Send stat as part of cache_invalidation notifications
Have added support to send attributes of both entries and
its parent (include oldparent in case of RENAME fop) in the
same notification request to avoid multiple rpc requests.
Also, made changes in gfapi to send parent object and its
attributes changed in a single upcall event.
Change-Id: I92833da3bcec38d65216921c2ce4d10367c32ef1
BUG: 1200262
Signed-off-by: Soumya Koduri <skoduri@redhat.com>
Reviewed-on: http://review.gluster.org/10460
Tested-by: Gluster Build System <jenkins@build.gluster.com>
Reviewed-by: Kaleb KEITHLEY <kkeithle@redhat.com>
Diffstat (limited to 'api/src')
-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 ae7bb087af5..4aad28005f2 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 c3ac789569d..13b47a1b74d 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 02204a76385..b5813b23448 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 20fbb5c3201..972f2e4cf49 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 */ |