3604df
From c1cf679813e86984bfa72964840d0e7b0a19e7e2 Mon Sep 17 00:00:00 2001
3604df
From: Pranith Kumar K <pkarampu@redhat.com>
3604df
Date: Mon, 23 Jan 2017 14:58:45 +0530
3604df
Subject: [PATCH 292/294] cluster/afr: Perform new entry mark before creating
3604df
 new entry
3604df
3604df
There is a chance for the source brick to go down just after
3604df
the new entry is created and before source brick is marked with
3604df
necessary pending markers. If after this any I/O happens then
3604df
new entry will become source and reverse heal will happen.
3604df
To prevent this mark the pending xattrs before creating the new
3604df
entry.
3604df
3604df
 >BUG: 1417466
3604df
 >Change-Id: I233b87e694d32e5d734df5a83b4d2ca711c17503
3604df
 >Signed-off-by: Pranith Kumar K <pkarampu@redhat.com>
3604df
 >Reviewed-on: https://review.gluster.org/16474
3604df
 >Smoke: Gluster Build System <jenkins@build.gluster.org>
3604df
 >NetBSD-regression: NetBSD Build System <jenkins@build.gluster.org>
3604df
 >CentOS-regression: Gluster Build System <jenkins@build.gluster.org>
3604df
 >Reviewed-by: Ravishankar N <ravishankar@redhat.com>
3604df
 >Reviewed-by: Krutika Dhananjay <kdhananj@redhat.com>
3604df
3604df
BUG: 1403180
3604df
Change-Id: I32a02c9e06edf700bbfd8acd274f37c99dfb9083
3604df
Signed-off-by: Pranith Kumar K <pkarampu@redhat.com>
3604df
Reviewed-on: https://code.engineering.redhat.com/gerrit/97977
3604df
---
3604df
 xlators/cluster/afr/src/afr-self-heal-common.c | 17 +++++--
3604df
 xlators/cluster/afr/src/afr-self-heal-entry.c  | 61 ++++++++++----------------
3604df
 xlators/cluster/afr/src/afr-self-heal-name.c   | 19 ++++----
3604df
 xlators/cluster/afr/src/afr-self-heal.h        |  8 ++--
3604df
 4 files changed, 51 insertions(+), 54 deletions(-)
3604df
3604df
diff --git a/xlators/cluster/afr/src/afr-self-heal-common.c b/xlators/cluster/afr/src/afr-self-heal-common.c
3604df
index f731d42..8b2c3fa 100644
3604df
--- a/xlators/cluster/afr/src/afr-self-heal-common.c
3604df
+++ b/xlators/cluster/afr/src/afr-self-heal-common.c
3604df
@@ -27,6 +27,8 @@ afr_selfheal_post_op_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
3604df
 
3604df
 	local = frame->local;
3604df
 
3604df
+        local->op_ret = op_ret;
3604df
+        local->op_errno = op_errno;
3604df
 	syncbarrier_wake (&local->barrier);
3604df
 
3604df
 	return 0;
