diff options
-rw-r--r-- | tests/bugs/shard/bug-1250855.t | 34 | ||||
-rw-r--r-- | xlators/features/shard/src/shard.c | 71 |
2 files changed, 79 insertions, 26 deletions
diff --git a/tests/bugs/shard/bug-1250855.t b/tests/bugs/shard/bug-1250855.t new file mode 100644 index 00000000000..b8bc3b42513 --- /dev/null +++ b/tests/bugs/shard/bug-1250855.t @@ -0,0 +1,34 @@ +#!/bin/bash + +. $(dirname $0)/../../include.rc + +cleanup; + +TESTS_EXPECTED_IN_LOOP=40 + +TEST glusterd +TEST pidof glusterd +TEST $CLI volume create $V0 $H0:$B0/${V0}{0,1} +TEST $CLI volume start $V0 + +TEST $GFS --volfile-id=$V0 --volfile-server=$H0 $M0 +TEST mkdir $M0/dir + +for i in {1..20}; do + TEST_IN_LOOP touch $M0/dir/$i; +done + +TEST $CLI volume set $V0 features.shard on + +TEST ls $M0 +TEST ls $M0/dir + +for i in {1..10}; do + TEST_IN_LOOP mv $M0/dir/$i $M0/dir/$i-sharded; +done + +for i in {11..20}; do + TEST_IN_LOOP unlink $M0/dir/$i; +done + +cleanup; diff --git a/xlators/features/shard/src/shard.c b/xlators/features/shard/src/shard.c index 8c9f9f8978e..52b95472ba7 100644 --- a/xlators/features/shard/src/shard.c +++ b/xlators/features/shard/src/shard.c @@ -550,18 +550,35 @@ err: return 0; } -int -shard_lookup_cbk (call_frame_t *frame, void *cookie, xlator_t *this, - int32_t op_ret, int32_t op_errno, inode_t *inode, - struct iatt *buf, dict_t *xdata, struct iatt *postparent) +static void +shard_inode_ctx_set_if_absent (inode_t *inode, xlator_t *this, dict_t *xdata, + struct iatt *buf) { int ret = 0; uint64_t size = 0; void *bsize = NULL; - void *size_attr = NULL; shard_inode_ctx_t ctx_tmp = {0,}; - uint64_t size_array[4]; + if (shard_inode_ctx_get_block_size (inode, this, &size)) { + ret = dict_get_ptr (xdata, GF_XATTR_SHARD_BLOCK_SIZE, &bsize); + if (!ret) { + ctx_tmp.block_size = ntoh64 (*((uint64_t *)bsize)); + ctx_tmp.mode = st_mode_from_ia (buf->ia_prot, + buf->ia_type); + ctx_tmp.rdev = buf->ia_rdev; + } + ret = shard_inode_ctx_set_all (inode, this, &ctx_tmp); + if (ret) + gf_log (this->name, GF_LOG_WARNING, "Failed to set " + "inode ctx for %s", uuid_utoa (buf->ia_gfid)); + } +} + +int +shard_lookup_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, inode_t *inode, + struct iatt *buf, dict_t *xdata, struct iatt *postparent) +{ if (op_ret < 0) goto unwind; @@ -576,31 +593,15 @@ shard_lookup_cbk (call_frame_t *frame, void *cookie, xlator_t *this, * (which are anyway don't cares) in inode ctx. Since @ctx_tmp is * already initialised to all zeroes, nothing more needs to be done. */ - if (shard_inode_ctx_get_block_size (inode, this, &size)) { - ret = dict_get_ptr (xdata, GF_XATTR_SHARD_BLOCK_SIZE, &bsize); - if (!ret) { - ctx_tmp.block_size = ntoh64 (*((uint64_t *)bsize)); - ctx_tmp.mode = st_mode_from_ia (buf->ia_prot, - buf->ia_type); - ctx_tmp.rdev = buf->ia_rdev; - } - ret = shard_inode_ctx_set_all (inode, this, &ctx_tmp); - if (ret) - gf_log (this->name, GF_LOG_WARNING, "Failed to set " - "inode ctx for %s", uuid_utoa (buf->ia_gfid)); - } + + (void) shard_inode_ctx_set_if_absent (inode, this, xdata, buf); /* Also, if the file is sharded, get the file size and block cnt xattr, * and store them in the stbuf appropriately. */ - ret = dict_get_ptr (xdata, GF_XATTR_SHARD_FILE_SIZE, &size_attr); - if (!ret) { - memcpy (size_array, size_attr, sizeof (size_array)); - - buf->ia_size = ntoh64 (size_array[0]); - buf->ia_blocks = ntoh64 (size_array[2]); - } + if (dict_get (xdata, GF_XATTR_SHARD_FILE_SIZE)) + shard_modify_size_and_block_count (buf, xdata); unwind: SHARD_STACK_UNWIND (lookup, frame, op_ret, op_errno, inode, buf, @@ -3403,6 +3404,12 @@ shard_readdir_cbk (call_frame_t *frame, void *cookie, xlator_t *this, if (dict_get (entry->dict, GF_XATTR_SHARD_FILE_SIZE)) shard_modify_size_and_block_count (&entry->d_stat, entry->dict); + + if (!entry->inode) + continue; + + shard_inode_ctx_set_if_absent (entry->inode, this, entry->dict, + &entry->d_stat); } local->op_ret = op_ret; @@ -3438,6 +3445,7 @@ int shard_readdir_do (call_frame_t *frame, xlator_t *this, fd_t *fd, size_t size, off_t offset, int whichop, dict_t *xdata) { + int ret = 0; shard_local_t *local = NULL; local = mem_get0 (this->local_pool); @@ -3463,6 +3471,17 @@ shard_readdir_do (call_frame_t *frame, xlator_t *this, fd_t *fd, size_t size, local->xattr_req = (xdata) ? dict_ref (xdata) : dict_new (); SHARD_MD_READ_FOP_INIT_REQ_DICT (this, local->xattr_req, fd->inode->gfid, local, err); + ret = dict_set_uint64 (local->xattr_req, + GF_XATTR_SHARD_BLOCK_SIZE, 0); + if (ret) { + gf_log (this->name, GF_LOG_WARNING, "Failed to set " + "dict value: key:%s, directory gfid=%s", + GF_XATTR_SHARD_BLOCK_SIZE, + uuid_utoa (fd->inode->gfid)); + local->op_ret = -1; + local->op_errno = ENOMEM; + goto err; + } STACK_WIND (frame, shard_readdir_cbk, FIRST_CHILD(this), FIRST_CHILD(this)->fops->readdirp, fd, size, offset, |