diff options
-rw-r--r-- | xlators/features/shard/src/shard.c | 156 | ||||
-rw-r--r-- | xlators/features/shard/src/shard.h | 3 |
2 files changed, 116 insertions, 43 deletions
diff --git a/xlators/features/shard/src/shard.c b/xlators/features/shard/src/shard.c index c3613711840..670fc60ddc0 100644 --- a/xlators/features/shard/src/shard.c +++ b/xlators/features/shard/src/shard.c @@ -214,6 +214,8 @@ shard_local_wipe (shard_local_t *local) GF_FREE (local->vector); if (local->iobref) iobref_unref (local->iobref); + if (local->list_inited) + gf_dirent_free (&local->entries_head); } int @@ -563,43 +565,39 @@ shard_lookup_cbk (call_frame_t *frame, void *cookie, xlator_t *this, if (IA_ISDIR (buf->ia_type)) goto unwind; - if (!shard_inode_ctx_get_block_size (inode, this, &size)) - goto unwind; - - ret = dict_get_uint64 (xdata, GF_XATTR_SHARD_BLOCK_SIZE, &size); - if (!ret) { - ctx_tmp.block_size = ntoh64 (size); - ctx_tmp.mode = st_mode_from_ia (buf->ia_prot, buf->ia_type); - ctx_tmp.rdev = buf->ia_rdev; - /* Sharding xlator would fetch size and block count only if - * @size is present. The absence of GF_XATTR_SHARD_BLOCK_SIZE on - * the file looked up could be because it was created before - * sharding was enabled on the volume. - */ - ret = dict_get_ptr (xdata, GF_XATTR_SHARD_FILE_SIZE, - &size_attr); - if (ret) { - gf_log (this->name, GF_LOG_WARNING, "Failed to " - "get xattr "GF_XATTR_SHARD_FILE_SIZE" from disk" - " for %s", uuid_utoa (inode->gfid)); - op_ret = -1; - op_errno = ENOMEM; - goto unwind; + /* If this was a fresh lookup, there are two possibilities: + * 1) If the file is sharded (indicated by the presence of block size + * xattr), store this block size, along with rdev and mode in its + * inode ctx. + * 2) If the file is not sharded, store size along with rdev and mode + * (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_uint64 (xdata, GF_XATTR_SHARD_BLOCK_SIZE, &size); + if (!ret) { + ctx_tmp.block_size = ntoh64 (size); + 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)); + } + /* 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]); } - /* else it is assumed that the file was created prior to enabling - * sharding on the volume. - */ - - 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)); unwind: SHARD_STACK_UNWIND (lookup, frame, op_ret, op_errno, inode, buf, @@ -3159,18 +3157,57 @@ shard_fsync (call_frame_t *frame, xlator_t *this, fd_t *fd, int32_t datasync, return 0; } +int +shard_readdir_past_dot_shard_cbk (call_frame_t *frame, void *cookie, + xlator_t *this, int32_t op_ret, + int32_t op_errno, gf_dirent_t *orig_entries, + dict_t *xdata) +{ + gf_dirent_t *entry = NULL; + gf_dirent_t *tmp = NULL; + shard_local_t *local = NULL; + + local = frame->local; + + if (op_ret < 0) + goto unwind; + + list_for_each_entry_safe (entry, tmp, (&orig_entries->list), list) { + + list_del_init (&entry->list); + list_add_tail (&entry->list, &local->entries_head.list); + + if (!entry->dict) + continue; + + if (IA_ISDIR (entry->d_stat.ia_type)) + continue; + + shard_modify_size_and_block_count (&entry->d_stat, entry->dict); + } + local->op_ret += op_ret; + +unwind: + if (local->fop == GF_FOP_READDIR) + SHARD_STACK_UNWIND (readdir, frame, local->op_ret, + local->op_errno, + &local->entries_head, xdata); + else + SHARD_STACK_UNWIND (readdirp, frame, op_ret, op_errno, + &local->entries_head, xdata); + return 0; +} + int32_t shard_readdir_cbk (call_frame_t *frame, void *cookie, xlator_t *this, - int32_t op_ret, int32_t op_errno, gf_dirent_t *entries, + int32_t op_ret, int32_t op_errno, gf_dirent_t *orig_entries, dict_t *xdata) { - fd_t *fd = NULL; - gf_dirent_t *entry = NULL; - gf_dirent_t *tmp = NULL; - shard_local_t *local = NULL; - gf_dirent_t skipped; - - INIT_LIST_HEAD (&skipped.list); + fd_t *fd = NULL; + gf_dirent_t *entry = NULL; + gf_dirent_t *tmp = NULL; + shard_local_t *local = NULL; + gf_boolean_t last_entry = _gf_false; local = frame->local; fd = local->fd; @@ -3178,26 +3215,55 @@ shard_readdir_cbk (call_frame_t *frame, void *cookie, xlator_t *this, if (op_ret < 0) goto unwind; - list_for_each_entry_safe (entry, tmp, &entries->list, list) { + list_for_each_entry_safe (entry, tmp, (&orig_entries->list), list) { + if (last_entry) + last_entry = _gf_false; + if (__is_root_gfid (fd->inode->gfid) && !(strcmp (entry->d_name, GF_SHARD_DIR))) { - list_del_init (&entry->list); - list_add_tail (&entry->list, &skipped.list); + local->offset = entry->d_off; + op_ret--; + last_entry = _gf_true; continue; } + list_del_init (&entry->list); + list_add_tail (&entry->list, &local->entries_head.list); + if (!entry->dict) continue; + if (IA_ISDIR (entry->d_stat.ia_type)) continue; shard_modify_size_and_block_count (&entry->d_stat, entry->dict); + } + + local->op_ret = op_ret; + if (last_entry) { + if (local->fop == GF_FOP_READDIR) + STACK_WIND (frame, shard_readdir_past_dot_shard_cbk, + FIRST_CHILD(this), + FIRST_CHILD(this)->fops->readdir, local->fd, + local->readdir_size, local->offset, + local->xattr_req); + else + STACK_WIND (frame, shard_readdir_past_dot_shard_cbk, + FIRST_CHILD(this), + FIRST_CHILD(this)->fops->readdirp, + local->fd, local->readdir_size, + local->offset, local->xattr_req); + return 0; } unwind: - SHARD_STACK_UNWIND (readdir, frame, op_ret, op_errno, entries, xdata); - gf_dirent_free (&skipped); + if (local->fop == GF_FOP_READDIR) + SHARD_STACK_UNWIND (readdir, frame, op_ret, op_errno, + &local->entries_head, xdata); + else + SHARD_STACK_UNWIND (readdirp, frame, op_ret, op_errno, + &local->entries_head, xdata); return 0; } @@ -3218,6 +3284,10 @@ shard_readdir_do (call_frame_t *frame, xlator_t *this, fd_t *fd, size_t size, frame->local = local; local->fd = fd_ref (fd); + local->fop = whichop; + local->readdir_size = size; + INIT_LIST_HEAD (&local->entries_head.list); + local->list_inited = _gf_true; if (whichop == GF_FOP_READDIR) { STACK_WIND (frame, shard_readdir_cbk, FIRST_CHILD(this), diff --git a/xlators/features/shard/src/shard.h b/xlators/features/shard/src/shard.h index 5423c03b1fa..6bdbcbb9b6e 100644 --- a/xlators/features/shard/src/shard.h +++ b/xlators/features/shard/src/shard.h @@ -153,6 +153,7 @@ typedef struct shard_local { size_t written_size; size_t hole_size; size_t req_size; + size_t readdir_size; loc_t loc; loc_t dot_shard_loc; loc_t loc2; @@ -171,6 +172,8 @@ typedef struct shard_local { struct iovec *vector; struct iobref *iobref; struct iobuf *iobuf; + gf_dirent_t entries_head; + gf_boolean_t list_inited; shard_post_fop_handler_t handler; shard_post_lookup_shards_fop_handler_t pls_fop_handler; shard_post_resolve_fop_handler_t post_res_handler; |