summaryrefslogtreecommitdiff
path: root/0189-features-shard-Fix-block-count-accounting-upon-trunc.patch
diff options
context:
space:
mode:
Diffstat (limited to '0189-features-shard-Fix-block-count-accounting-upon-trunc.patch')
-rw-r--r--0189-features-shard-Fix-block-count-accounting-upon-trunc.patch323
1 files changed, 323 insertions, 0 deletions
diff --git a/0189-features-shard-Fix-block-count-accounting-upon-trunc.patch b/0189-features-shard-Fix-block-count-accounting-upon-trunc.patch
new file mode 100644
index 0000000..bc07fad
--- /dev/null
+++ b/0189-features-shard-Fix-block-count-accounting-upon-trunc.patch
@@ -0,0 +1,323 @@
+From 369c5772a722b6e346ec8b41f992112785366778 Mon Sep 17 00:00:00 2001
+From: Krutika Dhananjay <kdhananj@redhat.com>
+Date: Wed, 8 May 2019 13:00:51 +0530
+Subject: [PATCH 189/192] features/shard: Fix block-count accounting upon
+ truncate to lower size
+
+ > Upstream: https://review.gluster.org/22681
+ > BUG: 1705884
+ > Change-Id: I9128a192e9bf8c3c3a959e96b7400879d03d7c53
+
+The way delta_blocks is computed in shard is incorrect, when a file
+is truncated to a lower size. The accounting only considers change
+in size of the last of the truncated shards.
+
+FIX:
+
+Get the block-count of each shard just before an unlink at posix in
+xdata. Their summation plus the change in size of last shard
+(from an actual truncate) is used to compute delta_blocks which is
+used in the xattrop for size update.
+
+Change-Id: I9128a192e9bf8c3c3a959e96b7400879d03d7c53
+updates: bz#1668001
+Signed-off-by: Krutika Dhananjay <kdhananj@redhat.com>
+Reviewed-on: https://code.engineering.redhat.com/gerrit/173477
+Tested-by: RHGS Build Bot <nigelb@redhat.com>
+Reviewed-by: Atin Mukherjee <amukherj@redhat.com>
+---
+ libglusterfs/src/glusterfs/glusterfs.h | 2 +
+ tests/bugs/shard/bug-1705884.t | 32 +++++++++++++++
+ xlators/features/shard/src/shard.c | 60 +++++++++++++++++++++++------
+ xlators/features/shard/src/shard.h | 2 +-
+ xlators/storage/posix/src/posix-entry-ops.c | 9 +++++
+ 5 files changed, 92 insertions(+), 13 deletions(-)
+ create mode 100644 tests/bugs/shard/bug-1705884.t
+
+diff --git a/libglusterfs/src/glusterfs/glusterfs.h b/libglusterfs/src/glusterfs/glusterfs.h
+index 516b497..9ec2365 100644
+--- a/libglusterfs/src/glusterfs/glusterfs.h
++++ b/libglusterfs/src/glusterfs/glusterfs.h
+@@ -328,6 +328,8 @@ enum gf_internal_fop_indicator {
+ #define GF_RESPONSE_LINK_COUNT_XDATA "gf_response_link_count"
+ #define GF_REQUEST_LINK_COUNT_XDATA "gf_request_link_count"
+
++#define GF_GET_FILE_BLOCK_COUNT "gf_get_file_block_count"
++
+ #define CTR_ATTACH_TIER_LOOKUP "ctr_attach_tier_lookup"
+
+ #define CLIENT_CMD_CONNECT "trusted.glusterfs.client-connect"
+diff --git a/tests/bugs/shard/bug-1705884.t b/tests/bugs/shard/bug-1705884.t
+new file mode 100644
+index 0000000..f6e5037
+--- /dev/null
++++ b/tests/bugs/shard/bug-1705884.t
+@@ -0,0 +1,32 @@
++#!/bin/bash
++
++. $(dirname $0)/../../include.rc
++. $(dirname $0)/../../volume.rc
++. $(dirname $0)/../../fallocate.rc
++
++cleanup
++
++require_fallocate -l 1m $M0/file
++
++TEST glusterd
++TEST pidof glusterd
++TEST $CLI volume create $V0 replica 3 $H0:$B0/${V0}{0,1,2}
++TEST $CLI volume set $V0 features.shard on
++TEST $CLI volume set $V0 performance.write-behind off
++TEST $CLI volume set $V0 performance.stat-prefetch off
++TEST $CLI volume start $V0
++
++TEST $GFS --volfile-id=$V0 --volfile-server=$H0 $M0
++
++TEST fallocate -l 200M $M0/foo
++EXPECT `echo "$(( ( 200 * 1024 * 1024 ) / 512 ))"` stat -c %b $M0/foo
++TEST truncate -s 0 $M0/foo
++EXPECT "0" stat -c %b $M0/foo
++TEST fallocate -l 100M $M0/foo
++EXPECT `echo "$(( ( 100 * 1024 * 1024 ) / 512 ))"` stat -c %b $M0/foo
++
++EXPECT_WITHIN $UMOUNT_TIMEOUT "Y" force_umount $M0
++TEST $CLI volume stop $V0
++TEST $CLI volume delete $V0
++
++cleanup
+diff --git a/xlators/features/shard/src/shard.c b/xlators/features/shard/src/shard.c
+index c1799ad..b248767 100644
+--- a/xlators/features/shard/src/shard.c
++++ b/xlators/features/shard/src/shard.c
+@@ -1135,6 +1135,7 @@ shard_update_file_size(call_frame_t *frame, xlator_t *this, fd_t *fd,
+ {
+ int ret = -1;
+ int64_t *size_attr = NULL;
++ int64_t delta_blocks = 0;
+ inode_t *inode = NULL;
+ shard_local_t *local = NULL;
+ dict_t *xattr_req = NULL;
+@@ -1156,13 +1157,13 @@ shard_update_file_size(call_frame_t *frame, xlator_t *this, fd_t *fd,
+
+ /* If both size and block count have not changed, then skip the xattrop.
+ */
+- if ((local->delta_size + local->hole_size == 0) &&
+- (local->delta_blocks == 0)) {
++ delta_blocks = GF_ATOMIC_GET(local->delta_blocks);
++ if ((local->delta_size + local->hole_size == 0) && (delta_blocks == 0)) {
+ goto out;
+ }
+
+ ret = shard_set_size_attrs(local->delta_size + local->hole_size,
+- local->delta_blocks, &size_attr);
++ delta_blocks, &size_attr);
+ if (ret) {
+ gf_msg(this->name, GF_LOG_ERROR, 0, SHARD_MSG_SIZE_SET_FAILED,
+ "Failed to set size attrs for %s", uuid_utoa(inode->gfid));
+@@ -1947,6 +1948,7 @@ shard_truncate_last_shard_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
+ dict_t *xdata)
+ {
+ inode_t *inode = NULL;
++ int64_t delta_blocks = 0;
+ shard_local_t *local = NULL;
+
+ local = frame->local;
+@@ -1967,14 +1969,15 @@ shard_truncate_last_shard_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
+ }
+
+ local->postbuf.ia_size = local->offset;
+- local->postbuf.ia_blocks -= (prebuf->ia_blocks - postbuf->ia_blocks);
+ /* Let the delta be negative. We want xattrop to do subtraction */
+ local->delta_size = local->postbuf.ia_size - local->prebuf.ia_size;
+- local->delta_blocks = postbuf->ia_blocks - prebuf->ia_blocks;
++ delta_blocks = GF_ATOMIC_ADD(local->delta_blocks,
++ postbuf->ia_blocks - prebuf->ia_blocks);
++ GF_ASSERT(delta_blocks <= 0);
++ local->postbuf.ia_blocks += delta_blocks;
+ local->hole_size = 0;
+
+- shard_inode_ctx_set(inode, this, postbuf, 0, SHARD_MASK_TIMES);
+-
++ shard_inode_ctx_set(inode, this, &local->postbuf, 0, SHARD_MASK_TIMES);
+ shard_update_file_size(frame, this, NULL, &local->loc,
+ shard_post_update_size_truncate_handler);
+ return 0;
+@@ -2034,8 +2037,10 @@ shard_truncate_htol_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
+ struct iatt *preparent, struct iatt *postparent,
+ dict_t *xdata)
+ {
++ int ret = 0;
+ int call_count = 0;
+ int shard_block_num = (long)cookie;
++ uint64_t block_count = 0;
+ shard_local_t *local = NULL;
+
+ local = frame->local;
+@@ -2045,6 +2050,16 @@ shard_truncate_htol_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
+ local->op_errno = op_errno;
+ goto done;
+ }
++ ret = dict_get_uint64(xdata, GF_GET_FILE_BLOCK_COUNT, &block_count);
++ if (!ret) {
++ GF_ATOMIC_SUB(local->delta_blocks, block_count);
++ } else {
++ /* dict_get failed possibly due to a heterogeneous cluster? */
++ gf_msg(this->name, GF_LOG_WARNING, 0, SHARD_MSG_DICT_OP_FAILED,
++ "Failed to get key %s from dict during truncate of gfid %s",
++ GF_GET_FILE_BLOCK_COUNT,
++ uuid_utoa(local->resolver_base_inode->gfid));
++ }
+
+ shard_unlink_block_inode(local, shard_block_num);
+ done:
+@@ -2074,6 +2089,7 @@ shard_truncate_htol(call_frame_t *frame, xlator_t *this, inode_t *inode)
+ gf_boolean_t wind_failed = _gf_false;
+ shard_local_t *local = NULL;
+ shard_priv_t *priv = NULL;
++ dict_t *xdata_req = NULL;
+
+ local = frame->local;
+ priv = this->private;
+@@ -2101,7 +2117,7 @@ shard_truncate_htol(call_frame_t *frame, xlator_t *this, inode_t *inode)
+ local->postbuf.ia_size = local->offset;
+ local->postbuf.ia_blocks = local->prebuf.ia_blocks;
+ local->delta_size = local->postbuf.ia_size - local->prebuf.ia_size;
+- local->delta_blocks = 0;
++ GF_ATOMIC_INIT(local->delta_blocks, 0);
+ local->hole_size = 0;
+ shard_update_file_size(frame, this, local->fd, &local->loc,
+ shard_post_update_size_truncate_handler);
+@@ -2110,6 +2126,21 @@ shard_truncate_htol(call_frame_t *frame, xlator_t *this, inode_t *inode)
+
+ local->call_count = call_count;
+ i = 1;
++ xdata_req = dict_new();
++ if (!xdata_req) {
++ shard_common_failure_unwind(local->fop, frame, -1, ENOMEM);
++ return 0;
++ }
++ ret = dict_set_uint64(xdata_req, GF_GET_FILE_BLOCK_COUNT, 8 * 8);
++ if (ret) {
++ gf_msg(this->name, GF_LOG_WARNING, 0, SHARD_MSG_DICT_OP_FAILED,
++ "Failed to set key %s into dict during truncate of %s",
++ GF_GET_FILE_BLOCK_COUNT,
++ uuid_utoa(local->resolver_base_inode->gfid));
++ dict_unref(xdata_req);
++ shard_common_failure_unwind(local->fop, frame, -1, ENOMEM);
++ return 0;
++ }
+
+ SHARD_SET_ROOT_FS_ID(frame, local);
+ while (cur_block <= last_block) {
+@@ -2148,7 +2179,7 @@ shard_truncate_htol(call_frame_t *frame, xlator_t *this, inode_t *inode)
+
+ STACK_WIND_COOKIE(frame, shard_truncate_htol_cbk,
+ (void *)(long)cur_block, FIRST_CHILD(this),
+- FIRST_CHILD(this)->fops->unlink, &loc, 0, NULL);
++ FIRST_CHILD(this)->fops->unlink, &loc, 0, xdata_req);
+ loc_wipe(&loc);
+ next:
+ i++;
+@@ -2156,6 +2187,7 @@ shard_truncate_htol(call_frame_t *frame, xlator_t *this, inode_t *inode)
+ if (!--call_count)
+ break;
+ }
++ dict_unref(xdata_req);
+ return 0;
+ }
+
+@@ -2608,7 +2640,7 @@ shard_post_lookup_truncate_handler(call_frame_t *frame, xlator_t *this)
+ */
+ local->hole_size = local->offset - local->prebuf.ia_size;
+ local->delta_size = 0;
+- local->delta_blocks = 0;
++ GF_ATOMIC_INIT(local->delta_blocks, 0);
+ local->postbuf.ia_size = local->offset;
+ tmp_stbuf.ia_size = local->offset;
+ shard_inode_ctx_set(local->loc.inode, this, &tmp_stbuf, 0,
+@@ -2624,7 +2656,7 @@ shard_post_lookup_truncate_handler(call_frame_t *frame, xlator_t *this)
+ */
+ local->hole_size = 0;
+ local->delta_size = (local->offset - local->prebuf.ia_size);
+- local->delta_blocks = 0;
++ GF_ATOMIC_INIT(local->delta_blocks, 0);
+ tmp_stbuf.ia_size = local->offset;
+ shard_inode_ctx_set(local->loc.inode, this, &tmp_stbuf, 0,
+ SHARD_INODE_WRITE_MASK);
+@@ -2680,6 +2712,7 @@ shard_truncate(call_frame_t *frame, xlator_t *this, loc_t *loc, off_t offset,
+ if (!local->xattr_req)
+ goto err;
+ local->resolver_base_inode = loc->inode;
++ GF_ATOMIC_INIT(local->delta_blocks, 0);
+
+ shard_lookup_base_file(frame, this, &local->loc,
+ shard_post_lookup_truncate_handler);
+@@ -2735,6 +2768,7 @@ shard_ftruncate(call_frame_t *frame, xlator_t *this, fd_t *fd, off_t offset,
+ local->loc.inode = inode_ref(fd->inode);
+ gf_uuid_copy(local->loc.gfid, fd->inode->gfid);
+ local->resolver_base_inode = fd->inode;
++ GF_ATOMIC_INIT(local->delta_blocks, 0);
+
+ shard_lookup_base_file(frame, this, &local->loc,
+ shard_post_lookup_truncate_handler);
+@@ -5295,7 +5329,8 @@ shard_common_inode_write_do_cbk(call_frame_t *frame, void *cookie,
+ local->op_errno = op_errno;
+ } else {
+ local->written_size += op_ret;
+- local->delta_blocks += (post->ia_blocks - pre->ia_blocks);
++ GF_ATOMIC_ADD(local->delta_blocks,
++ post->ia_blocks - pre->ia_blocks);
+ local->delta_size += (post->ia_size - pre->ia_size);
+ shard_inode_ctx_set(local->fd->inode, this, post, 0,
+ SHARD_MASK_TIMES);
+@@ -6599,6 +6634,7 @@ shard_common_inode_write_begin(call_frame_t *frame, xlator_t *this,
+ local->fd = fd_ref(fd);
+ local->block_size = block_size;
+ local->resolver_base_inode = local->fd->inode;
++ GF_ATOMIC_INIT(local->delta_blocks, 0);
+
+ local->loc.inode = inode_ref(fd->inode);
+ gf_uuid_copy(local->loc.gfid, fd->inode->gfid);
+diff --git a/xlators/features/shard/src/shard.h b/xlators/features/shard/src/shard.h
+index cd6a663..04abd62 100644
+--- a/xlators/features/shard/src/shard.h
++++ b/xlators/features/shard/src/shard.h
+@@ -275,7 +275,7 @@ typedef struct shard_local {
+ size_t req_size;
+ size_t readdir_size;
+ int64_t delta_size;
+- int64_t delta_blocks;
++ gf_atomic_t delta_blocks;
+ loc_t loc;
+ loc_t dot_shard_loc;
+ loc_t dot_shard_rm_loc;
+diff --git a/xlators/storage/posix/src/posix-entry-ops.c b/xlators/storage/posix/src/posix-entry-ops.c
+index b24a052..34ee2b8 100644
+--- a/xlators/storage/posix/src/posix-entry-ops.c
++++ b/xlators/storage/posix/src/posix-entry-ops.c
+@@ -1071,6 +1071,7 @@ posix_unlink(call_frame_t *frame, xlator_t *this, loc_t *loc, int xflag,
+ char *real_path = NULL;
+ char *par_path = NULL;
+ int32_t fd = -1;
++ int ret = -1;
+ struct iatt stbuf = {
+ 0,
+ };
+@@ -1235,6 +1236,14 @@ posix_unlink(call_frame_t *frame, xlator_t *this, loc_t *loc, int xflag,
+ goto out;
+ }
+
++ if (xdata && dict_get(xdata, GF_GET_FILE_BLOCK_COUNT)) {
++ ret = dict_set_uint64(unwind_dict, GF_GET_FILE_BLOCK_COUNT,
++ stbuf.ia_blocks);
++ if (ret)
++ gf_msg(this->name, GF_LOG_WARNING, 0, P_MSG_SET_XDATA_FAIL,
++ "Failed to set %s in rsp dict", GF_GET_FILE_BLOCK_COUNT);
++ }
++
+ if (xdata && dict_get(xdata, GET_LINK_COUNT))
+ get_link_count = _gf_true;
+ op_ret = posix_unlink_gfid_handle_and_entry(frame, this, real_path, &stbuf,
+--
+1.8.3.1
+