summaryrefslogtreecommitdiffstats
path: root/xlators
diff options
context:
space:
mode:
authorRavishankar N <ravishankar@redhat.com>2014-09-03 20:49:53 +0000
committerVijay Bellur <vbellur@redhat.com>2014-09-19 11:02:24 -0700
commit61bf585398c514d437a022792f6726a4292509dd (patch)
treeab207a62c19954fadb83406188452ce7b21868ad /xlators
parenta2e0602c0910ee448b4e8badeb00eed2a78ea452 (diff)
cluster/afr: perform list-xattr during lookup
Detect and heal mismatching user extended attributes during lookup. Backport of: http://review.gluster.org/8558 Change-Id: Id03c9746f083ffd3014711d0b3a2e5a71a45eed4 BUG: 1144274 Signed-off-by: Ravishankar N <ravishankar@redhat.com> Reviewed-on: http://review.gluster.org/8773 Tested-by: Gluster Build System <jenkins@build.gluster.com> Reviewed-by: Pranith Kumar Karampuri <pkarampu@redhat.com> Reviewed-by: Vijay Bellur <vbellur@redhat.com>
Diffstat (limited to 'xlators')
-rw-r--r--xlators/cluster/afr/src/afr-common.c198
-rw-r--r--xlators/cluster/afr/src/afr-self-heal-metadata.c30
-rw-r--r--xlators/cluster/afr/src/afr-self-heal.h2
-rw-r--r--xlators/cluster/afr/src/afr.h3
4 files changed, 222 insertions, 11 deletions
diff --git a/xlators/cluster/afr/src/afr-common.c b/xlators/cluster/afr/src/afr-common.c
index 0b2285afb68..d1bce6284a8 100644
--- a/xlators/cluster/afr/src/afr-common.c
+++ b/xlators/cluster/afr/src/afr-common.c
@@ -670,6 +670,12 @@ afr_xattr_req_prepare (xlator_t *this, dict_t *xattr_req)
"query flag");
}
+ ret = dict_set_int32 (xattr_req, "list-xattr", 1);
+ if (ret) {
+ gf_log (this->name, GF_LOG_DEBUG,
+ "Unable to set list-xattr in dict ");
+ }
+
return ret;
}
@@ -1140,6 +1146,73 @@ afr_handle_quota_size (call_frame_t *frame, xlator_t *this)
}
}
+static char *afr_ignore_xattrs[] = {
+ GLUSTERFS_OPEN_FD_COUNT,
+ GLUSTERFS_PARENT_ENTRYLK,
+ GLUSTERFS_ENTRYLK_COUNT,
+ GLUSTERFS_INODELK_COUNT,
+ GF_SELINUX_XATTR_KEY,
+ QUOTA_SIZE_KEY,
+ NULL
+};
+
+static gf_boolean_t
+afr_lookup_xattr_ignorable (char *key)
+{
+ int i = 0;
+
+ if (!strncmp (key, AFR_XATTR_PREFIX, strlen(AFR_XATTR_PREFIX)))
+ return _gf_true;
+ for (i = 0; afr_ignore_xattrs[i]; i++) {
+ if (!strcmp (key, afr_ignore_xattrs[i]))
+ return _gf_true;
+ }
+ return _gf_false;
+}
+
+int
+xattr_is_equal (dict_t *this, char *key1, data_t *value1, void *data)
+{
+ dict_t *xattr2 = (dict_t *)data;
+ data_t *value2 = NULL;
+
+ if (afr_lookup_xattr_ignorable (key1))
+ return 0;
+
+ value2 = dict_get (xattr2, key1);
+ if (!value2)
+ return -1;
+
+ if (value1->len != value2->len)
+ return -1;
+ if(memcmp(value1->data, value2->data, value1->len))
+ return -1;
+ else
+ return 0;
+
+}
+
+/* To conclude that both dicts are equal, we need to check if
+ * 1) For every key-val pair in dict1, a match is present in dict2
+ * 2) For every key-val pair in dict2, a match is present in dict1
+ * We need to do both because ignoring glusterfs' internal xattrs
+ * happens only in xattr_is_equal().
+ */
+static gf_boolean_t
+dicts_are_equal (dict_t *dict1, dict_t *dict2)
+{
+ int ret = 0;
+
+ ret = dict_foreach (dict1, xattr_is_equal, dict2);
+ if (ret == -1)
+ return _gf_false;
+
+ ret = dict_foreach (dict2, xattr_is_equal, dict1);
+ if (ret == -1)
+ return _gf_false;
+
+ return _gf_true;
+}
static void
afr_lookup_done (call_frame_t *frame, xlator_t *this)
@@ -1437,6 +1510,121 @@ afr_attempt_local_discovery (xlator_t *this, int32_t child_index)
&tmploc, GF_XATTR_PATHINFO_KEY, NULL);
}
+int
+afr_lookup_sh_metadata_wrap (void *opaque)
+{
+ call_frame_t *frame = opaque;
+ afr_local_t *local = NULL;
+ xlator_t *this = NULL;
+ inode_t *inode = NULL;
+ afr_private_t *priv = NULL;
+ struct afr_reply *replies = NULL;
+ int i= 0, first = -1;
+
+ local = frame->local;
+ this = frame->this;
+ priv = this->private;
+ replies = local->replies;
+
+ for (i =0; i < priv->child_count; i++) {
+ if(!replies[i].valid || replies[i].op_ret == -1)
+ continue;
+ first = i;
+ break;
+ }
+ if (first == -1)
+ goto out;
+
+ inode = afr_inode_link (local->inode,&replies[first].poststat);
+ if(!inode)
+ goto out;
+
+ afr_selfheal_metadata (frame, this, inode);
+ inode_forget (inode, 1);
+ inode_unref (inode);
+
+ afr_local_replies_wipe (local, this->private);
+ inode = afr_selfheal_unlocked_lookup_on (frame, local->loc.parent,
+ local->loc.name, local->replies,
+ local->child_up, NULL);
+ if (inode)
+ inode_unref (inode);
+out:
+ afr_lookup_done (frame, this);
+
+ return 0;
+}
+
+static gf_boolean_t
+afr_can_start_metadata_self_heal(call_frame_t *frame, xlator_t *this)
+{
+ afr_local_t *local = NULL;
+ afr_private_t *priv = NULL;
+ struct afr_reply *replies = NULL;
+ int i = 0, first = -1;
+ gf_boolean_t start = _gf_false;
+ struct iatt stbuf = {0, };
+
+ local = frame->local;
+ replies = local->replies;
+ priv = this->private;
+
+ for (i = 0; i < priv->child_count; i++) {
+ if(!replies[i].valid || replies[i].op_ret == -1)
+ continue;
+ if (first == -1) {
+ first = i;
+ stbuf = replies[i].poststat;
+ continue;
+ }
+
+ if (uuid_compare (stbuf.ia_gfid, replies[i].poststat.ia_gfid)) {
+ start = _gf_false;
+ break;
+ }
+ if (!IA_EQUAL (stbuf, replies[i].poststat, type)) {
+ start = _gf_false;
+ break;
+ }
+
+ /*Check if iattrs need heal*/
+ if ((!IA_EQUAL (stbuf, replies[i].poststat, uid)) ||
+ (!IA_EQUAL (stbuf, replies[i].poststat, gid)) ||
+ (!IA_EQUAL (stbuf, replies[i].poststat, prot))) {
+ start = _gf_true;
+ continue;
+ }
+
+ /*Check if xattrs need heal*/
+ if (!dicts_are_equal (replies[first].xdata, replies[i].xdata))
+ start = _gf_true;
+ }
+
+ return start;
+}
+
+int
+afr_lookup_metadata_heal_check (call_frame_t *frame, xlator_t *this)
+
+{
+ call_frame_t *heal = NULL;
+ int ret = 0;
+
+ if (!afr_can_start_metadata_self_heal (frame, this))
+ goto out;
+
+ heal = copy_frame (frame);
+ if (heal)
+ heal->root->pid = GF_CLIENT_PID_AFR_SELF_HEALD;
+ ret = synctask_new (this->ctx->env, afr_lookup_sh_metadata_wrap,
+ afr_refresh_selfheal_done, heal, frame);
+ if(ret)
+ goto out;
+ return ret;
+out:
+ afr_lookup_done (frame, this);
+ return ret;
+}
int
afr_lookup_selfheal_wrap (void *opaque)
@@ -1463,7 +1651,7 @@ afr_lookup_selfheal_wrap (void *opaque)
if (inode)
inode_unref (inode);
- afr_lookup_done (frame, this);
+ afr_lookup_metadata_heal_check(frame, this);
return 0;
unwind:
@@ -1519,11 +1707,11 @@ afr_lookup_entry_heal (call_frame_t *frame, xlator_t *this)
ret = synctask_new (this->ctx->env, afr_lookup_selfheal_wrap,
afr_refresh_selfheal_done, heal, frame);
if (ret)
- goto lookup_done;
- } else {
- lookup_done:
- afr_lookup_done (frame, this);
+ goto metadata_heal;
+ return ret;
}
+metadata_heal:
+ ret = afr_lookup_metadata_heal_check (frame, this);
return ret;
}
diff --git a/xlators/cluster/afr/src/afr-self-heal-metadata.c b/xlators/cluster/afr/src/afr-self-heal-metadata.c
index dc7825d3d16..e98728ba54f 100644
--- a/xlators/cluster/afr/src/afr-self-heal-metadata.c
+++ b/xlators/cluster/afr/src/afr-self-heal-metadata.c
@@ -82,12 +82,12 @@ __afr_selfheal_metadata_do (call_frame_t *frame, xlator_t *this, inode_t *inode,
/*
- * Look for mismatching uid/gid or mode even if xattrs don't say so, and
- * pick one arbitrarily as winner.
- */
+ * Look for mismatching uid/gid or mode or user xattrs even if
+ * AFR xattrs don't say so, and pick one arbitrarily as winner. */
static int
-__afr_selfheal_metadata_finalize_source (xlator_t *this, unsigned char *sources,
+__afr_selfheal_metadata_finalize_source (call_frame_t *frame, xlator_t *this,
+ unsigned char *sources,
unsigned char *healed_sinks,
unsigned char *locked_on,
struct afr_reply *replies)
@@ -97,6 +97,7 @@ __afr_selfheal_metadata_finalize_source (xlator_t *this, unsigned char *sources,
struct iatt first = {0, };
int source = -1;
int sources_count = 0;
+ int ret = 0;
priv = this->private;
@@ -124,11 +125,12 @@ __afr_selfheal_metadata_finalize_source (xlator_t *this, unsigned char *sources,
if (source == -1) {
source = i;
first = replies[i].poststat;
+ break;
}
}
for (i = 0; i < priv->child_count; i++) {
- if (!sources[i])
+ if (!sources[i] || i == source)
continue;
if (!IA_EQUAL (first, replies[i].poststat, type) ||
!IA_EQUAL (first, replies[i].poststat, uid) ||
@@ -139,6 +141,22 @@ __afr_selfheal_metadata_finalize_source (xlator_t *this, unsigned char *sources,
}
}
+ for (i =0; i < priv->child_count; i++) {
+ if (!sources[i] || i == source)
+ continue;
+ if (replies[source].xdata->count != replies[i].xdata->count) {
+ sources[i] = 0;
+ healed_sinks[i] = 1;
+ continue;
+ }
+ ret = dict_foreach(replies[source].xdata, xattr_is_equal,
+ (void*)replies[i].xdata);
+ if (ret == -1) {
+ sources[i] = 0;
+ healed_sinks[i] = 1;
+ }
+ }
+
return source;
}
@@ -176,7 +194,7 @@ __afr_selfheal_metadata_prepare (call_frame_t *frame, xlator_t *this, inode_t *i
*/
AFR_INTERSECT (healed_sinks, sinks, locked_on, priv->child_count);
- source = __afr_selfheal_metadata_finalize_source (this, sources,
+ source = __afr_selfheal_metadata_finalize_source (frame, this, sources,
healed_sinks,
locked_on, replies);
if (source < 0)
diff --git a/xlators/cluster/afr/src/afr-self-heal.h b/xlators/cluster/afr/src/afr-self-heal.h
index 2713ffa09bf..31f12a4e74a 100644
--- a/xlators/cluster/afr/src/afr-self-heal.h
+++ b/xlators/cluster/afr/src/afr-self-heal.h
@@ -179,4 +179,6 @@ afr_selfheal_newentry_mark (call_frame_t *frame, xlator_t *this, inode_t *inode,
int source, struct afr_reply *replies,
unsigned char *sources, unsigned char *newentry);
+inode_t*
+afr_inode_link (inode_t *inode, struct iatt *iatt);
#endif /* !_AFR_SELFHEAL_H */
diff --git a/xlators/cluster/afr/src/afr.h b/xlators/cluster/afr/src/afr.h
index e19ceac3653..cca964d9178 100644
--- a/xlators/cluster/afr/src/afr.h
+++ b/xlators/cluster/afr/src/afr.h
@@ -781,6 +781,9 @@ int32_t
afr_notify (xlator_t *this, int32_t event, void *data, void *data2);
int
+xattr_is_equal (dict_t *this, char *key1, data_t *value1, void *data);
+
+int
afr_init_entry_lockee (afr_entry_lockee_t *lockee, afr_local_t *local,
loc_t *loc, char *basename, int child_count);