You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
323 lines
13 KiB
323 lines
13 KiB
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 |
|
|
|
|