diff options
| author | Krutika Dhananjay <kdhananj@redhat.com> | 2015-07-22 15:18:20 +0530 | 
|---|---|---|
| committer | Pranith Kumar Karampuri <pkarampu@redhat.com> | 2015-07-30 00:28:52 -0700 | 
| commit | fc62b329ad6dc5f2e986f5cd50225015c3af199e (patch) | |
| tree | 6ef0c3a98e4907e3f400b75bed9825092baa1d81 | |
| parent | 2bb92b4837ee81b826c615b2e2280bf37fc5906f (diff) | |
features/shard: Handle unlink of files with holes appropriately in unlink() and rename().
        Backport of: http://review.gluster.org/11737
Change-Id: I94b089dc943ca20952834aa513134f7b9e925bd4
BUG: 1247014
Signed-off-by: Krutika Dhananjay <kdhananj@redhat.com>
Reviewed-on: http://review.gluster.org/11767
Tested-by: NetBSD Build System <jenkins@build.gluster.org>
Tested-by: Gluster Build System <jenkins@build.gluster.com>
Reviewed-by: Pranith Kumar Karampuri <pkarampu@redhat.com>
| -rw-r--r-- | tests/bugs/shard/bug-1245547.t | 35 | ||||
| -rw-r--r-- | xlators/features/shard/src/shard.c | 32 | 
2 files changed, 65 insertions, 2 deletions
diff --git a/tests/bugs/shard/bug-1245547.t b/tests/bugs/shard/bug-1245547.t new file mode 100644 index 00000000000..c19b2a6a042 --- /dev/null +++ b/tests/bugs/shard/bug-1245547.t @@ -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; diff --git a/xlators/features/shard/src/shard.c b/xlators/features/shard/src/shard.c index 6f3acdd40bd..5c11eb4105d 100644 --- a/xlators/features/shard/src/shard.c +++ b/xlators/features/shard/src/shard.c @@ -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)  | 
