diff options
| -rw-r--r-- | api/src/glfs-internal.h | 22 | ||||
| -rw-r--r-- | libglusterfs/src/dict.c | 20 | ||||
| -rw-r--r-- | libglusterfs/src/dict.h | 2 | ||||
| -rw-r--r-- | libglusterfs/src/syncop.h | 23 | ||||
| -rw-r--r-- | xlators/features/upcall/src/upcall-internal.c | 12 | ||||
| -rw-r--r-- | xlators/features/upcall/src/upcall.c | 117 | ||||
| -rw-r--r-- | xlators/features/upcall/src/upcall.h | 6 | ||||
| -rw-r--r-- | xlators/performance/md-cache/src/md-cache-mem-types.h | 1 | ||||
| -rw-r--r-- | xlators/performance/md-cache/src/md-cache-messages.h | 27 | ||||
| -rw-r--r-- | xlators/performance/md-cache/src/md-cache.c | 148 | 
10 files changed, 340 insertions, 38 deletions
diff --git a/api/src/glfs-internal.h b/api/src/glfs-internal.h index 471fa5fffc1..a10c7289115 100644 --- a/api/src/glfs-internal.h +++ b/api/src/glfs-internal.h @@ -103,28 +103,6 @@  #define GFAPI_SYMVER_PRIVATE(fn1, fn2, dotver) /**/  #endif -/* - * syncop_xxx() calls are executed in two ways, one is inside a synctask where - * the executing function will do 'swapcontext' and the other is without - * synctask where the executing thread is made to wait using pthread_cond_wait. - * Executing thread may change when syncop_xxx() is executed inside a synctask. - * This leads to errno_location change i.e. errno may give errno of - * non-executing thread. So errno is not touched inside a synctask execution. - * All gfapi calls are executed using the second way of executing syncop_xxx() - * where the executing thread waits using pthread_cond_wait so it is ok to set - * errno in these cases. The following macro makes syncop_xxx() behave just - * like a system call, where -1 is returned and errno is set when a failure - * occurs. - */ -#define DECODE_SYNCOP_ERR(ret) do {  \ -        if (ret < 0) {          \ -                errno = -ret;   \ -                ret = -1;       \ -        } else {                \ -                errno = 0;      \ -        }                       \ -        } while (0) -  #define ESTALE_RETRY(ret,errno,reval,loc,label) do {	\  	if (ret == -1 && errno == ESTALE) {	        \  		if (reval < DEFAULT_REVAL_COUNT) {	\ diff --git a/libglusterfs/src/dict.c b/libglusterfs/src/dict.c index 6f7adb51589..96cb9e94bda 100644 --- a/libglusterfs/src/dict.c +++ b/libglusterfs/src/dict.c @@ -473,6 +473,26 @@ dict_get (dict_t *this, char *key)          return NULL;  } +int +dict_key_count (dict_t *this) +{ +        int ret = -1; + +        if (!this) { +                gf_msg_callingfn ("dict", GF_LOG_WARNING, EINVAL, +                                  LG_MSG_INVALID_ARG, "dict passed is NULL"); +                return ret; +        } + +        LOCK (&this->lock); +        { +                ret = this->count; +        } +        UNLOCK (&this->lock); + +        return ret; +} +  void  dict_del (dict_t *this, char *key)  { diff --git a/libglusterfs/src/dict.h b/libglusterfs/src/dict.h index 04f0ed9b164..a7fb6c78425 100644 --- a/libglusterfs/src/dict.h +++ b/libglusterfs/src/dict.h @@ -107,6 +107,8 @@ data_t *dict_get (dict_t *this, char *key);  void dict_del (dict_t *this, char *key);  int dict_reset (dict_t *dict); +int dict_key_count (dict_t *this); +  int32_t dict_serialized_length (dict_t *dict);  int32_t dict_serialize (dict_t *dict, char *buf);  int32_t dict_unserialize (char *buf, int32_t size, dict_t **fill); diff --git a/libglusterfs/src/syncop.h b/libglusterfs/src/syncop.h index c2387e62cd2..0d0da58f4cf 100644 --- a/libglusterfs/src/syncop.h +++ b/libglusterfs/src/syncop.h @@ -258,6 +258,29 @@ struct syncopctx {          } while (0) +/* + * syncop_xxx() calls are executed in two ways, one is inside a synctask where + * the executing function will do 'swapcontext' and the other is without + * synctask where the executing thread is made to wait using pthread_cond_wait. + * Executing thread may change when syncop_xxx() is executed inside a synctask. + * This leads to errno_location change i.e. errno may give errno of + * non-executing thread. So errno is not touched inside a synctask execution. + * All gfapi calls are executed using the second way of executing syncop_xxx() + * where the executing thread waits using pthread_cond_wait so it is ok to set + * errno in these cases. The following macro makes syncop_xxx() behave just + * like a system call, where -1 is returned and errno is set when a failure + * occurs. + */ +#define DECODE_SYNCOP_ERR(ret) do {  \ +        if (ret < 0) {          \ +                errno = -ret;   \ +                ret = -1;       \ +        } else {                \ +                errno = 0;      \ +        }                       \ +        } while (0) + +  #define SYNCENV_DEFAULT_STACKSIZE (2 * 1024 * 1024)  struct syncenv * syncenv_new (size_t stacksize, int procmin, int procmax); diff --git a/xlators/features/upcall/src/upcall-internal.c b/xlators/features/upcall/src/upcall-internal.c index 3cde56a7ce8..0f07ae8df03 100644 --- a/xlators/features/upcall/src/upcall-internal.c +++ b/xlators/features/upcall/src/upcall-internal.c @@ -435,10 +435,16 @@ upcall_reaper_thread_init (xlator_t *this)  }  int -up_filter_virtual_xattr (dict_t *d, char *k, data_t *v, void *tmp) +up_filter_unregd_xattr (dict_t *xattrs, char *xattr, data_t *v, +                        void *regd_xattrs)  { -        if (is_virtual_xattr (k) == _gf_true) { -                dict_del (d, k); +        int ret = 0; + +        if (dict_get ((dict_t *)regd_xattrs, xattr) == NULL) { +                /* xattr was not found in the registered xattr, hence do not +                 * send notification for its change +                 */ +                dict_del (xattrs, xattr);          }          return 0; diff --git a/xlators/features/upcall/src/upcall.c b/xlators/features/upcall/src/upcall.c index c49a3fd8796..c7b74ed3c29 100644 --- a/xlators/features/upcall/src/upcall.c +++ b/xlators/features/upcall/src/upcall.c @@ -1596,9 +1596,13 @@ up_setxattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this,          upcall_local_t   *local         = NULL;          int              ret            = 0;          struct iatt      stbuf          = {0, }; +        upcall_private_t *priv          = NULL;          EXIT_IF_UPCALL_OFF (this, out); +        priv = this->private; +        GF_VALIDATE_OR_GOTO (this->name, priv, out); +          client = frame->root->client;          local = frame->local; @@ -1607,13 +1611,21 @@ up_setxattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this,          }          flags = UP_XATTR; -        /* Remove the virtual xattrs from the dict */ -        ret = dict_foreach (local->xattr, up_filter_virtual_xattr, NULL); +        /* Remove the xattrs from the dict, if they are not registered for +         * cache invalidation */ +        ret = dict_foreach (local->xattr, up_filter_unregd_xattr, priv->xattrs);          if (ret < 0) {                  op_ret = ret;                  goto out;          } +        if (dict_key_count(local->xattr) == 0) { +                gf_msg_trace (this->name, 0, "None of xattrs requested for" +                              " invalidation, were changed. Nothing to " +                              "invalidate"); +                goto out; /* nothing to invalidate */ +        } +          ret = syncop_stat (FIRST_CHILD(frame->this), &local->loc, &stbuf,                             NULL, NULL);          if (ret == 0) @@ -1677,9 +1689,13 @@ up_fsetxattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this,          upcall_local_t   *local         = NULL;          int              ret            = 0;          struct iatt      stbuf          = {0,}; +        upcall_private_t *priv          = NULL;          EXIT_IF_UPCALL_OFF (this, out); +        priv = this->private; +        GF_VALIDATE_OR_GOTO (this->name, priv, out); +          client = frame->root->client;          local = frame->local; @@ -1688,13 +1704,21 @@ up_fsetxattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this,          }          flags = UP_XATTR; -        /* Remove the virtual xattrs from the dict */ -        ret = dict_foreach (local->xattr, up_filter_virtual_xattr, NULL); +         /* Remove the xattrs from the dict, if they are not registered for +         * cache invalidation */ +        ret = dict_foreach (local->xattr, up_filter_unregd_xattr, priv->xattrs);          if (ret < 0) {                  op_ret = ret;                  goto out;          } +        if (dict_key_count(local->xattr) == 0) { +                gf_msg_trace (this->name, 0, "None of xattrs requested for" +                              " invalidation, were changed. Nothing to " +                              "invalidate"); +                goto out; /* nothing to invalidate */ +        } +          ret = syncop_fstat (FIRST_CHILD(frame->this), local->fd, &stbuf, NULL,                              NULL);          if (ret == 0) @@ -1758,9 +1782,13 @@ up_fremovexattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this,          upcall_local_t   *local         = NULL;          struct iatt      stbuf          = {0,};          int              ret            = 0; +        upcall_private_t *priv          = NULL;          EXIT_IF_UPCALL_OFF (this, out); +        priv = this->private; +        GF_VALIDATE_OR_GOTO (this->name, priv, out); +          client = frame->root->client;          local = frame->local; @@ -1769,6 +1797,21 @@ up_fremovexattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this,          }          flags = UP_XATTR_RM; +        /* Remove the xattrs from the dict, if they are not registered for +         * cache invalidation */ +        ret = dict_foreach (local->xattr, up_filter_unregd_xattr, priv->xattrs); +        if (ret < 0) { +                op_ret = ret; +                goto out; +        } + +        if (dict_key_count(local->xattr) == 0) { +                gf_msg_trace (this->name, 0, "None of xattrs requested for" +                              " invalidation, were changed. Nothing to " +                              "invalidate"); +                goto out; /* nothing to invalidate */ +        } +          ret = syncop_fstat (FIRST_CHILD(frame->this), local->fd, &stbuf, NULL,                              NULL);          if (ret == 0) @@ -1828,9 +1871,13 @@ up_removexattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this,          upcall_local_t   *local         = NULL;          struct iatt      stbuf          = {0,};          int              ret            = 0; +        upcall_private_t *priv          = NULL;          EXIT_IF_UPCALL_OFF (this, out); +        priv = this->private; +        GF_VALIDATE_OR_GOTO (this->name, priv, out); +          client = frame->root->client;          local = frame->local; @@ -1839,6 +1886,21 @@ up_removexattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this,          }          flags = UP_XATTR_RM; +         /* Remove the xattrs from the dict, if they are not registered for +         * cache invalidation */ +        ret = dict_foreach (local->xattr, up_filter_unregd_xattr, priv->xattrs); +        if (ret < 0) { +                op_ret = ret; +                goto out; +        } + +        if (dict_key_count(local->xattr) == 0) { +                gf_msg_trace (this->name, 0, "None of xattrs requested for" +                              " invalidation, were changed. Nothing to " +                              "invalidate"); +                goto out; /* nothing to invalidate */ +        } +          ret = syncop_stat (FIRST_CHILD(frame->this), &local->loc, &stbuf, NULL,                             NULL);          if (ret == 0) @@ -2064,6 +2126,47 @@ out:          return local;  } +static int32_t +update_xattrs (dict_t *dict, char *key, data_t *value, void *data) +{ +        dict_t *xattrs = data; +        int     ret    = 0; + +        ret = dict_set_int8 (xattrs, key, 0); +        return ret; +} + +int32_t +up_ipc (call_frame_t *frame, xlator_t *this, int32_t op, dict_t *xdata) +{ +        upcall_private_t *priv  = NULL; +        int               ret   = 0; + +        priv = this->private; +        GF_VALIDATE_OR_GOTO (this->name, priv, out); + +        if (op != GF_IPC_TARGET_UPCALL) +                goto wind; + +        /* TODO: Bz-1371622 Along with the xattrs also store list of clients +         * that are interested in notifications, so that the notification +         * can be sent to the clients that have registered. +         * Once this implemented there can be unregister of xattrs for +         * notifications. Until then there is no unregister of xattrs*/ +        if (xdata && priv->xattrs) { +                ret = dict_foreach (xdata, update_xattrs, priv->xattrs); +        } + +out: +        STACK_UNWIND_STRICT (ipc, frame, ret, 0, NULL); +        return 0; + +wind: +        STACK_WIND (frame, default_ipc_cbk, FIRST_CHILD (this), +                    FIRST_CHILD (this)->fops->ipc, op, xdata); +        return 0; +} +  int  reconfigure (xlator_t *this, dict_t *options)  { @@ -2071,7 +2174,7 @@ reconfigure (xlator_t *this, dict_t *options)          int              ret                    = -1;          priv = this->private; -        GF_ASSERT (priv); +        GF_VALIDATE_OR_GOTO (this->name, priv, out);          GF_OPTION_RECONF ("cache-invalidation", priv->cache_invalidation_enabled,                            options, bool, out); @@ -2120,6 +2223,7 @@ init (xlator_t *this)          LOCK_INIT (&priv->inode_ctx_lk);          INIT_LIST_HEAD (&priv->inode_ctx_list); +        priv->xattrs = dict_new ();          this->private = priv;          priv->fini = 0; @@ -2142,6 +2246,7 @@ init (xlator_t *this)          }  out:          if (ret) { +                dict_unref (priv->xattrs);                  GF_FREE (priv);          } @@ -2164,6 +2269,7 @@ fini (xlator_t *this)          if (priv->reaper_init_done)                  pthread_join (priv->reaper_thr, NULL); +        dict_unref (priv->xattrs);          LOCK_DESTROY (&priv->inode_ctx_lk);          /* Do we need to cleanup the inode_ctxs? IMO not required @@ -2226,6 +2332,7 @@ out:  }  struct xlator_fops fops = { +        .ipc         = up_ipc,          /* fops which change only "ATIME" do not result           * in any cache invalidation. Hence upcall           * notifications are not sent in this case. diff --git a/xlators/features/upcall/src/upcall.h b/xlators/features/upcall/src/upcall.h index f86849341ec..852f5511726 100644 --- a/xlators/features/upcall/src/upcall.h +++ b/xlators/features/upcall/src/upcall.h @@ -52,6 +52,8 @@ struct _upcall_private_t {          gf_boolean_t     reaper_init_done;          pthread_t        reaper_thr;          int32_t          fini; +        dict_t          *xattrs; /* list of xattrs registered by clients +                                    for receiving invalidation */  };  typedef struct _upcall_private_t upcall_private_t; @@ -130,6 +132,6 @@ void upcall_client_cache_invalidate (xlator_t *xl, uuid_t gfid,                                       struct iatt *p_stbuf,                                       struct iatt *oldp_stbuf, dict_t *xattr); -int up_filter_virtual_xattr (dict_t *d, char *k, data_t *v, void *tmp); - +int up_filter_unregd_xattr (dict_t *xattrs, char *xattr, data_t *v, +                            void *regd_xattrs);  #endif /* __UPCALL_H__ */ diff --git a/xlators/performance/md-cache/src/md-cache-mem-types.h b/xlators/performance/md-cache/src/md-cache-mem-types.h index 6634cf962a5..5cfc68e13c1 100644 --- a/xlators/performance/md-cache/src/md-cache-mem-types.h +++ b/xlators/performance/md-cache/src/md-cache-mem-types.h @@ -18,6 +18,7 @@ enum gf_mdc_mem_types_ {          gf_mdc_mt_mdc_local_t   = gf_common_mt_end + 1,  	gf_mdc_mt_md_cache_t,  	gf_mdc_mt_mdc_conf_t, +        gf_mdc_mt_mdc_ipc,          gf_mdc_mt_end  };  #endif diff --git a/xlators/performance/md-cache/src/md-cache-messages.h b/xlators/performance/md-cache/src/md-cache-messages.h index 1fe26ccc8b2..4aea7cd0a9d 100644 --- a/xlators/performance/md-cache/src/md-cache-messages.h +++ b/xlators/performance/md-cache/src/md-cache-messages.h @@ -40,7 +40,7 @@   */  #define GLFS_MD_CACHE_BASE                   GLFS_MSGID_COMP_MD_CACHE -#define GLFS_MD_CACHE_NUM_MESSAGES           3 +#define GLFS_MD_CACHE_NUM_MESSAGES           5  #define GLFS_MSGID_END  (GLFS_MD_CACHE_BASE + GLFS_MD_CACHE_NUM_MESSAGES + 1)  /* Messages with message IDs */ @@ -67,8 +67,33 @@  #define MD_CACHE_MSG_DISCARD_UPDATE    (GLFS_MD_CACHE_BASE + 2) +/*! + * @messageid + * @diagnosis + * @recommendedaction  None + * + */ +  #define MD_CACHE_MSG_CACHE_UPDATE      (GLFS_MD_CACHE_BASE + 3) +/*! + * @messageid + * @diagnosis + * @recommendedaction  None + * + */ + +#define MD_CACHE_MSG_IPC_UPCALL_FAILED  (GLFS_MD_CACHE_BASE + 4) + +/*! + * @messageid + * @diagnosis + * @recommendedaction  None + * + */ + +#define MD_CACHE_MSG_NO_XATTR_CACHE     (GLFS_MD_CACHE_BASE + 5) +  /*------------*/  #define glfs_msg_end_x GLFS_MSGID_END, "Invalid: End of messages" diff --git a/xlators/performance/md-cache/src/md-cache.c b/xlators/performance/md-cache/src/md-cache.c index bb2310e8c82..e0e7ee68e3b 100644 --- a/xlators/performance/md-cache/src/md-cache.c +++ b/xlators/performance/md-cache/src/md-cache.c @@ -13,6 +13,7 @@  #include "logging.h"  #include "dict.h"  #include "xlator.h" +#include "syncop.h"  #include "md-cache-mem-types.h"  #include "compat-errno.h"  #include "glusterfs-acl.h" @@ -2455,6 +2456,18 @@ is_strpfx (const char *str1, const char *str2)  } +static int +mdc_key_unload_all (struct mdc_key *keys) +{ +        struct mdc_key *key = NULL; + +        for (key = keys; key->name; key++) { +                key->load = 0; +        } + +        return 0; +} +  int  mdc_key_load_set (struct mdc_key *keys, char *pattern, gf_boolean_t val)  { @@ -2545,12 +2558,129 @@ out:          return ret;  } +struct mdc_ipc { +       xlator_t *this; +       dict_t   *xattr; +}; + +static int +mdc_send_xattrs_cbk (int ret, call_frame_t *frame, void *data) +{ +        struct mdc_ipc *tmp = data; + +        if (ret < 0) { +                mdc_key_unload_all (mdc_keys); +                gf_msg ("md-cache", GF_LOG_INFO, 0, MD_CACHE_MSG_NO_XATTR_CACHE, +                        "Disabled cache for all xattrs, as registering for " +                        "xattr cache invalidation failed"); +        } +        STACK_DESTROY (frame->root); +        dict_unref (tmp->xattr); +        GF_FREE (tmp); + +        return 0; +} + +static int +mdc_send_xattrs (void *data) +{ +        int             ret = 0; +        struct mdc_ipc *tmp = data; + +        ret = syncop_ipc (FIRST_CHILD (tmp->this), GF_IPC_TARGET_UPCALL, +                          tmp->xattr, NULL); +        DECODE_SYNCOP_ERR (ret); +        if (ret < 0) { +                gf_msg (tmp->this->name, GF_LOG_WARNING, errno, +                        MD_CACHE_MSG_IPC_UPCALL_FAILED, "Registering the list " +                        "of xattrs that needs invalidaton, with upcall, failed"); +        } + +        return ret; +} + + +static int +mdc_register_xattr_inval (xlator_t *this) +{ +        dict_t          *xattr = NULL; +        int              ret   = 0; +        struct mdc_conf *conf  = NULL; +        call_frame_t    *frame = NULL; +        struct mdc_ipc  *data  = NULL; + +        conf = this->private; + +        LOCK (&conf->lock); +        { +                if (!conf->mdc_invalidation) { +                        UNLOCK (&conf->lock); +                        goto out; +                } +        } +        UNLOCK (&conf->lock); + +        xattr = dict_new (); +        if (!xattr) { +                gf_msg (this->name, GF_LOG_WARNING, ENOMEM, +                        MD_CACHE_MSG_NO_MEMORY, "dict_new failed"); +                ret = -1; +                goto out; +        } + +        mdc_load_reqs (this, xattr); + +        frame = create_frame (this, this->ctx->pool); +        if (!frame) { +                gf_msg (this->name, GF_LOG_ERROR, ENOMEM, +                        MD_CACHE_MSG_NO_MEMORY, +                        "failed to create the frame"); +                ret = -1; +                goto out; +        } + +        data = GF_CALLOC (1, sizeof (struct mdc_ipc), gf_mdc_mt_mdc_ipc); +        if (!data) { +                gf_msg (this->name, GF_LOG_ERROR, ENOMEM, +                        MD_CACHE_MSG_NO_MEMORY, +                        "failed to allocate memory"); +                ret = -1; +                goto out; +        } + +        data->this = this; +        data->xattr = xattr; +        ret = synctask_new (this->ctx->env, mdc_send_xattrs, mdc_send_xattrs_cbk, +                            frame, data); +        if (ret < 0) { +                gf_msg (this->name, GF_LOG_WARNING, errno, +                        MD_CACHE_MSG_IPC_UPCALL_FAILED, "Registering the list " +                        "of xattrs that needs invalidaton, with upcall, failed"); +        } + +out: +        if (ret < 0) { +                mdc_key_unload_all (mdc_keys); +                if (xattr) +                        dict_unref (xattr); +                if (frame) +                        STACK_DESTROY (frame->root); +                GF_FREE (data); +                gf_msg (this->name, GF_LOG_INFO, 0, MD_CACHE_MSG_NO_XATTR_CACHE, +                        "Disabled cache for all xattrs, as registering for " +                        "xattr cache invalidation failed"); +        } + +        return ret; +} +  int  reconfigure (xlator_t *this, dict_t *options)  {  	struct mdc_conf *conf = NULL;          int    timeout = 0; +        int    ret     = 0;  	conf = this->private; @@ -2589,6 +2719,8 @@ reconfigure (xlator_t *this, dict_t *options)                          goto out;          }          conf->timeout = timeout; + +        ret = mdc_register_xattr_inval (this);  out:  	return 0;  } @@ -2686,22 +2818,28 @@ notify (xlator_t *this, int event, void *data, ...)          switch (event) {          case GF_EVENT_CHILD_DOWN:          case GF_EVENT_SOME_CHILD_DOWN: -        case GF_EVENT_CHILD_MODIFIED:                  time (&now);                  mdc_update_child_down_time (this, &now); -                ret = default_notify (this, event, data);                  break;          case GF_EVENT_UPCALL:                  if (conf->mdc_invalidation)                          ret = mdc_invalidate (this, data); -                if (default_notify (this, event, data) != 0) -                        ret = -1; +                break; +        case GF_EVENT_CHILD_MODIFIED: +                time (&now); +                mdc_update_child_down_time (this, &now); +                ret = mdc_register_xattr_inval (this); +                break; +        case GF_EVENT_CHILD_UP: +                ret = mdc_register_xattr_inval (this);                  break;          default: -                ret = default_notify (this, event, data);                  break;          } +        if (default_notify (this, event, data) != 0) +                ret = -1; +          return ret;  }  | 
