From 786343abca3474ff01aa1017210112d97cbc4843 Mon Sep 17 00:00:00 2001 From: Pranith Kumar K Date: Mon, 4 Sep 2017 16:57:25 +0530 Subject: cluster/afr: Fail open on split-brain Problem: Append on a file with split-brain succeeds. Open is intercepted by open-behind, when write comes on the file, open-behind does open+write. Open succeeds because afr doesn't fail it. Then write succeeds because write-behind intercepts it. Flush is also intercepted by write-behind, so the application never gets to know that the write failed. Fix: Fail open on split-brain, so that when open-behind does open+write open fails which leads to write failure. Application will know about this failure. Change-Id: I4bff1c747c97bb2925d6987f4ced5f1ce75dbc15 BUG: 1294051 Signed-off-by: Pranith Kumar K --- xlators/cluster/afr/src/afr-self-heal-data.c | 58 ++++++++++++++++++++++++++-- 1 file changed, 54 insertions(+), 4 deletions(-) (limited to 'xlators/cluster/afr/src/afr-self-heal-data.c') diff --git a/xlators/cluster/afr/src/afr-self-heal-data.c b/xlators/cluster/afr/src/afr-self-heal-data.c index 2c254e80aa1..8cf43f2807b 100644 --- a/xlators/cluster/afr/src/afr-self-heal-data.c +++ b/xlators/cluster/afr/src/afr-self-heal-data.c @@ -776,13 +776,37 @@ out: return ret; } +int +afr_selfheal_data_open_cbk (call_frame_t *frame, void *cookie, + xlator_t *this, int32_t op_ret, int32_t op_errno, + fd_t *fd, dict_t *xdata) +{ + afr_local_t *local = NULL; + int i = (long) cookie; + + local = frame->local; + + local->replies[i].valid = 1; + local->replies[i].op_ret = op_ret; + local->replies[i].op_errno = op_errno; + + syncbarrier_wake (&local->barrier); + + return 0; +} int afr_selfheal_data_open (xlator_t *this, inode_t *inode, fd_t **fd) { - int ret = 0; - fd_t *fd_tmp = NULL; - loc_t loc = {0,}; + int ret = 0; + fd_t *fd_tmp = NULL; + loc_t loc = {0,}; + call_frame_t *frame = NULL; + afr_local_t *local = NULL; + afr_private_t *priv = NULL; + int i = 0; + + priv = this->private; fd_tmp = fd_create (inode, 0); if (!fd_tmp) @@ -791,7 +815,31 @@ afr_selfheal_data_open (xlator_t *this, inode_t *inode, fd_t **fd) loc.inode = inode_ref (inode); gf_uuid_copy (loc.gfid, inode->gfid); - ret = syncop_open (this, &loc, O_RDWR|O_LARGEFILE, fd_tmp, NULL, NULL); + frame = afr_frame_create (this, &ret); + if (!frame) { + ret = -ret; + fd_unref (fd_tmp); + goto out; + } + local = frame->local; + + AFR_ONLIST (local->child_up, frame, afr_selfheal_data_open_cbk, open, + &loc, O_RDWR|O_LARGEFILE, fd_tmp, NULL); + + ret = -ENOTCONN; + for (i = 0; i < priv->child_count; i++) { + if (!local->replies[i].valid) + continue; + + if (local->replies[i].op_ret < 0) { + ret = -local->replies[i].op_errno; + continue; + } + + ret = 0; + break; + } + if (ret < 0) { fd_unref (fd_tmp); goto out; @@ -802,6 +850,8 @@ afr_selfheal_data_open (xlator_t *this, inode_t *inode, fd_t **fd) *fd = fd_tmp; out: loc_wipe (&loc); + if (frame) + AFR_STACK_DESTROY (frame); return ret; } -- cgit