diff options
Diffstat (limited to 'xlators/protocol/client/src')
-rw-r--r-- | xlators/protocol/client/src/client-common.c | 8 | ||||
-rw-r--r-- | xlators/protocol/client/src/client-helpers.c | 1391 | ||||
-rw-r--r-- | xlators/protocol/client/src/client-mem-types.h | 2 | ||||
-rw-r--r-- | xlators/protocol/client/src/client-rpc-fops.c | 228 | ||||
-rw-r--r-- | xlators/protocol/client/src/client.c | 144 | ||||
-rw-r--r-- | xlators/protocol/client/src/client.h | 77 |
6 files changed, 1848 insertions, 2 deletions
diff --git a/xlators/protocol/client/src/client-common.c b/xlators/protocol/client/src/client-common.c index 3d83bc94f59..51c2d95ea2b 100644 --- a/xlators/protocol/client/src/client-common.c +++ b/xlators/protocol/client/src/client-common.c @@ -1829,8 +1829,12 @@ int client_post_lookup (xlator_t *this, gfs3_lookup_rsp *rsp, struct iatt *stbuf, struct iatt *postparent, dict_t **xdata) { - gf_stat_to_iatt (&rsp->postparent, postparent); - gf_stat_to_iatt (&rsp->stat, stbuf); + + if (-1 != rsp->op_ret) { + gf_stat_to_iatt (&rsp->postparent, postparent); + gf_stat_to_iatt (&rsp->stat, stbuf); + } + GF_PROTOCOL_DICT_UNSERIALIZE (this, *xdata, (rsp->xdata.xdata_val), (rsp->xdata.xdata_len), rsp->op_ret, rsp->op_errno, out); diff --git a/xlators/protocol/client/src/client-helpers.c b/xlators/protocol/client/src/client-helpers.c index 804b4028803..e78242ffe65 100644 --- a/xlators/protocol/client/src/client-helpers.c +++ b/xlators/protocol/client/src/client-helpers.c @@ -11,6 +11,9 @@ #include "client.h" #include "fd.h" #include "client-messages.h" +#include "client-common.h" +#include "compat-errno.h" +#include "common-utils.h" int client_fd_lk_list_empty (fd_lk_ctx_t *lk_ctx, gf_boolean_t try_lock) @@ -132,8 +135,14 @@ client_local_wipe (clnt_local_t *local) iobref_unref (local->iobref); } + if (local->iobref2) { + iobref_unref (local->iobref2); + } + GF_FREE (local->name); + local->compound_args = NULL; + mem_put (local); } @@ -359,3 +368,1385 @@ client_fd_fop_prepare_local (call_frame_t *frame, fd_t *fd, int64_t remote_fd) out: return ret; } + +int +client_process_response (call_frame_t *frame, xlator_t *this, + struct rpc_req *req, gfs3_compound_rsp *rsp, + compound_args_cbk_t *args_cbk, + int index) +{ + int ret = 0; + default_args_cbk_t *this_args_cbk = &args_cbk->rsp_list[index]; + clnt_local_t *local = frame->local; + compound_rsp *this_rsp = NULL; + compound_args_t *args = local->compound_args; + void *data = NULL; + + this_rsp = &rsp->compound_rsp_array.compound_rsp_array_val[index]; + args_cbk->enum_list[index] = this_rsp->fop_enum; + + switch (args_cbk->enum_list[index]) { + + case GF_FOP_STAT: + { + gfs3_stat_rsp *tmp_rsp = NULL; + tmp_rsp = &this_rsp->compound_rsp_u.compound_stat_rsp; + + client_post_stat (this, tmp_rsp, + &this_args_cbk->stat, &this_args_cbk->xdata); + + CLIENT_POST_FOP_TYPE (stat, this_rsp, this_args_cbk, + &this_args_cbk->stat, + this_args_cbk->xdata); + break; + } + case GF_FOP_READLINK: + { + gfs3_readlink_rsp *tmp_rsp = NULL; + tmp_rsp = &this_rsp->compound_rsp_u.compound_readlink_rsp; + + client_post_readlink (this, tmp_rsp, + &this_args_cbk->stat, &this_args_cbk->xdata); + CLIENT_POST_FOP_TYPE (readlink, this_rsp, this_args_cbk, + tmp_rsp->path, + &this_args_cbk->stat, + this_args_cbk->xdata); + break; + } + case GF_FOP_MKNOD: + { + gfs3_mknod_rsp *tmp_rsp = NULL; + tmp_rsp = &this_rsp->compound_rsp_u.compound_mknod_rsp; + + client_post_mknod (this, tmp_rsp, + &this_args_cbk->stat, + &this_args_cbk->preparent, + &this_args_cbk->postparent, + &this_args_cbk->xdata); + CLIENT_POST_FOP_TYPE (mknod, this_rsp, this_args_cbk, + local->loc.inode, + &this_args_cbk->stat, + &this_args_cbk->preparent, + &this_args_cbk->postparent, + this_args_cbk->xdata); + break; + } + case GF_FOP_MKDIR: + { + gfs3_mkdir_rsp *tmp_rsp = NULL; + tmp_rsp = &this_rsp->compound_rsp_u.compound_mkdir_rsp; + + client_post_mkdir (this, + tmp_rsp, + &this_args_cbk->stat, + &this_args_cbk->preparent, + &this_args_cbk->postparent, + &this_args_cbk->xdata); + CLIENT_POST_FOP_TYPE (mkdir, this_rsp, this_args_cbk, + local->loc.inode, + &this_args_cbk->stat, + &this_args_cbk->preparent, + &this_args_cbk->postparent, + this_args_cbk->xdata); + break; + } + case GF_FOP_UNLINK: + { + gfs3_unlink_rsp *tmp_rsp = NULL; + tmp_rsp = &this_rsp->compound_rsp_u.compound_unlink_rsp; + + client_post_unlink (this, + tmp_rsp, + &this_args_cbk->preparent, + &this_args_cbk->postparent, + &this_args_cbk->xdata); + CLIENT_POST_FOP_TYPE (unlink, this_rsp, this_args_cbk, + &this_args_cbk->preparent, + &this_args_cbk->postparent, + this_args_cbk->xdata); + break; + } + case GF_FOP_RMDIR: + { + gfs3_rmdir_rsp *tmp_rsp = NULL; + tmp_rsp = &this_rsp->compound_rsp_u.compound_rmdir_rsp; + + client_post_rmdir (this, tmp_rsp, + &this_args_cbk->preparent, + &this_args_cbk->postparent, + &this_args_cbk->xdata); + CLIENT_POST_FOP_TYPE (rmdir, this_rsp, this_args_cbk, + &this_args_cbk->preparent, + &this_args_cbk->postparent, + this_args_cbk->xdata); + break; + } + case GF_FOP_SYMLINK: + { + gfs3_symlink_rsp *tmp_rsp = NULL; + tmp_rsp = &this_rsp->compound_rsp_u.compound_symlink_rsp; + + client_post_symlink (this, tmp_rsp, + &this_args_cbk->stat, + &this_args_cbk->preparent, + &this_args_cbk->postparent, + &this_args_cbk->xdata); + CLIENT_POST_FOP_TYPE (symlink, this_rsp, this_args_cbk, NULL, + &this_args_cbk->stat, + &this_args_cbk->preparent, + &this_args_cbk->postparent, + this_args_cbk->xdata); + break; + } + case GF_FOP_RENAME: + { + gfs3_rename_rsp *tmp_rsp = NULL; + tmp_rsp = &this_rsp->compound_rsp_u.compound_rename_rsp; + + client_post_rename (this, tmp_rsp, + &this_args_cbk->stat, + &this_args_cbk->preparent, + &this_args_cbk->postparent, + &this_args_cbk->preparent2, + &this_args_cbk->postparent2, + &this_args_cbk->xdata); + CLIENT_POST_FOP_TYPE (rename, this_rsp, this_args_cbk, + &this_args_cbk->stat, + &this_args_cbk->preparent, + &this_args_cbk->postparent, + &this_args_cbk->preparent2, + &this_args_cbk->postparent2, + this_args_cbk->xdata); + break; + } + case GF_FOP_LINK: + { + gfs3_link_rsp *tmp_rsp = NULL; + tmp_rsp = &this_rsp->compound_rsp_u.compound_link_rsp; + + client_post_link (this, tmp_rsp, + &this_args_cbk->stat, + &this_args_cbk->preparent, + &this_args_cbk->postparent, + &this_args_cbk->xdata); + CLIENT_POST_FOP_TYPE (link, this_rsp, this_args_cbk, NULL, + &this_args_cbk->stat, + &this_args_cbk->preparent, + &this_args_cbk->postparent, + this_args_cbk->xdata); + break; + } + case GF_FOP_TRUNCATE: + { + gfs3_truncate_rsp *tmp_rsp = NULL; + tmp_rsp = &this_rsp->compound_rsp_u.compound_truncate_rsp; + + client_post_truncate (this, tmp_rsp, + &this_args_cbk->prestat, + &this_args_cbk->poststat, + &this_args_cbk->xdata); + CLIENT_POST_FOP_TYPE (truncate, this_rsp, this_args_cbk, + &this_args_cbk->prestat, + &this_args_cbk->poststat, + this_args_cbk->xdata); + break; + } + case GF_FOP_OPEN: + { + gfs3_open_rsp *tmp_rsp = NULL; + tmp_rsp = &this_rsp->compound_rsp_u.compound_open_rsp; + + client_post_open (this, tmp_rsp, + &this_args_cbk->xdata); + CLIENT_POST_FOP_TYPE (open, this_rsp, this_args_cbk, + local->fd, + this_args_cbk->xdata); + if (-1 != this_args_cbk->op_ret) + ret = client_add_fd_to_saved_fds (this, local->fd, + &local->loc, + args->req_list[index].flags, + tmp_rsp->fd, + 0); + break; + } + case GF_FOP_READ: + { + gfs3_read_rsp *tmp_rsp = NULL; + tmp_rsp = &this_rsp->compound_rsp_u.compound_read_rsp; + + client_post_readv (this, tmp_rsp, &this_args_cbk->iobref, + req->rsp_iobref, + &this_args_cbk->stat, + this_args_cbk->vector, &req->rsp[1], + &this_args_cbk->count, + &this_args_cbk->xdata); + + /* Each read should be given read response that only + * corresponds to its request. + * Modify the iovecs accordingly. + * After each read, store the length of data already read + * so that the next ones can continue from there. + */ + if (local->read_length) { + this_args_cbk->vector[0].iov_base += local->read_length; + local->read_length += tmp_rsp->op_ret; + } else { + local->read_length = tmp_rsp->op_ret; + } + + args_readv_cbk_store (this_args_cbk, tmp_rsp->op_ret, + gf_error_to_errno (tmp_rsp->op_errno), + this_args_cbk->vector, + this_args_cbk->count, + &this_args_cbk->stat, + this_args_cbk->iobref, + this_args_cbk->xdata); + + if (tmp_rsp->op_ret >= 0) + if (local->attempt_reopen) + client_attempt_reopen (local->fd, this); + + break; + } + case GF_FOP_WRITE: + { + gfs3_write_rsp *tmp_rsp = NULL; + tmp_rsp = &this_rsp->compound_rsp_u.compound_write_rsp; + + client_post_writev (this, tmp_rsp, &this_args_cbk->prestat, + &this_args_cbk->poststat, + &this_args_cbk->xdata); + args_writev_cbk_store (this_args_cbk, tmp_rsp->op_ret, + gf_error_to_errno (tmp_rsp->op_errno), + &this_args_cbk->prestat, + &this_args_cbk->poststat, + this_args_cbk->xdata); + + if (tmp_rsp->op_ret == 0) + if (local->attempt_reopen) + client_attempt_reopen (local->fd, this); + break; + } + case GF_FOP_STATFS: + { + gfs3_statfs_rsp *tmp_rsp = NULL; + tmp_rsp = &this_rsp->compound_rsp_u.compound_statfs_rsp; + + client_post_statfs (this, tmp_rsp, + &this_args_cbk->statvfs, + &this_args_cbk->xdata); + + CLIENT_POST_FOP_TYPE (statfs, this_rsp, this_args_cbk, + &this_args_cbk->statvfs, + this_args_cbk->xdata); + break; + } + case GF_FOP_FLUSH: + { + gf_common_rsp *tmp_rsp = NULL; + tmp_rsp = &this_rsp->compound_rsp_u.compound_flush_rsp; + + client_post_flush (this, tmp_rsp, + &this_args_cbk->xdata); + + CLIENT_POST_FOP (flush, this_rsp, this_args_cbk, + this_args_cbk->xdata); + if (this_args_cbk->op_ret >= 0 && !fd_is_anonymous (local->fd)) { + /* Delete all saved locks of the owner issuing flush */ + ret = delete_granted_locks_owner (local->fd, &local->owner); + gf_msg_trace (this->name, 0, + "deleting locks of owner (%s) returned %d", + lkowner_utoa (&local->owner), ret); + } + break; + } + case GF_FOP_FSYNC: + { + gfs3_fsync_rsp *tmp_rsp = NULL; + tmp_rsp = &this_rsp->compound_rsp_u.compound_fsync_rsp; + + client_post_fsync (this, tmp_rsp, + &this_args_cbk->prestat, + &this_args_cbk->poststat, + &this_args_cbk->xdata); + + CLIENT_POST_FOP_TYPE (fsync, this_rsp, this_args_cbk, + &this_args_cbk->prestat, + &this_args_cbk->poststat, + this_args_cbk->xdata); + break; + } + case GF_FOP_SETXATTR: + { + gf_common_rsp *tmp_rsp = NULL; + tmp_rsp = &this_rsp->compound_rsp_u.compound_setxattr_rsp; + + client_post_setxattr (this, tmp_rsp, + &this_args_cbk->xdata); + + CLIENT_POST_FOP (setxattr, this_rsp, this_args_cbk, + this_args_cbk->xdata); + break; + } + case GF_FOP_GETXATTR: + { + gfs3_getxattr_rsp *tmp_rsp = NULL; + tmp_rsp = &this_rsp->compound_rsp_u.compound_getxattr_rsp; + + client_post_getxattr (this, tmp_rsp, + &this_args_cbk->xattr, + &this_args_cbk->xdata); + + CLIENT_POST_FOP_TYPE (getxattr, this_rsp, this_args_cbk, + this_args_cbk->xattr, + this_args_cbk->xdata); + break; + } + case GF_FOP_REMOVEXATTR: + { + gf_common_rsp *tmp_rsp = NULL; + tmp_rsp = &this_rsp->compound_rsp_u.compound_removexattr_rsp; + + client_post_removexattr (this, tmp_rsp, + &this_args_cbk->xdata); + + CLIENT_POST_FOP (removexattr, this_rsp, this_args_cbk, + this_args_cbk->xdata); + break; + } + case GF_FOP_OPENDIR: + { + gfs3_opendir_rsp *tmp_rsp = NULL; + tmp_rsp = &this_rsp->compound_rsp_u.compound_opendir_rsp; + + client_post_opendir (this, tmp_rsp, + &this_args_cbk->xdata); + + CLIENT_POST_FOP_TYPE (opendir, this_rsp, this_args_cbk, + local->fd, + this_args_cbk->xdata); + if (-1 != this_args_cbk->op_ret) + ret = client_add_fd_to_saved_fds (this, local->fd, + &local->loc, + args->req_list[index].flags, + tmp_rsp->fd, 0); + break; + } + case GF_FOP_FSYNCDIR: + { + gf_common_rsp *tmp_rsp = NULL; + tmp_rsp = &this_rsp->compound_rsp_u.compound_fsyncdir_rsp; + + client_post_fsyncdir (this, tmp_rsp, + &this_args_cbk->xdata); + + CLIENT_POST_FOP (fsyncdir, this_rsp, this_args_cbk, + this_args_cbk->xdata); + break; + } + case GF_FOP_ACCESS: + { + gf_common_rsp *tmp_rsp = NULL; + tmp_rsp = &this_rsp->compound_rsp_u.compound_access_rsp; + + client_post_access (this, tmp_rsp, + &this_args_cbk->xdata); + + CLIENT_POST_FOP (access, this_rsp, this_args_cbk, + this_args_cbk->xdata); + break; + } + case GF_FOP_CREATE: + { + gfs3_create_rsp *tmp_rsp = NULL; + tmp_rsp = &this_rsp->compound_rsp_u.compound_create_rsp; + + client_post_create (this, tmp_rsp, + &this_args_cbk->stat, + &this_args_cbk->preparent, + &this_args_cbk->postparent, + local, + &this_args_cbk->xdata); + CLIENT_POST_FOP_TYPE (create, this_rsp, this_args_cbk, + local->fd, + local->loc.inode, + &this_args_cbk->stat, + &this_args_cbk->preparent, + &this_args_cbk->postparent, + this_args_cbk->xdata); + if (-1 != this_args_cbk->op_ret) + ret = client_add_fd_to_saved_fds (this, local->fd, + &local->loc, + args->req_list[index].flags, + tmp_rsp->fd, 0); + break; + } + case GF_FOP_FTRUNCATE: + { + gfs3_ftruncate_rsp *tmp_rsp = NULL; + tmp_rsp = &this_rsp->compound_rsp_u.compound_ftruncate_rsp; + + client_post_ftruncate (this, tmp_rsp, + &this_args_cbk->prestat, + &this_args_cbk->poststat, + &this_args_cbk->xdata); + CLIENT_POST_FOP_TYPE (ftruncate, this_rsp, this_args_cbk, + &this_args_cbk->prestat, + &this_args_cbk->poststat, + this_args_cbk->xdata); + break; + } + case GF_FOP_FSTAT: + { + gfs3_fstat_rsp *tmp_rsp = NULL; + tmp_rsp = &this_rsp->compound_rsp_u.compound_fstat_rsp; + + client_post_fstat (this, tmp_rsp, + &this_args_cbk->stat, &this_args_cbk->xdata); + + CLIENT_POST_FOP_TYPE (fstat, this_rsp, this_args_cbk, + &this_args_cbk->stat, + this_args_cbk->xdata); + break; + } + case GF_FOP_LK: + { + gfs3_lk_rsp *tmp_rsp = NULL; + tmp_rsp = &this_rsp->compound_rsp_u.compound_lk_rsp; + + client_post_lk (this, tmp_rsp, + &this_args_cbk->lock, + &this_args_cbk->xdata); + + CLIENT_POST_FOP_TYPE (lk, this_rsp, this_args_cbk, + &this_args_cbk->lock, + this_args_cbk->xdata); + break; + } + case GF_FOP_LOOKUP: + { + gfs3_lookup_rsp *tmp_rsp = NULL; + tmp_rsp = &this_rsp->compound_rsp_u.compound_lookup_rsp; + + client_post_lookup (this, tmp_rsp, + &this_args_cbk->stat, + &this_args_cbk->postparent, + &this_args_cbk->xdata); + CLIENT_POST_FOP_TYPE (lookup, this_rsp, this_args_cbk, + local->loc.inode, + &this_args_cbk->stat, + this_args_cbk->xdata, + &this_args_cbk->postparent); + break; + } + case GF_FOP_READDIR: + { + gfs3_readdir_rsp *tmp_rsp = NULL; + tmp_rsp = &this_rsp->compound_rsp_u.compound_readdir_rsp; + + client_post_readdir (this, tmp_rsp, + &this_args_cbk->entries, &this_args_cbk->xdata); + + CLIENT_POST_FOP_TYPE (readdir, this_rsp, this_args_cbk, + &this_args_cbk->entries, this_args_cbk->xdata); + break; + } + case GF_FOP_INODELK: + { + gf_common_rsp *tmp_rsp = NULL; + tmp_rsp = &this_rsp->compound_rsp_u.compound_inodelk_rsp; + + client_post_inodelk (this, tmp_rsp, + &this_args_cbk->xdata); + + CLIENT_POST_FOP (inodelk, this_rsp, this_args_cbk, + this_args_cbk->xdata); + break; + } + case GF_FOP_FINODELK: + { + gf_common_rsp *tmp_rsp = NULL; + tmp_rsp = &this_rsp->compound_rsp_u.compound_finodelk_rsp; + + client_post_finodelk (this, tmp_rsp, + &this_args_cbk->xdata); + + CLIENT_POST_FOP (finodelk, this_rsp, this_args_cbk, + this_args_cbk->xdata); + if (tmp_rsp->op_ret == 0) + if (local->attempt_reopen) + client_attempt_reopen (local->fd, this); + break; + } + case GF_FOP_ENTRYLK: + { + gf_common_rsp *tmp_rsp = NULL; + tmp_rsp = &this_rsp->compound_rsp_u.compound_entrylk_rsp; + + client_post_entrylk (this, tmp_rsp, + &this_args_cbk->xdata); + + CLIENT_POST_FOP (entrylk, this_rsp, this_args_cbk, + this_args_cbk->xdata); + break; + } + case GF_FOP_FENTRYLK: + { + gf_common_rsp *tmp_rsp = NULL; + tmp_rsp = &this_rsp->compound_rsp_u.compound_fentrylk_rsp; + + client_post_fentrylk (this, tmp_rsp, + &this_args_cbk->xdata); + + CLIENT_POST_FOP (fentrylk, this_rsp, this_args_cbk, + this_args_cbk->xdata); + break; + } + case GF_FOP_XATTROP: + { + gfs3_xattrop_rsp *tmp_rsp = NULL; + tmp_rsp = &this_rsp->compound_rsp_u.compound_xattrop_rsp; + + client_post_xattrop (this, tmp_rsp, + &this_args_cbk->xattr, + &this_args_cbk->xdata); + + CLIENT_POST_FOP_TYPE (xattrop, this_rsp, this_args_cbk, + this_args_cbk->xattr, + this_args_cbk->xdata); + break; + } + case GF_FOP_FXATTROP: + { + gfs3_fxattrop_rsp *tmp_rsp = NULL; + tmp_rsp = &this_rsp->compound_rsp_u.compound_fxattrop_rsp; + + client_post_fxattrop (this, tmp_rsp, + &this_args_cbk->xattr, + &this_args_cbk->xdata); + + CLIENT_POST_FOP_TYPE (fxattrop, this_rsp, this_args_cbk, + this_args_cbk->xattr, + this_args_cbk->xdata); + if (rsp->op_ret == 0) + if (local->attempt_reopen) + client_attempt_reopen (local->fd, this); + break; + } + case GF_FOP_FGETXATTR: + { + gfs3_fgetxattr_rsp *tmp_rsp = NULL; + tmp_rsp = &this_rsp->compound_rsp_u.compound_fgetxattr_rsp; + + client_post_fgetxattr (this, tmp_rsp, + &this_args_cbk->xattr, + &this_args_cbk->xdata); + + CLIENT_POST_FOP_TYPE (fgetxattr, this_rsp, this_args_cbk, + this_args_cbk->xattr, + this_args_cbk->xdata); + break; + } + case GF_FOP_FSETXATTR: + { + gf_common_rsp *tmp_rsp = NULL; + tmp_rsp = &this_rsp->compound_rsp_u.compound_fsetxattr_rsp; + + client_post_fsetxattr (this, tmp_rsp, + &this_args_cbk->xdata); + + CLIENT_POST_FOP (fsetxattr, this_rsp, this_args_cbk, + this_args_cbk->xdata); + break; + } + case GF_FOP_RCHECKSUM: + { + gfs3_rchecksum_rsp *tmp_rsp = NULL; + tmp_rsp = &this_rsp->compound_rsp_u.compound_rchecksum_rsp; + + client_post_rchecksum (this, tmp_rsp, + &this_args_cbk->xdata); + + break; + CLIENT_POST_FOP_TYPE (rchecksum, this_rsp, this_args_cbk, + tmp_rsp->weak_checksum, + (uint8_t*)tmp_rsp->strong_checksum.strong_checksum_val, + this_args_cbk->xdata); + break; + } + case GF_FOP_SETATTR: + { + gfs3_setattr_rsp *tmp_rsp = NULL; + tmp_rsp = &this_rsp->compound_rsp_u.compound_setattr_rsp; + + client_post_setattr (this, tmp_rsp, + &this_args_cbk->prestat, + &this_args_cbk->poststat, + &this_args_cbk->xdata); + + CLIENT_POST_FOP_TYPE (setattr, this_rsp, this_args_cbk, + &this_args_cbk->prestat, + &this_args_cbk->poststat, + this_args_cbk->xdata); + break; + } + case GF_FOP_FSETATTR: + { + gfs3_fsetattr_rsp *tmp_rsp = NULL; + tmp_rsp = &this_rsp->compound_rsp_u.compound_fsetattr_rsp; + + client_post_fsetattr (this, tmp_rsp, + &this_args_cbk->prestat, + &this_args_cbk->poststat, + &this_args_cbk->xdata); + + CLIENT_POST_FOP_TYPE (fsetattr, this_rsp, this_args_cbk, + &this_args_cbk->prestat, + &this_args_cbk->poststat, + this_args_cbk->xdata); + break; + } + case GF_FOP_READDIRP: + { + gfs3_readdirp_rsp *tmp_rsp = NULL; + tmp_rsp = &this_rsp->compound_rsp_u.compound_readdirp_rsp; + + client_post_readdirp (this, tmp_rsp, local->fd, + &this_args_cbk->entries, + &this_args_cbk->xdata); + + CLIENT_POST_FOP_TYPE (readdirp, this_rsp, this_args_cbk, + &this_args_cbk->entries, + this_args_cbk->xdata); + break; + } + case GF_FOP_FREMOVEXATTR: + { + gf_common_rsp *tmp_rsp = NULL; + tmp_rsp = &this_rsp->compound_rsp_u.compound_fremovexattr_rsp; + + client_post_fremovexattr (this, tmp_rsp, + &this_args_cbk->xdata); + + CLIENT_POST_FOP (fremovexattr, this_rsp, this_args_cbk, + this_args_cbk->xdata); + break; + } + case GF_FOP_FALLOCATE: + { + gfs3_fallocate_rsp *tmp_rsp = NULL; + tmp_rsp = &this_rsp->compound_rsp_u.compound_fallocate_rsp; + + client_post_fallocate (this, tmp_rsp, + &this_args_cbk->prestat, + &this_args_cbk->poststat, + &this_args_cbk->xdata); + + CLIENT_POST_FOP_TYPE (fallocate, this_rsp, this_args_cbk, + &this_args_cbk->prestat, + &this_args_cbk->poststat, + this_args_cbk->xdata); + break; + } + case GF_FOP_DISCARD: + { + gfs3_discard_rsp *tmp_rsp = NULL; + tmp_rsp = &this_rsp->compound_rsp_u.compound_discard_rsp; + + client_post_discard (this, tmp_rsp, + &this_args_cbk->prestat, + &this_args_cbk->poststat, + &this_args_cbk->xdata); + + CLIENT_POST_FOP_TYPE (discard, this_rsp, this_args_cbk, + &this_args_cbk->prestat, + &this_args_cbk->poststat, + this_args_cbk->xdata); + break; + } + case GF_FOP_ZEROFILL: + { + gfs3_zerofill_rsp *tmp_rsp = NULL; + tmp_rsp = &this_rsp->compound_rsp_u.compound_zerofill_rsp; + + client_post_zerofill (this, tmp_rsp, + &this_args_cbk->prestat, + &this_args_cbk->poststat, + &this_args_cbk->xdata); + + CLIENT_POST_FOP_TYPE (zerofill, this_rsp, this_args_cbk, + &this_args_cbk->prestat, + &this_args_cbk->poststat, + this_args_cbk->xdata); + break; + } + case GF_FOP_IPC: + { + gfs3_ipc_rsp *tmp_rsp = NULL; + tmp_rsp = &this_rsp->compound_rsp_u.compound_ipc_rsp; + + client_post_ipc (this, tmp_rsp, &this_args_cbk->xdata); + + CLIENT_POST_FOP_TYPE (ipc, this_rsp, this_args_cbk, + this_args_cbk->xdata); + break; + } + case GF_FOP_SEEK: + { + gfs3_seek_rsp *tmp_rsp = NULL; + tmp_rsp = &this_rsp->compound_rsp_u.compound_seek_rsp; + + client_post_seek (this, tmp_rsp, &this_args_cbk->xdata); + + CLIENT_POST_FOP_TYPE (seek, this_rsp, this_args_cbk, + tmp_rsp->offset, + this_args_cbk->xdata); + break; + } + case GF_FOP_LEASE: + { + gfs3_lease_rsp *tmp_rsp = NULL; + tmp_rsp = &this_rsp->compound_rsp_u.compound_lease_rsp; + + client_post_lease (this, tmp_rsp, &this_args_cbk->lease, + &this_args_cbk->xdata); + + CLIENT_POST_FOP_TYPE (lease, this_rsp, this_args_cbk, + &this_args_cbk->lease, + this_args_cbk->xdata); + break; + } + default: + return -ENOTSUP; + } + return 0; +} + +int +client_handle_fop_requirements (xlator_t *this, call_frame_t *frame, + gfs3_compound_req *req, + clnt_local_t *local, + struct iobref *req_iobref, + struct iobref *rsp_iobref, + struct iovec *req_vector, + struct iovec *rsp_vector, int *req_count, + int *rsp_count, default_args_t *args, + int fop_enum, int index) +{ + int ret = 0; + int op_errno = ENOMEM; + struct iobuf *rsp_iobuf = NULL; + int64_t remote_fd = -1; + compound_req *this_req = &req->compound_req_array.compound_req_array_val[index]; + + this_req->fop_enum = fop_enum; + + switch (fop_enum) { + case GF_FOP_STAT: + CLIENT_PRE_FOP (stat, this, + &this_req->compound_req_u.compound_stat_req, + op_errno, out, + &args->loc, args->xdata); + break; + case GF_FOP_READLINK: + CLIENT_PRE_FOP (readlink, this, + &this_req->compound_req_u.compound_readlink_req, + op_errno, out, + &args->loc, args->size, args->xdata); + break; + case GF_FOP_MKNOD: + CLIENT_PRE_FOP (mknod, this, + &this_req->compound_req_u.compound_mknod_req, + op_errno, out, + &args->loc, args->mode, args->rdev, + args->umask, args->xdata); + if (!&local->loc) { + loc_copy (&local->loc, &args->loc); + loc_path (&local->loc, NULL); + } + break; + case GF_FOP_MKDIR: + CLIENT_PRE_FOP (mkdir, this, + &this_req->compound_req_u.compound_mkdir_req, + op_errno, out, + &args->loc, args->mode, + args->umask, args->xdata); + if (!&local->loc) { + loc_copy (&local->loc, &args->loc); + loc_path (&local->loc, NULL); + } + break; + case GF_FOP_UNLINK: + CLIENT_PRE_FOP (unlink, this, + &this_req->compound_req_u.compound_unlink_req, + op_errno, out, + &args->loc, args->xflag, args->xdata); + break; + case GF_FOP_RMDIR: + CLIENT_PRE_FOP (rmdir, this, + &this_req->compound_req_u.compound_rmdir_req, + op_errno, out, + &args->loc, args->flags, args->xdata); + break; + case GF_FOP_SYMLINK: + CLIENT_PRE_FOP (symlink, this, + &this_req->compound_req_u.compound_symlink_req, + op_errno, out, + &args->loc, args->linkname, args->umask, + args->xdata); + if (!&local->loc) { + loc_copy (&local->loc, &args->loc); + loc_path (&local->loc, NULL); + } + break; + case GF_FOP_RENAME: + CLIENT_PRE_FOP (rename, this, + &this_req->compound_req_u.compound_rename_req, + op_errno, out, + &args->loc, &args->loc2, args->xdata); + break; + case GF_FOP_LINK: + CLIENT_PRE_FOP (link, this, + &this_req->compound_req_u.compound_link_req, + op_errno, out, + &args->loc, &args->loc2, args->xdata); + break; + case GF_FOP_TRUNCATE: + CLIENT_PRE_FOP (truncate, this, + &this_req->compound_req_u.compound_truncate_req, + op_errno, out, + &args->loc, args->offset, args->xdata); + break; + case GF_FOP_OPEN: + CLIENT_PRE_FOP (open, this, + &this_req->compound_req_u.compound_open_req, + op_errno, out, + &args->loc, args->fd, args->flags, + args->xdata); + if (!local->fd) + local->fd = fd_ref (args->fd); + break; + case GF_FOP_READ: + op_errno = client_pre_readv (this, + &this_req->compound_req_u.compound_read_req, + args->fd, args->size, args->offset, + args->flags, args->xdata); + + if (op_errno) { + op_errno = -op_errno; + goto out; + } + if (!local->fd) + local->fd = fd_ref (args->fd); + local->attempt_reopen = client_is_reopen_needed + (args->fd, this, remote_fd); + rsp_iobuf = iobuf_get2 (this->ctx->iobuf_pool, args->size); + if (rsp_iobuf == NULL) { + op_errno = ENOMEM; + goto out; + } + + if (!rsp_iobref) { + rsp_iobref = iobref_new (); + if (rsp_iobref == NULL) { + op_errno = ENOMEM; + goto out; + } + } + + iobref_add (rsp_iobref, rsp_iobuf); + iobuf_unref (rsp_iobuf); + + if (*rsp_count + 1 >= MAX_IOVEC) { + op_errno = ENOMEM; + goto out; + } + rsp_vector[*rsp_count].iov_base = iobuf_ptr (rsp_iobuf); + rsp_vector[*rsp_count].iov_len = iobuf_pagesize (rsp_iobuf); + rsp_iobuf = NULL; + if (args->size > rsp_vector[*rsp_count].iov_len) { + gf_msg (this->name, GF_LOG_WARNING, ENOMEM, + PC_MSG_NO_MEMORY, + "read-size (%lu) is bigger than iobuf size " + "(%lu)", + (unsigned long)args->size, + (unsigned long)rsp_vector[*rsp_count].iov_len); + op_errno = EINVAL; + goto out; + } + *rsp_count += 1; + + break; + case GF_FOP_WRITE: + op_errno = client_pre_writev (this, + &this_req->compound_req_u.compound_write_req, + args->fd, args->count, args->offset, + args->flags, args->xdata); + + if (op_errno) { + op_errno = -op_errno; + goto out; + } + if (!local->fd) + local->fd = fd_ref (args->fd); + local->attempt_reopen = client_is_reopen_needed + (args->fd, this, remote_fd); + + if (*req_count + 1 >= MAX_IOVEC) { + op_errno = ENOMEM; + goto out; + } + memcpy (&req_vector[*req_count], args->vector, + (args->count * sizeof(req_vector[0]))); + *req_count += args->count; + + if (!req_iobref) + req_iobref = args->iobref; + else + if (iobref_merge (req_iobref, args->iobref)) + goto out; + break; + case GF_FOP_STATFS: + CLIENT_PRE_FOP (statfs, this, + &this_req->compound_req_u.compound_statfs_req, + op_errno, out, + &args->loc, args->xdata); + break; + case GF_FOP_FLUSH: + CLIENT_PRE_FOP (flush, this, + &this_req->compound_req_u.compound_flush_req, + op_errno, out, + args->fd, args->xdata); + if (!local->fd) + local->fd = fd_ref (args->fd); + local->owner = frame->root->lk_owner; + break; + case GF_FOP_FSYNC: + CLIENT_PRE_FOP (fsync, this, + &this_req->compound_req_u.compound_fsync_req, + op_errno, out, + args->fd, args->datasync, args->xdata); + break; + case GF_FOP_SETXATTR: + CLIENT_PRE_FOP (setxattr, this, + &this_req->compound_req_u.compound_setxattr_req, + op_errno, out, + &args->loc, args->xattr, args->flags, + args->xdata); + break; + case GF_FOP_GETXATTR: + CLIENT_PRE_FOP (getxattr, this, + &this_req->compound_req_u.compound_getxattr_req, + op_errno, out, + &args->loc, args->name, args->xdata); + if (!&local->loc) { + loc_copy (&local->loc, &args->loc); + loc_path (&local->loc, NULL); + } + break; + case GF_FOP_REMOVEXATTR: + CLIENT_PRE_FOP (removexattr, this, + &this_req->compound_req_u.compound_removexattr_req, + op_errno, out, + &args->loc, args->name, args->xdata); + break; + case GF_FOP_OPENDIR: + CLIENT_PRE_FOP (opendir, this, + &this_req->compound_req_u.compound_opendir_req, + op_errno, out, + &args->loc, args->fd, args->xdata); + if (!local->fd) + local->fd = fd_ref (args->fd); + if (!&local->loc) { + loc_copy (&local->loc, &args->loc); + loc_path (&local->loc, NULL); + } + break; + case GF_FOP_FSYNCDIR: + CLIENT_PRE_FOP (fsyncdir, this, + &this_req->compound_req_u.compound_fsyncdir_req, + op_errno, out, + args->fd, args->datasync, args->xdata); + break; + case GF_FOP_ACCESS: + CLIENT_PRE_FOP (access, this, + &this_req->compound_req_u.compound_access_req, + op_errno, out, + &args->loc, args->mask, args->xdata); + break; + case GF_FOP_CREATE: + CLIENT_PRE_FOP (create, this, + &this_req->compound_req_u.compound_create_req, + op_errno, out, + &args->loc, args->fd, args->mode, args->flags, + args->umask, args->xdata); + if (!local->fd) + local->fd = fd_ref (args->fd); + + if (!&local->loc) { + loc_copy (&local->loc, &args->loc); + loc_path (&local->loc, NULL); + } + break; + case GF_FOP_FTRUNCATE: + CLIENT_PRE_FOP (ftruncate, this, + &this_req->compound_req_u.compound_ftruncate_req, + op_errno, out, + args->fd, args->offset, args->xdata); + break; + case GF_FOP_FSTAT: + CLIENT_PRE_FOP (fstat, this, + &this_req->compound_req_u.compound_fstat_req, + op_errno, out, + args->fd, args->xdata); + break; + case GF_FOP_LK: + CLIENT_PRE_FOP (lk, this, + &this_req->compound_req_u.compound_lk_req, + op_errno, out, + args->cmd, &args->lock, args->fd, args->xdata); + if (!local->fd) + local->fd = fd_ref (args->fd); + local->owner = frame->root->lk_owner; + break; + case GF_FOP_LOOKUP: + CLIENT_PRE_FOP (lookup, this, + &this_req->compound_req_u.compound_lookup_req, + op_errno, out, + &args->loc, args->xdata); + if (!&local->loc) { + loc_copy (&local->loc, &args->loc); + loc_path (&local->loc, NULL); + } + break; + case GF_FOP_READDIR: + CLIENT_PRE_FOP (readdir, this, + &this_req->compound_req_u.compound_readdir_req, + op_errno, out, + args->fd, args->size, args->offset, + args->xdata); + break; + case GF_FOP_INODELK: + CLIENT_PRE_FOP (inodelk, this, + &this_req->compound_req_u.compound_inodelk_req, + op_errno, out, + &args->loc, args->cmd, &args->lock, + args->volume, args->xdata); + break; + case GF_FOP_FINODELK: + CLIENT_PRE_FOP (finodelk, this, + &this_req->compound_req_u.compound_finodelk_req, + op_errno, out, + args->fd, args->cmd, &args->lock, + args->volume, args->xdata); + if (!local->fd) + local->fd = fd_ref (args->fd); + local->attempt_reopen = client_is_reopen_needed + (args->fd, this, remote_fd); + break; + case GF_FOP_ENTRYLK: + CLIENT_PRE_FOP (entrylk, this, + &this_req->compound_req_u.compound_entrylk_req, + op_errno, out, + &args->loc, args->entrylkcmd, + args->entrylktype, args->volume, + args->name, args->xdata); + break; + case GF_FOP_FENTRYLK: + CLIENT_PRE_FOP (fentrylk, this, + &this_req->compound_req_u.compound_fentrylk_req, + op_errno, out, + args->fd, args->entrylkcmd, + args->entrylktype, args->volume, + args->name, args->xdata); + break; + case GF_FOP_XATTROP: + CLIENT_PRE_FOP (xattrop, this, + &this_req->compound_req_u.compound_xattrop_req, + op_errno, out, + &args->loc, args->xattr, args->optype, + args->xdata); + break; + case GF_FOP_FXATTROP: + CLIENT_PRE_FOP (fxattrop, this, + &this_req->compound_req_u.compound_fxattrop_req, + op_errno, out, + args->fd, args->xattr, args->optype, + args->xdata); + if (!local->fd) + local->fd = fd_ref (args->fd); + local->attempt_reopen = client_is_reopen_needed + (args->fd, this, remote_fd); + break; + case GF_FOP_FGETXATTR: + CLIENT_PRE_FOP (fgetxattr, this, + &this_req->compound_req_u.compound_fgetxattr_req, + op_errno, out, + args->fd, args->name, args->xdata); + break; + case GF_FOP_FSETXATTR: + CLIENT_PRE_FOP (fsetxattr, this, + &this_req->compound_req_u.compound_fsetxattr_req, + op_errno, out, + args->fd, args->flags, args->xattr, + args->xdata); + break; + case GF_FOP_RCHECKSUM: + CLIENT_PRE_FOP (rchecksum, this, + &this_req->compound_req_u.compound_rchecksum_req, + op_errno, out, + args->fd, args->size, args->offset, + args->xdata); + break; + case GF_FOP_SETATTR: + CLIENT_PRE_FOP (setattr, this, + &this_req->compound_req_u.compound_setattr_req, + op_errno, out, + &args->loc, args->valid, &args->stat, + args->xdata); + break; + case GF_FOP_FSETATTR: + CLIENT_PRE_FOP (fsetattr, this, + &this_req->compound_req_u.compound_fsetattr_req, + op_errno, out, + args->fd, args->valid, &args->stat, + args->xdata); + break; + case GF_FOP_READDIRP: + CLIENT_PRE_FOP (readdirp, this, + &this_req->compound_req_u.compound_readdirp_req, + op_errno, out, + args->fd, args->size, args->offset, + args->xdata); + if (!local->fd) + local->fd = fd_ref (args->fd); + break; + case GF_FOP_FREMOVEXATTR: + CLIENT_PRE_FOP (fremovexattr, this, + &this_req->compound_req_u.compound_fremovexattr_req, + op_errno, out, + args->fd, args->name, args->xdata); + break; + case GF_FOP_FALLOCATE: + CLIENT_PRE_FOP (fallocate, this, + &this_req->compound_req_u.compound_fallocate_req, + op_errno, out, + args->fd, args->flags, args->offset, + args->size, args->xdata); + break; + case GF_FOP_DISCARD: + CLIENT_PRE_FOP (discard, this, + &this_req->compound_req_u.compound_discard_req, + op_errno, out, + args->fd, args->offset, args->size, + args->xdata); + break; + case GF_FOP_ZEROFILL: + CLIENT_PRE_FOP (zerofill, this, + &this_req->compound_req_u.compound_zerofill_req, + op_errno, out, + args->fd, args->offset, args->size, + args->xdata); + break; + case GF_FOP_IPC: + CLIENT_PRE_FOP (ipc, this, + &this_req->compound_req_u.compound_ipc_req, + op_errno, out, + args->cmd, args->xdata); + break; + case GF_FOP_SEEK: + CLIENT_PRE_FOP (seek, this, + &this_req->compound_req_u.compound_seek_req, + op_errno, out, + args->fd, args->offset, args->what, + args->xdata); + break; + case GF_FOP_LEASE: + CLIENT_PRE_FOP (lease, this, + &this_req->compound_req_u.compound_lease_req, + op_errno, out, &args->loc, &args->lease, + args->xdata); + default: + return ENOTSUP; + } + return 0; +out: + return op_errno; +} + +void +compound_request_cleanup (gfs3_compound_req *req) +{ + int i = 0; + int length = req->compound_req_array.compound_req_array_len; + compound_req *curr_req = NULL; + + + for (i = 0; i < length; i++) { + curr_req = &req->compound_req_array.compound_req_array_val[i]; + + switch (curr_req->fop_enum) { + case GF_FOP_STAT: + CLIENT_COMPOUND_FOP_CLEANUP (curr_req, stat); + break; + case GF_FOP_READLINK: + CLIENT_COMPOUND_FOP_CLEANUP (curr_req, readlink); + break; + case GF_FOP_MKNOD: + CLIENT_COMPOUND_FOP_CLEANUP (curr_req, mknod); + break; + case GF_FOP_MKDIR: + CLIENT_COMPOUND_FOP_CLEANUP (curr_req, mkdir); + break; + case GF_FOP_UNLINK: + CLIENT_COMPOUND_FOP_CLEANUP (curr_req, unlink); + break; + case GF_FOP_RMDIR: + CLIENT_COMPOUND_FOP_CLEANUP (curr_req, rmdir); + break; + case GF_FOP_SYMLINK: + CLIENT_COMPOUND_FOP_CLEANUP (curr_req, symlink); + break; + case GF_FOP_RENAME: + CLIENT_COMPOUND_FOP_CLEANUP (curr_req, rename); + break; + case GF_FOP_LINK: + CLIENT_COMPOUND_FOP_CLEANUP (curr_req, link); + break; + case GF_FOP_TRUNCATE: + CLIENT_COMPOUND_FOP_CLEANUP (curr_req, truncate); + break; + case GF_FOP_OPEN: + CLIENT_COMPOUND_FOP_CLEANUP (curr_req, open); + break; + case GF_FOP_READ: + CLIENT_COMPOUND_FOP_CLEANUP (curr_req, read); + break; + case GF_FOP_WRITE: + CLIENT_COMPOUND_FOP_CLEANUP (curr_req, write); + break; + case GF_FOP_STATFS: + CLIENT_COMPOUND_FOP_CLEANUP (curr_req, statfs); + break; + case GF_FOP_FLUSH: + CLIENT_COMPOUND_FOP_CLEANUP (curr_req, flush); + break; + case GF_FOP_FSYNC: + CLIENT_COMPOUND_FOP_CLEANUP (curr_req, fsync); + break; + case GF_FOP_SETXATTR: + { + gfs3_setxattr_req args = curr_req->compound_req_u.compound_setxattr_req; + GF_FREE (args.dict.dict_val); + CLIENT_COMPOUND_FOP_CLEANUP (curr_req, setxattr); + break; + } + case GF_FOP_GETXATTR: + CLIENT_COMPOUND_FOP_CLEANUP (curr_req, getxattr); + break; + case GF_FOP_REMOVEXATTR: + CLIENT_COMPOUND_FOP_CLEANUP (curr_req, removexattr); + break; + case GF_FOP_OPENDIR: + CLIENT_COMPOUND_FOP_CLEANUP (curr_req, opendir); + break; + case GF_FOP_FSYNCDIR: + CLIENT_COMPOUND_FOP_CLEANUP (curr_req, fsyncdir); + break; + case GF_FOP_ACCESS: + CLIENT_COMPOUND_FOP_CLEANUP (curr_req, access); + break; + case GF_FOP_CREATE: + CLIENT_COMPOUND_FOP_CLEANUP (curr_req, create); + break; + case GF_FOP_FTRUNCATE: + CLIENT_COMPOUND_FOP_CLEANUP (curr_req, ftruncate); + break; + case GF_FOP_FSTAT: + CLIENT_COMPOUND_FOP_CLEANUP (curr_req, fstat); + break; + case GF_FOP_LK: + CLIENT_COMPOUND_FOP_CLEANUP (curr_req, lk); + break; + case GF_FOP_LOOKUP: + CLIENT_COMPOUND_FOP_CLEANUP (curr_req, lookup); + break; + case GF_FOP_READDIR: + CLIENT_COMPOUND_FOP_CLEANUP (curr_req, readdir); + break; + case GF_FOP_INODELK: + CLIENT_COMPOUND_FOP_CLEANUP (curr_req, inodelk); + break; + case GF_FOP_FINODELK: + CLIENT_COMPOUND_FOP_CLEANUP (curr_req, finodelk); + break; + case GF_FOP_ENTRYLK: + CLIENT_COMPOUND_FOP_CLEANUP (curr_req, entrylk); + break; + case GF_FOP_FENTRYLK: + CLIENT_COMPOUND_FOP_CLEANUP (curr_req, fentrylk); + break; + case GF_FOP_XATTROP: + { + gfs3_xattrop_req args = curr_req->compound_req_u.compound_xattrop_req; + GF_FREE (args.dict.dict_val); + CLIENT_COMPOUND_FOP_CLEANUP (curr_req, xattrop); + break; + } + case GF_FOP_FXATTROP: + { + gfs3_fxattrop_req args = curr_req->compound_req_u.compound_fxattrop_req; + GF_FREE (args.dict.dict_val); + CLIENT_COMPOUND_FOP_CLEANUP (curr_req, fxattrop); + break; + } + case GF_FOP_FGETXATTR: + CLIENT_COMPOUND_FOP_CLEANUP (curr_req, fgetxattr); + break; + case GF_FOP_FSETXATTR: + { + gfs3_fsetxattr_req args = curr_req->compound_req_u.compound_fsetxattr_req; + GF_FREE (args.dict.dict_val); + CLIENT_COMPOUND_FOP_CLEANUP (curr_req, fsetxattr); + break; + } + case GF_FOP_RCHECKSUM: + CLIENT_COMPOUND_FOP_CLEANUP (curr_req, rchecksum); + break; + case GF_FOP_SETATTR: + CLIENT_COMPOUND_FOP_CLEANUP (curr_req, setattr); + break; + case GF_FOP_FSETATTR: + CLIENT_COMPOUND_FOP_CLEANUP (curr_req, fsetattr); + break; + case GF_FOP_READDIRP: + { + gfs3_readdirp_req args = curr_req->compound_req_u.compound_readdirp_req; + GF_FREE (args.dict.dict_val); + break; + } + case GF_FOP_FREMOVEXATTR: + CLIENT_COMPOUND_FOP_CLEANUP (curr_req, fremovexattr); + break; + case GF_FOP_FALLOCATE: + CLIENT_COMPOUND_FOP_CLEANUP (curr_req, fallocate); + break; + case GF_FOP_DISCARD: + CLIENT_COMPOUND_FOP_CLEANUP (curr_req, discard); + break; + case GF_FOP_ZEROFILL: + CLIENT_COMPOUND_FOP_CLEANUP (curr_req, zerofill); + break; + case GF_FOP_IPC: + CLIENT_COMPOUND_FOP_CLEANUP (curr_req, ipc); + break; + case GF_FOP_SEEK: + CLIENT_COMPOUND_FOP_CLEANUP (curr_req, seek); + break; + default: + break; + } + } + + return; +} diff --git a/xlators/protocol/client/src/client-mem-types.h b/xlators/protocol/client/src/client-mem-types.h index f6573da2ddd..e6cb9a2e0f4 100644 --- a/xlators/protocol/client/src/client-mem-types.h +++ b/xlators/protocol/client/src/client-mem-types.h @@ -20,6 +20,8 @@ enum gf_client_mem_types_ { gf_client_mt_clnt_fdctx_t, gf_client_mt_clnt_lock_t, gf_client_mt_clnt_fd_lk_local_t, + gf_client_mt_clnt_args_t, + gf_client_mt_compound_req_t, gf_client_mt_end, }; #endif /* __CLIENT_MEM_TYPES_H__ */ diff --git a/xlators/protocol/client/src/client-rpc-fops.c b/xlators/protocol/client/src/client-rpc-fops.c index b09c169b806..a80c9e610d8 100644 --- a/xlators/protocol/client/src/client-rpc-fops.c +++ b/xlators/protocol/client/src/client-rpc-fops.c @@ -3030,6 +3030,90 @@ client3_3_releasedir_cbk (struct rpc_req *req, struct iovec *iov, int count, } int +client3_3_compound_cbk (struct rpc_req *req, struct iovec *iov, int count, + void *myframe) +{ + gfs3_compound_rsp rsp = {0,}; + compound_args_cbk_t *args_cbk = NULL; + call_frame_t *frame = NULL; + int ret = -1; + xlator_t *this = NULL; + dict_t *xdata = NULL; + clnt_local_t *local = NULL; + int op_errno = 0; + int i,length = 0; + + this = THIS; + + frame = myframe; + local = frame->local; + + if (-1 == req->rpc_status) { + op_errno = ENOTCONN; + goto out; + } + + ret = xdr_to_generic (*iov, &rsp, (xdrproc_t)xdr_gfs3_compound_rsp); + if (ret < 0) { + gf_msg (this->name, GF_LOG_ERROR, EINVAL, + PC_MSG_XDR_DECODING_FAILED, "XDR decoding failed"); + op_errno = EINVAL; + goto out; + } + + args_cbk = GF_CALLOC (1, sizeof (compound_args_cbk_t), gf_mt_compound_rsp_t); + if (!args_cbk) { + op_errno = ENOMEM; + goto out; + } + + length = args_cbk->fop_length = local->length; + + args_cbk->rsp_list = GF_CALLOC (length, sizeof (default_args_cbk_t), + gf_mt_default_args_cbk_t); + if (!args_cbk->rsp_list) { + op_errno = ENOMEM; + goto out; + } + + op_errno = rsp.op_errno; + + for (i = 0; i < args_cbk->fop_length; i++) { + ret = client_process_response (frame, this, req, &rsp, + args_cbk, i); + if (ret) { + op_errno = -ret; + ret = -1; + goto out; + } + + } + + GF_PROTOCOL_DICT_UNSERIALIZE (this, xdata, (rsp.xdata.xdata_val), + (rsp.xdata.xdata_len), ret, + rsp.op_errno, out); + + ret = 0; +out: + CLIENT_STACK_UNWIND (compound, frame, ret, + gf_error_to_errno (op_errno), args_cbk, xdata); + + free (rsp.xdata.xdata_val); + + if (xdata) + dict_unref (xdata); + + if (args_cbk->rsp_list) { + for (i = 0; i < length; i++) { + args_cbk_wipe (&args_cbk->rsp_list[i]); + } + } + GF_FREE (args_cbk->rsp_list); + GF_FREE (args_cbk); + return 0; +} + +int client_fdctx_destroy (xlator_t *this, clnt_fd_ctx_t *fdctx) { clnt_conf_t *conf = NULL; @@ -5889,6 +5973,150 @@ unwind: return 0; } +/* Brief explanation of gfs3_compound_req structure : + * 1) It consists of version of compounding. + * 2) A compound-fop enum, new enum for compound fops + * 3) A 'compound_req_arrray' structure that has + * a) array len - based on the number of fops compounded + * b) compound_req_array_val - pointer to an array of compound_req's + * 4) compound_req - structure that contains: + * a) fop enum of type glusterfs_fop_t + * b) union of structures of xdr requests of all fops. + */ + +int32_t +client3_3_compound (call_frame_t *frame, xlator_t *this, void *data) +{ + clnt_conf_t *conf = NULL; + compound_args_t *c_args = data; + default_args_t *args = NULL; + gfs3_compound_req req = {0,}; + clnt_local_t *local = NULL; + int op_errno = ENOMEM; + int ret = 0; + int i = 0; + int rsp_count = 0; + struct iovec rsp_vector[MAX_IOVEC] = {{0}, }; + struct iovec req_vector[MAX_IOVEC] = {{0}, }; + struct iovec vector[MAX_IOVEC] = {{0}, }; + struct iovec *rsphdr = NULL; + struct iobref *req_iobref = NULL; + struct iobref *rsp_iobref = NULL; + struct iobref *rsphdr_iobref = NULL; + struct iobuf *rsphdr_iobuf = NULL; + int rsphdr_count = 0; + int req_count = 0; + int index = 0; + dict_t *xdata = c_args->xdata; + + GF_ASSERT (frame); + + if (!this || !data) + goto unwind; + + memset (req_vector, 0, sizeof (req_vector)); + memset (rsp_vector, 0, sizeof (rsp_vector)); + + conf = this->private; + + local = mem_get0 (this->local_pool); + if (!local) { + op_errno = ENOMEM; + goto unwind; + } + frame->local = local; + + local->length = c_args->fop_length; + local->compound_args = c_args; + + rsphdr_iobref = iobref_new (); + if (rsphdr_iobref == NULL) { + goto unwind; + } + + /* TODO: what is the size we should send ? */ + rsphdr_iobuf = iobuf_get (this->ctx->iobuf_pool); + if (rsphdr_iobuf == NULL) { + goto unwind; + } + + iobref_add (rsphdr_iobref, rsphdr_iobuf); + iobuf_unref (rsphdr_iobuf); + rsphdr = &vector[0]; + rsphdr->iov_base = iobuf_ptr (rsphdr_iobuf); + rsphdr->iov_len = iobuf_pagesize (rsphdr_iobuf); + rsphdr_count = 1; + local->iobref = rsp_iobref; + rsphdr_iobuf = NULL; + rsphdr_iobref = NULL; + + req.compound_fop_enum = c_args->fop_enum; + req.compound_req_array.compound_req_array_len = c_args->fop_length; + /*TODO : Talk to Sowmya about this */ + req.compound_version = 0; + if (xdata) { + GF_PROTOCOL_DICT_SERIALIZE (this, xdata, + (&req.xdata.xdata_val), + req.xdata.xdata_len, + op_errno, unwind); + } + + req.compound_req_array.compound_req_array_val = GF_CALLOC (local->length, + sizeof (compound_req), + gf_client_mt_compound_req_t); + + if (!req.compound_req_array.compound_req_array_val) { + op_errno = ENOMEM; + goto unwind; + } + + for (i = 0; i < local->length; i++) { + ret = client_handle_fop_requirements (this, frame, + &req, local, + req_iobref, rsp_iobref, + req_vector, + rsp_vector, &req_count, + &rsp_count, + &c_args->req_list[i], + c_args->enum_list[i], + index); + if (ret) { + op_errno = ret; + goto unwind; + } + index++; + } + + local->iobref2 = rsp_iobref; + rsp_iobref = NULL; + + ret = client_submit_compound_request (this, &req, frame, conf->fops, + GFS3_OP_COMPOUND, client3_3_compound_cbk, + req_vector, req_count, local->iobref, + rsphdr, rsphdr_count, + rsp_vector, rsp_count, + local->iobref2, + (xdrproc_t) xdr_gfs3_compound_req); + + GF_FREE (req.xdata.xdata_val); + + compound_request_cleanup (&req); + return 0; +unwind: + CLIENT_STACK_UNWIND (compound, frame, -1, op_errno, NULL, NULL); + + if (rsp_iobref) + iobref_unref (rsp_iobref); + + if (rsphdr_iobref) + iobref_unref (rsphdr_iobref); + + GF_FREE (req.xdata.xdata_val); + + compound_request_cleanup (&req); + return 0; +} + /* Table Specific to FOPS */ diff --git a/xlators/protocol/client/src/client.c b/xlators/protocol/client/src/client.c index aae712acd4b..c37c1e25b44 100644 --- a/xlators/protocol/client/src/client.c +++ b/xlators/protocol/client/src/client.c @@ -339,6 +339,123 @@ out: } +int +client_submit_compound_request (xlator_t *this, void *req, call_frame_t *frame, + rpc_clnt_prog_t *prog, int procnum, fop_cbk_fn_t cbkfn, + struct iovec *req_payload, int req_count, + struct iobref *iobref, struct iovec *rsphdr, + int rsphdr_count, struct iovec *rsp_payload, + int rsp_payload_count, struct iobref *rsp_iobref, + xdrproc_t xdrproc) +{ + int ret = -1; + clnt_conf_t *conf = NULL; + struct iovec iov = {0, }; + struct iobuf *iobuf = NULL; + int count = 0; + struct iobref *new_iobref = NULL; + ssize_t xdr_size = 0; + struct rpc_req rpcreq = {0, }; + + GF_VALIDATE_OR_GOTO ("client", this, out); + GF_VALIDATE_OR_GOTO (this->name, prog, out); + GF_VALIDATE_OR_GOTO (this->name, frame, out); + + conf = this->private; + + /* If 'setvolume' is not successful, we should not send frames to + * server + */ + + if (!conf->connected) { + gf_msg_debug (this->name, 0, + "connection in disconnected state"); + goto out; + } + + if (req && xdrproc) { + xdr_size = xdr_sizeof (xdrproc, req); + iobuf = iobuf_get2 (this->ctx->iobuf_pool, xdr_size); + if (!iobuf) { + goto out; + }; + + new_iobref = iobref_new (); + if (!new_iobref) { + goto out; + } + + if (iobref != NULL) { + ret = iobref_merge (new_iobref, iobref); + if (ret != 0) { + goto out; + } + } + + ret = iobref_add (new_iobref, iobuf); + if (ret != 0) { + goto out; + } + + iov.iov_base = iobuf->ptr; + iov.iov_len = iobuf_size (iobuf); + + /* Create the xdr payload */ + ret = xdr_serialize_generic (iov, req, xdrproc); + if (ret == -1) { + /* callingfn so that, we can get to know which xdr + function was called */ + gf_log_callingfn (this->name, GF_LOG_WARNING, + "XDR payload creation failed"); + goto out; + } + iov.iov_len = ret; + count = 1; + } + + /* do not send all groups if they are resolved server-side */ + if (!conf->send_gids) { + if (frame->root->ngrps <= SMALL_GROUP_COUNT) { + frame->root->groups_small[0] = frame->root->gid; + frame->root->groups = frame->root->groups_small; + } + frame->root->ngrps = 1; + } + + /* Send the msg */ + ret = rpc_clnt_submit (conf->rpc, prog, procnum, cbkfn, &iov, count, + req_payload, req_count, new_iobref, frame, + rsphdr, rsphdr_count, + rsp_payload, rsp_payload_count, rsp_iobref); + + if (ret < 0) { + gf_msg_debug (this->name, 0, "rpc_clnt_submit failed"); + } + + ret = 0; + + if (new_iobref) + iobref_unref (new_iobref); + + if (iobuf) + iobuf_unref (iobuf); + + return ret; + +out: + rpcreq.rpc_status = -1; + + cbkfn (&rpcreq, NULL, 0, frame); + + if (new_iobref) + iobref_unref (new_iobref); + + if (iobuf) + iobuf_unref (iobuf); + + return 0; +} + int32_t client_forget (xlator_t *this, inode_t *inode) { @@ -1980,6 +2097,32 @@ out: } +int32_t +client_compound (call_frame_t *frame, xlator_t *this, + void *data, dict_t *xdata) +{ + int ret = -1; + clnt_conf_t *conf = NULL; + compound_args_t *args = data; + rpc_clnt_procedure_t *proc = NULL; + + conf = this->private; + if (!conf || !conf->fops) + goto out; + + args->xdata = xdata; + + proc = &conf->fops->proctable[GF_FOP_COMPOUND]; + if (proc->fn) + ret = proc->fn (frame, this, args); +out: + if (ret) + STACK_UNWIND_STRICT (compound, frame, -1, ENOTCONN, + NULL, NULL); + + return 0; +} + int client_mark_fd_bad (xlator_t *this) { @@ -2749,6 +2892,7 @@ struct xlator_fops fops = { .ipc = client_ipc, .seek = client_seek, .lease = client_lease, + .compound = client_compound, }; diff --git a/xlators/protocol/client/src/client.h b/xlators/protocol/client/src/client.h index e27b1dbca21..efa9d21437a 100644 --- a/xlators/protocol/client/src/client.h +++ b/xlators/protocol/client/src/client.h @@ -20,6 +20,7 @@ #include "client-mem-types.h" #include "protocol-common.h" #include "glusterfs3.h" +#include "glusterfs3-xdr.h" #include "fd-lk.h" #include "defaults.h" #include "default-args.h" @@ -42,6 +43,47 @@ typedef enum { FALLBACK_TO_ANON_FD = 1 } clnt_remote_fd_flags_t; +#define CLIENT_POST_FOP(fop, this_rsp_u, this_args_cbk, params ...) \ + do { \ + gf_common_rsp *_this_rsp = &this_rsp_u->compound_rsp_u.compound_##fop##_rsp; \ + int _op_ret = 0; \ + int _op_errno = 0; \ + \ + _op_ret = _this_rsp->op_ret; \ + _op_errno = gf_error_to_errno (_this_rsp->op_errno); \ + args_##fop##_cbk_store (this_args_cbk, _op_ret, _op_errno, params); \ + } while (0) + +#define CLIENT_POST_FOP_TYPE(fop, this_rsp_u, this_args_cbk, params ...) \ + do { \ + gfs3_##fop##_rsp *_this_rsp = &this_rsp_u->compound_rsp_u.compound_##fop##_rsp; \ + int _op_ret = 0; \ + int _op_errno = 0; \ + \ + _op_ret = _this_rsp->op_ret; \ + _op_errno = gf_error_to_errno (_this_rsp->op_errno); \ + args_##fop##_cbk_store (this_args_cbk, _op_ret, _op_errno, params); \ + } while (0) + +#define CLIENT_PRE_FOP(fop, xl, compound_req, op_errno, label, params ...) \ + do { \ + gfs3_##fop##_req *_req = (gfs3_##fop##_req *) compound_req; \ + int _ret = 0; \ + \ + _ret = client_pre_##fop (xl, _req, params); \ + if (_ret < 0) { \ + op_errno = -ret; \ + goto label; \ + } \ + } while (0) + +#define CLIENT_COMPOUND_FOP_CLEANUP(curr_req, fop) \ + do { \ + gfs3_##fop##_req *_req = &curr_req->compound_req_u.compound_##fop##_req;\ + \ + GF_FREE (_req->xdata.xdata_val); \ + } while (0) + #define CLIENT_GET_REMOTE_FD(xl, fd, flags, remote_fd, op_errno, label) \ do { \ int _ret = 0; \ @@ -185,6 +227,11 @@ typedef struct client_local { pthread_mutex_t mutex; char *name; gf_boolean_t attempt_reopen; + /* required for compound fops */ + struct iobref *iobref2; + compound_args_t *compound_args; + unsigned int length; /* length of a compound fop */ + unsigned int read_length; /* defines the last processed length for a compound read */ } clnt_local_t; typedef struct client_args { @@ -238,6 +285,15 @@ int client_submit_request (xlator_t *this, void *req, struct iovec *rsp_payload, int rsp_count, struct iobref *rsp_iobref, xdrproc_t xdrproc); +int +client_submit_compound_request (xlator_t *this, void *req, call_frame_t *frame, + rpc_clnt_prog_t *prog, int procnum, fop_cbk_fn_t cbkfn, + struct iovec *req_vector, int req_count, + struct iobref *iobref, struct iovec *rsphdr, + int rsphdr_count, struct iovec *rsp_payload, + int rsp_payload_count, struct iobref *rsp_iobref, + xdrproc_t xdrproc); + int unserialize_rsp_dirent (xlator_t *this, struct gfs3_readdir_rsp *rsp, gf_dirent_t *entries); int unserialize_rsp_direntp (xlator_t *this, fd_t *fd, @@ -283,4 +339,25 @@ client_notify_dispatch_uniq (xlator_t *this, int32_t event, void *data, ...); gf_boolean_t client_is_reopen_needed (fd_t *fd, xlator_t *this, int64_t remote_fd); + +int +client_add_fd_to_saved_fds (xlator_t *this, fd_t *fd, loc_t *loc, int32_t flags, + int64_t remote_fd, int is_dir); +int +client_handle_fop_requirements (xlator_t *this, call_frame_t *frame, + gfs3_compound_req *req, + clnt_local_t *local, + struct iobref *req_iobref, + struct iobref *rsp_iobref, + struct iovec *req_vector, + struct iovec *rsp_vector, int *req_count, + int *rsp_count, default_args_t *args, + int fop_enum, int index); +int +client_process_response (call_frame_t *frame, xlator_t *this, + struct rpc_req *req, + gfs3_compound_rsp *rsp, compound_args_cbk_t *args_cbk, + int index); +void +compound_request_cleanup (gfs3_compound_req *req); #endif /* !_CLIENT_H */ |