diff options
| author | Krutika Dhananjay <kdhananj@redhat.com> | 2015-06-22 17:06:07 +0530 | 
|---|---|---|
| committer | Pranith Kumar Karampuri <pkarampu@redhat.com> | 2015-06-27 04:03:52 -0700 | 
| commit | ea1039c177ec781506fdae01132a7a876620693f (patch) | |
| tree | a59b7da6252ed6531a9d67a5bba6898b14624c4b /xlators | |
| parent | 6800068bb94137e25e2cab9cf5f999f05461c7a1 (diff) | |
storage/posix: Introduce flag instructing posix to perform prestat, writev and poststat atomically
        Backport of: http://review.gluster.org/11345
Change-Id: I0d7e3a851c744777083974ec4cdb01b08c23727b
BUG: 1236271
Signed-off-by: Krutika Dhananjay <kdhananj@redhat.com>
Reviewed-on: http://review.gluster.org/11439
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')
| -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 42b1d0f112f..008fd004cdb 100644 --- a/xlators/storage/posix/src/posix.c +++ b/xlators/storage/posix/src/posix.c @@ -2830,6 +2830,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); @@ -2851,16 +2853,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) { @@ -2870,7 +2888,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;  	} @@ -2878,7 +2896,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;  	} @@ -2892,43 +2910,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) {  | 
