From 641b3a9164227db52df1aab05795c90d06b315f2 Mon Sep 17 00:00:00 2001 From: Ravishankar N Date: Wed, 21 Oct 2015 21:05:46 +0530 Subject: afr: write zeros to sink for non-sparse files Problem: If a file is created with zeroes ('dd', 'fallocate' etc.) when a brick is down, the self-heal does not write the zeroes to the sink after it comes up. Consequenty, there is a mismatch in disk-usage amongst the bricks of the replica. Fix: If we definitely know that the file is not sparse, then write the zeroes to the sink even if the checksums match. Change-Id: Ic739b3da5dbf47d99801c0e1743bb13aeb3af864 BUG: 1272460 Signed-off-by: Ravishankar N Reviewed-on: http://review.gluster.org/12371 Reviewed-by: Pranith Kumar Karampuri Tested-by: Gluster Build System --- xlators/storage/posix/src/posix.c | 43 +++++++++++++++++++++++++++++++-------- 1 file changed, 35 insertions(+), 8 deletions(-) (limited to 'xlators/storage/posix') diff --git a/xlators/storage/posix/src/posix.c b/xlators/storage/posix/src/posix.c index bc4e4904b74..b544e3739c6 100644 --- a/xlators/storage/posix/src/posix.c +++ b/xlators/storage/posix/src/posix.c @@ -5895,9 +5895,13 @@ posix_rchecksum (call_frame_t *frame, xlator_t *this, int op_ret = -1; int op_errno = 0; int ret = 0; + ssize_t bytes_read = 0; int32_t weak_checksum = 0; + int32_t zerofillcheck = 0; unsigned char strong_checksum[MD5_DIGEST_LENGTH] = {0}; struct posix_private *priv = NULL; + dict_t *rsp_xdata = NULL; + gf_boolean_t buf_has_zeroes = _gf_false; VALIDATE_OR_GOTO (frame, out); VALIDATE_OR_GOTO (this, out); @@ -5912,6 +5916,12 @@ posix_rchecksum (call_frame_t *frame, xlator_t *this, goto out; } + rsp_xdata = dict_new(); + if (!rsp_xdata) { + op_errno = ENOMEM; + goto out; + } + ret = posix_fd_ctx_get (fd, this, &pfd); if (ret < 0) { gf_msg (this->name, GF_LOG_WARNING, -ret, P_MSG_PFD_NULL, @@ -5927,12 +5937,12 @@ posix_rchecksum (call_frame_t *frame, xlator_t *this, if (priv->aio_capable && priv->aio_init_done) __posix_fd_set_odirect (fd, pfd, 0, offset, len); - ret = pread (_fd, buf, len, offset); - if (ret < 0) { + bytes_read = pread (_fd, buf, len, offset); + if (bytes_read < 0) { gf_msg (this->name, GF_LOG_WARNING, errno, P_MSG_PREAD_FAILED, - "pread of %d bytes returned %d ", - len, ret); + "pread of %d bytes returned %ld ", + len, bytes_read); op_errno = errno; } @@ -5940,17 +5950,34 @@ posix_rchecksum (call_frame_t *frame, xlator_t *this, } UNLOCK (&fd->lock); - if (ret < 0) + if (bytes_read < 0) goto out; + if (xdata && dict_get_int32 (xdata, "check-zero-filled", + &zerofillcheck) == 0) { + buf_has_zeroes = (mem_0filled (buf, bytes_read)) ? _gf_false : + _gf_true; + ret = dict_set_uint32 (rsp_xdata, "buf-has-zeroes", + buf_has_zeroes); + if (ret) { + gf_msg (this->name, GF_LOG_WARNING, -ret, + P_MSG_DICT_SET_FAILED, "%s: Failed to set " + "dictionary value for key: %s", + uuid_utoa (fd->inode->gfid), "buf-has-zeroes"); + op_errno = -ret; + goto out; + } + } weak_checksum = gf_rsync_weak_checksum ((unsigned char *) buf, (size_t) ret); - gf_rsync_strong_checksum ((unsigned char *) buf, (size_t) ret, (unsigned char *) strong_checksum); + gf_rsync_strong_checksum ((unsigned char *) buf, (size_t) bytes_read, + (unsigned char *) strong_checksum); op_ret = 0; out: STACK_UNWIND_STRICT (rchecksum, frame, op_ret, op_errno, - weak_checksum, strong_checksum, NULL); - + weak_checksum, strong_checksum, rsp_xdata); + if (rsp_xdata) + dict_unref (rsp_xdata); GF_FREE (alloc_buf); return 0; -- cgit