From 9f670a342ffed3eee7cb91a67dcc2f2a27600983 Mon Sep 17 00:00:00 2001 From: karthik-us Date: Fri, 23 Feb 2018 15:12:19 +0530 Subject: [PATCH 191/201] cluster/afr: Make afr_fsync a transaction Upstream patch: https://review.gluster.org/#/c/19621/ Change-Id: I713401feb96393f668efb074f2d5b870d19e6fda BUG: 1552425 Signed-off-by: karthik-us Reviewed-on: https://code.engineering.redhat.com/gerrit/131942 Tested-by: RHGS Build Bot Reviewed-by: Pranith Kumar Karampuri --- xlators/cluster/afr/src/afr-common.c | 163 ------------------------------ xlators/cluster/afr/src/afr-inode-write.c | 108 ++++++++++++++++++++ xlators/cluster/afr/src/afr-inode-write.h | 4 + xlators/cluster/afr/src/afr.c | 2 +- xlators/cluster/afr/src/afr.h | 4 + 5 files changed, 117 insertions(+), 164 deletions(-) diff --git a/xlators/cluster/afr/src/afr-common.c b/xlators/cluster/afr/src/afr-common.c index 855e568..a790402 100644 --- a/xlators/cluster/afr/src/afr-common.c +++ b/xlators/cluster/afr/src/afr-common.c @@ -3435,169 +3435,6 @@ out: return 0; } -/* }}} */ - - -/* {{{ fsync */ - -int -afr_fsync_unwind_cbk (call_frame_t *frame, void *cookie, xlator_t *this, - int32_t op_ret, int32_t op_errno, struct iatt *prebuf, - struct iatt *postbuf, dict_t *xdata) -{ - AFR_STACK_UNWIND (fsync, frame, op_ret, op_errno, prebuf, postbuf, - xdata); - return 0; -} - -int -afr_fsync_cbk (call_frame_t *frame, void *cookie, xlator_t *this, - int32_t op_ret, int32_t op_errno, struct iatt *prebuf, - struct iatt *postbuf, dict_t *xdata) -{ - afr_local_t *local = NULL; - afr_private_t *priv = NULL; - int i = 0; - int call_count = -1; - int child_index = (long) cookie; - int read_subvol = 0; - call_stub_t *stub = NULL; - - local = frame->local; - priv = this->private; - - LOCK (&frame->lock); - { - local->replies[child_index].valid = 1; - local->replies[child_index].op_ret = op_ret; - local->replies[child_index].op_errno = op_errno; - if (op_ret == 0) { - if (prebuf) - local->replies[child_index].prestat = *prebuf; - if (postbuf) - local->replies[child_index].poststat = *postbuf; - if (xdata) - local->replies[child_index].xdata = - dict_ref (xdata); - } - } - UNLOCK (&frame->lock); - - call_count = afr_frame_return (frame); - - if (call_count == 0) { - local->op_ret = -1; - local->op_errno = afr_final_errno (local, priv); - read_subvol = afr_data_subvol_get (local->inode, this, NULL, - local->readable, NULL, NULL); - /* Pick a reply that is valid and readable, with a preference - * given to read_subvol. */ - for (i = 0; i < priv->child_count; i++) { - if (!local->replies[i].valid) - continue; - if (local->replies[i].op_ret != 0) - continue; - if (!local->readable[i]) - continue; - local->op_ret = local->replies[i].op_ret; - local->op_errno = local->replies[i].op_errno; - local->cont.inode_wfop.prebuf = - local->replies[i].prestat; - local->cont.inode_wfop.postbuf = - local->replies[i].poststat; - if (local->replies[i].xdata) { - if (local->xdata_rsp) - dict_unref (local->xdata_rsp); - local->xdata_rsp = - dict_ref (local->replies[i].xdata); - } - if (i == read_subvol) - break; - } - - /* Make a stub out of the frame, and register it - with the waking up post-op. When the call-stub resumes, - we are guaranteed that there was no post-op pending - (i.e changelogs were unset in the server). This is an - essential "guarantee", that fsync() returns only after - completely finishing EVERYTHING, including the delayed - post-op. This guarantee is expected by FUSE graph switching - for example. - */ - stub = fop_fsync_cbk_stub (frame, afr_fsync_unwind_cbk, - local->op_ret, local->op_errno, - &local->cont.inode_wfop.prebuf, - &local->cont.inode_wfop.postbuf, - local->xdata_rsp); - if (!stub) { - AFR_STACK_UNWIND (fsync, frame, -1, ENOMEM, 0, 0, 0); - return 0; - } - - /* If no new unstable writes happened between the - time we cleared the unstable write witness flag in afr_fsync - and now, calling afr_delayed_changelog_wake_up() should - wake up and skip over the fsync phase and go straight to - afr_changelog_post_op_now() - */ - afr_delayed_changelog_wake_resume (this, local->fd, stub); - } - - return 0; -} - - -int -afr_fsync (call_frame_t *frame, xlator_t *this, fd_t *fd, int32_t datasync, - dict_t *xdata) -{ - afr_private_t *priv = NULL; - afr_local_t *local = NULL; - int i = 0; - int32_t call_count = 0; - int32_t op_errno = ENOMEM; - - priv = this->private; - - local = AFR_FRAME_INIT (frame, op_errno); - if (!local) - goto out; - - local->op = GF_FOP_FSYNC; - if (!afr_is_consistent_io_possible (local, priv, &op_errno)) - goto out; - - local->fd = fd_ref (fd); - - if (afr_fd_has_witnessed_unstable_write (this, fd)) { - /* don't care. we only wanted to CLEAR the bit */ - } - - local->inode = inode_ref (fd->inode); - - call_count = local->call_count; - for (i = 0; i < priv->child_count; i++) { - if (local->child_up[i]) { - STACK_WIND_COOKIE (frame, afr_fsync_cbk, - (void *) (long) i, - priv->children[i], - priv->children[i]->fops->fsync, - fd, datasync, xdata); - if (!--call_count) - break; - } - } - - return 0; -out: - AFR_STACK_UNWIND (fsync, frame, -1, op_errno, NULL, NULL, NULL); - - return 0; -} - -/* }}} */ - -/* {{{ fsync */ int afr_fsyncdir_cbk (call_frame_t *frame, void *cookie, xlator_t *this, diff --git a/xlators/cluster/afr/src/afr-inode-write.c b/xlators/cluster/afr/src/afr-inode-write.c index f0231b7..0e50443 100644 --- a/xlators/cluster/afr/src/afr-inode-write.c +++ b/xlators/cluster/afr/src/afr-inode-write.c @@ -2539,3 +2539,111 @@ out: AFR_STACK_UNWIND (fxattrop, frame, -1, op_errno, NULL, NULL); return 0; } + + +int +afr_fsync_unwind (call_frame_t *frame, xlator_t *this) +{ + afr_local_t *local = NULL; + call_frame_t *main_frame = NULL; + + local = frame->local; + + main_frame = afr_transaction_detach_fop_frame (frame); + if (!main_frame) + return 0; + + AFR_STACK_UNWIND (fsync, main_frame, local->op_ret, local->op_errno, + &local->cont.inode_wfop.prebuf, + &local->cont.inode_wfop.postbuf, local->xdata_rsp); + + return 0; +} + + +int +afr_fsync_wind_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, struct iatt *prebuf, + struct iatt *postbuf, dict_t *xdata) +{ + return __afr_inode_write_cbk (frame, cookie, this, op_ret, op_errno, + prebuf, postbuf, NULL, xdata); +} + + +int +afr_fsync_wind (call_frame_t *frame, xlator_t *this, int subvol) +{ + afr_local_t *local = NULL; + afr_private_t *priv = NULL; + + local = frame->local; + priv = this->private; + + STACK_WIND_COOKIE (frame, afr_fsync_wind_cbk, (void *)(long) subvol, + priv->children[subvol], + priv->children[subvol]->fops->fsync, + local->fd, local->cont.fsync.datasync, + local->xdata_req); + return 0; +} + +int +afr_fsync (call_frame_t *frame, xlator_t *this, fd_t *fd, int32_t datasync, + dict_t *xdata) +{ + afr_local_t *local = NULL; + call_frame_t *transaction_frame = NULL; + int ret = -1; + int32_t op_errno = ENOMEM; + + transaction_frame = copy_frame (frame); + if (!transaction_frame) + goto out; + + local = AFR_FRAME_INIT (transaction_frame, op_errno); + if (!local) + goto out; + + if (xdata) + local->xdata_req = dict_copy_with_ref (xdata, NULL); + else + local->xdata_req = dict_new (); + + if (!local->xdata_req) + goto out; + + local->fd = fd_ref (fd); + ret = afr_set_inode_local (this, local, fd->inode); + if (ret) + goto out; + + local->op = GF_FOP_FSYNC; + local->cont.fsync.datasync = datasync; + + if (afr_fd_has_witnessed_unstable_write (this, fd)) { + /* don't care. we only wanted to CLEAR the bit */ + } + + local->transaction.wind = afr_fsync_wind; + local->transaction.fop = __afr_txn_write_fop; + local->transaction.done = __afr_txn_write_done; + local->transaction.unwind = afr_fsync_unwind; + + local->transaction.main_frame = frame; + + ret = afr_transaction (transaction_frame, this, AFR_DATA_TRANSACTION); + if (ret < 0) { + op_errno = -ret; + goto out; + } + + return 0; +out: + if (transaction_frame) + AFR_STACK_DESTROY (transaction_frame); + + AFR_STACK_UNWIND (fsync, frame, -1, op_errno, NULL, NULL, NULL); + + return 0; +} diff --git a/xlators/cluster/afr/src/afr-inode-write.h b/xlators/cluster/afr/src/afr-inode-write.h index e174cc2..1e8bb5c 100644 --- a/xlators/cluster/afr/src/afr-inode-write.h +++ b/xlators/cluster/afr/src/afr-inode-write.h @@ -87,4 +87,8 @@ afr_xattrop (call_frame_t *frame, xlator_t *this, loc_t *loc, int32_t afr_fxattrop (call_frame_t *frame, xlator_t *this, fd_t *fd, gf_xattrop_flags_t optype, dict_t *xattr, dict_t *xdata); + +int +afr_fsync (call_frame_t *frame, xlator_t *this, fd_t *fd, int32_t datasync, + dict_t *xdata); #endif /* __INODE_WRITE_H__ */ diff --git a/xlators/cluster/afr/src/afr.c b/xlators/cluster/afr/src/afr.c index 9493fbb..aa48e76 100644 --- a/xlators/cluster/afr/src/afr.c +++ b/xlators/cluster/afr/src/afr.c @@ -664,7 +664,6 @@ struct xlator_fops fops = { .lk = afr_lk, .flush = afr_flush, .statfs = afr_statfs, - .fsync = afr_fsync, .fsyncdir = afr_fsyncdir, .inodelk = afr_inodelk, .finodelk = afr_finodelk, @@ -696,6 +695,7 @@ struct xlator_fops fops = { .zerofill = afr_zerofill, .xattrop = afr_xattrop, .fxattrop = afr_fxattrop, + .fsync = afr_fsync, /*inode open*/ .opendir = afr_opendir, diff --git a/xlators/cluster/afr/src/afr.h b/xlators/cluster/afr/src/afr.h index b6f5388..11278fb 100644 --- a/xlators/cluster/afr/src/afr.h +++ b/xlators/cluster/afr/src/afr.h @@ -725,6 +725,10 @@ typedef struct _afr_local { gf_seek_what_t what; } seek; + struct { + int32_t datasync; + } fsync; + } cont; struct { -- 1.8.3.1