summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--api/src/glfs-internal.h22
-rw-r--r--libglusterfs/src/dict.c20
-rw-r--r--libglusterfs/src/dict.h2
-rw-r--r--libglusterfs/src/syncop.h23
-rw-r--r--xlators/features/upcall/src/upcall-internal.c12
-rw-r--r--xlators/features/upcall/src/upcall.c117
-rw-r--r--xlators/features/upcall/src/upcall.h6
-rw-r--r--xlators/performance/md-cache/src/md-cache-mem-types.h1
-rw-r--r--xlators/performance/md-cache/src/md-cache-messages.h27
-rw-r--r--xlators/performance/md-cache/src/md-cache.c148
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;
}