diff options
author | Vikas Gorur <vikas@gluster.com> | 2009-11-25 07:51:23 +0000 |
---|---|---|
committer | Anand V. Avati <avati@dev.gluster.com> | 2009-11-25 06:03:39 -0800 |
commit | 1bcb009cf65e57117653bbbb5cdf673f9d9142e9 (patch) | |
tree | c9e4d4b7f29c1c6498e7b0ae3b010f710ffc081d /xlators/cluster/afr/src/afr-open.c | |
parent | 9806bd1f58d80d158e3cfb6edee40e92ee30c6d7 (diff) |
cluster/afr: Do self-heal on unopened fds.
This patch completes the previous patch for self-heal of
open fds in replicate.
If an fd was never opened on a subvolume, we remember that
and do the open after we've done self-heal on that fd.
Signed-off-by: Vikas Gorur <vikas@gluster.com>
Signed-off-by: Anand V. Avati <avati@dev.gluster.com>
BUG: 170 (Auto-heal fails on files that are open()-ed/mmap()-ed)
URL: http://bugs.gluster.com/cgi-bin/bugzilla3/show_bug.cgi?id=170
Diffstat (limited to 'xlators/cluster/afr/src/afr-open.c')
-rw-r--r-- | xlators/cluster/afr/src/afr-open.c | 185 |
1 files changed, 163 insertions, 22 deletions
diff --git a/xlators/cluster/afr/src/afr-open.c b/xlators/cluster/afr/src/afr-open.c index 1918dee81..539e258a1 100644 --- a/xlators/cluster/afr/src/afr-open.c +++ b/xlators/cluster/afr/src/afr-open.c @@ -62,14 +62,6 @@ afr_open_ftruncate_cbk (call_frame_t *frame, void *cookie, xlator_t *this, struct stat *postbuf) { afr_local_t * local = frame->local; - int ret = 0; - - ret = afr_fd_ctx_set (this, local->fd); - - if (ret < 0) { - local->op_ret = -1; - local->op_errno = -ret; - } AFR_STACK_UNWIND (open, frame, local->op_ret, local->op_errno, local->fd); @@ -85,6 +77,11 @@ afr_open_cbk (call_frame_t *frame, void *cookie, afr_local_t * local = NULL; afr_private_t * priv = NULL; + int child_index = (long) cookie; + + uint64_t ctx; + afr_fd_ctx_t *fd_ctx; + int ret = 0; int call_count = -1; @@ -101,6 +98,32 @@ afr_open_cbk (call_frame_t *frame, void *cookie, if (op_ret >= 0) { local->op_ret = op_ret; local->success_count++; + + ret = afr_fd_ctx_set (this, fd); + + if (ret < 0) { + gf_log (this->name, GF_LOG_DEBUG, + "could not set fd ctx for fd=%p", + fd); + + local->op_ret = -1; + local->op_errno = -ret; + } + + ret = fd_ctx_get (fd, this, &ctx); + + if (ret < 0) { + gf_log (this->name, GF_LOG_DEBUG, + "could not get fd ctx for fd=%p", fd); + local->op_ret = -1; + local->op_errno = -ret; + } + + fd_ctx = (afr_fd_ctx_t *)(long) ctx; + + fd_ctx->opened_on[child_index] = 1; + fd_ctx->flags = local->cont.open.flags; + fd_ctx->wbflags = local->cont.open.wbflags; } } UNLOCK (&frame->lock); @@ -114,17 +137,6 @@ afr_open_cbk (call_frame_t *frame, void *cookie, this, this->fops->ftruncate, fd, 0); } else { - ret = afr_fd_ctx_set (this, fd); - - if (ret < 0) { - gf_log (this->name, GF_LOG_DEBUG, - "could not set fd ctx for fd=%p", - fd); - - local->op_ret = -1; - local->op_errno = -ret; - } - AFR_STACK_UNWIND (open, frame, local->op_ret, local->op_errno, local->fd); } @@ -173,7 +185,11 @@ afr_open (call_frame_t *frame, xlator_t *this, loc_t *loc, int32_t flags, frame->local = local; call_count = local->call_count; - local->cont.open.flags = flags; + loc_copy (&local->loc, loc); + + local->cont.open.flags = flags; + local->cont.open.wbflags = wbflags; + local->fd = fd_ref (fd); for (i = 0; i < priv->child_count; i++) { @@ -199,13 +215,133 @@ out: int +afr_up_down_flush_open_cbk (call_frame_t *frame, void *cookie, + xlator_t *this, int32_t op_ret, int32_t op_errno, + fd_t *fd) +{ + afr_local_t *local = NULL; + afr_private_t *priv = NULL; + + int ret = 0; + + uint64_t ctx; + afr_fd_ctx_t *fd_ctx; + + int call_count = 0; + int child_index = (long) cookie; + + priv = this->private; + local = frame->local; + + LOCK (&frame->lock); + { + if (op_ret >= 0) { + ret = fd_ctx_get (fd, this, &ctx); + + if (ret < 0) { + goto out; + } + + fd_ctx = (afr_fd_ctx_t *)(long) ctx; + + fd_ctx->opened_on[child_index] = 1; + + gf_log (this->name, GF_LOG_TRACE, + "fd for %s opened successfully on subvolume %s", + local->loc.path, priv->children[child_index]->name); + } + } +out: + UNLOCK (&frame->lock); + + call_count = afr_frame_return (frame); + + if (call_count == 0) { + local->transaction.post_post_op (frame, this); + } + + return 0; +} + + +static int +__unopened_count (int child_count, unsigned char *opened_on, unsigned char *child_up) +{ + int i; + int count = 0; + + for (i = 0; i < child_count; i++) { + if (!opened_on[i] && child_up[i]) + count++; + } + + return count; +} + + +int afr_up_down_flush_sh_unwind (call_frame_t *frame, xlator_t *this) { - afr_local_t *local = NULL; + afr_local_t *local = NULL; + afr_private_t *priv = NULL; + + uint64_t ctx; + afr_fd_ctx_t *fd_ctx; + int abandon = 0; + int ret = 0; + int i; + int call_count = 0; + + priv = this->private; local = frame->local; - local->transaction.post_post_op (frame, this); + /* + * Some subvolumes might have come up on which we never + * opened this fd in the first place. Re-open fd's on those + * subvolumes now. + */ + + ret = fd_ctx_get (local->fd, this, &ctx); + + if (ret < 0) { + abandon = 1; + goto out; + } + + fd_ctx = (afr_fd_ctx_t *)(long) ctx; + + call_count = __unopened_count (priv->child_count, fd_ctx->opened_on, + local->child_up); + + if (call_count == 0) { + abandon = 1; + goto out; + } + + local->call_count = call_count; + + for (i = 0; i < priv->child_count; i++) { + if (!fd_ctx->opened_on[i] && local->child_up[i]) { + gf_log (this->name, GF_LOG_TRACE, + "opening fd for %s on subvolume %s", + local->loc.path, priv->children[i]->name); + + STACK_WIND_COOKIE (frame, afr_up_down_flush_open_cbk, + (void *)(long) i, + priv->children[i], + priv->children[i]->fops->open, + &local->loc, fd_ctx->flags, local->fd, + fd_ctx->wbflags); + + if (!--call_count) + break; + } + } + +out: + if (abandon) + local->transaction.post_post_op (frame, this); return 0; } @@ -227,6 +363,11 @@ afr_up_down_flush_post_post_op (call_frame_t *frame, xlator_t *this) local->loc.inode = inode_ref (local->fd->inode); local->loc.parent = inode_parent (local->fd->inode, 0, NULL); + /* forcibly trigger missing-entries self-heal */ + + local->success_count = 1; + local->enoent_count = 1; + sh->data_lock_held = _gf_true; sh->need_data_self_heal = _gf_true; sh->mode = local->fd->inode->st_mode; |