summaryrefslogtreecommitdiffstats
path: root/xlators/features/upcall
diff options
context:
space:
mode:
authorPoornima G <pgurusid@redhat.com>2016-07-11 15:04:55 +0530
committerRaghavendra G <rgowdapp@redhat.com>2016-08-30 23:07:01 -0700
commit8f053f9d7270f1c6d50c0b3ab5d020503ceeb31a (patch)
tree754b2dbc815e8b0d619016b5d53f7e0acfae8c40 /xlators/features/upcall
parent55c255b27a99f027cb716800f8330f8faa4eb1f5 (diff)
md-cache: Register the list of xattrs with cache-invalidation
Issue: md-cache caches a specified list of xattrs, and when cache invalidation is enabled, it makes sense to recieve invalidation only when those xattrs are modified by other clients. But the current implementation of upcall is that, it will send invalidation when any of the on-disk xattrs is modified. Solution: md-cache sends a list of xattrs that it is interested in, to upcall by issuing an ipc(). The challenge here is to make sure everytime a brick goes offline and comes back up, the ipc() needs to be issued to the bricks. Hence ipc() is sent from md-cache every time there is a CHILD_UP/CHILD_MODIFIED event. TODO: There will be patches following, in cluster xlators, to implement ipc fop. Change-Id: I6efcf3df474f5ce6eabd3d6694c00c7bd89bc25d BUG: 1211863 Signed-off-by: Poornima G <pgurusid@redhat.com> Reviewed-on: http://review.gluster.org/15002 Smoke: Gluster Build System <jenkins@build.gluster.org> CentOS-regression: Gluster Build System <jenkins@build.gluster.org> Reviewed-by: Rajesh Joseph <rjoseph@redhat.com> NetBSD-regression: NetBSD Build System <jenkins@build.gluster.org> Reviewed-by: Prashanth Pai <ppai@redhat.com> Reviewed-by: Raghavendra G <rgowdapp@redhat.com>
Diffstat (limited to 'xlators/features/upcall')
-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
3 files changed, 125 insertions, 10 deletions
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__ */