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 | 3 | ||||
| -rw-r--r-- | libglusterfs/src/glusterfs.h | 18 | ||||
| -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, 318 insertions, 199 deletions
diff --git a/api/src/glfs-fops.c b/api/src/glfs-fops.c index 0e32ec2ee78..944868effc6 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 b02aefc7477..4a544f7c905 100644 --- a/api/src/glfs-handleops.c +++ b/api/src/glfs-handleops.c @@ -1672,6 +1672,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. @@ -1679,11 +1749,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 @@ -1692,8 +1768,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; @@ -1702,7 +1776,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; @@ -1719,8 +1792,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           */ @@ -1742,7 +1813,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;                  } @@ -1751,11 +1821,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, @@ -1765,32 +1844,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 9f81cb9dcbf..28e9e79b9a3 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 cdec56a2b51..f9accdf42f1 100644 --- a/libglusterfs/src/Makefile.am +++ b/libglusterfs/src/Makefile.am @@ -47,7 +47,8 @@ noinst_HEADERS = common-utils.h defaults.h dict.h glusterfs.h hashfn.h timespec.  	$(CONTRIBDIR)/mount/mntent_compat.h lvm-defaults.h \  	$(CONTRIBDIR)/libexecinfo/execinfo_compat.h \  	unittest/unittest.h quota-common-utils.h rot-buffs.h \ -	$(CONTRIBDIR)/timer-wheel/timer-wheel.h compat-uuid.h +	$(CONTRIBDIR)/timer-wheel/timer-wheel.h compat-uuid.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 78398310a39..d8d92ad7546 100644 --- a/libglusterfs/src/glusterfs.h +++ b/libglusterfs/src/glusterfs.h @@ -369,12 +369,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 @@ -613,18 +607,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 af5134034eb..19c9f9e5f24 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 {                  if (t_expired > (2*timeout)) {                          /* Cleanup the entry */ @@ -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__ */  | 
