diff options
author | Ravishankar N <ravishankar@redhat.com> | 2017-06-05 09:40:51 +0530 |
---|---|---|
committer | jiffin tony Thottan <jthottan@redhat.com> | 2017-06-19 04:54:40 +0000 |
commit | 5d13784dc6aa406f69061f2608a19ef0c8a80581 (patch) | |
tree | 2ce796379466db474488fe8c61bf2d1a755d24c0 | |
parent | 5a48cf93a0383d79b6525268cee93158dbee8132 (diff) |
afr: add errno to afr_inode_refresh_done()
Backport of https://review.gluster.org/17413 and
https://review.gluster.org/17436
Problem:
When parellel `rm -rf`s were being done from cifs clients, opendir might
fail on some replicas with ENOENT. DHT ignores partial opendir failures
in dht_fd_cbk() and winds readdirs on those replicas. Afr inode refresh
(as a part of readdirp read_txn) sees in its fd context that the state
of the fds is *not* AFR_FD_OPENED and bails out to
afr_inode_refresh_done() without doing a refresh. When this happens, the
errno is set as EIO due to lack of readable subvols, logging split-brain
messages in the logs.
Fix:
Introduce an errno argument to afr_inode_refresh_do() to bail out with
the right error value when inode refresh is not performed.
Change-Id: I8eed4d6e6c85332c1f5813c74cb54ae73693a369
BUG: 1460661
Signed-off-by: Ravishankar N <ravishankar@redhat.com>
Reviewed-on: https://review.gluster.org/17518
Smoke: Gluster Build System <jenkins@build.gluster.org>
NetBSD-regression: NetBSD Build System <jenkins@build.gluster.org>
CentOS-regression: Gluster Build System <jenkins@build.gluster.org>
Reviewed-by: Pranith Kumar Karampuri <pkarampu@redhat.com>
-rw-r--r-- | xlators/cluster/afr/src/afr-common.c | 23 |
1 files changed, 16 insertions, 7 deletions
diff --git a/xlators/cluster/afr/src/afr-common.c b/xlators/cluster/afr/src/afr-common.c index 5ebe86bb368..7532b014ff7 100644 --- a/xlators/cluster/afr/src/afr-common.c +++ b/xlators/cluster/afr/src/afr-common.c @@ -1076,7 +1076,7 @@ refresh_done: } int -afr_inode_refresh_done (call_frame_t *frame, xlator_t *this) +afr_inode_refresh_done (call_frame_t *frame, xlator_t *this, int error) { call_frame_t *heal_frame = NULL; afr_local_t *local = NULL; @@ -1086,6 +1086,11 @@ afr_inode_refresh_done (call_frame_t *frame, xlator_t *this) int ret = 0; int err = 0; + if (error != 0) { + err = error; + goto refresh_done; + } + local = frame->local; ret = afr_replies_interpret (frame, this, local->refreshinode, @@ -1149,7 +1154,7 @@ afr_inode_refresh_subvol_cbk (call_frame_t *frame, void *cookie, xlator_t *this, call_count = afr_frame_return (frame); if (call_count == 0) { afr_set_need_heal (this, local); - afr_inode_refresh_done (frame, this); + afr_inode_refresh_done (frame, this, 0); } } @@ -1240,20 +1245,21 @@ afr_inode_refresh_do (call_frame_t *frame, xlator_t *this) if (local->fd) { fd_ctx = afr_fd_ctx_get (local->fd, this); if (!fd_ctx) { - afr_inode_refresh_done (frame, this); + afr_inode_refresh_done (frame, this, EINVAL); return 0; } } xdata = dict_new (); if (!xdata) { - afr_inode_refresh_done (frame, this); + afr_inode_refresh_done (frame, this, ENOMEM); return 0; } - if (afr_xattr_req_prepare (this, xdata) != 0) { + ret = afr_xattr_req_prepare (this, xdata); + if (ret != 0) { dict_unref (xdata); - afr_inode_refresh_done (frame, this); + afr_inode_refresh_done (frame, this, -ret); return 0; } @@ -1286,7 +1292,10 @@ afr_inode_refresh_do (call_frame_t *frame, xlator_t *this) call_count = local->call_count; if (!call_count) { dict_unref (xdata); - afr_inode_refresh_done (frame, this); + if (local->fd && AFR_COUNT(local->child_up, priv->child_count)) + afr_inode_refresh_done (frame, this, EBADFD); + else + afr_inode_refresh_done (frame, this, ENOTCONN); return 0; } for (i = 0; i < priv->child_count; i++) { |