|
|
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 |
|