diff options
author | Krutika Dhananjay <kdhananj@redhat.com> | 2015-06-22 17:06:07 +0530 |
---|---|---|
committer | Pranith Kumar Karampuri <pkarampu@redhat.com> | 2015-06-26 22:40:26 -0700 |
commit | f5f5cef19e2afa1e2bcee896269e004353d3180f (patch) | |
tree | 0840b05de951c29caa53f4c9008eb9b6a997ed73 /xlators/storage | |
parent | 43aea2da863d94079dbf4dfceabee41a0be67ef7 (diff) |
storage/posix: Introduce flag instructing posix to perform prestat, writev and poststat atomically
Change-Id: I9b52ddaed4e306e9a49f39c86450c94bea843a7b
BUG: 1233617
Signed-off-by: Krutika Dhananjay <kdhananj@redhat.com>
Reviewed-on: http://review.gluster.org/11345
Tested-by: NetBSD Build System <jenkins@build.gluster.org>
Tested-by: Gluster Build System <jenkins@build.gluster.com>
Reviewed-by: Pranith Kumar Karampuri <pkarampu@redhat.com>
Diffstat (limited to 'xlators/storage')
-rw-r--r-- | xlators/storage/posix/src/posix.c | 95 |
1 files changed, 58 insertions, 37 deletions
diff --git a/xlators/storage/posix/src/posix.c b/xlators/storage/posix/src/posix.c index 046ec90ea00..5e9dbf7ee5c 100644 --- a/xlators/storage/posix/src/posix.c +++ b/xlators/storage/posix/src/posix.c @@ -2825,6 +2825,8 @@ posix_writev (call_frame_t *frame, xlator_t *this, fd_t *fd, dict_t *rsp_xdata = NULL; int is_append = 0; gf_boolean_t locked = _gf_false; + gf_boolean_t write_append = _gf_false; + gf_boolean_t update_atomic = _gf_false; VALIDATE_OR_GOTO (frame, out); VALIDATE_OR_GOTO (this, out); @@ -2846,16 +2848,32 @@ posix_writev (call_frame_t *frame, xlator_t *this, fd_t *fd, _fd = pfd->fd; - if (xdata && dict_get (xdata, GLUSTERFS_WRITE_IS_APPEND)) { - /* The write_is_append check and write must happen - atomically. Else another write can overtake this - write after the check and get written earlier. + if (xdata) { + if (dict_get (xdata, GLUSTERFS_WRITE_IS_APPEND)) + write_append = _gf_true; + if (dict_get (xdata, GLUSTERFS_WRITE_UPDATE_ATOMIC)) + update_atomic = _gf_true; + } - So lock before preop-stat and unlock after write. - */ + /* The write_is_append check and write must happen + atomically. Else another write can overtake this + write after the check and get written earlier. + + So lock before preop-stat and unlock after write. + */ + + /* + * The update_atomic option is to instruct posix to do prestat, + * write and poststat atomically. This is to prevent any modification to + * ia_size and ia_blocks until poststat and the diff in their values + * between pre and poststat could be of use for some translators (shard + * as of today). + */ + + if (write_append || update_atomic) { locked = _gf_true; LOCK(&fd->inode->lock); - } + } op_ret = posix_fdstat (this, _fd, &preop); if (op_ret == -1) { @@ -2865,7 +2883,7 @@ posix_writev (call_frame_t *frame, xlator_t *this, fd_t *fd, goto out; } - if (locked) { + if (locked && write_append) { if (preop.ia_size == offset || (fd->flags & O_APPEND)) is_append = 1; } @@ -2873,7 +2891,7 @@ posix_writev (call_frame_t *frame, xlator_t *this, fd_t *fd, op_ret = __posix_writev (_fd, vector, count, offset, (pfd->flags & O_DIRECT)); - if (locked) { + if (locked && (!update_atomic)) { UNLOCK (&fd->inode->lock); locked = _gf_false; } @@ -2887,43 +2905,46 @@ posix_writev (call_frame_t *frame, xlator_t *this, fd_t *fd, goto out; } - LOCK (&priv->lock); - { - priv->write_value += op_ret; - } - UNLOCK (&priv->lock); + rsp_xdata = _fill_writev_xdata (fd, xdata, this, is_append); + /* writev successful, we also need to get the stat of + * the file we wrote to + */ - if (op_ret >= 0) { - rsp_xdata = _fill_writev_xdata (fd, xdata, this, is_append); - /* wiretv successful, we also need to get the stat of - * the file we wrote to - */ + ret = posix_fdstat (this, _fd, &postop); + if (ret == -1) { + op_ret = -1; + op_errno = errno; + gf_msg (this->name, GF_LOG_ERROR, errno, + P_MSG_FSTAT_FAILED, + "post-operation fstat failed on fd=%p", + fd); + goto out; + } - if (flags & (O_SYNC|O_DSYNC)) { - ret = fsync (_fd); - if (ret) { - gf_msg (this->name, GF_LOG_ERROR, errno, - P_MSG_WRITEV_FAILED, - "fsync() in writev on fd %d failed", - _fd); - op_ret = -1; - op_errno = errno; - goto out; - } - } + if (locked) { + UNLOCK (&fd->inode->lock); + locked = _gf_false; + } - ret = posix_fdstat (this, _fd, &postop); - if (ret == -1) { + if (flags & (O_SYNC|O_DSYNC)) { + ret = fsync (_fd); + if (ret) { + gf_msg (this->name, GF_LOG_ERROR, errno, + P_MSG_WRITEV_FAILED, + "fsync() in writev on fd %d failed", + _fd); op_ret = -1; op_errno = errno; - gf_msg (this->name, GF_LOG_ERROR, errno, - P_MSG_FSTAT_FAILED, - "post-operation fstat failed on fd=%p", - fd); goto out; } } + LOCK (&priv->lock); + { + priv->write_value += op_ret; + } + UNLOCK (&priv->lock); + out: if (locked) { |