diff options
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.patch | 323 |
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 + |