From 6b4add6b3f54b6d3202535a492eaf906d619ad75 Mon Sep 17 00:00:00 2001 From: Krutika Dhananjay Date: Wed, 3 Jun 2015 16:51:49 +0530 Subject: features/shard: Skip shards resolution if lookup on /.shard returns ENOENT This change is done in [f]truncate, rename, unlink and readv. Also, this patch also makes lookup in shard delete GF_CONTENT_KEY as a workaround for the problems with read caching of sparse files by quick-read. A proper solution would involve shard_lookup_cbk() performing a readv, aggregating and ordering the responses and setting it in the xdata before unwinding the response to upper translators, which will be done in a separate patch. Change-Id: Ie12edb9ba8c1fcea38fea0a797916cb2a98fb30c BUG: 1223759 Signed-off-by: Krutika Dhananjay Reviewed-on: http://review.gluster.org/11065 Reviewed-by: Pranith Kumar Karampuri Tested-by: NetBSD Build System --- xlators/features/shard/src/shard.c | 140 +++++++++++++++++++++++++++++++------ 1 file changed, 118 insertions(+), 22 deletions(-) (limited to 'xlators/features') diff --git a/xlators/features/shard/src/shard.c b/xlators/features/shard/src/shard.c index cbc836476d0..c99f9cf8fc1 100644 --- a/xlators/features/shard/src/shard.c +++ b/xlators/features/shard/src/shard.c @@ -495,7 +495,9 @@ shard_lookup_dot_shard_cbk (call_frame_t *frame, void *cookie, xlator_t *this, } shard_link_dot_shard_inode (local, inode, buf); - shard_common_resolve_shards (frame, this, local->loc.inode, + shard_common_resolve_shards (frame, this, + (local->fop == GF_FOP_RENAME) ? + local->loc2.inode : local->loc.inode, local->post_res_handler); return 0; @@ -647,6 +649,8 @@ shard_lookup (call_frame_t *frame, xlator_t *this, loc_t *loc, loc->path); goto err; } + if (dict_get (xattr_req, GF_CONTENT_KEY)) + dict_del (xattr_req, GF_CONTENT_KEY); STACK_WIND (frame, shard_lookup_cbk, FIRST_CHILD (this), FIRST_CHILD (this)->fops->lookup, loc, local->xattr_req); @@ -938,12 +942,6 @@ shard_truncate_last_shard (call_frame_t *frame, xlator_t *this, inode_t *inode) local = frame->local; - if (!inode) { - shard_update_file_size (frame, this, NULL, &local->loc, - shard_post_update_size_truncate_handler); - return 0; - } - loc.inode = inode_ref (inode); gf_uuid_copy (loc.gfid, inode->gfid); @@ -1292,13 +1290,36 @@ shard_post_resolve_truncate_handler (call_frame_t *frame, xlator_t *this) local = frame->local; if (local->op_ret < 0) { - if (local->fop == GF_FOP_TRUNCATE) - SHARD_STACK_UNWIND (truncate, frame, local->op_ret, - local->op_errno, NULL, NULL, NULL); - else - SHARD_STACK_UNWIND (ftruncate, frame, local->op_ret, - local->op_errno, NULL, NULL, NULL); - return 0; + if (local->op_errno == ENOENT) { + /* If lookup on /.shard fails with ENOENT, it means that + * the file was 0-byte in size but truncated sometime in + * the past to a higher size which is reflected in the + * size xattr, and now being truncated to a lower size. + * In this case, the only thing that needs to be done is + * to update the size xattr of the file and unwind. + */ + local->first_block = local->last_block = 0; + local->num_blocks = 1; + local->call_count = 0; + local->op_ret = 0; + local->postbuf.ia_size = local->offset; + shard_update_file_size (frame, this, local->fd, + &local->loc, + shard_post_update_size_truncate_handler); + return 0; + } else { + if (local->fop == GF_FOP_TRUNCATE) + SHARD_STACK_UNWIND (truncate, frame, + local->op_ret, + local->op_errno, NULL, NULL, + NULL); + else + SHARD_STACK_UNWIND (ftruncate, frame, + local->op_ret, + local->op_errno, NULL, NULL, + NULL); + return 0; + } } if (!local->call_count) @@ -1373,7 +1394,10 @@ shard_truncate_begin (call_frame_t *frame, xlator_t *this) shard_lookup_dot_shard (frame, this, shard_post_resolve_truncate_handler); } else { - shard_common_resolve_shards (frame, this, local->loc.inode, + shard_common_resolve_shards (frame, this, + (local->fop == GF_FOP_TRUNCATE) ? + local->loc.inode : + local->fd->inode, shard_post_resolve_truncate_handler); } return 0; @@ -1789,6 +1813,38 @@ shard_post_resolve_unlink_handler (call_frame_t *frame, xlator_t *this) local = frame->local; + if (local->op_ret < 0) { + if (local->op_errno == ENOENT) { + /* If lookup on /.shard fails with ENOENT, it probably + * means that the file is being unlinked before it + * could grow beyond its first block. In this case, + * unlink boils down to unlinking the base file and + * unwinding the call. + */ + local->op_ret = 0; + local->first_block = local->last_block = 0; + 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->xflag, + local->xattr_req); + else + shard_rename_cbk (frame, this); + return 0; + } else { + if (local->fop == GF_FOP_UNLINK) + SHARD_STACK_UNWIND (unlink, frame, + local->op_ret, + local->op_errno, NULL, NULL, + NULL); + else + shard_rename_cbk (frame, this); + return 0; + } + } + if (!local->call_count) shard_unlink_shards_do (frame, this, (local->fop == GF_FOP_RENAME) @@ -1806,8 +1862,11 @@ shard_post_resolve_unlink_handler (call_frame_t *frame, xlator_t *this) int shard_post_lookup_unlink_handler (call_frame_t *frame, xlator_t *this) { + int ret = -1; + shard_priv_t *priv = NULL; shard_local_t *local = NULL; + priv = this->private; local = frame->local; if (local->op_ret < 0) { @@ -1840,8 +1899,18 @@ shard_post_lookup_unlink_handler (call_frame_t *frame, xlator_t *this) if (!local->inode_list) goto out; - shard_common_resolve_shards (frame, this, local->loc.inode, - shard_post_resolve_unlink_handler); + local->dot_shard_loc.inode = inode_find (this->itable, + priv->dot_shard_gfid); + if (!local->dot_shard_loc.inode) { + ret = shard_init_dot_shard_loc (this, local); + if (ret) + goto out; + shard_lookup_dot_shard (frame, this, + shard_post_resolve_unlink_handler); + } else { + shard_common_resolve_shards (frame, this, local->loc.inode, + shard_post_resolve_unlink_handler); + } return 0; out: @@ -1881,6 +1950,8 @@ shard_unlink (call_frame_t *frame, xlator_t *this, loc_t *loc, int xflag, local->xattr_req = (xdata) ? dict_ref (xdata) : dict_new (); local->block_size = block_size; local->fop = GF_FOP_UNLINK; + if (!this->itable) + this->itable = (local->loc.inode)->table; shard_lookup_base_file (frame, this, &local->loc, shard_post_lookup_unlink_handler); @@ -1909,9 +1980,12 @@ shard_rename_cbk (call_frame_t *frame, xlator_t *this) int shard_rename_unlink_dst_shards_do (call_frame_t *frame, xlator_t *this) { + int ret = -1; shard_local_t *local = NULL; + shard_priv_t *priv = NULL; local = frame->local; + priv = this->private; local->first_block = get_lowest_block (0, local->dst_block_size); local->last_block = get_highest_block (0, local->postbuf.ia_size, @@ -1928,8 +2002,18 @@ shard_rename_unlink_dst_shards_do (call_frame_t *frame, xlator_t *this) if (!local->inode_list) goto out; - shard_common_resolve_shards (frame, this, local->loc2.inode, - shard_post_resolve_unlink_handler); + local->dot_shard_loc.inode = inode_find (this->itable, + priv->dot_shard_gfid); + if (!local->dot_shard_loc.inode) { + ret = shard_init_dot_shard_loc (this, local); + if (ret) + goto out; + shard_lookup_dot_shard (frame, this, + shard_post_resolve_unlink_handler); + } else { + shard_common_resolve_shards (frame, this, local->loc2.inode, + shard_post_resolve_unlink_handler); + } return 0; @@ -2549,9 +2633,21 @@ shard_post_resolve_readv_handler (call_frame_t *frame, xlator_t *this) local = frame->local; if (local->op_ret < 0) { - SHARD_STACK_UNWIND (readv, frame, local->op_ret, - local->op_errno, NULL, 0, NULL, NULL, NULL); - return 0; + if (local->op_errno != ENOENT) { + SHARD_STACK_UNWIND (readv, frame, local->op_ret, + local->op_errno, NULL, 0, NULL, + NULL, NULL); + return 0; + } else { + struct iovec vec = {0,}; + + vec.iov_base = local->iobuf->ptr; + vec.iov_len = local->total_size; + SHARD_STACK_UNWIND (readv, frame, local->total_size, + 0, &vec, 1, &local->prebuf, + local->iobref, NULL); + return 0; + } } if (local->call_count) -- cgit