summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--libglusterfs/src/glusterfs/glusterfs.h2
-rw-r--r--tests/bugs/shard/bug-1705884.t32
-rw-r--r--xlators/features/shard/src/shard.c60
-rw-r--r--xlators/features/shard/src/shard.h2
-rw-r--r--xlators/storage/posix/src/posix-entry-ops.c9
5 files changed, 92 insertions, 13 deletions
diff --git a/libglusterfs/src/glusterfs/glusterfs.h b/libglusterfs/src/glusterfs/glusterfs.h
index 4e5669c6dae..930d83cdfe6 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 00000000000..f6e50376a58
--- /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 b8f5a31742e..2249cefc5ab 100644
--- a/xlators/features/shard/src/shard.c
+++ b/xlators/features/shard/src/shard.c
@@ -1137,6 +1137,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;
@@ -1158,13 +1159,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));
@@ -1949,6 +1950,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;
@@ -1969,14 +1971,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;
@@ -2035,8 +2038,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;
@@ -2046,6 +2051,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:
@@ -2075,6 +2090,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;
@@ -2102,7 +2118,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);
@@ -2111,6 +2127,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) {
@@ -2149,7 +2180,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++;
@@ -2157,6 +2188,7 @@ shard_truncate_htol(call_frame_t *frame, xlator_t *this, inode_t *inode)
if (!--call_count)
break;
}
+ dict_unref(xdata_req);
return 0;
}
@@ -2609,7 +2641,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,
@@ -2625,7 +2657,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);
@@ -2681,6 +2713,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);
@@ -2736,6 +2769,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);
@@ -5296,7 +5330,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);
@@ -6600,6 +6635,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 cd6a663c03b..04abd62c21c 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 240f237a39a..0b612dcc99c 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,