diff options
-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 | ||||
-rw-r--r-- | libglusterfs/src/Makefile.am | 2 | ||||
-rw-r--r-- | libglusterfs/src/glusterfs.h | 17 | ||||
-rw-r--r-- | libglusterfs/src/upcall-utils.h | 38 | ||||
-rw-r--r-- | rpc/xdr/src/glusterfs3.h | 8 | ||||
-rw-r--r-- | tests/basic/gfapi/upcall-cache-invalidate.c | 17 | ||||
-rw-r--r-- | xlators/features/upcall/src/upcall-cache-invalidation.h | 3 | ||||
-rw-r--r-- | xlators/features/upcall/src/upcall-internal.c | 71 | ||||
-rw-r--r-- | xlators/features/upcall/src/upcall-messages.h | 1 | ||||
-rw-r--r-- | xlators/features/upcall/src/upcall.c | 153 | ||||
-rw-r--r-- | xlators/features/upcall/src/upcall.h | 32 |
14 files changed, 317 insertions, 198 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 */ diff --git a/libglusterfs/src/Makefile.am b/libglusterfs/src/Makefile.am index c7b85bdf839..e5f9f52f323 100644 --- a/libglusterfs/src/Makefile.am +++ b/libglusterfs/src/Makefile.am @@ -48,7 +48,7 @@ noinst_HEADERS = common-utils.h defaults.h dict.h glusterfs.h hashfn.h timespec. $(CONTRIBDIR)/libexecinfo/execinfo_compat.h \ unittest/unittest.h quota-common-utils.h rot-buffs.h \ $(CONTRIBDIR)/timer-wheel/timer-wheel.h compat-uuid.h \ - tw.h + tw.h upcall-utils.h if !HAVE_LIBUUID # FIXME: unbundle libuuid, see compat-uuid.h. diff --git a/libglusterfs/src/glusterfs.h b/libglusterfs/src/glusterfs.h index 50c86d91467..ba59e4d54db 100644 --- a/libglusterfs/src/glusterfs.h +++ b/libglusterfs/src/glusterfs.h @@ -370,11 +370,6 @@ typedef enum { GF_XATTROP_AND_ARRAY } gf_xattrop_flags_t; -typedef enum { - GF_UPCALL_EVENT_NULL, - GF_UPCALL_CACHE_INVALIDATION, -} gf_upcall_event_t; - #define GF_SET_IF_NOT_PRESENT 0x1 /* default behaviour */ #define GF_SET_OVERWRITE 0x2 /* Overwrite with the buf given */ #define GF_SET_DIR_ONLY 0x4 @@ -621,18 +616,6 @@ struct gf_flock { gf_lkowner_t l_owner; }; -struct gf_upcall { - char *client_uid; - uuid_t gfid; - u_int event_type; - void *data; -}; - -struct gf_upcall_cache_invalidation { - u_int flags; - u_int expire_time_attr; -}; - #define GF_MUST_CHECK __attribute__((warn_unused_result)) /* * Some macros (e.g. ALLOC_OR_GOTO) set variables in function scope, but the diff --git a/libglusterfs/src/upcall-utils.h b/libglusterfs/src/upcall-utils.h new file mode 100644 index 00000000000..001566fd85e --- /dev/null +++ b/libglusterfs/src/upcall-utils.h @@ -0,0 +1,38 @@ +/* + Copyright (c) 2015, Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. +*/ + +#ifndef _UPCALL_UTILS_H +#define _UPCALL_UTILS_H + +#include "iatt.h" +#include "compat-uuid.h" +#include "compat.h" + +typedef enum { + GF_UPCALL_EVENT_NULL, + GF_UPCALL_CACHE_INVALIDATION, +} gf_upcall_event_t; + +struct gf_upcall { + char *client_uid; + uuid_t gfid; + uint32_t event_type; + void *data; +}; + +struct gf_upcall_cache_invalidation { + uint32_t flags; + uint32_t expire_time_attr; + struct iatt stat; + struct iatt p_stat; /* parent dir stat */ + struct iatt oldp_stat; /* oldparent dir stat */ +}; + +#endif /* _UPCALL_UTILS_H */ diff --git a/rpc/xdr/src/glusterfs3.h b/rpc/xdr/src/glusterfs3.h index 6808064cb95..e50bd9e6c59 100644 --- a/rpc/xdr/src/glusterfs3.h +++ b/rpc/xdr/src/glusterfs3.h @@ -16,6 +16,8 @@ #include "xdr-generic.h" #include "glusterfs3-xdr.h" #include "iatt.h" +#include "protocol-common.h" +#include "upcall-utils.h" #define xdr_decoded_remaining_addr(xdr) ((&xdr)->x_private) #define xdr_decoded_remaining_len(xdr) ((&xdr)->x_handy) @@ -289,6 +291,9 @@ gf_proto_cache_invalidation_from_upcall (gfs3_cbk_cache_invalidation_req *gf_c_r gf_c_req->event_type = gf_up_data->event_type; gf_c_req->flags = gf_c_data->flags; gf_c_req->expire_time_attr = gf_c_data->expire_time_attr; + gf_stat_from_iatt (&gf_c_req->stat, &gf_c_data->stat); + gf_stat_from_iatt (&gf_c_req->parent_stat, &gf_c_data->p_stat); + gf_stat_from_iatt (&gf_c_req->oldparent_stat, &gf_c_data->oldp_stat); out: return; @@ -319,6 +324,9 @@ gf_proto_cache_invalidation_to_upcall (gfs3_cbk_cache_invalidation_req *gf_c_req gf_c_data->flags = gf_c_req->flags; gf_c_data->expire_time_attr = gf_c_req->expire_time_attr; + gf_stat_to_iatt (&gf_c_req->stat, &gf_c_data->stat); + gf_stat_to_iatt (&gf_c_req->parent_stat, &gf_c_data->p_stat); + gf_stat_to_iatt (&gf_c_req->oldparent_stat, &gf_c_data->oldp_stat); out: return; diff --git a/tests/basic/gfapi/upcall-cache-invalidate.c b/tests/basic/gfapi/upcall-cache-invalidate.c index 64811f3274a..cc2e6a0fe33 100644 --- a/tests/basic/gfapi/upcall-cache-invalidate.c +++ b/tests/basic/gfapi/upcall-cache-invalidate.c @@ -41,8 +41,9 @@ main (int argc, char *argv[]) struct callback_arg cbk; char *logfile = NULL; char *volname = NULL; + struct callback_inode_arg *in_arg = NULL; - cbk.object = NULL; + cbk.reason = 0; if (argc != 3) { fprintf (stderr, "Invalid argument\n"); @@ -147,10 +148,18 @@ main (int argc, char *argv[]) if (cnt > 2) { ret = glfs_h_poll_upcall(fs_tmp, &cbk); LOG_ERR ("glfs_h_poll_upcall", ret); - if (cbk.object) { + /* Expect 'GFAPI_INODE_INVALIDATE' upcall event. */ + if (cbk.reason == GFAPI_INODE_INVALIDATE) { + in_arg = cbk.event_arg; fprintf (stderr, " upcall event type - %d," - " flags - %d, expire_time_attr - %d\n" , - cbk.reason, cbk.flags, cbk.expire_time_attr); + " 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); } else { fprintf (stderr, "Dint receive upcall notify event"); diff --git a/xlators/features/upcall/src/upcall-cache-invalidation.h b/xlators/features/upcall/src/upcall-cache-invalidation.h index c39962b68c4..edb8285827f 100644 --- a/xlators/features/upcall/src/upcall-cache-invalidation.h +++ b/xlators/features/upcall/src/upcall-cache-invalidation.h @@ -33,6 +33,7 @@ delete the cache entry */ #define UP_FORGET 0x00000100 /* inode_forget on server side - invalidate the cache entry */ +#define UP_PARENT_TIMES 0x00000200 /* update parent dir times */ /* for fops - open, read, lk, */ #define UP_UPDATE_CLIENT (UP_ATIME) @@ -48,7 +49,7 @@ /* to invalidate parent directory entries for fops -rename, unlink, * rmdir, mkdir, create */ -#define UP_PARENT_DENTRY_FLAGS (UP_TIMES) +#define UP_PARENT_DENTRY_FLAGS (UP_PARENT_TIMES) /* for fop - unlink, link, rmdir, mkdir */ #define UP_NLINK_FLAGS (UP_NLINK | UP_TIMES) diff --git a/xlators/features/upcall/src/upcall-internal.c b/xlators/features/upcall/src/upcall-internal.c index 19d19289624..b128ab3bdc9 100644 --- a/xlators/features/upcall/src/upcall-internal.c +++ b/xlators/features/upcall/src/upcall-internal.c @@ -294,7 +294,7 @@ upcall_cleanup_expired_clients (xlator_t *this, goto out; } gf_log (THIS->name, GF_LOG_TRACE, - "Cleaned up client_entry(%s) of", + "Cleaned up client_entry(%s)", up_client->client_uid); } } @@ -450,24 +450,6 @@ upcall_reaper_thread_init (xlator_t *this) return ret; } -void -upcall_cache_invalidate_dir (call_frame_t *frame, xlator_t *this, - client_t *client, inode_t *inode, uint32_t flags) -{ - dentry_t *dentry; - dentry_t *dentry_tmp; - - if (!is_cache_invalidation_enabled(this)) - return; - - list_for_each_entry_safe (dentry, dentry_tmp, - &inode->dentry_list, - inode_list) { - upcall_cache_invalidate (frame, this, client, - dentry->inode, flags); - } -} - /* * Given a gfid, client, first fetch upcall_entry_t based on gfid. * Later traverse through the client list of that upcall entry. If this client @@ -480,7 +462,8 @@ upcall_cache_invalidate_dir (call_frame_t *frame, xlator_t *this, */ void upcall_cache_invalidate (call_frame_t *frame, xlator_t *this, client_t *client, - inode_t *inode, uint32_t flags) + inode_t *inode, uint32_t flags, struct iatt *stbuf, + struct iatt *p_stbuf, struct iatt *oldp_stbuf) { upcall_client_t *up_client = NULL; upcall_client_t *up_client_entry = NULL; @@ -536,7 +519,8 @@ upcall_cache_invalidate (call_frame_t *frame, xlator_t *this, client_t *client, upcall_client_cache_invalidate(this, inode->gfid, up_client_entry, - flags); + flags, stbuf, + p_stbuf, oldp_stbuf); } if (!found) { @@ -556,28 +540,50 @@ upcall_cache_invalidate (call_frame_t *frame, xlator_t *this, client_t *client, void upcall_client_cache_invalidate (xlator_t *this, uuid_t gfid, upcall_client_t *up_client_entry, - uint32_t flags) + uint32_t flags, struct iatt *stbuf, + struct iatt *p_stbuf, + struct iatt *oldp_stbuf) { - notify_event_data_t n_event_data; - time_t timeout = 0; + struct gf_upcall up_req = {0,}; + struct gf_upcall_cache_invalidation ca_req = {0,}; + time_t timeout = 0; + int ret = -1; time_t t_expired = time(NULL) - up_client_entry->access_time; timeout = get_cache_invalidation_timeout(this); if (t_expired < timeout) { /* Send notify call */ - gf_uuid_copy(n_event_data.gfid, gfid); - n_event_data.client_entry = up_client_entry; - n_event_data.event_type = GF_UPCALL_CACHE_INVALIDATION; - n_event_data.invalidate_flags = flags; - - /* Need to send inode flags */ - this->notify (this, GF_EVENT_UPCALL, &n_event_data); + up_req.client_uid = up_client_entry->client_uid; + gf_uuid_copy (up_req.gfid, gfid); + + ca_req.flags = flags; + ca_req.expire_time_attr = + up_client_entry->expire_time_attr; + if (stbuf) + ca_req.stat = *stbuf; + if (p_stbuf) + ca_req.p_stat = *p_stbuf; + if (oldp_stbuf) + ca_req.oldp_stat = *oldp_stbuf; + + up_req.data = &ca_req; + up_req.event_type = GF_UPCALL_CACHE_INVALIDATION; gf_log (THIS->name, GF_LOG_TRACE, "Cache invalidation notification sent to %s", up_client_entry->client_uid); + /* Need to send inode flags */ + ret = this->notify (this, GF_EVENT_UPCALL, &up_req); + + /* + * notify may fail as the client could have been + * dis(re)connected. Cleanup the client entry. + */ + if (ret < 0) + __upcall_cleanup_client_entry (up_client_entry); + } else { gf_log (THIS->name, GF_LOG_TRACE, "Cache invalidation notification NOT sent to %s", @@ -621,7 +627,8 @@ upcall_cache_forget (xlator_t *this, inode_t *inode, upcall_inode_ctx_t *up_inod upcall_client_cache_invalidate(this, inode->gfid, up_client_entry, - flags); + flags, NULL, + NULL, NULL); } } diff --git a/xlators/features/upcall/src/upcall-messages.h b/xlators/features/upcall/src/upcall-messages.h index 7b004d678c3..5472b4a5cbd 100644 --- a/xlators/features/upcall/src/upcall-messages.h +++ b/xlators/features/upcall/src/upcall-messages.h @@ -57,6 +57,7 @@ */ #define UPCALL_MSG_NO_MEMORY (GLFS_COMP_BASE_UPCALL + 1) #define UPCALL_MSG_INTERNAL_ERROR (GLFS_COMP_BASE_UPCALL + 2) +#define UPCALL_MSG_NOTIFY_FAILED (GLFS_COMP_BASE_UPCALL + 3) #define glfs_msg_end_x GLFS_MSGID_END, "Invalid: End of messages" diff --git a/xlators/features/upcall/src/upcall.c b/xlators/features/upcall/src/upcall.c index c68c0258fb8..5f6c29e1b79 100644 --- a/xlators/features/upcall/src/upcall.c +++ b/xlators/features/upcall/src/upcall.c @@ -51,7 +51,8 @@ up_open_cbk (call_frame_t *frame, void *cookie, xlator_t *this, goto out; } flags = UP_UPDATE_CLIENT; - upcall_cache_invalidate (frame, this, client, local->inode, flags); + upcall_cache_invalidate (frame, this, client, local->inode, flags, + NULL, NULL, NULL); out: UPCALL_STACK_UNWIND (open, frame, op_ret, op_errno, fd, xdata); @@ -105,7 +106,8 @@ up_writev_cbk (call_frame_t *frame, void *cookie, xlator_t *this, goto out; } flags = UP_WRITE_FLAGS; - upcall_cache_invalidate (frame, this, client, local->inode, flags); + upcall_cache_invalidate (frame, this, client, local->inode, flags, + postbuf, NULL, NULL); out: UPCALL_STACK_UNWIND (writev, frame, op_ret, op_errno, @@ -166,7 +168,8 @@ up_readv_cbk (call_frame_t *frame, void *cookie, xlator_t *this, goto out; } flags = UP_UPDATE_CLIENT; - upcall_cache_invalidate (frame, this, client, local->inode, flags); + upcall_cache_invalidate (frame, this, client, local->inode, flags, + NULL, NULL, NULL); out: UPCALL_STACK_UNWIND (readv, frame, op_ret, op_errno, vector, @@ -224,7 +227,8 @@ up_lk_cbk (call_frame_t *frame, void *cookie, xlator_t *this, goto out; } flags = UP_UPDATE_CLIENT; - upcall_cache_invalidate (frame, this, client, local->inode, flags); + upcall_cache_invalidate (frame, this, client, local->inode, flags, + NULL, NULL, NULL); out: UPCALL_STACK_UNWIND (lk, frame, op_ret, op_errno, lock, xdata); @@ -278,7 +282,8 @@ up_truncate_cbk (call_frame_t *frame, void *cookie, xlator_t *this, goto out; } flags = UP_WRITE_FLAGS; - upcall_cache_invalidate (frame, this, client, local->inode, flags); + upcall_cache_invalidate (frame, this, client, local->inode, flags, + postbuf, NULL, NULL); out: UPCALL_STACK_UNWIND (truncate, frame, op_ret, op_errno, @@ -339,7 +344,8 @@ up_setattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this, * Bug1200271. */ flags = UP_ATTR_FLAGS; - upcall_cache_invalidate (frame, this, client, local->inode, flags); + upcall_cache_invalidate (frame, this, client, local->inode, flags, + statpost, NULL, NULL); out: UPCALL_STACK_UNWIND (setattr, frame, op_ret, op_errno, @@ -397,17 +403,9 @@ up_rename_cbk (call_frame_t *frame, void *cookie, xlator_t *this, if ((op_ret < 0) || !local) { goto out; } - flags = UP_RENAME_FLAGS; - upcall_cache_invalidate (frame, this, client, local->inode, flags); - - /* Need to invalidate old and new parent entries as well */ - flags = UP_PARENT_DENTRY_FLAGS; - upcall_cache_invalidate_dir (frame, this, client, local->inode, flags); - - /* notify oldparent as well */ - flags = UP_PARENT_DENTRY_FLAGS; - upcall_cache_invalidate_dir (frame, this, client, - local->rename_oldloc.inode, flags); + flags = (UP_RENAME_FLAGS | UP_PARENT_DENTRY_FLAGS); + upcall_cache_invalidate (frame, this, client, local->inode, flags, + stbuf, postnewparent, postoldparent); out: UPCALL_STACK_UNWIND (rename, frame, op_ret, op_errno, @@ -466,12 +464,9 @@ up_unlink_cbk (call_frame_t *frame, void *cookie, xlator_t *this, if ((op_ret < 0) || !local) { goto out; } - flags = UP_NLINK_FLAGS; - upcall_cache_invalidate (frame, this, client, local->inode, flags); - - flags = UP_PARENT_DENTRY_FLAGS; - /* invalidate parent's entry too */ - upcall_cache_invalidate_dir (frame, this, client, local->inode, flags); + flags = (UP_NLINK_FLAGS | UP_PARENT_DENTRY_FLAGS); + upcall_cache_invalidate (frame, this, client, local->inode, flags, + NULL, postparent, NULL); out: UPCALL_STACK_UNWIND (unlink, frame, op_ret, op_errno, @@ -526,10 +521,10 @@ up_link_cbk (call_frame_t *frame, void *cookie, xlator_t *this, if ((op_ret < 0) || !local) { goto out; } - flags = UP_NLINK_FLAGS; - upcall_cache_invalidate (frame, this, client, local->inode, flags); + flags = (UP_NLINK_FLAGS | UP_PARENT_DENTRY_FLAGS); + upcall_cache_invalidate (frame, this, client, local->inode, flags, + stbuf, postparent, NULL); - /* do we need to update parent as well?? */ out: UPCALL_STACK_UNWIND (link, frame, op_ret, op_errno, inode, stbuf, preparent, postparent, xdata); @@ -584,12 +579,10 @@ up_rmdir_cbk (call_frame_t *frame, void *cookie, xlator_t *this, if ((op_ret < 0) || !local) { goto out; } - flags = UP_NLINK_FLAGS; - upcall_cache_invalidate (frame, this, client, local->inode, flags); - /* invalidate parent's entry too */ - flags = UP_PARENT_DENTRY_FLAGS; - upcall_cache_invalidate_dir (frame, this, client, local->inode, flags); + flags = (UP_NLINK_FLAGS | UP_PARENT_DENTRY_FLAGS); + upcall_cache_invalidate (frame, this, client, local->inode, flags, + NULL, postparent, NULL); out: UPCALL_STACK_UNWIND (rmdir, frame, op_ret, op_errno, @@ -648,7 +641,8 @@ up_mkdir_cbk (call_frame_t *frame, void *cookie, xlator_t *this, /* invalidate parent's entry too */ flags = UP_PARENT_DENTRY_FLAGS; - upcall_cache_invalidate_dir (frame, this, client, local->inode, flags); + upcall_cache_invalidate (frame, this, client, local->inode, flags, + stbuf, postparent, NULL); out: UPCALL_STACK_UNWIND (mkdir, frame, op_ret, op_errno, @@ -709,7 +703,8 @@ up_create_cbk (call_frame_t *frame, void *cookie, xlator_t *this, /* As its a new file create, no need of sending notification */ /* However invalidate parent's entry */ flags = UP_PARENT_DENTRY_FLAGS; - upcall_cache_invalidate_dir (frame, this, client, local->inode, flags); + upcall_cache_invalidate (frame, this, client, local->inode, flags, + stbuf, postparent, NULL); out: UPCALL_STACK_UNWIND (create, frame, op_ret, op_errno, fd, @@ -769,7 +764,8 @@ up_lookup_cbk (call_frame_t *frame, void *cookie, xlator_t *this, goto out; } flags = UP_UPDATE_CLIENT; - upcall_cache_invalidate (frame, this, client, local->inode, flags); + upcall_cache_invalidate (frame, this, client, local->inode, flags, + NULL, NULL, NULL); out: UPCALL_STACK_UNWIND (lookup, frame, op_ret, op_errno, inode, stbuf, @@ -826,7 +822,8 @@ up_stat_cbk (call_frame_t *frame, void *cookie, goto out; } flags = UP_UPDATE_CLIENT; - upcall_cache_invalidate (frame, this, client, local->inode, flags); + upcall_cache_invalidate (frame, this, client, local->inode, flags, + NULL, NULL, NULL); out: UPCALL_STACK_UNWIND (stat, frame, op_ret, op_errno, buf, @@ -939,7 +936,8 @@ up_access_cbk (call_frame_t *frame, void *cookie, xlator_t *this, goto out; } flags = UP_UPDATE_CLIENT; - upcall_cache_invalidate (frame, this, client, local->inode, flags); + upcall_cache_invalidate (frame, this, client, local->inode, flags, + NULL, NULL, NULL); out: UPCALL_STACK_UNWIND (access, frame, op_ret, op_errno, xdata); @@ -994,7 +992,8 @@ up_readlink_cbk (call_frame_t *frame, void *cookie, xlator_t *this, goto out; } flags = UP_UPDATE_CLIENT; - upcall_cache_invalidate (frame, this, client, local->inode, flags); + upcall_cache_invalidate (frame, this, client, local->inode, flags, + NULL, NULL, NULL); out: UPCALL_STACK_UNWIND (readlink, frame, op_ret, op_errno, path, stbuf, @@ -1054,7 +1053,8 @@ up_mknod_cbk (call_frame_t *frame, void *cookie, xlator_t *this, /* invalidate parent's entry too */ flags = UP_PARENT_DENTRY_FLAGS; - upcall_cache_invalidate_dir (frame, this, client, local->inode, flags); + upcall_cache_invalidate (frame, this, client, local->inode, flags, + buf, postparent, NULL); out: UPCALL_STACK_UNWIND (mknod, frame, op_ret, op_errno, inode, buf, @@ -1114,7 +1114,8 @@ up_symlink_cbk (call_frame_t *frame, void *cookie, xlator_t *this, /* invalidate parent's entry too */ flags = UP_PARENT_DENTRY_FLAGS; - upcall_cache_invalidate_dir (frame, this, client, local->inode, flags); + upcall_cache_invalidate (frame, this, client, local->inode, flags, + buf, postparent, NULL); out: UPCALL_STACK_UNWIND (symlink, frame, op_ret, op_errno, inode, buf, @@ -1172,7 +1173,8 @@ up_opendir_cbk (call_frame_t *frame, void *cookie, xlator_t *this, goto out; } flags = UP_UPDATE_CLIENT; - upcall_cache_invalidate (frame, this, client, local->inode, flags); + upcall_cache_invalidate (frame, this, client, local->inode, flags, + NULL, NULL, NULL); out: UPCALL_STACK_UNWIND (opendir, frame, op_ret, op_errno, fd, xdata); @@ -1227,7 +1229,8 @@ up_statfs_cbk (call_frame_t *frame, void *cookie, xlator_t *this, goto out; } flags = UP_UPDATE_CLIENT; - upcall_cache_invalidate (frame, this, client, local->inode, flags); + upcall_cache_invalidate (frame, this, client, local->inode, flags, + NULL, NULL, NULL); out: UPCALL_STACK_UNWIND (statfs, frame, op_ret, op_errno, buf, xdata); @@ -1282,7 +1285,8 @@ up_readdir_cbk (call_frame_t *frame, void *cookie, xlator_t *this, goto out; } flags = UP_UPDATE_CLIENT; - upcall_cache_invalidate (frame, this, client, local->inode, flags); + upcall_cache_invalidate (frame, this, client, local->inode, flags, + NULL, NULL, NULL); out: UPCALL_STACK_UNWIND (readdir, frame, op_ret, op_errno, entries, xdata); @@ -1396,7 +1400,8 @@ up_fallocate_cbk(call_frame_t *frame, void *cookie, xlator_t *this, goto out; } flags = UP_WRITE_FLAGS; - upcall_cache_invalidate (frame, this, client, local->inode, flags); + upcall_cache_invalidate (frame, this, client, local->inode, flags, + post, NULL, NULL); out: UPCALL_STACK_UNWIND (fallocate, frame, op_ret, op_errno, pre, @@ -1453,7 +1458,8 @@ up_discard_cbk(call_frame_t *frame, void *cookie, xlator_t *this, goto out; } flags = UP_WRITE_FLAGS; - upcall_cache_invalidate (frame, this, client, local->inode, flags); + upcall_cache_invalidate (frame, this, client, local->inode, flags, + post, NULL, NULL); out: UPCALL_STACK_UNWIND (discard, frame, op_ret, op_errno, pre, @@ -1510,7 +1516,8 @@ up_zerofill_cbk(call_frame_t *frame, void *cookie, xlator_t *this, goto out; } flags = UP_WRITE_FLAGS; - upcall_cache_invalidate (frame, this, client, local->inode, flags); + upcall_cache_invalidate (frame, this, client, local->inode, flags, + post, NULL, NULL); out: UPCALL_STACK_UNWIND (zerofill, frame, op_ret, op_errno, pre, @@ -1725,10 +1732,7 @@ notify (xlator_t *this, int32_t event, void *data, ...) { int ret = -1; int32_t val = 0; - notify_event_data_t *notify_event = NULL; - struct gf_upcall up_req = {0,}; - upcall_client_t *up_client_entry = NULL; - struct gf_upcall_cache_invalidation ca_req = {0,}; + struct gf_upcall *up_req = NULL; switch (event) { case GF_EVENT_UPCALL: @@ -1736,41 +1740,20 @@ notify (xlator_t *this, int32_t event, void *data, ...) gf_log (this->name, GF_LOG_DEBUG, "Upcall Notify event = %d", event); - notify_event = (notify_event_data_t *) data; - up_client_entry = notify_event->client_entry; + up_req = (struct gf_upcall *) data; - if (!up_client_entry) { - goto out; - } + GF_VALIDATE_OR_GOTO(this->name, up_req, out); + + ret = default_notify (this, event, up_req); - up_req.client_uid = up_client_entry->client_uid; - - gf_uuid_copy (up_req.gfid, notify_event->gfid); - gf_log (this->name, GF_LOG_DEBUG, - "Sending notify to the client- %s, gfid - %s", - up_client_entry->client_uid, up_req.gfid); - - switch (notify_event->event_type) { - case GF_UPCALL_CACHE_INVALIDATION: - ca_req.flags = notify_event->invalidate_flags; - ca_req.expire_time_attr = - up_client_entry->expire_time_attr; - up_req.data = &ca_req; - break; - default: + if (ret) { + gf_msg (this->name, GF_LOG_WARNING, 0, + UPCALL_MSG_NOTIFY_FAILED, + "Failed to notify cache invalidation" + " to client(%s)", + up_req->client_uid); goto out; } - - up_req.event_type = notify_event->event_type; - - ret = default_notify (this, event, &up_req); - - /* - * notify may fail as the client could have been - * dis(re)connected. Cleanup the client entry. - */ - if (ret < 0) - __upcall_cleanup_client_entry (up_client_entry); } break; default: @@ -1784,7 +1767,15 @@ out: } struct xlator_fops fops = { - /* fops which do not trigger upcall + /* fops which change only "ATIME" do not result + * in any cache invalidation. Hence upcall + * notifications are not sent in this case. + * But however, we need to store/update the + * client info in the upcall state to be able + * to notify them incase of any changes done + * to the data. + * + * Below such fops do not trigger upcall * notifications but will add/update * clients info in the upcall inode ctx.*/ .lookup = up_lookup, diff --git a/xlators/features/upcall/src/upcall.h b/xlators/features/upcall/src/upcall.h index 41895786382..295ddc26167 100644 --- a/xlators/features/upcall/src/upcall.h +++ b/xlators/features/upcall/src/upcall.h @@ -16,15 +16,11 @@ #endif #include "compat-errno.h" -#include "stack.h" -#include "call-stub.h" #include "upcall-mem-types.h" #include "client_t.h" -#include "rpcsvc.h" -#include "lkowner.h" -#include "locking.h" #include "upcall-messages.h" #include "upcall-cache-invalidation.h" +#include "upcall-utils.h" #define EXIT_IF_UPCALL_OFF(this, label) do { \ if (!is_upcall_enabled(this)) \ @@ -84,18 +80,6 @@ struct _upcall_inode_ctx_t { }; typedef struct _upcall_inode_ctx_t upcall_inode_ctx_t; -struct _notify_event_data { - uuid_t gfid; - upcall_client_t *client_entry; - gf_upcall_event_t event_type; - uint32_t invalidate_flags; - /* any extra data needed, like inode flags - * to be invalidated incase of cache invalidation, - * may be fd for lease recalls */ - void *extra; -}; -typedef struct _notify_event_data notify_event_data_t; - struct upcall_local { /* XXX: need to check if we can store * pointers in 'local' which may get freed @@ -137,13 +121,15 @@ int upcall_reaper_thread_init (xlator_t *this); gf_boolean_t is_upcall_enabled(xlator_t *this); /* Cache invalidation specific */ -void upcall_cache_invalidate (call_frame_t *frame, xlator_t *this, client_t *client, - inode_t *inode, uint32_t flags); +void upcall_cache_invalidate (call_frame_t *frame, xlator_t *this, + client_t *client, inode_t *inode, + uint32_t flags, struct iatt *stbuf, + struct iatt *p_stbuf, + struct iatt *oldp_stbuf); void upcall_client_cache_invalidate (xlator_t *xl, uuid_t gfid, upcall_client_t *up_client_entry, - uint32_t flags); -void upcall_cache_invalidate_dir (call_frame_t *frame, xlator_t *this, - client_t *client, inode_t *inode, - uint32_t flags); + uint32_t flags, struct iatt *stbuf, + struct iatt *p_stbuf, + struct iatt *oldp_stbuf); #endif /* __UPCALL_H__ */ |