diff options
author | Ravishankar N <ravishankar@redhat.com> | 2014-09-03 20:49:53 +0000 |
---|---|---|
committer | Vijay Bellur <vbellur@redhat.com> | 2014-09-19 11:02:24 -0700 |
commit | 61bf585398c514d437a022792f6726a4292509dd (patch) | |
tree | ab207a62c19954fadb83406188452ce7b21868ad /xlators | |
parent | a2e0602c0910ee448b4e8badeb00eed2a78ea452 (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.c | 198 | ||||
-rw-r--r-- | xlators/cluster/afr/src/afr-self-heal-metadata.c | 30 | ||||
-rw-r--r-- | xlators/cluster/afr/src/afr-self-heal.h | 2 | ||||
-rw-r--r-- | xlators/cluster/afr/src/afr.h | 3 |
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); |