features/shard: Handle unlink of files with holes appropriately in unlink() and rename().

Change-Id: I25a02386dc95580c2e76a13fdd8e11a0df234d56
BUG: 1245547
Signed-off-by: Krutika Dhananjay <kdhananj@redhat.com>
Reviewed-on: http://review.gluster.org/11737
Tested-by: Gluster Build System <jenkins@build.gluster.com>
Reviewed-by: Pranith Kumar Karampuri <pkarampu@redhat.com>
Tested-by: NetBSD Build System <jenkins@build.gluster.org>
This commit is contained in:
Krutika Dhananjay 2015-07-22 15:18:20 +05:30 committed by Pranith Kumar Karampuri
parent d49b4b1086
commit 385acc675c
2 changed files with 65 additions and 2 deletions

View File

@ -0,0 +1,35 @@
#!/bin/bash
. $(dirname $0)/../../include.rc
cleanup;
TEST glusterd
TEST pidof glusterd
TEST $CLI volume create $V0 $H0:$B0/${V0}{0,1}
TEST $CLI volume set $V0 features.shard on
TEST $CLI volume start $V0
TEST $GFS --volfile-id=$V0 --volfile-server=$H0 $M0
#Create a file.
TEST touch $M0/foo
#Write some data into it.
TEST `echo "abc" > $M0/foo`
#This should ensure /.shard is created on the bricks.
TEST stat $B0/${V0}0/.shard
TEST stat $B0/${V0}1/.shard
#Create a file 'bar' with holes.
TEST touch $M0/bar
TEST truncate -s 10G $M0/bar
#Unlink on such a file should succeed.
TEST unlink $M0/bar
#
#Create a file 'baz' with holes.
TEST touch $M0/baz
TEST truncate -s 10G $M0/baz
#Rename with a sharded existing dest that has holes must succeed.
TEST mv -f $M0/foo $M0/baz
cleanup;

View File

@ -649,7 +649,7 @@ shard_lookup (call_frame_t *frame, xlator_t *this, loc_t *loc,
loc->path);
goto err;
}
if (dict_get (xattr_req, GF_CONTENT_KEY))
if ((xattr_req) && (dict_get (xattr_req, GF_CONTENT_KEY)))
dict_del (xattr_req, GF_CONTENT_KEY);
STACK_WIND (frame, shard_lookup_cbk, FIRST_CHILD (this),
@ -1724,7 +1724,9 @@ done:
int
shard_unlink_shards_do (call_frame_t *frame, xlator_t *this, inode_t *inode)
{
int i = 0;
int ret = -1;
int count = 0;
int call_count = 0;
uint32_t last_block = 0;
uint32_t cur_block = 0;
@ -1740,6 +1742,30 @@ shard_unlink_shards_do (call_frame_t *frame, xlator_t *this, inode_t *inode)
local->call_count = call_count = local->num_blocks - 1;
last_block = local->last_block;
for (i = 1; i < local->num_blocks; i++) {
if (!local->inode_list[i])
continue;
count++;
}
if (!count) {
/* callcount = 0 implies that all of the shards that need to be
* unlinked are non-existent (in other words the file is full of
* holes). So shard xlator would now proceed to do the final
* unlink on the base file.
*/
local->num_blocks = 1;
if (local->fop == GF_FOP_UNLINK) {
STACK_WIND (frame, shard_unlink_cbk, FIRST_CHILD(this),
FIRST_CHILD(this)->fops->unlink,
&local->loc, local->flags,
local->xattr_req);
} else if (local->fop == GF_FOP_RENAME) {
shard_rename_cbk (frame, this);
}
return 0;
}
while (cur_block <= last_block) {
/* The base file is unlinked in the end to mark the
* successful completion of the fop.
@ -1803,7 +1829,7 @@ shard_post_lookup_shards_unlink_handler (call_frame_t *frame, xlator_t *this)
local = frame->local;
if (local->op_ret < 0) {
if ((local->op_ret < 0) && (local->op_errno != ENOENT)) {
if (local->fop == GF_FOP_UNLINK)
SHARD_STACK_UNWIND (unlink, frame, local->op_ret,
local->op_errno, NULL, NULL, NULL);
@ -1813,6 +1839,8 @@ shard_post_lookup_shards_unlink_handler (call_frame_t *frame, xlator_t *this)
NULL, NULL, NULL);
return 0;
}
local->op_ret = 0;
local->op_errno = 0;
shard_unlink_shards_do (frame, this,
(local->fop == GF_FOP_RENAME)