summaryrefslogtreecommitdiffstats
path: root/xlators/cluster/afr/src/afr-self-heal-common.c
diff options
context:
space:
mode:
authorRavishankar N <ravishankar@redhat.com>2017-09-20 12:16:06 +0530
committerjiffin tony Thottan <jthottan@redhat.com>2017-10-10 05:33:15 +0000
commitf73814ad08d552d94d0139b2592175d206e7a166 (patch)
tree16158b80a3b60f5726f3c3819a0116a85fe659a2 /xlators/cluster/afr/src/afr-self-heal-common.c
parent47604fad4c2a3951077e41e0c007ceb979bb2c24 (diff)
afr: heal gfid as a part of entry heal
Problem: If a brick crashes after an entry (file or dir) is created but before gfid is assigned, the good bricks will have pending entry heal xattrs but the heal won't complete because afr_selfheal_recreate_entry() tries to create the entry again and it fails with EEXIST. Fix: We could have fixed posx_mknod/mkdir etc to assign the gfid if the file already exists but the right thing to do seems to be to trigger a lookup on the bad brick and let it heal the gfid instead of winding an mknod/mkdir in the first place. (cherry picked from commit 20fa80057eb430fd72b4fa31b9b65598b8ec1265) Change-Id: I82f76665a7541f1893ef8d847b78af6466aff1ff BUG: 1499202 Signed-off-by: Ravishankar N <ravishankar@redhat.com>
Diffstat (limited to 'xlators/cluster/afr/src/afr-self-heal-common.c')
-rw-r--r--xlators/cluster/afr/src/afr-self-heal-common.c78
1 files changed, 78 insertions, 0 deletions
diff --git a/xlators/cluster/afr/src/afr-self-heal-common.c b/xlators/cluster/afr/src/afr-self-heal-common.c
index 55b978bf962..20e81dd43e0 100644
--- a/xlators/cluster/afr/src/afr-self-heal-common.c
+++ b/xlators/cluster/afr/src/afr-self-heal-common.c
@@ -20,6 +20,84 @@ void
afr_heal_synctask (xlator_t *this, afr_local_t *local);
int
+afr_lookup_and_heal_gfid (xlator_t *this, inode_t *parent, const char *name,
+ inode_t *inode, struct afr_reply *replies,
+ int source, void *gfid)
+{
+ afr_private_t *priv = NULL;
+ call_frame_t *frame = NULL;
+ afr_local_t *local = NULL;
+ unsigned char *wind_on = NULL;
+ ia_type_t ia_type = IA_INVAL;
+ dict_t *xdata = NULL;
+ loc_t loc = {0, };
+ int ret = 0;
+ int i = 0;
+
+ priv = this->private;
+ wind_on = alloca0 (priv->child_count);
+ ia_type = replies[source].poststat.ia_type;
+
+ /* gfid heal on those subvolumes that do not have gfid associated
+ * with the inode and update those replies.
+ */
+ for (i = 0; i < priv->child_count; i++) {
+ if (!replies[i].valid || replies[i].op_ret != 0)
+ continue;
+ if (!gf_uuid_is_null (replies[i].poststat.ia_gfid) ||
+ replies[i].poststat.ia_type != ia_type)
+ continue;
+
+ wind_on[i] = 1;
+ }
+
+ if (AFR_COUNT(wind_on, priv->child_count) == 0)
+ return 0;
+
+ xdata = dict_new ();
+ if (!xdata) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ ret = dict_set_static_bin (xdata, "gfid-req", gfid, 16);
+ if (ret) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ frame = afr_frame_create (this);
+ if (!frame) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ local = frame->local;
+ loc.parent = inode_ref (parent);
+ gf_uuid_copy (loc.pargfid, parent->gfid);
+ loc.name = name;
+ loc.inode = inode_ref (inode);
+
+ AFR_ONLIST (wind_on, frame, afr_selfheal_discover_cbk, lookup,
+ &loc, xdata);
+
+ for (i = 0; i < priv->child_count; i++) {
+ if (!wind_on[i])
+ continue;
+ afr_reply_wipe (&replies[i]);
+ afr_reply_copy (&replies[i], &local->replies[i]);
+ }
+out:
+ loc_wipe (&loc);
+ if (frame)
+ AFR_STACK_DESTROY (frame);
+ if (xdata)
+ dict_unref (xdata);
+
+ return ret;
+}
+
+int
afr_gfid_sbrain_source_from_src_brick (xlator_t *this,
struct afr_reply *replies,
char *src_brick)