diff options
author | Pranith Kumar K <pkarampu@redhat.com> | 2017-09-04 16:57:25 +0530 |
---|---|---|
committer | Pranith Kumar Karampuri <pkarampu@redhat.com> | 2017-10-26 18:23:35 +0000 |
commit | 786343abca3474ff01aa1017210112d97cbc4843 (patch) | |
tree | 0077eacbf8b9e7f9638a7b694f7a092e4546111a /xlators/cluster/afr/src/afr-self-heal-data.c | |
parent | 0bb928264a9fb100dc927687eed6ad4d22675950 (diff) |
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 <pkarampu@redhat.com>
Diffstat (limited to 'xlators/cluster/afr/src/afr-self-heal-data.c')
-rw-r--r-- | xlators/cluster/afr/src/afr-self-heal-data.c | 58 |
1 files changed, 54 insertions, 4 deletions
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; } |