diff options
author | Vikas Gorur <vikas@gluster.com> | 2009-11-24 08:45:09 +0000 |
---|---|---|
committer | Anand V. Avati <avati@dev.gluster.com> | 2009-11-24 06:40:08 -0800 |
commit | 74612a456ad1602f8038fae79fee654eb427602a (patch) | |
tree | a8c57ae1b5919688faa00985aad3677e0df9ea1b /xlators/cluster/afr/src/afr-inode-write.c | |
parent | 218959e0597b16755a98b19786ed6a42cd15cbc4 (diff) |
cluster/afr: Do self-heal on reopened fds.
This patch brings in partial support for self-heal of open
fds. The precondition is that the fd should have been opened
successfully during the initial open() (or create()), and we
assume that protocol/client has successfully reopened the fd
when the subvolume comes back up.
It works by doing an "up/down flush" (a dummy flush transaction
to do post-op wherever necessary) and then triggering
data self-heal on the file in the post-post-op hook of the
dummy flush transaction. This ensures that any writes
that come in during self-heal will wait until self-heal completes.
The up/down flush is also done when a subvolume goes down,
so that post-op is done on all subvolumes where pre-op was done.
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-inode-write.c')
-rw-r--r-- | xlators/cluster/afr/src/afr-inode-write.c | 179 |
1 files changed, 135 insertions, 44 deletions
diff --git a/xlators/cluster/afr/src/afr-inode-write.c b/xlators/cluster/afr/src/afr-inode-write.c index 7dcc06708..5f35aa26f 100644 --- a/xlators/cluster/afr/src/afr-inode-write.c +++ b/xlators/cluster/afr/src/afr-inode-write.c @@ -205,32 +205,79 @@ afr_writev_done (call_frame_t *frame, xlator_t *this) int +afr_do_writev (call_frame_t *frame, xlator_t *this) +{ + call_frame_t * transaction_frame = NULL; + afr_local_t * local = NULL; + + int op_ret = -1; + int op_errno = 0; + + local = frame->local; + + transaction_frame = copy_frame (frame); + if (!transaction_frame) { + gf_log (this->name, GF_LOG_ERROR, + "Out of memory."); + op_errno = ENOMEM; + goto out; + } + + transaction_frame->local = local; + frame->local = NULL; + + local->op = GF_FOP_WRITE; + + local->transaction.fop = afr_writev_wind; + local->transaction.done = afr_writev_done; + local->transaction.unwind = afr_writev_unwind; + + local->transaction.main_frame = frame; + if (local->fd->flags & O_APPEND) { + local->transaction.start = 0; + local->transaction.len = 0; + } else { + local->transaction.start = local->cont.writev.offset; + local->transaction.len = iov_length (local->cont.writev.vector, + local->cont.writev.count); + } + + afr_transaction (transaction_frame, this, AFR_DATA_TRANSACTION); + + op_ret = 0; +out: + if (op_ret == -1) { + if (transaction_frame) + AFR_STACK_DESTROY (transaction_frame); + AFR_STACK_UNWIND (writev, frame, op_ret, op_errno, NULL, NULL); + } + + return 0; +} + + +int afr_writev (call_frame_t *frame, xlator_t *this, fd_t *fd, struct iovec *vector, int32_t count, off_t offset, struct iobref *iobref) { afr_private_t * priv = NULL; afr_local_t * local = NULL; - call_frame_t *transaction_frame = NULL; int ret = -1; int op_ret = -1; int op_errno = 0; + uint64_t ctx; + afr_fd_ctx_t *fd_ctx = NULL; + VALIDATE_OR_GOTO (frame, out); VALIDATE_OR_GOTO (this, out); VALIDATE_OR_GOTO (this->private, out); priv = this->private; - transaction_frame = copy_frame (frame); - if (!transaction_frame) { - gf_log (this->name, GF_LOG_ERROR, - "Out of memory."); - goto out; - } - ALLOC_OR_GOTO (local, afr_local_t, out); ret = AFR_LOCAL_INIT (local, priv); @@ -239,37 +286,38 @@ afr_writev (call_frame_t *frame, xlator_t *this, fd_t *fd, goto out; } - transaction_frame->local = local; + frame->local = local; - local->op = GF_FOP_WRITE; local->cont.writev.vector = iov_dup (vector, count); local->cont.writev.count = count; local->cont.writev.offset = offset; local->cont.writev.ino = fd->inode->ino; local->cont.writev.iobref = iobref_ref (iobref); - local->transaction.fop = afr_writev_wind; - local->transaction.done = afr_writev_done; - local->transaction.unwind = afr_writev_unwind; - local->fd = fd_ref (fd); - local->transaction.main_frame = frame; - if (fd->flags & O_APPEND) { - local->transaction.start = 0; - local->transaction.len = 0; - } else { - local->transaction.start = offset; - local->transaction.len = iov_length (vector, count); - } + ret = fd_ctx_get (fd, this, &ctx); + if (ret < 0) { + goto out; + } - afr_transaction (transaction_frame, this, AFR_DATA_TRANSACTION); + fd_ctx = (afr_fd_ctx_t *)(long) ctx; + + if (fd_ctx->down_count < priv->down_count) { + local->up_down_flush_cbk = afr_do_writev; + afr_up_down_flush (frame, this, fd, AFR_CHILD_DOWN_FLUSH); + + } else if (fd_ctx->up_count < priv->up_count) { + local->up_down_flush_cbk = afr_do_writev; + afr_up_down_flush (frame, this, fd, AFR_CHILD_UP_FLUSH); + + } else { + afr_do_writev (frame, this); + } op_ret = 0; out: if (op_ret == -1) { - if (transaction_frame) - AFR_STACK_DESTROY (transaction_frame); AFR_STACK_UNWIND (writev, frame, op_ret, op_errno, NULL, NULL); } @@ -648,6 +696,52 @@ afr_ftruncate_done (call_frame_t *frame, xlator_t *this) int +afr_do_ftruncate (call_frame_t *frame, xlator_t *this) +{ + call_frame_t * transaction_frame = NULL; + afr_local_t * local = NULL; + + int op_ret = -1; + int op_errno = 0; + + local = frame->local; + + transaction_frame = copy_frame (frame); + if (!transaction_frame) { + gf_log (this->name, GF_LOG_ERROR, + "Out of memory."); + goto out; + } + + transaction_frame->local = local; + frame->local = NULL; + + local->op = GF_FOP_FTRUNCATE; + + local->transaction.fop = afr_ftruncate_wind; + local->transaction.done = afr_ftruncate_done; + local->transaction.unwind = afr_ftruncate_unwind; + + local->transaction.main_frame = frame; + + local->transaction.start = 0; + local->transaction.len = local->cont.ftruncate.offset; + + afr_transaction (transaction_frame, this, AFR_DATA_TRANSACTION); + + op_ret = 0; +out: + if (op_ret == -1) { + if (transaction_frame) + AFR_STACK_DESTROY (transaction_frame); + AFR_STACK_UNWIND (ftruncate, frame, op_ret, op_errno, NULL, NULL); + } + + return 0; +} + + +int afr_ftruncate (call_frame_t *frame, xlator_t *this, fd_t *fd, off_t offset) { @@ -660,19 +754,15 @@ afr_ftruncate (call_frame_t *frame, xlator_t *this, int op_ret = -1; int op_errno = 0; + uint64_t ctx; + afr_fd_ctx_t *fd_ctx = NULL; + VALIDATE_OR_GOTO (frame, out); VALIDATE_OR_GOTO (this, out); VALIDATE_OR_GOTO (this->private, out); priv = this->private; - transaction_frame = copy_frame (frame); - if (!transaction_frame) { - gf_log (this->name, GF_LOG_ERROR, - "Out of memory."); - goto out; - } - ALLOC_OR_GOTO (local, afr_local_t, out); ret = AFR_LOCAL_INIT (local, priv); @@ -681,25 +771,26 @@ afr_ftruncate (call_frame_t *frame, xlator_t *this, goto out; } - transaction_frame->local = local; - - local->op = GF_FOP_FTRUNCATE; - local->op_ret = -1; + frame->local = local; local->cont.ftruncate.offset = offset; local->cont.ftruncate.ino = fd->inode->ino; - local->transaction.fop = afr_ftruncate_wind; - local->transaction.done = afr_ftruncate_done; - local->transaction.unwind = afr_ftruncate_unwind; - local->fd = fd_ref (fd); - local->transaction.main_frame = frame; - local->transaction.start = 0; - local->transaction.len = offset; + ret = fd_ctx_get (fd, this, &ctx); + if (ret < 0) { + goto out; + } - afr_transaction (transaction_frame, this, AFR_DATA_TRANSACTION); + fd_ctx = (afr_fd_ctx_t *)(long) ctx; + + if (fd_ctx->down_count < priv->down_count) { + local->up_down_flush_cbk = afr_do_ftruncate; + afr_up_down_flush (frame, this, fd, AFR_CHILD_DOWN_FLUSH); + } else { + afr_do_ftruncate (frame, this); + } op_ret = 0; out: |