3604df
@@ -40,6 +42,7 @@ afr_selfheal_post_op (call_frame_t *frame, xlator_t *this, inode_t *inode,
3604df
 	afr_private_t *priv = NULL;
3604df
 	afr_local_t *local = NULL;
3604df
 	loc_t loc = {0, };
3604df
+        int ret = 0;
3604df
 
3604df
 	priv = this->private;
3604df
 	local = frame->local;
3604df
@@ -47,15 +50,20 @@ afr_selfheal_post_op (call_frame_t *frame, xlator_t *this, inode_t *inode,
3604df
 	loc.inode = inode_ref (inode);
3604df
 	gf_uuid_copy (loc.gfid, inode->gfid);
3604df
 
3604df
+        local->op_ret = 0;
3604df
+
3604df
 	STACK_WIND (frame, afr_selfheal_post_op_cbk, priv->children[subvol],
3604df
 		    priv->children[subvol]->fops->xattrop, &loc,
3604df
 		    GF_XATTROP_ADD_ARRAY, xattr, xdata);
3604df
 
3604df
 	syncbarrier_wait (&local->barrier, 1);
3604df
+        if (local->op_ret < 0)
3604df
+                ret = -local->op_errno;
3604df
 
3604df
         loc_wipe (&loc;;
3604df
+        local->op_ret = 0;
3604df
 
3604df
-	return 0;
3604df
+	return ret;
3604df
 }
3604df
 
3604df
 int
3604df
@@ -1945,13 +1953,16 @@ afr_selfheal_newentry_mark (call_frame_t *frame, xlator_t *this, inode_t *inode,
3604df
         changelog = afr_mark_pending_changelog (priv, newentry, xattr,
3604df
                                             replies[source].poststat.ia_type);
3604df
 
3604df
-        if (!changelog)
3604df
+        if (!changelog) {
3604df
+                ret = -ENOMEM;
3604df
                 goto out;
3604df
+        }
3604df
 
3604df
 	for (i = 0; i < priv->child_count; i++) {
3604df
 		if (!sources[i])
3604df
 			continue;
3604df
-		afr_selfheal_post_op (frame, this, inode, i, xattr, NULL);
3604df
+		ret |= afr_selfheal_post_op (frame, this, inode, i, xattr,
3604df
+                                             NULL);
3604df
 	}
3604df
 out:
3604df
         if (changelog)
3604df
diff --git a/xlators/cluster/afr/src/afr-self-heal-entry.c b/xlators/cluster/afr/src/afr-self-heal-entry.c
3604df
index 2efeedf..6b79da0 100644
3604df
--- a/xlators/cluster/afr/src/afr-self-heal-entry.c
3604df
+++ b/xlators/cluster/afr/src/afr-self-heal-entry.c
3604df
@@ -17,11 +17,6 @@
3604df
 #include "syncop-utils.h"
3604df
 #include "events.h"
3604df
 
3604df
-/* Max file name length is 255 this filename is of length 256. No file with
3604df
- * this name can ever come, entry-lock with this name is going to prevent
3604df
- * self-heals from older versions while the granular entry-self-heal is going
3604df
- * on in newer version.*/
3604df
-
3604df
 static int
3604df
 afr_selfheal_entry_delete (xlator_t *this, inode_t *dir, const char *name,
3604df
                            inode_t *inode, int child, struct afr_reply *replies)
3604df
@@ -71,26 +66,29 @@ afr_selfheal_entry_delete (xlator_t *this, inode_t *dir, const char *name,
3604df
 
3604df
 
3604df
 int
3604df
-afr_selfheal_recreate_entry (xlator_t *this, int dst, int source, inode_t *dir,
3604df
+afr_selfheal_recreate_entry (call_frame_t *frame, int dst, int source,
3604df
+                             unsigned char *sources, inode_t *dir,
3604df
                              const char *name, inode_t *inode,
3604df
-                             struct afr_reply *replies,
3604df
-                             unsigned char *newentry)
3604df
+                             struct afr_reply *replies)
3604df
 {
3604df
 	int ret = 0;
3604df
 	loc_t loc = {0,};
3604df
 	loc_t srcloc = {0,};
3604df
+        xlator_t *this = frame->this;
3604df
 	afr_private_t *priv = NULL;
3604df
 	dict_t *xdata = NULL;
3604df
 	struct iatt *iatt = NULL;
3604df
 	char *linkname = NULL;
3604df
 	mode_t mode = 0;
3604df
 	struct iatt newent = {0,};
3604df
-	priv = this->private;
3604df
+        unsigned char *newentry = NULL;
3604df
 
3604df
+        priv = this->private;
3604df
 	xdata = dict_new();
3604df
 	if (!xdata)
3604df
 		return -ENOMEM;
3604df
 
3604df
+        newentry = alloca0 (priv->child_count);
3604df
 	loc.parent = inode_ref (dir);
3604df
 	gf_uuid_copy (loc.pargfid, dir->gfid);
3604df
 	loc.name = name;
3604df
@@ -109,6 +107,15 @@ afr_selfheal_recreate_entry (xlator_t *this, int dst, int source, inode_t *dir,
3604df
 
3604df
 	srcloc.inode = inode_ref (inode);
3604df
 	gf_uuid_copy (srcloc.gfid, iatt->ia_gfid);
3604df
+        if (iatt->ia_type != IA_IFDIR)
3604df
+                ret = syncop_lookup (priv->children[dst], &srcloc, 0, 0, 0, 0);
3604df
+        if (iatt->ia_type == IA_IFDIR || ret == -ENOENT || ret == -ESTALE) {
3604df
+                newentry[dst] = 1;
3604df
+                ret = afr_selfheal_newentry_mark (frame, this, inode, source,
3604df
+                                                  replies, sources, newentry);
3604df
+                if (ret)
3604df
+                        goto out;
3604df
+        }
3604df
 
3604df
 	mode = st_mode_from_ia (iatt->ia_prot, iatt->ia_type);
3604df
 
3604df
@@ -116,12 +123,9 @@ afr_selfheal_recreate_entry (xlator_t *this, int dst, int source, inode_t *dir,
3604df
 	case IA_IFDIR:
3604df
 		ret = syncop_mkdir (priv->children[dst], &loc, mode, 0,
3604df
                                     xdata, NULL);
3604df
-                if (ret == 0)
3604df
-                        newentry[dst] = 1;
3604df
 		break;
3604df
 	case IA_IFLNK:
3604df
-		ret = syncop_lookup (priv->children[dst], &srcloc, 0, 0, 0, 0);
3604df
-		if (ret == 0) {
3604df
+		if (!newentry[dst]) {
3604df
 			ret = syncop_link (priv->children[dst], &srcloc, &loc,
3604df
 					   &newent, NULL, NULL);
3604df
 		} else {
3604df
@@ -131,8 +135,6 @@ afr_selfheal_recreate_entry (xlator_t *this, int dst, int source, inode_t *dir,
3604df
 				goto out;
3604df
 			ret = syncop_symlink (priv->children[dst], &loc,
3604df
                                               linkname, NULL, xdata, NULL);
3604df
-                        if (ret == 0)
3604df
-                                newentry[dst] = 1;
3604df
                 }
3604df
 		break;
3604df
 	default:
3604df
@@ -142,10 +144,6 @@ afr_selfheal_recreate_entry (xlator_t *this, int dst, int source, inode_t *dir,
3604df
 		ret = syncop_mknod (priv->children[dst], &loc, mode,
3604df
                     makedev (ia_major(iatt->ia_rdev), ia_minor (iatt->ia_rdev)),
3604df
                     &newent, xdata, NULL);
3604df
-		if (ret == 0 && newent.ia_nlink == 1) {
3604df
-			/* New entry created. Mark @dst pending on all sources */
3604df
-                        newentry[dst] = 1;
3604df
-		}
3604df
 		break;
3604df
 	}
3604df
 
3604df
@@ -168,12 +166,9 @@ __afr_selfheal_heal_dirent (call_frame_t *frame, xlator_t *this, fd_t *fd,
3604df
 	int ret = 0;
3604df
 	afr_private_t *priv = NULL;
3604df
 	int i = 0;
3604df
-	unsigned char *newentry = NULL;
3604df
 
3604df
 	priv = this->private;
3604df
 
3604df
-	newentry = alloca0 (priv->child_count);
3604df
-
3604df
 	if (!replies[source].valid)
3604df
 		return -EIO;
3604df
 
3604df
@@ -196,17 +191,15 @@ __afr_selfheal_heal_dirent (call_frame_t *frame, xlator_t *this, fd_t *fd,
3604df
 					   replies[source].poststat.ia_gfid))
3604df
 				continue;
3604df
 
3604df
-			ret = afr_selfheal_recreate_entry (this, i, source,
3604df
-							   fd->inode, name, inode,
3604df
-							   replies, newentry);
3604df
+			ret = afr_selfheal_recreate_entry (frame, i, source,
3604df
+                                                           sources, fd->inode,
3604df
+                                                           name, inode,
3604df
+							   replies);
3604df
                 }
3604df
 		if (ret < 0)
3604df
 			break;
3604df
 	}
3604df
 
3604df
-	if (AFR_COUNT (newentry, priv->child_count))
3604df
-		afr_selfheal_newentry_mark (frame, this, inode, source, replies,
3604df
-					    sources, newentry);
3604df
 	return ret;
3604df
 }
3604df
 
3604df
@@ -290,13 +283,10 @@ __afr_selfheal_merge_dirent (call_frame_t *frame, xlator_t *this, fd_t *fd,
3604df
         int             ret       = 0;
3604df
         int             i         = 0;
3604df
         int             source    = -1;
3604df
-        unsigned char  *newentry  = NULL;
3604df
         afr_private_t  *priv      = NULL;
3604df
 
3604df
 	priv = this->private;
3604df
 
3604df
-	newentry = alloca0 (priv->child_count);
3604df
-
3604df
 	for (i = 0; i < priv->child_count; i++) {
3604df
 		if (replies[i].valid && replies[i].op_ret == 0) {
3604df
 			source = i;
3604df
@@ -331,14 +321,11 @@ __afr_selfheal_merge_dirent (call_frame_t *frame, xlator_t *this, fd_t *fd,
3604df
 		if (replies[i].op_errno != ENOENT)
3604df
 			continue;
3604df
 
3604df
-		ret = afr_selfheal_recreate_entry (this, i, source, fd->inode,
3604df
-                                                   name, inode, replies,
3604df
-                                                   newentry);
3604df
+		ret = afr_selfheal_recreate_entry (frame, i, source, sources,
3604df
+                                                   fd->inode, name, inode,
3604df
+                                                   replies);
3604df
 	}
3604df
 
3604df
-	if (AFR_COUNT (newentry, priv->child_count))
3604df
-		afr_selfheal_newentry_mark (frame, this, inode, source, replies,
3604df
-					    sources, newentry);
3604df
 	return ret;
3604df
 }
3604df
 
3604df
diff --git a/xlators/cluster/afr/src/afr-self-heal-name.c b/xlators/cluster/afr/src/afr-self-heal-name.c
3604df
index 1d7b0cc..3ac5219 100644
3604df
--- a/xlators/cluster/afr/src/afr-self-heal-name.c
3604df
+++ b/xlators/cluster/afr/src/afr-self-heal-name.c
3604df
@@ -110,12 +110,10 @@ __afr_selfheal_name_impunge (call_frame_t *frame, xlator_t *this,
3604df
 	int i = 0;
3604df
 	afr_private_t *priv = NULL;
3604df
         int ret = 0;
3604df
-        unsigned char *newentry = NULL;
3604df
         unsigned char *sources = NULL;
3604df
 
3604df
         priv = this->private;
3604df
 
3604df
-	newentry = alloca0 (priv->child_count);
3604df
 	sources = alloca0 (priv->child_count);
3604df
 
3604df
 	gf_uuid_copy (parent->gfid, pargfid);
3604df
@@ -129,15 +127,17 @@ __afr_selfheal_name_impunge (call_frame_t *frame, xlator_t *this,
3604df
                         sources[i] = 1;
3604df
 			continue;
3604df
                 }
3604df
+        }
3604df
+
3604df
+        for (i = 0; i < priv->child_count; i++) {
3604df
+                if (sources[i])
3604df
+                        continue;
3604df
 
3604df
-		ret |= afr_selfheal_recreate_entry (this, i, gfid_idx, parent,
3604df
-                                                    bname, inode, replies,
3604df
-                                                    newentry);
3604df
+		ret |= afr_selfheal_recreate_entry (frame, i, gfid_idx, sources,
3604df
+                                                    parent, bname, inode,
3604df
+                                                    replies);
3604df
 	}
3604df
 
3604df
-	if (AFR_COUNT (newentry, priv->child_count))
3604df
-		afr_selfheal_newentry_mark (frame, this, inode, gfid_idx, replies,
3604df
-					    sources, newentry);
3604df
 	return ret;
3604df
 }
3604df
 
3604df
@@ -484,8 +484,7 @@ __afr_selfheal_name_do (call_frame_t *frame, xlator_t *this, inode_t *parent,
3604df
         }
3604df
 
3604df
 	ret = __afr_selfheal_name_impunge (frame, this, parent, pargfid,
3604df
-                                           bname, inode,
3604df
-                                           replies, gfid_idx);
3604df
+                                           bname, inode, replies, gfid_idx);
3604df
         if (ret == -EIO)
3604df
                 ret = -1;
3604df
 
3604df
diff --git a/xlators/cluster/afr/src/afr-self-heal.h b/xlators/cluster/afr/src/afr-self-heal.h
3604df
index a339050..2b3a87e 100644
3604df
--- a/xlators/cluster/afr/src/afr-self-heal.h
3604df
+++ b/xlators/cluster/afr/src/afr-self-heal.h
3604df
@@ -174,10 +174,10 @@ afr_selfheal_undo_pending (call_frame_t *frame, xlator_t *this, inode_t *inode,
3604df
                            unsigned char *locked_on);
3604df
 
3604df
 int
3604df
-afr_selfheal_recreate_entry (xlator_t *this, int dst, int source, inode_t *dir,
3604df
-                             const char *name, inode_t *inode,
3604df
-                             struct afr_reply *replies,
3604df
-                             unsigned char *newentry);
3604df
+afr_selfheal_recreate_entry (call_frame_t *frame, int dst, int source,
3604df
+                             unsigned char *sources,
3604df
+                             inode_t *dir, const char *name, inode_t *inode,
3604df
+                             struct afr_reply *replies);
3604df
 
3604df
 int
3604df
 afr_selfheal_post_op (call_frame_t *frame, xlator_t *this, inode_t *inode,
3604df
-- 
3604df
2.9.3
3604df