21ab4e
From f66ecbb0964a143c5c4023f5ba0992f1369908d7 Mon Sep 17 00:00:00 2001
21ab4e
From: Ravishankar N <ravishankar@redhat.com>
21ab4e
Date: Tue, 9 May 2017 02:31:39 +0530
21ab4e
Subject: [PATCH 438/473] afr: send the correct iatt values in fsync cbk
21ab4e
21ab4e
Backport of: https://review.gluster.org/17227
21ab4e
21ab4e
Problem:
21ab4e
afr unwinds the fsync fop with an iatt buffer from one of its children
21ab4e
on whom fsync was successful. But that child might not be a valid read
21ab4e
subvolume for that inode because of pending heals or because it happens
21ab4e
to be the arbiter brick etc. Thus we end up sending the wrong iatt to
21ab4e
mdcache which will in turn serve it to the application on a subsequent
21ab4e
stat call as reported in the BZ.
21ab4e
21ab4e
Fix:
21ab4e
Pick a child on whom the fsync was successful *and* that is readable as
21ab4e
indicated in the inode context.
21ab4e
21ab4e
Change-Id: Ie8647289219cebe02dde4727e19a729b3353ebcf
21ab4e
BUG: 1449593
21ab4e
Signed-off-by: Ravishankar N <ravishankar@redhat.com>
21ab4e
Reviewed-on: https://code.engineering.redhat.com/gerrit/105893
21ab4e
---
21ab4e
 xlators/cluster/afr/src/afr-common.c | 68 +++++++++++++++++++++++-------------
21ab4e
 1 file changed, 43 insertions(+), 25 deletions(-)
21ab4e
21ab4e
diff --git a/xlators/cluster/afr/src/afr-common.c b/xlators/cluster/afr/src/afr-common.c
21ab4e
index 03ae7f9..e9117b8 100644
21ab4e
--- a/xlators/cluster/afr/src/afr-common.c
21ab4e
+++ b/xlators/cluster/afr/src/afr-common.c
21ab4e
@@ -3230,47 +3230,65 @@ afr_fsync_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
21ab4e
                struct iatt *postbuf, dict_t *xdata)
21ab4e
 {
21ab4e
         afr_local_t *local = NULL;
21ab4e
+        afr_private_t *priv = NULL;
21ab4e
+        int i = 0;
21ab4e
         int call_count = -1;
21ab4e
         int child_index = (long) cookie;
21ab4e
 	int read_subvol = 0;
21ab4e
 	call_stub_t *stub = NULL;
21ab4e
 
21ab4e
         local = frame->local;
21ab4e
-
21ab4e
-	read_subvol = afr_data_subvol_get (local->inode, this, NULL, NULL,
21ab4e
-                                           NULL, NULL);
21ab4e
+        priv = this->private;
21ab4e
 
21ab4e
         LOCK (&frame->lock);
21ab4e
         {
21ab4e
+                local->replies[child_index].valid = 1;
21ab4e
+                local->replies[child_index].op_ret = op_ret;
21ab4e
+                local->replies[child_index].op_errno = op_errno;
21ab4e
                 if (op_ret == 0) {
21ab4e
-                        if (local->op_ret == -1) {
21ab4e
-				local->op_ret = 0;
21ab4e
-
21ab4e
-                                local->cont.inode_wfop.prebuf  = *prebuf;
21ab4e
-                                local->cont.inode_wfop.postbuf = *postbuf;
21ab4e
-
21ab4e
-				if (xdata)
21ab4e
-					local->xdata_rsp = dict_ref (xdata);
21ab4e
-                        }
21ab4e
-
21ab4e
-                        if (child_index == read_subvol) {
21ab4e
-                                local->cont.inode_wfop.prebuf  = *prebuf;
21ab4e
-                                local->cont.inode_wfop.postbuf = *postbuf;
21ab4e
-				if (xdata) {
21ab4e
-					if (local->xdata_rsp)
21ab4e
-						dict_unref (local->xdata_rsp);
21ab4e
-					local->xdata_rsp = dict_ref (xdata);
21ab4e
-				}
21ab4e
-                        }
21ab4e
-                } else {
21ab4e
-			local->op_errno = op_errno;
21ab4e
-		}
21ab4e
+                        if (prebuf)
21ab4e
+                                local->replies[child_index].prestat = *prebuf;
21ab4e
+                        if (postbuf)
21ab4e
+                                local->replies[child_index].poststat = *postbuf;
21ab4e
+                        if (xdata)
21ab4e
+                                local->replies[child_index].xdata =
21ab4e
+                                        dict_ref (xdata);
21ab4e
+                }
21ab4e
         }
21ab4e
         UNLOCK (&frame->lock);
21ab4e
 
21ab4e
         call_count = afr_frame_return (frame);
21ab4e
 
21ab4e
         if (call_count == 0) {
21ab4e
+                local->op_ret = -1;
21ab4e
+                local->op_errno = afr_final_errno (local, priv);
21ab4e
+	        read_subvol = afr_data_subvol_get (local->inode, this, NULL,
21ab4e
+                                                   local->readable, NULL, NULL);
21ab4e
+                /* Pick a reply that is valid and readable, with a preference
21ab4e
+                 * given to read_subvol. */
21ab4e
+                for (i = 0; i < priv->child_count; i++) {
21ab4e
+                        if (!local->replies[i].valid)
21ab4e
+                                continue;
21ab4e
+                        if (local->replies[i].op_ret != 0)
21ab4e
+                                continue;
21ab4e
+                        if (!local->readable[i])
21ab4e
+                                continue;
21ab4e
+                        local->op_ret = local->replies[i].op_ret;
21ab4e
+                        local->op_errno = local->replies[i].op_errno;
21ab4e
+                        local->cont.inode_wfop.prebuf =
21ab4e
+                                local->replies[i].prestat;
21ab4e
+                        local->cont.inode_wfop.postbuf =
21ab4e
+                                local->replies[i].poststat;
21ab4e
+                        if (local->replies[i].xdata) {
21ab4e
+                                if (local->xdata_rsp)
21ab4e
+                                        dict_unref (local->xdata_rsp);
21ab4e
+                                local->xdata_rsp =
21ab4e
+                                        dict_ref (local->replies[i].xdata);
21ab4e
+                        }
21ab4e
+                        if (i == read_subvol)
21ab4e
+                                break;
21ab4e
+                }
21ab4e
+
21ab4e
 		/* Make a stub out of the frame, and register it
21ab4e
 		   with the waking up post-op. When the call-stub resumes,
21ab4e
 		   we are guaranteed that there was no post-op pending
21ab4e
-- 
21ab4e
1.8.3.1
21ab4e