diff options
author | Amar Tumballi <amar@gluster.com> | 2010-06-21 07:00:04 +0000 |
---|---|---|
committer | Anand V. Avati <avati@dev.gluster.com> | 2010-06-21 20:21:10 -0700 |
commit | fdd20492638fe98a62b5e6d5e82f18cf4799fd1a (patch) | |
tree | 98082d7bfdc66157f40666f2070d3a45b582327a /xlators/protocol/client | |
parent | b9b8734a9496ccf5f8ed5527dc7714930a59948b (diff) |
rpc protocol
Signed-off-by: Amar Tumballi <amar@gluster.com>
Signed-off-by: Raghavendra G <raghavendra@gluster.com>
Signed-off-by: Anand V. Avati <avati@dev.gluster.com>
BUG: 875 (Implement a new protocol to provide proper backward/forward compatibility)
URL: http://bugs.gluster.com/cgi-bin/bugzilla3/show_bug.cgi?id=875
Diffstat (limited to 'xlators/protocol/client')
-rw-r--r-- | xlators/protocol/client/Makefile.am | 1 | ||||
-rw-r--r-- | xlators/protocol/client/src/Makefile.am | 16 | ||||
-rw-r--r-- | xlators/protocol/client/src/client-handshake.c | 738 | ||||
-rw-r--r-- | xlators/protocol/client/src/client-helpers.c | 109 | ||||
-rw-r--r-- | xlators/protocol/client/src/client-mem-types.h | 32 | ||||
-rw-r--r-- | xlators/protocol/client/src/client.c | 1791 | ||||
-rw-r--r-- | xlators/protocol/client/src/client.h | 125 | ||||
-rw-r--r-- | xlators/protocol/client/src/client3_1-fops.c | 4662 |
8 files changed, 7474 insertions, 0 deletions
diff --git a/xlators/protocol/client/Makefile.am b/xlators/protocol/client/Makefile.am new file mode 100644 index 00000000..af437a64 --- /dev/null +++ b/xlators/protocol/client/Makefile.am @@ -0,0 +1 @@ +SUBDIRS = src diff --git a/xlators/protocol/client/src/Makefile.am b/xlators/protocol/client/src/Makefile.am new file mode 100644 index 00000000..40281467 --- /dev/null +++ b/xlators/protocol/client/src/Makefile.am @@ -0,0 +1,16 @@ + +xlator_LTLIBRARIES = client.la +xlatordir = $(libdir)/glusterfs/$(PACKAGE_VERSION)/xlator/alpha/protocol + +client_la_LDFLAGS = -module -avoidversion + +client_la_LIBADD = $(top_builddir)/libglusterfs/src/libglusterfs.la \ + $(top_builddir)/xlators/protocol/rpc/rpc-lib/src/libgfrpc.la \ + $(top_builddir)/xlators/protocol/lib/src/libgfproto1.la + +client_la_SOURCES = client.c client-helpers.c client3_1-fops.c client-handshake.c +noinst_HEADERS = client.h client-mem-types.h + +AM_CFLAGS = -fPIC -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE -Wall -D$(GF_HOST_OS) \ + -I$(top_srcdir)/libglusterfs/src -shared -nostartfiles $(GF_CFLAGS) \ + -I$(top_srcdir)/xlators/protocol/lib/src -I$(top_srcdir)/xlators/protocol/rpc/rpc-lib/src/ diff --git a/xlators/protocol/client/src/client-handshake.c b/xlators/protocol/client/src/client-handshake.c new file mode 100644 index 00000000..79cabd10 --- /dev/null +++ b/xlators/protocol/client/src/client-handshake.c @@ -0,0 +1,738 @@ +/* + Copyright (c) 2010 Gluster, Inc. <http://www.gluster.com> + This file is part of GlusterFS. + + GlusterFS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3 of the License, + or (at your option) any later version. + + GlusterFS is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see + <http://www.gnu.org/licenses/>. +*/ + +#ifndef _CONFIG_H +#define _CONFIG_H +#include "config.h" +#endif + +#include "client.h" +#include "xlator.h" +#include "defaults.h" +#include "glusterfs.h" +#include "msg-xdr.h" +#include "statedump.h" +#include "compat-errno.h" + +extern rpc_clnt_prog_t clnt3_1_fop_prog; +extern rpc_clnt_prog_t clnt3_1_mgmt_prog; + +/* Handshake */ + +void +rpc_client_ping_timer_expired (void *data) +{ + rpc_transport_t *trans = NULL; + rpc_clnt_connection_t *conn = NULL; + int disconnect = 0; + int transport_activity = 0; + struct timeval timeout = {0, }; + struct timeval current = {0, }; + struct rpc_clnt *clnt = NULL; + xlator_t *this = NULL; + clnt_conf_t *conf = NULL; + + if (!data) { + goto out; + } + + this = data; + conf = this->private; + + conn = &conf->rpc->conn; + trans = conn->trans; + + if (!clnt || !trans) { + goto out; + } + + pthread_mutex_lock (&conn->lock); + { + if (conn->ping_timer) + gf_timer_call_cancel (this->ctx, + conn->ping_timer); + gettimeofday (¤t, NULL); + + if (((current.tv_sec - conn->last_received.tv_sec) < + conf->opt.ping_timeout) + || ((current.tv_sec - conn->last_sent.tv_sec) < + conf->opt.ping_timeout)) { + transport_activity = 1; + } + + if (transport_activity) { + gf_log (trans->name, GF_LOG_TRACE, + "ping timer expired but transport activity " + "detected - not bailing transport"); + timeout.tv_sec = conf->opt.ping_timeout; + timeout.tv_usec = 0; + + conn->ping_timer = + gf_timer_call_after (this->ctx, timeout, + rpc_client_ping_timer_expired, + (void *) this); + if (conn->ping_timer == NULL) + gf_log (trans->name, GF_LOG_DEBUG, + "unable to setup timer"); + + } else { + conn->ping_started = 0; + conn->ping_timer = NULL; + disconnect = 1; + } + } + pthread_mutex_unlock (&conn->lock); + + if (disconnect) { + gf_log (trans->name, GF_LOG_ERROR, + "Server %s has not responded in the last %d " + "seconds, disconnecting.", + conn->trans->peerinfo.identifier, + conf->opt.ping_timeout); + + rpc_transport_disconnect (conn->trans); + } + +out: + return; +} + + +void +client_start_ping (void *data) +{ + xlator_t *this = NULL; + clnt_conf_t *conf = NULL; + rpc_clnt_connection_t *conn = NULL; + int32_t ret = -1; + struct timeval timeout = {0, }; + call_frame_t *frame = NULL; + int frame_count = 0; + rpc_transport_t *trans = NULL; + + this = data; + conf = this->private; + + conn = &conf->rpc->conn; + trans = conn->trans; + + if (conf->opt.ping_timeout == 0) + return; + + pthread_mutex_lock (&conn->lock); + { + if (conn->ping_timer) + gf_timer_call_cancel (this->ctx, conn->ping_timer); + + conn->ping_timer = NULL; + conn->ping_started = 0; + + if (conn->saved_frames) + /* treat the case where conn->saved_frames is NULL + as no pending frames */ + frame_count = conn->saved_frames->count; + + if ((frame_count == 0) || !conn->connected) { + /* using goto looked ugly here, + * hence getting out this way */ + /* unlock */ + pthread_mutex_unlock (&conn->lock); + return; + } + + if (frame_count < 0) { + gf_log (this->name, GF_LOG_DEBUG, + "saved_frames->count is %"PRId64, + conn->saved_frames->count); + conn->saved_frames->count = 0; + } + + timeout.tv_sec = conf->opt.ping_timeout; + timeout.tv_usec = 0; + + conn->ping_timer = + gf_timer_call_after (this->ctx, timeout, + rpc_client_ping_timer_expired, + (void *) this); + + if (conn->ping_timer == NULL) { + gf_log (this->name, GF_LOG_DEBUG, + "unable to setup timer"); + } else { + conn->ping_started = 1; + } + } + pthread_mutex_unlock (&conn->lock); + + frame = create_frame (this, this->ctx->pool); + if (!frame) + goto fail; + + ret = client_submit_request (this, NULL, frame, conf->handshake, + GF_HNDSK_PING, NULL, NULL); + + return; +fail: + + if (frame) { + STACK_DESTROY (frame->root); + } + + return; +} + + +int +client_ping_cbk (struct rpc_req *req, struct iovec *iov, int count, + void *myframe) +{ + xlator_t *this = NULL; + rpc_clnt_connection_t *conn = NULL; + struct timeval timeout = {0, }; + call_frame_t *frame = NULL; + clnt_conf_t *conf = NULL; + + frame = myframe; + + this = frame->this; + conf = this->private; + conn = &conf->rpc->conn; + + if (req->rpc_status == -1) { + /* timer expired and transport bailed out */ + gf_log (this->name, GF_LOG_DEBUG, "timer must have expired"); + goto out; + } + + pthread_mutex_lock (&conn->lock); + { + timeout.tv_sec = conf->opt.ping_timeout; + timeout.tv_usec = 0; + + gf_timer_call_cancel (this->ctx, + conn->ping_timer); + + conn->ping_timer = + gf_timer_call_after (this->ctx, timeout, + client_start_ping, (void *)this); + + if (conn->ping_timer == NULL) + gf_log (this->name, GF_LOG_DEBUG, + "gf_timer_call_after() returned NULL"); + } + pthread_mutex_unlock (&conn->lock); +out: + STACK_DESTROY (frame->root); + return 0; +} + + +int +client_getspec_cbk (struct rpc_req *req, struct iovec *iov, int count, void *myframe) +{ + gf_getspec_rsp rsp = {0,}; + call_frame_t *frame = NULL; + clnt_conf_t *conf = NULL; + int ret = 0; + char spec[(32*1024)] = {0,}; + + frame = myframe; + conf = frame->this->private; + + if (-1 == req->rpc_status) { + rsp.op_ret = -1; + rsp.op_errno = EINVAL; + goto out; + } + + rsp.spec = spec; + ret = xdr_to_dump_version_rsp (*iov, &rsp); + if (ret < 0) { + gf_log ("", GF_LOG_ERROR, "error"); + rsp.op_ret = -1; + rsp.op_errno = EINVAL; + goto out; + } + + if (-1 == rsp.op_ret) { + gf_log (frame->this->name, GF_LOG_ERROR, + "failed to get the 'volume file' from server"); + goto out; + } + +out: + /* no _STRICT for mops */ + STACK_UNWIND_STRICT (getspec, frame, rsp.op_ret, rsp.op_errno, rsp.spec); + return 0; +} + + +int +client_post_handshake (call_frame_t *frame, xlator_t *this) +{ + clnt_conf_t *conf = NULL; + clnt_fd_ctx_t *tmp = NULL; + clnt_fd_ctx_t *fdctx = NULL; + xlator_list_t *parent = NULL; + struct list_head reopen_head; + + if (!this || !this->private) + goto out; + + conf = this->private; + INIT_LIST_HEAD (&reopen_head); + + pthread_mutex_lock (&conf->lock); + { + list_for_each_entry_safe (fdctx, tmp, &conf->saved_fds, + sfd_pos) { + if (fdctx->remote_fd != -1) + continue; + + list_del_init (&fdctx->sfd_pos); + list_add_tail (&fdctx->sfd_pos, &reopen_head); + } + } + pthread_mutex_unlock (&conf->lock); + + list_for_each_entry_safe (fdctx, tmp, &reopen_head, sfd_pos) { + list_del_init (&fdctx->sfd_pos); + + if (fdctx->is_dir) + protocol_client_reopendir (this, fdctx); + else + protocol_client_reopen (this, fdctx); + } + + parent = this->parents; + + while (parent) { + xlator_notify (parent->xlator, GF_EVENT_CHILD_UP, + this); + parent = parent->next; + } + +out: + return 0; +} + +int +client_setvolume_cbk (struct rpc_req *req, struct iovec *iov, int count, void *myframe) +{ + call_frame_t *frame = NULL; + clnt_conf_t *conf = NULL; + xlator_t *this = NULL; + dict_t *reply = NULL; + xlator_list_t *parent = NULL; + char *process_uuid = NULL; + char *remote_error = NULL; + char *remote_subvol = NULL; + rpc_transport_t *peer_trans = NULL; + gf_setvolume_rsp rsp = {0,}; + uint64_t peertrans_int = 0; + int ret = 0; + int op_ret = 0; + int op_errno = 0; + + frame = myframe; + this = frame->this; + conf = this->private; + + if (-1 == req->rpc_status) { + op_ret = -1; + op_errno = EINVAL; + goto out; + } + + ret = xdr_to_setvolume_rsp (*iov, &rsp); + if (ret < 0) { + gf_log ("", GF_LOG_ERROR, "error"); + op_errno = EINVAL; + op_ret = -1; + goto out; + } + op_ret = rsp.op_ret; + op_errno = gf_error_to_errno (rsp.op_errno); + if (-1 == rsp.op_ret) { + gf_log (frame->this->name, GF_LOG_WARNING, + "failed to set the volume"); + } + + reply = dict_new (); + if (!reply) + goto out; + + if (rsp.dict.dict_len) { + ret = dict_unserialize (rsp.dict.dict_val, + rsp.dict.dict_len, &reply); + if (ret < 0) { + gf_log (frame->this->name, GF_LOG_DEBUG, + "failed to unserialize buffer to dict"); + goto out; + } + } + + ret = dict_get_str (reply, "ERROR", &remote_error); + if (ret < 0) { + gf_log (this->name, GF_LOG_DEBUG, + "failed to get ERROR string from reply dict"); + } + + ret = dict_get_str (reply, "process-uuid", &process_uuid); + if (ret < 0) { + gf_log (this->name, GF_LOG_DEBUG, + "failed to get 'process-uuid' from reply dict"); + } + + if (op_ret < 0) { + gf_log (this->name, GF_LOG_ERROR, + "SETVOLUME on remote-host failed: %s", + remote_error ? remote_error : strerror (op_errno)); + errno = op_errno; + if (op_errno == ESTALE) { + parent = this->parents; + while (parent) { + xlator_notify (parent->xlator, + GF_EVENT_VOLFILE_MODIFIED, + this); + parent = parent->next; + } + } + goto out; + } + ret = dict_get_str (this->options, "remote-subvolume", + &remote_subvol); + if (!remote_subvol) + goto out; + + if (process_uuid && + !strcmp (this->ctx->process_uuid, process_uuid)) { + ret = dict_get_uint64 (reply, "transport-ptr", + &peertrans_int); + + peer_trans = (void *) (long) (peertrans_int); + + gf_log (this->name, GF_LOG_WARNING, + "attaching to the local volume '%s'", + remote_subvol); + + if (req->conn) { + /* TODO: Some issues with this logic at present */ + //rpc_transport_setpeer (req->conn->trans, peer_trans); + } + } + + gf_log (this->name, GF_LOG_NORMAL, + "Connected to %s, attached to remote volume '%s'.", + conf->rpc->conn.trans->peerinfo.identifier, + remote_subvol); + + rpc_clnt_set_connected (&conf->rpc->conn); + + op_ret = 0; + conf->connecting = 0; + + /* TODO: more to test */ + client_post_handshake (frame, frame->this); + +out: + + if (-1 == op_ret) { + /* Let the connection/re-connection happen in + * background, for now, don't hang here, + * tell the parents that i am all ok.. + */ + parent = this->parents; + while (parent) { + xlator_notify (parent->xlator, + GF_EVENT_CHILD_CONNECTING, this); + parent = parent->next; + } + + conf->connecting= 1; + } + + if (rsp.dict.dict_val) + free (rsp.dict.dict_val); + + STACK_DESTROY (frame->root); + + if (reply) + dict_unref (reply); + + return 0; +} + +int +client_setvolume (xlator_t *this, struct rpc_clnt *rpc) +{ + int ret = 0; + gf_setvolume_req req = {0,}; + call_frame_t *fr = NULL; + char *process_uuid_xl = NULL; + clnt_conf_t *conf = NULL; + dict_t *options = NULL; + + options = this->options; + conf = this->private; + + if (conf->fops || !dict_get (options, "fops-version")) { + ret = dict_set_int32 (options, "fops-version", + conf->fops->prognum); + if (ret < 0) { + gf_log (this->name, GF_LOG_ERROR, + "failed to set version-fops(%d) in handshake msg", + conf->fops->prognum); + goto fail; + } + } + + if (conf->mgmt) { + ret = dict_set_int32 (options, "mgmt-version", conf->mgmt->prognum); + if (ret < 0) { + gf_log (this->name, GF_LOG_ERROR, + "failed to set version-mgmt(%d) in handshake msg", + conf->mgmt->prognum); + goto fail; + } + } + + ret = gf_asprintf (&process_uuid_xl, "%s-%s", this->ctx->process_uuid, + this->name); + if (-1 == ret) { + gf_log (this->name, GF_LOG_ERROR, + "asprintf failed while setting process_uuid"); + goto fail; + } + ret = dict_set_dynstr (options, "process-uuid", process_uuid_xl); + if (ret < 0) { + gf_log (this->name, GF_LOG_ERROR, + "failed to set process-uuid(%s) in handshake msg", + process_uuid_xl); + goto fail; + } + + if (this->ctx->cmd_args.volfile_server) { + if (this->ctx->cmd_args.volfile_id) + ret = dict_set_str (options, "volfile-key", + this->ctx->cmd_args.volfile_id); + ret = dict_set_uint32 (options, "volfile-checksum", + this->graph->volfile_checksum); + } + + req.dict.dict_len = dict_serialized_length (options); + if (req.dict.dict_len < 0) { + gf_log (this->name, GF_LOG_ERROR, + "failed to get serialized length of dict"); + ret = -1; + goto fail; + } + req.dict.dict_val = GF_CALLOC (1, req.dict.dict_len, 0); + ret = dict_serialize (options, req.dict.dict_val); + if (ret < 0) { + gf_log (this->name, GF_LOG_ERROR, + "failed to serialize dictionary"); + goto fail; + } + + fr = create_frame (this, this->ctx->pool); + if (!fr) + goto fail; + + ret = client_submit_request (this, &req, fr, conf->handshake, + GF_HNDSK_SETVOLUME, NULL, xdr_from_setvolume_req); + +fail: + if (req.dict.dict_val) + GF_FREE (req.dict.dict_val); + + return ret; +} + +int +select_server_supported_programs (xlator_t *this, char *msg) +{ + clnt_conf_t *conf = NULL; + char *tmp_str = NULL; + char *prog_str = NULL; + char *dup_str = NULL; + char *tmp_str1 = NULL; + char *tmp_msg = NULL; + char *progname = NULL; + char *progver_str = NULL; + char *prognum_str = NULL; + int ret = -1; + int progver = 0; + int prognum = 0; + + if (!this || !msg) + goto out; + + conf = this->private; + + /* Reply in "Name:Program-Number:Program-Version,..." format */ + tmp_msg = gf_strdup (msg); + prog_str = strtok_r (tmp_msg, ",", &tmp_str); + while (prog_str) { + dup_str = gf_strdup (prog_str); + + progname = strtok_r (dup_str, ":", &tmp_str1); + prognum_str = strtok_r (NULL, ":", &tmp_str1); + if (!prognum_str) { + gf_log (this->name, GF_LOG_WARNING, + "Supported versions not formatted"); + goto out; + } + sscanf (prognum_str, "%d", &prognum); + progver_str = strtok_r (NULL, ":", &tmp_str1); + if (!progver_str) { + gf_log (this->name, GF_LOG_WARNING, + "Supported versions not formatted"); + goto out; + } + sscanf (progver_str, "%d", &progver); + + /* Select 'programs' */ + if ((clnt3_1_fop_prog.prognum == prognum) && + (clnt3_1_fop_prog.progver == progver)) { + conf->fops = &clnt3_1_fop_prog; + gf_log (this->name, GF_LOG_INFO, + "Using Program %s, Num (%s), Version (%s)", + progname, prognum_str, progver_str); + ret = 0; + } + if ((clnt3_1_mgmt_prog.prognum == prognum) && + (clnt3_1_mgmt_prog.progver == progver)) { + conf->mgmt = &clnt3_1_mgmt_prog; + gf_log (this->name, GF_LOG_INFO, + "Using Program %s, Num (%s), Version (%s)", + progname, prognum_str, progver_str); + ret = 0; + } + + prog_str = strtok_r (NULL, ",", &tmp_str); + GF_FREE (dup_str); + } + + if (ret) { + gf_log (this->name, GF_LOG_ERROR, + "none of the server versions are supported by client"); + } + ret = 0; +out: + if (tmp_msg) + GF_FREE (tmp_msg); + return ret; +} + +int +client_dump_version_cbk (struct rpc_req *req, struct iovec *iov, int count, void *myframe) +{ + gf_dump_version_rsp rsp = {0,}; + call_frame_t *frame = NULL; + clnt_conf_t *conf = NULL; + int ret = 0; + + frame = myframe; + conf = frame->this->private; + + if (-1 == req->rpc_status) { + gf_log ("", 1, "some error, retry again later"); + goto out; + } + + ret = xdr_to_dump_version_rsp (*iov, &rsp); + if (ret < 0) { + gf_log ("", GF_LOG_ERROR, "error"); + goto out; + } + if (-1 == rsp.op_ret) { + gf_log (frame->this->name, GF_LOG_ERROR, + "failed to get the 'versions' from server"); + goto out; + } + + /* Check for the proper version string */ + /* Reply in "Name:Program-Number:Program-Version,..." format */ + ret = select_server_supported_programs (frame->this, + rsp.msg.msg_val); + if (ret) { + gf_log (frame->this->name, GF_LOG_ERROR, + "Server versions are not present in this " + "release (%s)", rsp.msg.msg_val); + goto out; + } + + client_setvolume (frame->this, conf->rpc); + +out: + /* don't use GF_FREE, buffer was allocated by libc */ + if (rsp.msg.msg_val) { + free (rsp.msg.msg_val); + } + + STACK_DESTROY (frame->root); + return ret; +} + +int +client_handshake (xlator_t *this, struct rpc_clnt *rpc) +{ + call_frame_t *frame = NULL; + clnt_conf_t *conf = NULL; + gf_dump_version_req req = {0,}; + int ret = 0; + + conf = this->private; + if (!conf->handshake) + goto out; + + frame = create_frame (this, this->ctx->pool); + if (!frame) + goto out; + + req.key = "fop-handshake"; + req.gfs_id = 123456; + ret = client_submit_request (this, &req, frame, conf->handshake, + GF_HNDSK_DUMP_VERSION, + NULL, xdr_from_dump_version_req); + +out: + return ret; +} + + +/* */ +/* This table should ideally remain same irrespective of versions */ +static rpc_clnt_procedure_t clnt_handshake_actors[] = { + [GF_HNDSK_NULL] = { "NULL", NULL, NULL}, + [GF_HNDSK_DUMP_VERSION] = { "VERSION", NULL, client_dump_version_cbk}, + [GF_HNDSK_SETVOLUME] = { "SETVOLUME", NULL, client_setvolume_cbk}, + [GF_HNDSK_GETSPEC] = { "GETSPEC", NULL, client_getspec_cbk }, + [GF_HNDSK_PING] = { "PING", NULL, client_ping_cbk }, +}; + +rpc_clnt_prog_t clnt_handshake_prog = { + .progname = "GlusterFS Handshake", + .prognum = GLUSTER_HNDSK_PROGRAM, + .progver = GLUSTER_HNDSK_VERSION, + .actor = clnt_handshake_actors, + .numproc = (sizeof (*clnt_handshake_actors) / + sizeof (rpc_clnt_procedure_t)), +}; diff --git a/xlators/protocol/client/src/client-helpers.c b/xlators/protocol/client/src/client-helpers.c new file mode 100644 index 00000000..ae091ed1 --- /dev/null +++ b/xlators/protocol/client/src/client-helpers.c @@ -0,0 +1,109 @@ +/* + Copyright (c) 2010 Gluster, Inc. <http://www.gluster.com> + This file is part of GlusterFS. + + GlusterFS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3 of the License, + or (at your option) any later version. + + GlusterFS is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see + <http://www.gnu.org/licenses/>. +*/ + +#ifndef _CONFIG_H +#define _CONFIG_H +#include "config.h" +#endif + +#include "client.h" +#include "fd.h" + + +clnt_fd_ctx_t * +this_fd_del_ctx (fd_t *file, xlator_t *this) +{ + int dict_ret = -1; + uint64_t ctxaddr = 0; + + GF_VALIDATE_OR_GOTO ("client", this, out); + GF_VALIDATE_OR_GOTO (this->name, file, out); + + dict_ret = fd_ctx_del (file, this, &ctxaddr); + + if (dict_ret < 0) { + ctxaddr = 0; + } + +out: + return (clnt_fd_ctx_t *)(unsigned long)ctxaddr; +} + + +clnt_fd_ctx_t * +this_fd_get_ctx (fd_t *file, xlator_t *this) +{ + int dict_ret = -1; + uint64_t ctxaddr = 0; + + GF_VALIDATE_OR_GOTO ("client", this, out); + GF_VALIDATE_OR_GOTO (this->name, file, out); + + dict_ret = fd_ctx_get (file, this, &ctxaddr); + + if (dict_ret < 0) { + ctxaddr = 0; + } + +out: + return (clnt_fd_ctx_t *)(unsigned long)ctxaddr; +} + + +void +this_fd_set_ctx (fd_t *file, xlator_t *this, loc_t *loc, clnt_fd_ctx_t *ctx) +{ + uint64_t oldaddr = 0; + int32_t ret = -1; + + GF_VALIDATE_OR_GOTO ("client", this, out); + GF_VALIDATE_OR_GOTO (this->name, file, out); + + ret = fd_ctx_get (file, this, &oldaddr); + if (ret >= 0) { + gf_log (this->name, GF_LOG_DEBUG, + "%s (%"PRId64"): trying duplicate remote fd set. ", + loc->path, loc->inode->ino); + } + + ret = fd_ctx_set (file, this, (uint64_t)(unsigned long)ctx); + if (ret < 0) { + gf_log (this->name, GF_LOG_DEBUG, + "%s (%"PRId64"): failed to set remote fd", + loc->path, loc->inode->ino); + } +out: + return; +} + + +int +client_local_wipe (clnt_local_t *local) +{ + if (local) { + loc_wipe (&local->loc); + + if (local->fd) + fd_unref (local->fd); + + GF_FREE (local); + } + + return 0; +} diff --git a/xlators/protocol/client/src/client-mem-types.h b/xlators/protocol/client/src/client-mem-types.h new file mode 100644 index 00000000..5fadfafc --- /dev/null +++ b/xlators/protocol/client/src/client-mem-types.h @@ -0,0 +1,32 @@ +/* + Copyright (c) 2010 Gluster, Inc. <http://www.gluster.com> + This file is part of GlusterFS. + + GlusterFS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3 of the License, + or (at your option) any later version. + + GlusterFS is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see + <http://www.gnu.org/licenses/>. +*/ + + +#ifndef __CLIENT_MEM_TYPES_H__ +#define __CLIENT_MEM_TYPES_H__ + +#include "mem-types.h" + +enum gf_client_mem_types_ { + gf_client_mt_clnt_conf_t = gf_common_mt_end + 1, + gf_client_mt_clnt_local_t, + gf_client_mt_clnt_fdctx_t, + gf_client_mt_end, +}; +#endif /* __CLIENT_MEM_TYPES_H__ */ diff --git a/xlators/protocol/client/src/client.c b/xlators/protocol/client/src/client.c new file mode 100644 index 00000000..49e88bfd --- /dev/null +++ b/xlators/protocol/client/src/client.c @@ -0,0 +1,1791 @@ +/* + Copyright (c) 2010 Gluster, Inc. <http://www.gluster.com> + This file is part of GlusterFS. + + GlusterFS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3 of the License, + or (at your option) any later version. + + GlusterFS is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see + <http://www.gnu.org/licenses/>. +*/ + + +#ifndef _CONFIG_H +#define _CONFIG_H +#include "config.h" +#endif + +#include "client.h" +#include "xlator.h" +#include "defaults.h" +#include "glusterfs.h" +#include "msg-xdr.h" +#include "statedump.h" +#include "compat-errno.h" + +extern rpc_clnt_prog_t clnt_handshake_prog; +int +client_handshake (xlator_t *this, struct rpc_clnt *rpc); + +void +client_start_ping (void *data); + +int +client_submit_request (xlator_t *this, void *req, + call_frame_t *frame, rpc_clnt_prog_t *prog, int procnum, + struct iobref *iobref, gfs_serialize_t sfunc) +{ + int ret = -1; + clnt_conf_t *conf = NULL; + struct iovec iov = {0, }; + struct iobuf *iobuf = NULL; + int count = 0; + char new_iobref = 0, start_ping = 0; + + conf = this->private; + + iobuf = iobuf_get (this->ctx->iobuf_pool); + if (!iobuf) { + goto out; + }; + + if (!iobref) { + iobref = iobref_new (); + if (!iobref) { + goto out; + } + + new_iobref = 1; + } + + iobref_add (iobref, iobuf); + + iov.iov_base = iobuf->ptr; + iov.iov_len = 128 * GF_UNIT_KB; + + /* Create the xdr payload */ + if (req && sfunc) { + ret = sfunc (iov, req); + if (ret == -1) { + goto out; + } + iov.iov_len = ret; + count = 1; + } + /* Send the msg */ + ret = rpc_clnt_submit (conf->rpc, prog, procnum, &iov, count, NULL, 0, + iobref, frame); + + if (ret == 0) { + pthread_mutex_lock (&conf->rpc->conn.lock); + { + if (!conf->rpc->conn.ping_started) { + start_ping = 1; + } + } + pthread_mutex_unlock (&conf->rpc->conn.lock); + } + + if (start_ping) + client_start_ping ((void *) this); + + ret = 0; +out: + if (new_iobref) { + iobref_unref (iobref); + } + + iobuf_unref (iobuf); + + return ret; +} + + +int32_t +client_forget (xlator_t *this, inode_t *inode) +{ + /* Nothing here */ + return 0; +} + +int32_t +client_releasedir (xlator_t *this, fd_t *fd) +{ + int ret = -1; + clnt_conf_t *conf = NULL; + rpc_clnt_procedure_t *proc = NULL; + clnt_args_t args = {0,}; + call_frame_t *frame = NULL; + + conf = this->private; + if (!conf->fops) + goto out; + + args.fd = fd; + + proc = &conf->fops->actor[GF_FOP_RELEASEDIR]; + if (proc->fn) { + frame = create_frame (this, this->ctx->pool); + if (!frame) { + goto out; + } + ret = proc->fn (frame, this, conf->fops, &args); + } +out: + return 0; +} + +int32_t +client_release (xlator_t *this, fd_t *fd) +{ + int ret = -1; + clnt_conf_t *conf = NULL; + rpc_clnt_procedure_t *proc = NULL; + clnt_args_t args = {0,}; + call_frame_t *frame = NULL; + + conf = this->private; + if (!conf->fops) + goto out; + + args.fd = fd; + proc = &conf->fops->actor[GF_FOP_RELEASE]; + if (proc->fn) { + frame = create_frame (this, this->ctx->pool); + if (!frame) { + goto out; + } + ret = proc->fn (frame, this, conf->fops, &args); + } +out: + return 0; +} + + +int32_t +client_lookup (call_frame_t *frame, xlator_t *this, loc_t *loc, + dict_t *xattr_req) +{ + int ret = -1; + clnt_conf_t *conf = NULL; + rpc_clnt_procedure_t *proc = NULL; + clnt_args_t args = {0,}; + + conf = this->private; + if (!conf->fops) + goto out; + + args.loc = loc; + args.dict = xattr_req; + + proc = &conf->fops->actor[GF_FOP_LOOKUP]; + if (proc->fn) + ret = proc->fn (frame, this, conf->fops, &args); +out: + /* think of avoiding a missing frame */ + if (ret) + STACK_UNWIND_STRICT (lookup, frame, -1, ENOTCONN, + NULL, NULL, NULL, NULL); + + return 0; +} + + +int32_t +client_stat (call_frame_t *frame, xlator_t *this, loc_t *loc) +{ + int ret = -1; + clnt_conf_t *conf = NULL; + rpc_clnt_procedure_t *proc = NULL; + clnt_args_t args = {0,}; + + conf = this->private; + if (!conf->fops) + goto out; + + args.loc = loc; + + proc = &conf->fops->actor[GF_FOP_STAT]; + if (proc->fn) + ret = proc->fn (frame, this, conf->fops, &args); +out: + if (ret) + STACK_UNWIND_STRICT (stat, frame, -1, ENOTCONN, NULL); + + + return 0; +} + + +int32_t +client_truncate (call_frame_t *frame, xlator_t *this, loc_t *loc, off_t offset) +{ + int ret = -1; + clnt_conf_t *conf = NULL; + rpc_clnt_procedure_t *proc = NULL; + clnt_args_t args = {0,}; + + conf = this->private; + if (!conf->fops) + goto out; + + args.loc = loc; + args.offset = offset; + + proc = &conf->fops->actor[GF_FOP_TRUNCATE]; + if (proc->fn) + ret = proc->fn (frame, this, conf->fops, &args); +out: + if (ret) + STACK_UNWIND_STRICT (truncate, frame, -1, ENOTCONN, NULL, NULL); + + + return 0; +} + + +int32_t +client_ftruncate (call_frame_t *frame, xlator_t *this, fd_t *fd, off_t offset) +{ + int ret = -1; + clnt_conf_t *conf = NULL; + rpc_clnt_procedure_t *proc = NULL; + clnt_args_t args = {0,}; + + conf = this->private; + if (!conf->fops) + goto out; + + args.fd = fd; + args.offset = offset; + + proc = &conf->fops->actor[GF_FOP_FTRUNCATE]; + if (proc->fn) + ret = proc->fn (frame, this, conf->fops, &args); +out: + if (ret) + STACK_UNWIND_STRICT (ftruncate, frame, -1, ENOTCONN, NULL, NULL); + + return 0; +} + + + +int32_t +client_access (call_frame_t *frame, xlator_t *this, loc_t *loc, int32_t mask) +{ + int ret = -1; + clnt_conf_t *conf = NULL; + rpc_clnt_procedure_t *proc = NULL; + clnt_args_t args = {0,}; + + conf = this->private; + if (!conf->fops) + goto out; + + args.loc = loc; + args.mask = mask; + + proc = &conf->fops->actor[GF_FOP_ACCESS]; + if (proc->fn) + ret = proc->fn (frame, this, conf->fops, &args); +out: + if (ret) + STACK_UNWIND_STRICT (access, frame, -1, ENOTCONN); + + return 0; +} + + + + +int32_t +client_readlink (call_frame_t *frame, xlator_t *this, loc_t *loc, size_t size) +{ + int ret = -1; + clnt_conf_t *conf = NULL; + rpc_clnt_procedure_t *proc = NULL; + clnt_args_t args = {0,}; + + conf = this->private; + if (!conf->fops) + goto out; + + args.loc = loc; + args.size = size; + + proc = &conf->fops->actor[GF_FOP_READLINK]; + if (proc->fn) + ret = proc->fn (frame, this, conf->fops, &args); +out: + if (ret) + STACK_UNWIND_STRICT (readlink, frame, -1, ENOTCONN, NULL, NULL); + + return 0; +} + + + +int32_t +client_mknod (call_frame_t *frame, xlator_t *this, loc_t *loc, mode_t mode, + dev_t rdev) +{ + int ret = -1; + clnt_conf_t *conf = NULL; + rpc_clnt_procedure_t *proc = NULL; + clnt_args_t args = {0,}; + + conf = this->private; + if (!conf->fops) + goto out; + + args.loc = loc; + args.mode = mode; + args.rdev = rdev; + + proc = &conf->fops->actor[GF_FOP_MKNOD]; + if (proc->fn) + ret = proc->fn (frame, this, conf->fops, &args); +out: + if (ret) + STACK_UNWIND_STRICT (mknod, frame, -1, ENOTCONN, + NULL, NULL, NULL, NULL); + + return 0; +} + + + +int32_t +client_mkdir (call_frame_t *frame, xlator_t *this, loc_t *loc, + mode_t mode) +{ + int ret = -1; + clnt_conf_t *conf = NULL; + rpc_clnt_procedure_t *proc = NULL; + clnt_args_t args = {0,}; + + conf = this->private; + if (!conf->fops) + goto out; + + args.loc = loc; + args.mode = mode; + + proc = &conf->fops->actor[GF_FOP_MKDIR]; + if (proc->fn) + ret = proc->fn (frame, this, conf->fops, &args); +out: + if (ret) + STACK_UNWIND_STRICT (mkdir, frame, -1, ENOTCONN, + NULL, NULL, NULL, NULL); + + return 0; +} + + + +int32_t +client_unlink (call_frame_t *frame, xlator_t *this, loc_t *loc) +{ + int ret = -1; + clnt_conf_t *conf = NULL; + rpc_clnt_procedure_t *proc = NULL; + clnt_args_t args = {0,}; + + conf = this->private; + if (!conf->fops) + goto out; + + args.loc = loc; + + proc = &conf->fops->actor[GF_FOP_UNLINK]; + if (proc->fn) + ret = proc->fn (frame, this, conf->fops, &args); +out: + if (ret) + STACK_UNWIND_STRICT (unlink, frame, -1, ENOTCONN, + NULL, NULL); + + return 0; +} + +int32_t +client_rmdir (call_frame_t *frame, xlator_t *this, loc_t *loc) +{ + int ret = -1; + clnt_conf_t *conf = NULL; + rpc_clnt_procedure_t *proc = NULL; + clnt_args_t args = {0,}; + + conf = this->private; + if (!conf->fops) + goto out; + + args.loc = loc; + + proc = &conf->fops->actor[GF_FOP_RMDIR]; + if (proc->fn) + ret = proc->fn (frame, this, conf->fops, &args); +out: + /* think of avoiding a missing frame */ + if (ret) + STACK_UNWIND_STRICT (rmdir, frame, -1, ENOTCONN, + NULL, NULL); + + return 0; +} + + + +int32_t +client_symlink (call_frame_t *frame, xlator_t *this, const char *linkpath, + loc_t *loc) +{ + int ret = -1; + clnt_conf_t *conf = NULL; + rpc_clnt_procedure_t *proc = NULL; + clnt_args_t args = {0,}; + + conf = this->private; + if (!conf->fops) + goto out; + + args.linkname = linkpath; + args.loc = loc; + + proc = &conf->fops->actor[GF_FOP_SYMLINK]; + if (proc->fn) + ret = proc->fn (frame, this, conf->fops, &args); +out: + if (ret) + STACK_UNWIND_STRICT (symlink, frame, -1, ENOTCONN, + NULL, NULL, NULL, NULL); + + return 0; +} + + + +int32_t +client_rename (call_frame_t *frame, xlator_t *this, loc_t *oldloc, + loc_t *newloc) +{ + int ret = -1; + clnt_conf_t *conf = NULL; + rpc_clnt_procedure_t *proc = NULL; + clnt_args_t args = {0,}; + + conf = this->private; + if (!conf->fops) + goto out; + + args.oldloc = oldloc; + args.newloc = newloc; + proc = &conf->fops->actor[GF_FOP_RENAME]; + if (proc->fn) + ret = proc->fn (frame, this, conf->fops, &args); +out: + if (ret) + STACK_UNWIND_STRICT (rename, frame, -1, ENOTCONN, + NULL, NULL, NULL, NULL, NULL); + + return 0; +} + + + +int32_t +client_link (call_frame_t *frame, xlator_t *this, loc_t *oldloc, + loc_t *newloc) +{ + int ret = -1; + clnt_conf_t *conf = NULL; + rpc_clnt_procedure_t *proc = NULL; + clnt_args_t args = {0,}; + + conf = this->private; + if (!conf->fops) + goto out; + + args.oldloc = oldloc; + args.newloc = newloc; + + proc = &conf->fops->actor[GF_FOP_LINK]; + if (proc->fn) + ret = proc->fn (frame, this, conf->fops, &args); +out: + if (ret) + STACK_UNWIND_STRICT (link, frame, -1, ENOTCONN, + NULL, NULL, NULL, NULL); + + return 0; +} + + + +int32_t +client_create (call_frame_t *frame, xlator_t *this, loc_t *loc, + int32_t flags, mode_t mode, fd_t *fd) +{ + int ret = -1; + clnt_conf_t *conf = NULL; + rpc_clnt_procedure_t *proc = NULL; + clnt_args_t args = {0,}; + + conf = this->private; + if (!conf->fops) + goto out; + + args.loc = loc; + args.flags = flags; + args.mode = mode; + args.fd = fd; + + proc = &conf->fops->actor[GF_FOP_CREATE]; + if (proc->fn) + ret = proc->fn (frame, this, conf->fops, &args); +out: + if (ret) + STACK_UNWIND_STRICT (create, frame, -1, ENOTCONN, + NULL, NULL, NULL, NULL, NULL); + + return 0; +} + + + +int32_t +client_open (call_frame_t *frame, xlator_t *this, loc_t *loc, + int32_t flags, fd_t *fd, int32_t wbflags) +{ + int ret = -1; + clnt_conf_t *conf = NULL; + rpc_clnt_procedure_t *proc = NULL; + clnt_args_t args = {0,}; + + conf = this->private; + if (!conf->fops) + goto out; + + args.loc = loc; + args.flags = flags; + args.fd = fd; + args.wbflags = wbflags; + + proc = &conf->fops->actor[GF_FOP_OPEN]; + if (proc->fn) + ret = proc->fn (frame, this, conf->fops, &args); + +out: + if (ret) + STACK_UNWIND_STRICT (open, frame, -1, ENOTCONN, NULL); + + return 0; +} + + + +int32_t +client_readv (call_frame_t *frame, xlator_t *this, fd_t *fd, size_t size, + off_t offset) +{ + int ret = -1; + clnt_conf_t *conf = NULL; + rpc_clnt_procedure_t *proc = NULL; + clnt_args_t args = {0,}; + + conf = this->private; + if (!conf->fops) + goto out; + + args.fd = fd; + args.size = size; + args.offset = offset; + + proc = &conf->fops->actor[GF_FOP_READ]; + if (proc->fn) + ret = proc->fn (frame, this, conf->fops, &args); + +out: + if (ret) + STACK_UNWIND_STRICT (readv, frame, -1, ENOTCONN, + NULL, 0, NULL, NULL); + + return 0; +} + + + + +int32_t +client_writev (call_frame_t *frame, xlator_t *this, fd_t *fd, + struct iovec *vector, int32_t count, off_t off, + struct iobref *iobref) +{ + int ret = -1; + clnt_conf_t *conf = NULL; + rpc_clnt_procedure_t *proc = NULL; + clnt_args_t args = {0,}; + + conf = this->private; + if (!conf->fops) + goto out; + + args.fd = fd; + args.vector = vector; + args.count = count; + args.offset = off; + args.iobref = iobref; + + proc = &conf->fops->actor[GF_FOP_WRITE]; + if (proc->fn) + ret = proc->fn (frame, this, conf->fops, &args); +out: + if (ret) + STACK_UNWIND_STRICT (writev, frame, -1, ENOTCONN, NULL, NULL); + + return 0; +} + + + +int32_t +client_flush (call_frame_t *frame, xlator_t *this, fd_t *fd) +{ + int ret = -1; + clnt_conf_t *conf = NULL; + rpc_clnt_procedure_t *proc = NULL; + clnt_args_t args = {0,}; + + conf = this->private; + if (!conf->fops) + goto out; + + args.fd = fd; + + proc = &conf->fops->actor[GF_FOP_FLUSH]; + if (proc->fn) + ret = proc->fn (frame, this, conf->fops, &args); +out: + if (ret) + STACK_UNWIND_STRICT (flush, frame, -1, ENOTCONN); + + return 0; +} + + + +int32_t +client_fsync (call_frame_t *frame, xlator_t *this, fd_t *fd, + int32_t flags) +{ + int ret = -1; + clnt_conf_t *conf = NULL; + rpc_clnt_procedure_t *proc = NULL; + clnt_args_t args = {0,}; + + conf = this->private; + if (!conf->fops) + goto out; + + args.fd = fd; + args.flags = flags; + + proc = &conf->fops->actor[GF_FOP_FSYNC]; + if (proc->fn) + ret = proc->fn (frame, this, conf->fops, &args); +out: + if (ret) + STACK_UNWIND_STRICT (fsync, frame, -1, ENOTCONN, NULL, NULL); + + return 0; +} + + + +int32_t +client_fstat (call_frame_t *frame, xlator_t *this, fd_t *fd) +{ + int ret = -1; + clnt_conf_t *conf = NULL; + rpc_clnt_procedure_t *proc = NULL; + clnt_args_t args = {0,}; + + conf = this->private; + if (!conf->fops) + goto out; + + args.fd = fd; + + proc = &conf->fops->actor[GF_FOP_FSTAT]; + if (proc->fn) + ret = proc->fn (frame, this, conf->fops, &args); +out: + if (ret) + STACK_UNWIND_STRICT (fstat, frame, -1, ENOTCONN, NULL); + + return 0; +} + + + +int32_t +client_opendir (call_frame_t *frame, xlator_t *this, loc_t *loc, fd_t *fd) +{ + int ret = -1; + clnt_conf_t *conf = NULL; + rpc_clnt_procedure_t *proc = NULL; + clnt_args_t args = {0,}; + + conf = this->private; + if (!conf->fops) + goto out; + + args.loc = loc; + args.fd = fd; + + proc = &conf->fops->actor[GF_FOP_OPENDIR]; + if (proc->fn) + ret = proc->fn (frame, this, conf->fops, &args); +out: + if (ret) + STACK_UNWIND_STRICT (opendir, frame, -1, ENOTCONN, NULL); + + return 0; +} + + + +int32_t +client_fsyncdir (call_frame_t *frame, xlator_t *this, fd_t *fd, int32_t flags) +{ + int ret = -1; + clnt_conf_t *conf = NULL; + rpc_clnt_procedure_t *proc = NULL; + clnt_args_t args = {0,}; + + conf = this->private; + if (!conf->fops) + goto out; + + args.fd = fd; + args.flags = flags; + + proc = &conf->fops->actor[GF_FOP_FSYNCDIR]; + if (proc->fn) + ret = proc->fn (frame, this, conf->fops, &args); +out: + if (ret) + STACK_UNWIND_STRICT (fsyncdir, frame, -1, ENOTCONN); + + return 0; +} + + + +int32_t +client_statfs (call_frame_t *frame, xlator_t *this, loc_t *loc) +{ + int ret = -1; + clnt_conf_t *conf = NULL; + rpc_clnt_procedure_t *proc = NULL; + clnt_args_t args = {0,}; + + conf = this->private; + if (!conf->fops) + goto out; + + args.loc = loc; + + proc = &conf->fops->actor[GF_FOP_STATFS]; + if (proc->fn) + ret = proc->fn (frame, this, conf->fops, &args); +out: + if (ret) + STACK_UNWIND_STRICT (statfs, frame, -1, ENOTCONN, NULL); + + return 0; +} + + + +int32_t +client_setxattr (call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *dict, + int32_t flags) +{ + int ret = -1; + clnt_conf_t *conf = NULL; + rpc_clnt_procedure_t *proc = NULL; + clnt_args_t args = {0,}; + + conf = this->private; + if (!conf->fops) + goto out; + + args.loc = loc; + args.dict = dict; + args.flags = flags; + + proc = &conf->fops->actor[GF_FOP_SETXATTR]; + if (proc->fn) + ret = proc->fn (frame, this, conf->fops, &args); +out: + if (ret) + STACK_UNWIND_STRICT (setxattr, frame, -1, ENOTCONN); + + return 0; +} + + + +int32_t +client_fsetxattr (call_frame_t *frame, xlator_t *this, fd_t *fd, + dict_t *dict, int32_t flags) +{ + int ret = -1; + clnt_conf_t *conf = NULL; + rpc_clnt_procedure_t *proc = NULL; + clnt_args_t args = {0,}; + + conf = this->private; + if (!conf->fops) + goto out; + + args.fd = fd; + args.dict = dict; + args.flags = flags; + + proc = &conf->fops->actor[GF_FOP_FSETXATTR]; + if (proc->fn) + ret = proc->fn (frame, this, conf->fops, &args); +out: + if (ret) + STACK_UNWIND_STRICT (fsetxattr, frame, -1, ENOTCONN); + + return 0; +} + + + + +int32_t +client_fgetxattr (call_frame_t *frame, xlator_t *this, fd_t *fd, + const char *name) +{ + int ret = -1; + clnt_conf_t *conf = NULL; + rpc_clnt_procedure_t *proc = NULL; + clnt_args_t args = {0,}; + + conf = this->private; + if (!conf->fops) + goto out; + + args.fd = fd; + args.name = name; + + proc = &conf->fops->actor[GF_FOP_FGETXATTR]; + if (proc->fn) + ret = proc->fn (frame, this, conf->fops, &args); +out: + if (ret) + STACK_UNWIND_STRICT (fgetxattr, frame, -1, ENOTCONN, NULL); + + return 0; +} + + + +int32_t +client_getxattr (call_frame_t *frame, xlator_t *this, loc_t *loc, + const char *name) +{ + int ret = -1; + clnt_conf_t *conf = NULL; + rpc_clnt_procedure_t *proc = NULL; + clnt_args_t args = {0,}; + + conf = this->private; + if (!conf->fops) + goto out; + + args.name = name; + args.loc = loc; + + proc = &conf->fops->actor[GF_FOP_GETXATTR]; + if (proc->fn) + ret = proc->fn (frame, this, conf->fops, &args); +out: + if (ret) + STACK_UNWIND_STRICT (getxattr, frame, -1, ENOTCONN, NULL); + + return 0; +} + + + +int32_t +client_xattrop (call_frame_t *frame, xlator_t *this, loc_t *loc, + gf_xattrop_flags_t flags, dict_t *dict) +{ + int ret = -1; + clnt_conf_t *conf = NULL; + rpc_clnt_procedure_t *proc = NULL; + clnt_args_t args = {0,}; + + conf = this->private; + if (!conf->fops) + goto out; + + args.loc = loc; + args.flags = flags; + args.dict = dict; + + proc = &conf->fops->actor[GF_FOP_XATTROP]; + if (proc->fn) + ret = proc->fn (frame, this, conf->fops, &args); +out: + if (ret) + STACK_UNWIND_STRICT (xattrop, frame, -1, ENOTCONN, NULL); + + return 0; +} + + + +int32_t +client_fxattrop (call_frame_t *frame, xlator_t *this, fd_t *fd, + gf_xattrop_flags_t flags, dict_t *dict) +{ + int ret = -1; + clnt_conf_t *conf = NULL; + rpc_clnt_procedure_t *proc = NULL; + clnt_args_t args = {0,}; + + conf = this->private; + if (!conf->fops) + goto out; + + args.fd = fd; + args.flags = flags; + args.dict = dict; + + proc = &conf->fops->actor[GF_FOP_FXATTROP]; + if (proc->fn) + ret = proc->fn (frame, this, conf->fops, &args); +out: + if (ret) + STACK_UNWIND_STRICT (fxattrop, frame, -1, ENOTCONN, NULL); + + return 0; +} + + + +int32_t +client_removexattr (call_frame_t *frame, xlator_t *this, loc_t *loc, + const char *name) +{ + int ret = -1; + clnt_conf_t *conf = NULL; + rpc_clnt_procedure_t *proc = NULL; + clnt_args_t args = {0,}; + + conf = this->private; + if (!conf->fops) + goto out; + + args.name = name; + args.loc = loc; + + proc = &conf->fops->actor[GF_FOP_REMOVEXATTR]; + if (proc->fn) + ret = proc->fn (frame, this, conf->fops, &args); +out: + if (ret) + STACK_UNWIND_STRICT (removexattr, frame, -1, ENOTCONN); + + return 0; +} + + +int32_t +client_lk (call_frame_t *frame, xlator_t *this, fd_t *fd, int32_t cmd, + struct flock *lock) +{ + int ret = -1; + clnt_conf_t *conf = NULL; + rpc_clnt_procedure_t *proc = NULL; + clnt_args_t args = {0,}; + + conf = this->private; + if (!conf->fops) + goto out; + + args.fd = fd; + args.cmd = cmd; + args.flock = lock; + + proc = &conf->fops->actor[GF_FOP_LK]; + if (proc->fn) + ret = proc->fn (frame, this, conf->fops, &args); +out: + if (ret) + STACK_UNWIND_STRICT (lk, frame, -1, ENOTCONN, NULL); + + return 0; +} + + +int32_t +client_inodelk (call_frame_t *frame, xlator_t *this, const char *volume, + loc_t *loc, int32_t cmd, struct flock *lock) +{ + int ret = -1; + clnt_conf_t *conf = NULL; + rpc_clnt_procedure_t *proc = NULL; + clnt_args_t args = {0,}; + + conf = this->private; + if (!conf->fops) + goto out; + + args.loc = loc; + args.cmd = cmd; + args.flock = lock; + args.volume = volume; + + proc = &conf->fops->actor[GF_FOP_INODELK]; + if (proc->fn) + ret = proc->fn (frame, this, conf->fops, &args); +out: + if (ret) + STACK_UNWIND_STRICT (inodelk, frame, -1, ENOTCONN); + + return 0; +} + + + +int32_t +client_finodelk (call_frame_t *frame, xlator_t *this, const char *volume, + fd_t *fd, int32_t cmd, struct flock *lock) +{ + int ret = -1; + clnt_conf_t *conf = NULL; + rpc_clnt_procedure_t *proc = NULL; + clnt_args_t args = {0,}; + + conf = this->private; + if (!conf->fops) + goto out; + + args.fd = fd; + args.cmd = cmd; + args.flock = lock; + args.volume = volume; + + proc = &conf->fops->actor[GF_FOP_FINODELK]; + if (proc->fn) + ret = proc->fn (frame, this, conf->fops, &args); +out: + if (ret) + STACK_UNWIND_STRICT (finodelk, frame, -1, ENOTCONN); + + return 0; +} + + +int32_t +client_entrylk (call_frame_t *frame, xlator_t *this, const char *volume, + loc_t *loc, const char *basename, entrylk_cmd cmd, + entrylk_type type) +{ + int ret = -1; + clnt_conf_t *conf = NULL; + rpc_clnt_procedure_t *proc = NULL; + clnt_args_t args = {0,}; + + conf = this->private; + if (!conf->fops) + goto out; + + args.loc = loc; + args.basename = basename; + args.type = type; + args.volume = volume; + args.cmd_entrylk = cmd; + + proc = &conf->fops->actor[GF_FOP_ENTRYLK]; + if (proc->fn) + ret = proc->fn (frame, this, conf->fops, &args); +out: + if (ret) + STACK_UNWIND_STRICT (entrylk, frame, -1, ENOTCONN); + + return 0; +} + + + +int32_t +client_fentrylk (call_frame_t *frame, xlator_t *this, const char *volume, + fd_t *fd, const char *basename, entrylk_cmd cmd, + entrylk_type type) +{ + int ret = -1; + clnt_conf_t *conf = NULL; + rpc_clnt_procedure_t *proc = NULL; + clnt_args_t args = {0,}; + + conf = this->private; + if (!conf->fops) + goto out; + + args.fd = fd; + args.basename = basename; + args.type = type; + args.volume = volume; + args.cmd_entrylk = cmd; + + proc = &conf->fops->actor[GF_FOP_FENTRYLK]; + if (proc->fn) + ret = proc->fn (frame, this, conf->fops, &args); +out: + if (ret) + STACK_UNWIND_STRICT (fentrylk, frame, -1, ENOTCONN); + + return 0; +} + + +int32_t +client_checksum (call_frame_t *frame, xlator_t *this, loc_t *loc, + int32_t flag) +{ + int ret = -1; + clnt_conf_t *conf = NULL; + rpc_clnt_procedure_t *proc = NULL; + clnt_args_t args = {0,}; + + conf = this->private; + if (!conf->fops) + goto out; + + args.loc = loc; + args.flags = flag; + + proc = &conf->fops->actor[GF_FOP_CHECKSUM]; + if (proc->fn) + ret = proc->fn (frame, this, conf->fops, &args); +out: + if (ret) + STACK_UNWIND_STRICT (checksum, frame, -1, ENOTCONN, NULL, NULL); + + return 0; +} + + + +int32_t +client_rchecksum (call_frame_t *frame, xlator_t *this, fd_t *fd, off_t offset, + int32_t len) +{ + int ret = -1; + clnt_conf_t *conf = NULL; + rpc_clnt_procedure_t *proc = NULL; + clnt_args_t args = {0,}; + + conf = this->private; + if (!conf->fops) + goto out; + + args.fd = fd; + args.offset = offset; + args.len = len; + + proc = &conf->fops->actor[GF_FOP_RCHECKSUM]; + if (proc->fn) + ret = proc->fn (frame, this, conf->fops, &args); +out: + if (ret) + STACK_UNWIND_STRICT (rchecksum, frame, -1, ENOTCONN, 0, NULL); + + return 0; +} + +int32_t +client_readdir (call_frame_t *frame, xlator_t *this, fd_t *fd, + size_t size, off_t off) +{ + int ret = -1; + clnt_conf_t *conf = NULL; + rpc_clnt_procedure_t *proc = NULL; + clnt_args_t args = {0,}; + + conf = this->private; + if (!conf->fops) + goto out; + + args.fd = fd; + args.size = size; + args.offset = off; + + proc = &conf->fops->actor[GF_FOP_READDIR]; + if (proc->fn) + ret = proc->fn (frame, this, conf->fops, &args); +out: + if (ret) + STACK_UNWIND_STRICT (readdir, frame, -1, ENOTCONN, NULL); + + return 0; +} + + +int32_t +client_readdirp (call_frame_t *frame, xlator_t *this, fd_t *fd, + size_t size, off_t off) +{ + int ret = -1; + clnt_conf_t *conf = NULL; + rpc_clnt_procedure_t *proc = NULL; + clnt_args_t args = {0,}; + + conf = this->private; + if (!conf->fops) + goto out; + + args.fd = fd; + args.size = size; + args.offset = off; + + proc = &conf->fops->actor[GF_FOP_READDIRP]; + if (proc->fn) + ret = proc->fn (frame, this, conf->fops, &args); +out: + if (ret) + STACK_UNWIND_STRICT (readdirp, frame, -1, ENOTCONN, NULL); + + return 0; +} + + +int32_t +client_setattr (call_frame_t *frame, xlator_t *this, loc_t *loc, + struct iatt *stbuf, int32_t valid) +{ + int ret = -1; + clnt_conf_t *conf = NULL; + rpc_clnt_procedure_t *proc = NULL; + clnt_args_t args = {0,}; + + conf = this->private; + if (!conf->fops) + goto out; + + args.loc = loc; + args.stbuf = stbuf; + args.valid = valid; + + proc = &conf->fops->actor[GF_FOP_SETATTR]; + if (proc->fn) + ret = proc->fn (frame, this, conf->fops, &args); +out: + if (ret) + STACK_UNWIND_STRICT (setattr, frame, -1, ENOTCONN, NULL, NULL); + + return 0; +} + +int32_t +client_fsetattr (call_frame_t *frame, xlator_t *this, fd_t *fd, + struct iatt *stbuf, int32_t valid) +{ + int ret = -1; + clnt_conf_t *conf = NULL; + rpc_clnt_procedure_t *proc = NULL; + clnt_args_t args = {0,}; + + conf = this->private; + if (!conf->fops) + goto out; + + args.fd = fd; + args.stbuf = stbuf; + args.valid = valid; + + proc = &conf->fops->actor[GF_FOP_FSETATTR]; + if (proc->fn) + ret = proc->fn (frame, this, conf->fops, &args); +out: + if (ret) + STACK_UNWIND_STRICT (fsetattr, frame, -1, ENOTCONN, NULL, NULL); + + return 0; +} + +///////////////// +int32_t +client_getspec (call_frame_t *frame, xlator_t *this, const char *key, + int32_t flags) +{ + int ret = -1; + clnt_conf_t *conf = NULL; + gf_getspec_req req = {0,}; + + conf = this->private; + if (!conf->handshake) + goto out; + + req.key = (char *)key; + req.flags = flags; + + client_submit_request (this, &req, frame, conf->handshake, + GF_HNDSK_GETSPEC, NULL, xdr_from_getspec_req); + ret = 0; +out: + if (ret) + STACK_UNWIND_STRICT (getspec, frame, -1, EINVAL, NULL); + + return 0; +} + + + int +client_mark_fd_bad (xlator_t *this) +{ + clnt_conf_t *conf = NULL; + clnt_fd_ctx_t *tmp = NULL, *fdctx = NULL; + + conf = this->private; + + pthread_mutex_lock (&conf->lock); + { + list_for_each_entry_safe (fdctx, tmp, &conf->saved_fds, + sfd_pos) { + fdctx->remote_fd = -1; + } + } + pthread_mutex_unlock (&conf->lock); + + return 0; +} + + +int +client_rpc_notify (struct rpc_clnt *rpc, void *mydata, rpc_clnt_event_t event, + void *data) +{ + xlator_t *this = NULL; + char *handshake = NULL; + clnt_conf_t *conf = NULL; + int ret = 0; + + this = mydata; + conf = this->private; + + switch (event) { + case RPC_CLNT_CONNECT: + { + // connect happened, send 'get_supported_versions' mop + ret = dict_get_str (this->options, "disable-handshake", + &handshake); + + gf_log (this->name, GF_LOG_TRACE, "got RPC_CLNT_CONNECT"); + + if ((ret < 0) || (strcasecmp (handshake, "on"))) { + ret = client_handshake (this, conf->rpc); + + } else { + //conf->rpc->connected = 1; + ret = default_notify (this, GF_EVENT_CHILD_UP, NULL); + } + break; + } + case RPC_CLNT_DISCONNECT: + + client_mark_fd_bad (this); + + gf_log (this->name, GF_LOG_TRACE, "got RPC_CLNT_DISCONNECT"); + + default_notify (this, GF_EVENT_CHILD_DOWN, NULL); + break; + + default: + gf_log (this->name, GF_LOG_TRACE, + "got some other RPC event %d", event); + + break; + } + + return 0; +} + + +int +notify (xlator_t *this, int32_t event, void *data, ...) +{ + clnt_conf_t *conf = NULL; + void *trans = NULL; + + conf = this->private; + + switch (event) { + case GF_EVENT_PARENT_UP: + { + if (conf->rpc) + trans = conf->rpc->conn.trans; + + if (!trans) { + gf_log (this->name, GF_LOG_DEBUG, + "transport init failed"); + return 0; + } + + gf_log (this->name, GF_LOG_DEBUG, + "got GF_EVENT_PARENT_UP, attempting connect " + "on transport"); + + rpc_clnt_reconnect (trans); + } + break; + + default: + gf_log (this->name, GF_LOG_DEBUG, + "got %d, calling default_notify ()", event); + + default_notify (this, event, data); + break; + } + + return 0; +} + +int +build_client_config (xlator_t *this, clnt_conf_t *conf) +{ + int ret = 0; + + ret = dict_get_str (this->options, "remote-subvolume", + &conf->opt.remote_subvolume); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, + "option 'remote-subvolume' not given"); + goto out; + } + + ret = dict_get_int32 (this->options, "frame-timeout", + &conf->rpc_conf.rpc_timeout); + if (ret >= 0) { + gf_log (this->name, GF_LOG_DEBUG, + "setting frame-timeout to %d", + conf->rpc_conf.rpc_timeout); + } else { + gf_log (this->name, GF_LOG_DEBUG, + "defaulting frame-timeout to 30mins"); + conf->rpc_conf.rpc_timeout = 1800; + } + + ret = dict_get_int32 (this->options, "remote-port", + &conf->rpc_conf.remote_port); + if (ret >= 0) { + gf_log (this->name, GF_LOG_DEBUG, + "remote-port is %d", conf->rpc_conf.remote_port); + } else { + gf_log (this->name, GF_LOG_DEBUG, + "defaulting remote-port to %d", + GF_PROTOCOL_DEFAULT_PORT); + conf->rpc_conf.remote_port = GF_PROTOCOL_DEFAULT_PORT; + } + + ret = dict_get_int32 (this->options, "ping-timeout", + &conf->opt.ping_timeout); + if (ret >= 0) { + gf_log (this->name, GF_LOG_DEBUG, + "setting ping-timeout to %d", conf->opt.ping_timeout); + } else { + gf_log (this->name, GF_LOG_DEBUG, + "defaulting ping-timeout to 42"); + conf->opt.ping_timeout = GF_UNIVERSAL_ANSWER; + } + + ret = 0; +out: + return ret;} + + +static int32_t +mem_acct_init (xlator_t *this) +{ + int ret = -1; + + if (!this) + return ret; + + ret = xlator_mem_acct_init (this, gf_client_mt_end + 1); + + if (ret != 0) { + gf_log (this->name, GF_LOG_ERROR, "Memory accounting init" + "failed"); + return ret; + } + + return ret; +} + + +int +init (xlator_t *this) +{ + int ret = -1; + clnt_conf_t *conf = NULL; + + /* */ + if (this->children) { + gf_log (this->name, GF_LOG_ERROR, + "FATAL: client protocol translator cannot have any " + "subvolumes"); + goto out; + } + + if (!this->parents) { + gf_log (this->name, GF_LOG_WARNING, + "Volume is dangling. "); + } + + ret = mem_acct_init (this); + if (ret) + goto out; + + conf = GF_CALLOC (1, sizeof (*conf), gf_client_mt_clnt_conf_t); + if (!conf) + goto out; + + pthread_mutex_init (&conf->lock, NULL); + INIT_LIST_HEAD (&conf->saved_fds); + + ret = build_client_config (this, conf); + if (ret) + goto out; + + conf->rpc = rpc_clnt_init (&conf->rpc_conf, this->options, this->ctx, + this->name); + if (!conf->rpc) + goto out; + conf->rpc->xid = 42; /* It should be enough random everytime :O */ + ret = rpc_clnt_register_notify (conf->rpc, client_rpc_notify, this); + if (ret) + goto out; + + conf->handshake = &clnt_handshake_prog; + this->private = conf; + + ret = 0; +out: + if (ret) + this->fini (this); + + return ret; +} + +void +fini (xlator_t *this) +{ + clnt_conf_t *conf = NULL; + + conf = this->private; + this->private = NULL; + + if (conf) { + if (conf->rpc) + rpc_clnt_destroy (conf->rpc); + + /* Saved Fds */ + /* TODO: */ + + pthread_mutex_destroy (&conf->lock); + + GF_FREE (conf); + } + return; +} + +int +client_priv_dump (xlator_t *this) +{ + clnt_conf_t *conf = NULL; + int ret = -1; + clnt_fd_ctx_t *tmp = NULL; + int i = 0; + char key[GF_DUMP_MAX_BUF_LEN]; + char key_prefix[GF_DUMP_MAX_BUF_LEN]; + + if (!this) + return -1; + + conf = this->private; + if (!conf) { + gf_log (this->name, GF_LOG_WARNING, + "conf null in xlator"); + return -1; + } + + ret = pthread_mutex_trylock(&conf->lock); + if (ret) { + gf_log("", GF_LOG_WARNING, "Unable to lock client %s" + " errno: %d", this->name, errno); + return -1; + } + + gf_proc_dump_build_key(key_prefix, "xlator.protocol.client", + "%s.priv", this->name); + + gf_proc_dump_add_section(key_prefix); + + list_for_each_entry(tmp, &conf->saved_fds, sfd_pos) { + gf_proc_dump_build_key(key, key_prefix, + "fd.%d.remote_fd", ++i); + gf_proc_dump_write(key, "%d", tmp->remote_fd); + } + + gf_proc_dump_build_key(key, key_prefix, "connecting"); + gf_proc_dump_write(key, "%d", conf->connecting); + gf_proc_dump_build_key(key, key_prefix, "last_sent"); + gf_proc_dump_write(key, "%s", ctime(&conf->last_sent.tv_sec)); + gf_proc_dump_build_key(key, key_prefix, "last_received"); + gf_proc_dump_write(key, "%s", ctime(&conf->last_received.tv_sec)); + + pthread_mutex_unlock(&conf->lock); + + return 0; + +} + +int32_t +client_inodectx_dump (xlator_t *this, inode_t *inode) +{ + ino_t par = 0; + uint64_t gen = 0; + int ret = -1; + char key[GF_DUMP_MAX_BUF_LEN]; + + if (!inode) + return -1; + + if (!this) + return -1; + + ret = inode_ctx_get2 (inode, this, &par, &gen); + + if (ret != 0) + return ret; + + gf_proc_dump_build_key(key, "xlator.protocol.client", + "%s.inode.%ld.par", + this->name,inode->ino); + gf_proc_dump_write(key, "%ld, %ld", par, gen); + + return 0; +} + + + + +struct xlator_cbks cbks = { + .forget = client_forget, + .release = client_release, + .releasedir = client_releasedir +}; + +struct xlator_fops fops = { + .stat = client_stat, + .readlink = client_readlink, + .mknod = client_mknod, + .mkdir = client_mkdir, + .unlink = client_unlink, + .rmdir = client_rmdir, + .symlink = client_symlink, + .rename = client_rename, + .link = client_link, + .truncate = client_truncate, + .open = client_open, + .readv = client_readv, + .writev = client_writev, + .statfs = client_statfs, + .flush = client_flush, + .fsync = client_fsync, + .setxattr = client_setxattr, + .getxattr = client_getxattr, + .fsetxattr = client_fsetxattr, + .fgetxattr = client_fgetxattr, + .removexattr = client_removexattr, + .opendir = client_opendir, + .readdir = client_readdir, + .readdirp = client_readdirp, + .fsyncdir = client_fsyncdir, + .access = client_access, + .ftruncate = client_ftruncate, + .fstat = client_fstat, + .create = client_create, + .lk = client_lk, + .inodelk = client_inodelk, + .finodelk = client_finodelk, + .entrylk = client_entrylk, + .fentrylk = client_fentrylk, + .lookup = client_lookup, + .checksum = client_checksum, + .rchecksum = client_rchecksum, + .xattrop = client_xattrop, + .fxattrop = client_fxattrop, + .setattr = client_setattr, + .fsetattr = client_fsetattr, + .getspec = client_getspec, +}; + + +struct xlator_dumpops dumpops = { + .priv = client_priv_dump, + .inodectx = client_inodectx_dump, +}; + + +struct volume_options options[] = { + { .key = {"username"}, + .type = GF_OPTION_TYPE_ANY + }, + { .key = {"password"}, + .type = GF_OPTION_TYPE_ANY + }, + { .key = {"transport-type"}, + .value = {"tcp", "socket", "ib-verbs", "unix", "ib-sdp", + "tcp/client", "ib-verbs/client"}, + .type = GF_OPTION_TYPE_STR + }, + { .key = {"remote-host"}, + .type = GF_OPTION_TYPE_INTERNET_ADDRESS + }, + { .key = {"remote-subvolume"}, + .type = GF_OPTION_TYPE_ANY + }, + { .key = {"frame-timeout", + "rpc-timeout" }, + .type = GF_OPTION_TYPE_TIME, + .min = 0, + .max = 86400, + }, + { .key = {"ping-timeout"}, + .type = GF_OPTION_TYPE_TIME, + .min = 1, + .max = 1013, + }, + { .key = {NULL} }, +}; diff --git a/xlators/protocol/client/src/client.h b/xlators/protocol/client/src/client.h new file mode 100644 index 00000000..9d713bed --- /dev/null +++ b/xlators/protocol/client/src/client.h @@ -0,0 +1,125 @@ +/* + Copyright (c) 2010 Gluster, Inc. <http://www.gluster.com> + This file is part of GlusterFS. + + GlusterFS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3 of the License, + or (at your option) any later version. + + GlusterFS is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see + <http://www.gnu.org/licenses/>. +*/ + +#ifndef _CLIENT_H +#define _CLIENT_H + +#include <pthread.h> +#include <stdint.h> + +#include "rpc-clnt.h" +#include "list.h" +#include "inode.h" +#include "client-mem-types.h" +#include "protocol-common.h" + +struct clnt_options { + char *remote_subvolume; + int ping_timeout; +}; + +typedef struct clnt_conf { + struct rpc_clnt *rpc; + struct clnt_options opt; + struct rpc_clnt_config rpc_conf; + struct list_head saved_fds; + pthread_mutex_t lock; + int connecting; + struct timeval last_sent; + struct timeval last_received; + + rpc_clnt_prog_t *fops; + rpc_clnt_prog_t *mgmt; + rpc_clnt_prog_t *handshake; +} clnt_conf_t; + +typedef struct _client_fd_ctx { + struct list_head sfd_pos; /* Stores the reference to this + fd's position in the saved_fds list. + */ + int64_t remote_fd; + inode_t *inode; + uint64_t ino; + uint64_t gen; + char is_dir; + char released; + int32_t flags; + int32_t wbflags; +} clnt_fd_ctx_t; + +typedef struct client_local { + loc_t loc; + loc_t loc2; + fd_t *fd; + clnt_fd_ctx_t *fdctx; + uint32_t flags; + uint32_t wbflags; + fop_cbk_fn_t op; +} clnt_local_t; + +typedef struct client_args { + loc_t *loc; + fd_t *fd; + dict_t *xattr_req; + const char *linkname; + struct iobref *iobref; + struct iovec *vector; + dict_t *xattr; + struct iatt *stbuf; + dict_t *dict; + loc_t *oldloc; + loc_t *newloc; + const char *name; + struct flock *flock; + const char *volume; + const char *basename; + off_t offset; + int32_t mask; + int32_t cmd; + size_t size; + mode_t mode; + dev_t rdev; + int32_t flags; + int32_t wbflags; + int32_t count; + int32_t datasync; + entrylk_cmd cmd_entrylk; + entrylk_type type; + gf_xattrop_flags_t optype; + int32_t valid; + int32_t len; +} clnt_args_t; + +typedef ssize_t (*gfs_serialize_t) (struct iovec outmsg, void *args); + +clnt_fd_ctx_t *this_fd_get_ctx (fd_t *file, xlator_t *this); +clnt_fd_ctx_t *this_fd_del_ctx (fd_t *file, xlator_t *this); +void this_fd_set_ctx (fd_t *file, xlator_t *this, loc_t *loc, + clnt_fd_ctx_t *ctx); + +int client_local_wipe (clnt_local_t *local); +int client_submit_request (xlator_t *this, void *req, + call_frame_t *frame, rpc_clnt_prog_t *prog, + int procnum, struct iobref *iobref, + gfs_serialize_t sfunc); + +int protocol_client_reopendir (xlator_t *this, clnt_fd_ctx_t *fdctx); +int protocol_client_reopen (xlator_t *this, clnt_fd_ctx_t *fdctx); + +#endif /* !_CLIENT_H */ diff --git a/xlators/protocol/client/src/client3_1-fops.c b/xlators/protocol/client/src/client3_1-fops.c new file mode 100644 index 00000000..01b78436 --- /dev/null +++ b/xlators/protocol/client/src/client3_1-fops.c @@ -0,0 +1,4662 @@ +/* + Copyright (c) 2010 Gluster, Inc. <http://www.gluster.com> + This file is part of GlusterFS. + + GlusterFS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3 of the License, + or (at your option) any later version. + + GlusterFS is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see + <http://www.gnu.org/licenses/>. +*/ + + +#ifndef _CONFIG_H +#define _CONFIG_H +#include "config.h" +#endif + +#include "client.h" +#include "glusterfs-xdr.h" +#include "msg-xdr.h" +#include "compat-errno.h" + +void client_start_ping (void *data); +rpc_clnt_prog_t clnt3_1_fop_prog; + +int +client_submit_vec_request (xlator_t *this, void *req, + call_frame_t *frame, rpc_clnt_prog_t *prog, int procnum, + struct iovec *payload, int payloadcnt, + struct iobref *iobref, gfs_serialize_t sfunc) +{ + int ret = 0; + clnt_conf_t *conf = NULL; + struct iovec iov = {0, }; + struct iobuf *iobuf = NULL; + int count = 0; + char new_iobref = 0; + int start_ping = 0; + + start_ping = 0; + + conf = this->private; + + iobuf = iobuf_get (this->ctx->iobuf_pool); + if (!iobuf) { + goto out; + }; + + if (!iobref) { + iobref = iobref_new (); + if (!iobref) { + goto out; + } + + new_iobref = 1; + } + + iobref_add (iobref, iobuf); + + iov.iov_base = iobuf->ptr; + iov.iov_len = 128 * GF_UNIT_KB; + + /* Create the xdr payload */ + if (req && sfunc) { + ret = sfunc (iov, req); + if (ret == -1) { + goto out; + } + iov.iov_len = ret; + count = 1; + } + /* Send the msg */ + ret = rpc_clnt_submit (conf->rpc, prog, procnum, &iov, count, + payload, payloadcnt, iobref, frame); + + if (ret == 0) { + pthread_mutex_lock (&conf->rpc->conn.lock); + { + if (!conf->rpc->conn.ping_started) { + start_ping = 1; + } + } + pthread_mutex_unlock (&conf->rpc->conn.lock); + } + + if (start_ping) + client_start_ping ((void *) this); + +out: + if (new_iobref) { + iobref_unref (iobref); + } + + iobuf_unref (iobuf); + + return 0; +} + +int +client_fdctx_destroy (xlator_t *this, clnt_fd_ctx_t *fdctx) +{ + call_frame_t *fr = NULL; + int32_t ret = -1; + + if (!fdctx) + goto out; + + if (fdctx->remote_fd == -1) + goto out; + + fr = create_frame (this, this->ctx->pool); + + if (fdctx->is_dir) { + gfs3_releasedir_req req = {0,}; + req.fd = fdctx->remote_fd; + client_submit_request (this, &req, fr, &clnt3_1_fop_prog, + GFS3_OP_RELEASEDIR, NULL, + xdr_from_releasedir_req); + } else { + gfs3_release_req req = {0,}; + req.fd = fdctx->remote_fd; + client_submit_request (this, &req, fr, &clnt3_1_fop_prog, + GFS3_OP_RELEASE, NULL, + xdr_from_release_req); + } + +out: + fdctx->remote_fd = -1; + inode_unref (fdctx->inode); + GF_FREE (fdctx); + + return ret; +} + +int +client3_1_reopen_cbk (struct rpc_req *req, struct iovec *iov, int count, + void *myframe) +{ + int32_t ret = -1; + gfs3_open_rsp rsp = {0,}; + clnt_local_t *local = NULL; + clnt_conf_t *conf = NULL; + clnt_fd_ctx_t *fdctx = NULL; + call_frame_t *frame = NULL; + + frame = myframe; + + local = frame->local; + conf = frame->this->private; + fdctx = local->fdctx; + + if (-1 == req->rpc_status) { + rsp.op_ret = -1; + rsp.op_errno = ENOTCONN; + goto out; + } + + ret = xdr_to_open_rsp (*iov, &rsp); + if (ret < 0) { + gf_log ("", GF_LOG_ERROR, "error"); + rsp.op_ret = -1; + rsp.op_errno = EINVAL; + goto out; + } + + gf_log (frame->this->name, GF_LOG_DEBUG, + "reopen on %s returned %d (%"PRId64")", + local->loc.path, rsp.op_ret, rsp.fd); + + if (-1 != rsp.op_ret) { + pthread_mutex_lock (&conf->lock); + { + fdctx->remote_fd = rsp.fd; + + if (!fdctx->released) { + list_add_tail (&fdctx->sfd_pos, &conf->saved_fds); + fdctx = NULL; + } + } + pthread_mutex_unlock (&conf->lock); + } + +out: + if (fdctx) + client_fdctx_destroy (frame->this, fdctx); + + frame->local = NULL; + STACK_DESTROY (frame->root); + + client_local_wipe (local); + + return 0; +} + +int +client3_1_reopendir_cbk (struct rpc_req *req, struct iovec *iov, int count, + void *myframe) +{ + int32_t ret = -1; + gfs3_open_rsp rsp = {0,}; + clnt_local_t *local = NULL; + clnt_conf_t *conf = NULL; + clnt_fd_ctx_t *fdctx = NULL; + call_frame_t *frame = NULL; + + frame = myframe; + if (!frame || !frame->this) + goto out; + + local = frame->local; + frame->local = NULL; + conf = frame->this->private; + fdctx = local->fdctx; + + if (-1 == req->rpc_status) { + rsp.op_ret = -1; + rsp.op_errno = ENOTCONN; + goto out; + } + + ret = xdr_to_opendir_rsp (*iov, &rsp); + if (ret < 0) { + gf_log ("", GF_LOG_ERROR, "error"); + rsp.op_ret = -1; + rsp.op_errno = EINVAL; + goto out; + } + + gf_log (frame->this->name, GF_LOG_DEBUG, + "reopendir on %s returned %d (%"PRId64")", + local->loc.path, rsp.op_ret, rsp.fd); + + if (fdctx) { + pthread_mutex_lock (&conf->lock); + { + fdctx->remote_fd = rsp.fd; + + if (!fdctx->released) { + list_add_tail (&fdctx->sfd_pos, &conf->saved_fds); + fdctx = NULL; + } + } + pthread_mutex_unlock (&conf->lock); + } + +out: + if (fdctx) + client_fdctx_destroy (frame->this, fdctx); + + frame->local = NULL; + STACK_DESTROY (frame->root); + + client_local_wipe (local); + + return 0; +} + +int +protocol_client_reopendir (xlator_t *this, clnt_fd_ctx_t *fdctx) +{ + int ret = -1; + gfs3_opendir_req req = {0,}; + clnt_local_t *local = NULL; + inode_t *inode = NULL; + char *path = NULL; + call_frame_t *frame = NULL; + clnt_conf_t *conf = NULL; + + if (!this || !fdctx) + goto out; + + inode = fdctx->inode; + conf = this->private; + + ret = inode_path (inode, NULL, &path); + if (ret < 0) { + goto out; + } + + local = GF_CALLOC (1, sizeof (*local), 0); + if (!local) { + goto out; + } + + local->fdctx = fdctx; + local->op = client3_1_reopendir_cbk; + local->loc.path = path; + path = NULL; + + frame = create_frame (this, this->ctx->pool); + if (!frame) { + goto out; + } + + req.ino = fdctx->ino; + req.gen = fdctx->gen; + req.path = (char *)local->loc.path; + + gf_log (frame->this->name, GF_LOG_DEBUG, + "attempting reopen on %s", local->loc.path); + + frame->local = local; local = NULL; + + client_submit_request (this, &req, frame, conf->fops, + GFS3_OP_OPENDIR, NULL, xdr_from_opendir_req); + + return ret; + +out: + if (frame) { + frame->local = NULL; + STACK_DESTROY (frame->root); + } + + if (local) + client_local_wipe (local); + + if (path) + GF_FREE (path); + + return 0; + +} + +int +protocol_client_reopen (xlator_t *this, clnt_fd_ctx_t *fdctx) +{ + int ret = -1; + gfs3_open_req req = {0,}; + clnt_local_t *local = NULL; + inode_t *inode = NULL; + char *path = NULL; + call_frame_t *frame = NULL; + clnt_conf_t *conf = NULL; + + if (!this || !fdctx) + goto out; + + inode = fdctx->inode; + conf = this->private; + + ret = inode_path (inode, NULL, &path); + if (ret < 0) { + goto out; + } + + frame = create_frame (this, this->ctx->pool); + if (!frame) { + goto out; + } + + local = GF_CALLOC (1, sizeof (*local), 0); + if (!local) { + goto out; + } + + local->fdctx = fdctx; + local->op = client3_1_reopen_cbk; + local->loc.path = path; + path = NULL; + frame->local = local; + + req.ino = fdctx->ino; + req.gen = fdctx->gen; + req.flags = gf_flags_from_flags (fdctx->flags); + req.wbflags = fdctx->wbflags; + req.path = (char *)local->loc.path; + + gf_log (frame->this->name, GF_LOG_DEBUG, + "attempting reopen on %s", local->loc.path); + + local = NULL; + client_submit_request (this, &req, frame, conf->fops, + GFS3_OP_OPEN, NULL, xdr_from_open_req); + + return ret; + +out: + if (frame) { + frame->local = NULL; + STACK_DESTROY (frame->root); + } + + if (local) + client_local_wipe (local); + + if (path) + GF_FREE (path); + + return 0; + +} + + + +int32_t +client3_1_releasedir (call_frame_t *frame, xlator_t *this, rpc_clnt_prog_t *prog, + void *data) +{ + clnt_conf_t *conf = NULL; + clnt_fd_ctx_t *fdctx = NULL; + clnt_args_t *args = NULL; + gfs3_releasedir_req req = {0,}; + int64_t remote_fd = -1; + + if (!frame || !this || !prog || !data) + goto unwind; + + args = data; + conf = this->private; + + pthread_mutex_lock (&conf->lock); + { + fdctx = this_fd_del_ctx (args->fd, this); + if (fdctx != NULL) { + remote_fd = fdctx->remote_fd; + + /* fdctx->remote_fd == -1 indicates a reopen attempt + in progress. Just mark ->released = 1 and let + reopen_cbk handle releasing + */ + + if (remote_fd != -1) + list_del_init (&fdctx->sfd_pos); + + fdctx->released = 1; + } + } + pthread_mutex_unlock (&conf->lock); + + if (remote_fd != -1) { + req.fd = remote_fd; + client_submit_request (this, &req, frame, prog, + GFS3_OP_RELEASEDIR, + NULL, xdr_from_releasedir_req); + inode_unref (fdctx->inode); + GF_FREE (fdctx); + } + + return 0; +unwind: + return 0; +} + +int32_t +client3_1_release (call_frame_t *frame, xlator_t *this, rpc_clnt_prog_t *prog, + void *data) +{ + int64_t remote_fd = -1; + clnt_conf_t *conf = NULL; + clnt_fd_ctx_t *fdctx = NULL; + clnt_args_t *args = NULL; + gfs3_release_req req = {0,}; + + if (!frame || !this || !prog || !data) + goto unwind; + + args = data; + conf = this->private; + + pthread_mutex_lock (&conf->lock); + { + fdctx = this_fd_del_ctx (args->fd, this); + if (fdctx != NULL) { + remote_fd = fdctx->remote_fd; + + /* fdctx->remote_fd == -1 indicates a reopen attempt + in progress. Just mark ->released = 1 and let + reopen_cbk handle releasing + */ + + if (remote_fd != -1) + list_del_init (&fdctx->sfd_pos); + + fdctx->released = 1; + } + } + pthread_mutex_unlock (&conf->lock); + + if (remote_fd != -1) { + req.fd = remote_fd; + client_submit_request (this, &req, frame, prog, + GFS3_OP_RELEASE, NULL, + xdr_from_release_req); + inode_unref (fdctx->inode); + GF_FREE (fdctx); + } + return 0; +unwind: + return 0; +} + + +int32_t +client3_1_lookup (call_frame_t *frame, xlator_t *this, rpc_clnt_prog_t *prog, + void *data) +{ + clnt_local_t *local = NULL; + clnt_args_t *args = NULL; + gfs3_lookup_req req = {0,}; + int ret = 0; + size_t dict_len = 0; + int op_errno = ESTALE; + + if (!frame || !this || !prog || !data) + goto unwind; + + args = data; + local = GF_CALLOC (1, sizeof (*local), gf_client_mt_clnt_local_t); + if (!local) { + op_errno = ENOMEM; + goto unwind; + } + + loc_copy (&local->loc, args->loc); + frame->local = local; + + if (args->loc->ino != 1 && args->loc->parent) { + ret = inode_ctx_get2 (args->loc->parent, this, + &req.par, &req.gen); + if (args->loc->parent->ino && ret < 0) { + gf_log (this->name, GF_LOG_TRACE, + "LOOKUP %"PRId64"/%s (%s): failed to get " + "remote inode number for parent", + args->loc->parent->ino, args->loc->name, + args->loc->path); + goto unwind; + } + GF_VALIDATE_OR_GOTO (this->name, args->loc->name, unwind); + } else { + req.ino = 1; + } + + if (args->dict) { + ret = dict_allocate_and_serialize (args->dict, + &req.dict.dict_val, + &dict_len); + if (ret < 0) { + gf_log (this->name, GF_LOG_DEBUG, + "failed to get serialized length of dict"); + op_errno = EINVAL; + goto unwind; + } + } + + req.path = (char *)args->loc->path; + req.bname = (char *)args->loc->name; + req.dict.dict_len = dict_len; + + client_submit_request (this, &req, frame,prog, + GFS3_OP_LOOKUP, NULL, xdr_from_lookup_req); + + if (req.dict.dict_val) { + GF_FREE (req.dict.dict_val); + } + + return 0; + +unwind: + frame->local = NULL; + STACK_UNWIND_STRICT (lookup, frame, -1, op_errno, NULL, NULL, NULL, NULL); + + if (local) + client_local_wipe (local); + + if (req.dict.dict_val) { + GF_FREE (req.dict.dict_val); + } + + return 0; +} + + + +int32_t +client3_1_stat (call_frame_t *frame, xlator_t *this, rpc_clnt_prog_t *prog, + void *data) +{ + clnt_args_t *args = NULL; + gfs3_stat_req req = {0,}; + int ret = 0; + int op_errno = ESTALE; + + if (!frame || !this || !prog || !data) + goto unwind; + + args = data; + + ret = inode_ctx_get2 (args->loc->inode, this, &req.ino, &req.gen); + if (args->loc->inode->ino && ret < 0) { + gf_log (this->name, GF_LOG_TRACE, + "STAT %"PRId64" (%s): " + "failed to get remote inode number", + args->loc->inode->ino, args->loc->path); + goto unwind; + } + req.path = (char *)args->loc->path; + + client_submit_request (this, &req, frame,prog, GFS3_OP_STAT, + NULL, xdr_from_stat_req); + + return 0; +unwind: + STACK_UNWIND_STRICT (stat, frame, -1, op_errno, NULL); + return 0; +} + + +int32_t +client3_1_truncate (call_frame_t *frame, xlator_t *this, rpc_clnt_prog_t *prog, + void *data) +{ + clnt_args_t *args = NULL; + gfs3_truncate_req req = {0,}; + int ret = 0; + int op_errno = ESTALE; + + if (!frame || !this || !prog || !data) + goto unwind; + + args = data; + + ret = inode_ctx_get2 (args->loc->inode, this, &req.ino, &req.gen); + if (args->loc->inode->ino && ret < 0) { + gf_log (this->name, GF_LOG_TRACE, + "STAT %"PRId64" (%s): " + "failed to get remote inode number", + args->loc->inode->ino, args->loc->path); + goto unwind; + } + req.path = (char *)args->loc->path; + req.offset = args->offset; + + client_submit_request (this, &req, frame,prog, GFS3_OP_TRUNCATE, + NULL, xdr_from_truncate_req); + + return 0; +unwind: + STACK_UNWIND_STRICT (truncate, frame, -1, op_errno, NULL, NULL); + return 0; +} + + +int32_t +client3_1_ftruncate (call_frame_t *frame, xlator_t *this, rpc_clnt_prog_t *prog, + void *data) +{ + clnt_args_t *args = NULL; + clnt_fd_ctx_t *fdctx = NULL; + clnt_conf_t *conf = NULL; + gfs3_ftruncate_req req = {0,}; + int op_errno = EINVAL; + + if (!frame || !this || !prog || !data) + goto unwind; + + args = data; + + conf = this->private; + + pthread_mutex_lock (&conf->lock); + { + fdctx = this_fd_get_ctx (args->fd, this); + } + pthread_mutex_unlock (&conf->lock); + + if (fdctx == NULL) { + gf_log (this->name, GF_LOG_DEBUG, + "(%"PRId64"): failed to get fd ctx. EBADFD", + args->fd->inode->ino); + op_errno = EBADFD; + goto unwind; + } + + if (fdctx->remote_fd == -1) { + gf_log (this->name, GF_LOG_DEBUG, "(%"PRId64"): failed to get" + " fd ctx. EBADFD", args->fd->inode->ino); + op_errno = EBADFD; + goto unwind; + } + + req.offset = args->offset; + req.fd = fdctx->remote_fd; + + client_submit_request (this, &req, frame,prog, GFS3_OP_FTRUNCATE, + NULL, xdr_from_ftruncate_req); + + return 0; +unwind: + STACK_UNWIND_STRICT (ftruncate, frame, -1, op_errno, NULL, NULL); + return 0; +} + + + +int32_t +client3_1_access (call_frame_t *frame, xlator_t *this, rpc_clnt_prog_t *prog, + void *data) +{ + clnt_args_t *args = NULL; + gfs3_access_req req = {0,}; + int ret = 0; + int op_errno = ESTALE; + + if (!frame || !this || !prog || !data) + goto unwind; + + args = data; + + ret = inode_ctx_get2 (args->loc->inode, this, &req.ino, &req.gen); + if (args->loc->inode->ino && ret < 0) { + gf_log (this->name, GF_LOG_TRACE, + "STAT %"PRId64" (%s): " + "failed to get remote inode number", + args->loc->inode->ino, args->loc->path); + goto unwind; + } + req.path = (char *)args->loc->path; + req.mask = args->mask; + + client_submit_request (this, &req, frame,prog, GFS3_OP_ACCESS, + NULL, xdr_from_access_req); + + return 0; +unwind: + STACK_UNWIND_STRICT (access, frame, -1, op_errno); + return 0; +} + +int32_t +client3_1_readlink (call_frame_t *frame, xlator_t *this, rpc_clnt_prog_t *prog, + void *data) +{ + clnt_args_t *args = NULL; + gfs3_readlink_req req = {0,}; + int ret = 0; + int op_errno = ESTALE; + + if (!frame || !this || !prog || !data) + goto unwind; + + args = data; + + ret = inode_ctx_get2 (args->loc->inode, this, &req.ino, &req.gen); + if (args->loc->inode->ino && ret < 0) { + gf_log (this->name, GF_LOG_TRACE, + "STAT %"PRId64" (%s): " + "failed to get remote inode number", + args->loc->inode->ino, args->loc->path); + goto unwind; + } + req.path = (char *)args->loc->path; + req.size = args->size; + + client_submit_request (this, &req, frame,prog, GFS3_OP_READLINK, + NULL, xdr_from_readlink_req); + + return 0; +unwind: + STACK_UNWIND_STRICT (readlink, frame, -1, op_errno, NULL, NULL); + return 0; +} + + + + +int32_t +client3_1_unlink (call_frame_t *frame, xlator_t *this, rpc_clnt_prog_t *prog, + void *data) +{ + clnt_args_t *args = NULL; + gfs3_unlink_req req = {0,}; + int ret = 0; + int op_errno = 0; + + if (!frame || !this || !prog || !data) + goto unwind; + + args = data; + + ret = inode_ctx_get2 (args->loc->parent, this, &req.par, &req.gen); + if (args->loc->parent->ino && ret < 0) { + gf_log (this->name, GF_LOG_TRACE, + "STAT %"PRId64"/%s (%s): " + "failed to get remote inode number for parent", + args->loc->parent->ino, args->loc->name, args->loc->path); + goto unwind; + } + req.path = (char *)args->loc->path; + req.bname = (char *)args->loc->name; + + client_submit_request (this, &req, frame,prog, GFS3_OP_UNLINK, + NULL, xdr_from_unlink_req); + + return 0; +unwind: + STACK_UNWIND_STRICT (unlink, frame, -1, op_errno, NULL, NULL); + return 0; +} + + + +int32_t +client3_1_rmdir (call_frame_t *frame, xlator_t *this, rpc_clnt_prog_t *prog, + void *data) +{ + clnt_args_t *args = NULL; + gfs3_rmdir_req req = {0,}; + int ret = 0; + int op_errno = ESTALE; + + if (!frame || !this || !prog || !data) + goto unwind; + + args = data; + + ret = inode_ctx_get2 (args->loc->parent, this, &req.par, &req.gen); + if (args->loc->inode->ino && ret < 0) { + gf_log (this->name, GF_LOG_TRACE, + "STAT %"PRId64"/%s (%s): " + "failed to get remote inode number for parent", + args->loc->parent->ino, args->loc->name, args->loc->path); + goto unwind; + } + req.path = (char *)args->loc->path; + req.bname = (char *)args->loc->name; + + client_submit_request (this, &req, frame,prog, GFS3_OP_RMDIR, + NULL, xdr_from_rmdir_req); + + return 0; +unwind: + STACK_UNWIND_STRICT (rmdir, frame, -1, op_errno, NULL, NULL); + return 0; +} + + + +int32_t +client3_1_symlink (call_frame_t *frame, xlator_t *this, rpc_clnt_prog_t *prog, + void *data) +{ + clnt_local_t *local = NULL; + clnt_args_t *args = NULL; + gfs3_symlink_req req = {0,}; + int ret = 0; + int op_errno = ESTALE; + + if (!frame || !this || !prog || !data) + goto unwind; + + args = data; + local = GF_CALLOC (1, sizeof (*local), gf_client_mt_clnt_local_t); + if (!local) { + op_errno = ENOMEM; + goto unwind; + } + + loc_copy (&local->loc, args->loc); + frame->local = local; + + ret = inode_ctx_get2 (args->loc->parent, this, &req.par, &req.gen); + if (args->loc->parent->ino && ret < 0) { + gf_log (this->name, GF_LOG_DEBUG, + "SYMLINK %"PRId64"/%s (%s): failed to get remote inode" + " number parent", + args->loc->parent->ino, args->loc->name, + args->loc->path); + goto unwind; + } + + req.path = (char *)args->loc->path; + req.linkname = (char *)args->linkname; + req.bname = (char *)args->loc->name; + + client_submit_request (this, &req, frame,prog, GFS3_OP_SYMLINK, + NULL, xdr_from_symlink_req); + + return 0; +unwind: + frame->local = NULL; + STACK_UNWIND_STRICT (symlink, frame, -1, op_errno, NULL, NULL, NULL, NULL); + if (local) + client_local_wipe (local); + return 0; +} + + + +int32_t +client3_1_rename (call_frame_t *frame, xlator_t *this, rpc_clnt_prog_t *prog, + void *data) +{ + clnt_args_t *args = NULL; + gfs3_rename_req req = {0,}; + int ret = 0; + int op_errno = ESTALE; + + if (!frame || !this || !prog || !data) + goto unwind; + + args = data; + + ret = inode_ctx_get2 (args->oldloc->parent, this, + &req.oldpar, &req.oldgen); + if (args->oldloc->parent->ino && ret < 0) { + gf_log (this->name, GF_LOG_DEBUG, + "RENAME %"PRId64"/%s (%s): failed to get remote inode " + "number for source parent", args->oldloc->parent->ino, + args->oldloc->name, args->oldloc->path); + goto unwind; + } + + ret = inode_ctx_get2 (args->newloc->parent, this, &req.newpar, + &req.newgen); + if (args->newloc->parent->ino && ret < 0) { + gf_log (this->name, GF_LOG_DEBUG, + "CREATE %"PRId64"/%s (%s): failed to get remote inode " + "number for destination parent", + args->newloc->parent->ino, args->newloc->name, + args->newloc->path); + goto unwind; + } + + req.oldpath = (char *)args->oldloc->path; + req.oldbname = (char *)args->oldloc->name; + req.newpath = (char *)args->newloc->path; + req.newbname = (char *)args->newloc->name; + + client_submit_request (this, &req, frame,prog, GFS3_OP_RENAME, + NULL, xdr_from_rename_req); + + return 0; +unwind: + STACK_UNWIND_STRICT (rename, frame, -1, op_errno, NULL, NULL, NULL, NULL, NULL); + return 0; +} + + + +int32_t +client3_1_link (call_frame_t *frame, xlator_t *this, rpc_clnt_prog_t *prog, + void *data) +{ + clnt_local_t *local = NULL; + clnt_args_t *args = NULL; + gfs3_link_req req = {0,}; + int ret = 0; + int op_errno = ESTALE; + + if (!frame || !this || !prog || !data) + goto unwind; + + args = data; + + local = GF_CALLOC (1, sizeof (*local), gf_client_mt_clnt_local_t); + if (!local) { + op_errno = ENOMEM; + goto unwind; + } + + loc_copy (&local->loc, args->oldloc); + frame->local = local; + + ret = inode_ctx_get2 (args->oldloc->inode, this, + &req.oldino, &req.oldgen); + if (args->oldloc->parent->ino && ret < 0) { + gf_log (this->name, GF_LOG_DEBUG, + "RENAME %"PRId64"/%s (%s): failed to get remote inode " + "number for source parent", args->oldloc->parent->ino, + args->oldloc->name, args->oldloc->path); + goto unwind; + } + + ret = inode_ctx_get2 (args->newloc->parent, this, &req.newpar, + &req.newgen); + if (args->newloc->parent->ino && ret < 0) { + gf_log (this->name, GF_LOG_DEBUG, + "CREATE %"PRId64"/%s (%s): failed to get remote inode " + "number for destination parent", + args->newloc->parent->ino, args->newloc->name, + args->newloc->path); + goto unwind; + } + + req.oldpath = (char *)args->oldloc->path; + req.newpath = (char *)args->newloc->path; + req.newbname = (char *)args->newloc->name; + + client_submit_request (this, &req, frame,prog, GFS3_OP_LINK, + NULL, xdr_from_link_req); + + return 0; +unwind: + STACK_UNWIND_STRICT (link, frame, -1, op_errno, NULL, NULL, NULL, NULL); + return 0; +} + + + +int32_t +client3_1_mknod (call_frame_t *frame, xlator_t *this, rpc_clnt_prog_t *prog, + void *data) +{ + clnt_local_t *local = NULL; + clnt_args_t *args = NULL; + gfs3_mknod_req req = {0,}; + int ret = 0; + int op_errno = ESTALE; + + if (!frame || !this || !prog || !data) + goto unwind; + + args = data; + + local = GF_CALLOC (1, sizeof (*local), gf_client_mt_clnt_local_t); + if (!local) { + op_errno = ENOMEM; + goto unwind; + } + + loc_copy (&local->loc, args->loc); + frame->local = local; + + ret = inode_ctx_get2 (args->loc->parent, this, &req.par, &req.gen); + if (args->loc->parent->ino && ret < 0) { + gf_log (this->name, GF_LOG_DEBUG, + "SYMLINK %"PRId64"/%s (%s): failed to get remote inode" + " number parent", + args->loc->parent->ino, args->loc->name, + args->loc->path); + goto unwind; + } + + req.path = (char *)args->loc->path; + req.bname = (char *)args->loc->name; + req.mode = args->mode; + req.dev = args->rdev; + + client_submit_request (this, &req, frame,prog, GFS3_OP_MKNOD, + NULL, xdr_from_mknod_req); + + return 0; +unwind: + frame->local = NULL; + STACK_UNWIND_STRICT (mknod, frame, -1, op_errno, NULL, NULL, NULL, NULL); + if (local) + client_local_wipe (local); + return 0; +} + + + +int32_t +client3_1_mkdir (call_frame_t *frame, xlator_t *this, rpc_clnt_prog_t *prog, + void *data) +{ + clnt_local_t *local = NULL; + clnt_args_t *args = NULL; + gfs3_mkdir_req req = {0,}; + int ret = 0; + int op_errno = ESTALE; + + if (!frame || !this || !prog || !data) + goto unwind; + + args = data; + + local = GF_CALLOC (1, sizeof (*local), gf_client_mt_clnt_local_t); + if (!local) { + op_errno = ENOMEM; + goto unwind; + } + + loc_copy (&local->loc, args->loc); + frame->local = local; + + ret = inode_ctx_get2 (args->loc->parent, this, &req.par, &req.gen); + if (args->loc->parent->ino && ret < 0) { + gf_log (this->name, GF_LOG_DEBUG, + "SYMLINK %"PRId64"/%s (%s): failed to get remote inode" + " number parent", + args->loc->parent->ino, args->loc->name, + args->loc->path); + goto unwind; + } + + req.path = (char *)args->loc->path; + req.bname = (char *)args->loc->name; + req.mode = args->mode; + + client_submit_request (this, &req, frame,prog, GFS3_OP_MKDIR, + NULL, xdr_from_mkdir_req); + + return 0; +unwind: + frame->local = NULL; + STACK_UNWIND_STRICT (mkdir, frame, -1, op_errno, NULL, NULL, NULL, NULL); + if (local) + client_local_wipe (local); + return 0; +} + + +int32_t +client3_1_create (call_frame_t *frame, xlator_t *this, rpc_clnt_prog_t *prog, + void *data) +{ + clnt_local_t *local = NULL; + clnt_args_t *args = NULL; + gfs3_create_req req = {0,}; + int ret = 0; + int op_errno = ESTALE; + + if (!frame || !this || !prog || !data) + goto unwind; + + args = data; + + local = GF_CALLOC (1, sizeof (*local), gf_client_mt_clnt_local_t); + if (!local) { + op_errno = ENOMEM; + goto unwind; + } + local->fd = fd_ref (args->fd); + local->flags = args->flags; + loc_copy (&local->loc, args->loc); + frame->local = local; + + ret = inode_ctx_get2 (args->loc->parent, this, &req.par, &req.gen); + if (args->loc->parent->ino && ret < 0) { + gf_log (this->name, GF_LOG_DEBUG, + "SYMLINK %"PRId64"/%s (%s): failed to get remote inode" + " number parent", + args->loc->parent->ino, args->loc->name, + args->loc->path); + goto unwind; + } + + req.path = (char *)args->loc->path; + req.bname = (char *)args->loc->name; + req.mode = args->mode; + req.flags = gf_flags_from_flags (args->flags); + + client_submit_request (this, &req, frame,prog, GFS3_OP_CREATE, + NULL, xdr_from_create_req); + + return 0; +unwind: + frame->local = NULL; + STACK_UNWIND_STRICT (create, frame, -1, op_errno, NULL, NULL, NULL, NULL, NULL); + if (local) + client_local_wipe (local); + return 0; +} + + + +int32_t +client3_1_open (call_frame_t *frame, xlator_t *this, rpc_clnt_prog_t *prog, + void *data) +{ + clnt_local_t *local = NULL; + clnt_args_t *args = NULL; + gfs3_open_req req = {0,}; + int ret = 0; + int op_errno = ESTALE; + + if (!frame || !this || !prog || !data) + goto unwind; + + args = data; + + local = GF_CALLOC (1, sizeof (*local), gf_client_mt_clnt_local_t); + if (!local) { + op_errno = ENOMEM; + goto unwind; + } + local->fd = fd_ref (args->fd); + local->flags = args->flags; + local->wbflags = args->wbflags; + loc_copy (&local->loc, args->loc); + frame->local = local; + + ret = inode_ctx_get2 (args->loc->inode, this, &req.ino, &req.gen); + if (args->loc->inode->ino && ret < 0) { + gf_log (this->name, GF_LOG_DEBUG, + "OPEN %"PRId64" (%s): " + "failed to get remote inode number", + args->loc->inode->ino, args->loc->path); + goto unwind; + } + req.flags = gf_flags_from_flags (args->flags); + req.wbflags = args->wbflags; + req.path = (char *)args->loc->path; + + client_submit_request (this, &req, frame,prog, GFS3_OP_OPEN, + NULL, xdr_from_open_req); + + return 0; +unwind: + frame->local = NULL; + STACK_UNWIND_STRICT (open, frame, -1, op_errno, NULL); + if (local) + client_local_wipe (local); + return 0; +} + + + +int32_t +client3_1_readv (call_frame_t *frame, xlator_t *this, rpc_clnt_prog_t *prog, + void *data) +{ + clnt_args_t *args = NULL; + clnt_fd_ctx_t *fdctx = NULL; + clnt_conf_t *conf = NULL; + int op_errno = ESTALE; + gfs3_read_req req = {0,}; + + if (!frame || !this || !prog || !data) + goto unwind; + + args = data; + conf = this->private; + + pthread_mutex_lock (&conf->lock); + { + fdctx = this_fd_get_ctx (args->fd, this); + } + pthread_mutex_unlock (&conf->lock); + + if (fdctx == NULL) { + gf_log (this->name, GF_LOG_DEBUG, + "(%"PRId64"): failed to get fd ctx. EBADFD", + args->fd->inode->ino); + op_errno = EBADFD; + goto unwind; + } + + if (fdctx->remote_fd == -1) { + gf_log (this->name, GF_LOG_DEBUG, "(%"PRId64"): failed to get" + " fd ctx. EBADFD", args->fd->inode->ino); + op_errno = EBADFD; + goto unwind; + } + + req.size = args->size; + req.offset = args->offset; + req.fd = fdctx->remote_fd; + + client_submit_request (this, &req, frame,prog, GFS3_OP_READ, + NULL, xdr_from_readv_req); + + return 0; +unwind: + STACK_UNWIND_STRICT (readv, frame, -1, op_errno, NULL, 0, NULL, NULL); + return 0; +} + + +int32_t +client3_1_writev (call_frame_t *frame, xlator_t *this, rpc_clnt_prog_t *prog, + void *data) +{ + clnt_args_t *args = NULL; + clnt_fd_ctx_t *fdctx = NULL; + clnt_conf_t *conf = NULL; + gfs3_write_req req = {0,}; + int op_errno = ESTALE; + + if (!frame || !this || !prog || !data) + goto unwind; + + args = data; + conf = this->private; + + pthread_mutex_lock (&conf->lock); + { + fdctx = this_fd_get_ctx (args->fd, this); + } + pthread_mutex_unlock (&conf->lock); + + if (fdctx == NULL) { + gf_log (this->name, GF_LOG_DEBUG, + "(%"PRId64"): failed to get fd ctx. EBADFD", + args->fd->inode->ino); + op_errno = EBADFD; + goto unwind; + } + + if (fdctx->remote_fd == -1) { + gf_log (this->name, GF_LOG_DEBUG, "(%"PRId64"): failed to get" + " fd ctx. EBADFD", args->fd->inode->ino); + op_errno = EBADFD; + goto unwind; + } + + req.size = args->size; + req.offset = args->offset; + req.fd = fdctx->remote_fd; + + /* TODO: Buffer */ + + client_submit_vec_request (this, &req, frame,prog, GFS3_OP_WRITE, + args->vector, args->count, + args->iobref, xdr_from_writev_req); + + return 0; +unwind: + STACK_UNWIND_STRICT (writev, frame, -1, op_errno, NULL, NULL); + return 0; +} + + + +int32_t +client3_1_flush (call_frame_t *frame, xlator_t *this, rpc_clnt_prog_t *prog, + void *data) +{ + clnt_args_t *args = NULL; + gfs3_flush_req req = {0,}; + clnt_fd_ctx_t *fdctx = NULL; + clnt_conf_t *conf = NULL; + int op_errno = ESTALE; + + if (!frame || !this || !prog || !data) + goto unwind; + + args = data; + conf = this->private; + + pthread_mutex_lock (&conf->lock); + { + fdctx = this_fd_get_ctx (args->fd, this); + } + pthread_mutex_unlock (&conf->lock); + + if (fdctx == NULL) { + gf_log (this->name, GF_LOG_DEBUG, + "(%"PRId64"): failed to get fd ctx. EBADFD", + args->fd->inode->ino); + op_errno = EBADFD; + goto unwind; + } + + if (fdctx->remote_fd == -1) { + gf_log (this->name, GF_LOG_DEBUG, "(%"PRId64"): failed to get" + " fd ctx. EBADFD", args->fd->inode->ino); + op_errno = EBADFD; + goto unwind; + } + + req.fd = fdctx->remote_fd; + + client_submit_request (this, &req, frame,prog, GFS3_OP_FLUSH, + NULL, xdr_from_flush_req); + + return 0; +unwind: + STACK_UNWIND_STRICT (flush, frame, -1, op_errno); + return 0; +} + + + +int32_t +client3_1_fsync (call_frame_t *frame, xlator_t *this, rpc_clnt_prog_t *prog, + void *data) +{ + clnt_args_t *args = NULL; + gfs3_fsync_req req = {0,}; + clnt_fd_ctx_t *fdctx = NULL; + clnt_conf_t *conf = NULL; + int op_errno = 0; + + if (!frame || !this || !prog || !data) + goto unwind; + + args = data; + conf = this->private; + + pthread_mutex_lock (&conf->lock); + { + fdctx = this_fd_get_ctx (args->fd, this); + } + pthread_mutex_unlock (&conf->lock); + + if (fdctx == NULL) { + gf_log (this->name, GF_LOG_DEBUG, + "(%"PRId64"): failed to get fd ctx. EBADFD", + args->fd->inode->ino); + op_errno = EBADFD; + goto unwind; + } + + if (fdctx->remote_fd == -1) { + gf_log (this->name, GF_LOG_DEBUG, "(%"PRId64"): failed to get" + " fd ctx. EBADFD", args->fd->inode->ino); + op_errno = EBADFD; + goto unwind; + } + + req.fd = fdctx->remote_fd; + req.data = args->flags; + + client_submit_request (this, &req, frame,prog, GFS3_OP_FSYNC, + NULL, xdr_from_fsync_req); + + return 0; +unwind: + STACK_UNWIND_STRICT (fsync, frame, -1, op_errno, NULL, NULL); + return 0; +} + + + +int32_t +client3_1_fstat (call_frame_t *frame, xlator_t *this, rpc_clnt_prog_t *prog, + void *data) +{ + clnt_args_t *args = NULL; + gfs3_fstat_req req = {0,}; + clnt_fd_ctx_t *fdctx = NULL; + clnt_conf_t *conf = NULL; + int op_errno = ESTALE; + + if (!frame || !this || !prog || !data) + goto unwind; + + args = data; + conf = this->private; + + pthread_mutex_lock (&conf->lock); + { + fdctx = this_fd_get_ctx (args->fd, this); + } + pthread_mutex_unlock (&conf->lock); + + if (fdctx == NULL) { + gf_log (this->name, GF_LOG_DEBUG, + "(%"PRId64"): failed to get fd ctx. EBADFD", + args->fd->inode->ino); + op_errno = EBADFD; + goto unwind; + } + + if (fdctx->remote_fd == -1) { + gf_log (this->name, GF_LOG_DEBUG, "(%"PRId64"): failed to get" + " fd ctx. EBADFD", args->fd->inode->ino); + op_errno = EBADFD; + goto unwind; + } + + req.fd = fdctx->remote_fd; + + client_submit_request (this, &req, frame,prog, GFS3_OP_FSTAT, + NULL, xdr_from_fstat_req); + + return 0; +unwind: + STACK_UNWIND_STRICT (fstat, frame, -1, op_errno, NULL); + return 0; +} + + + +int32_t +client3_1_opendir (call_frame_t *frame, xlator_t *this, rpc_clnt_prog_t *prog, + void *data) +{ + clnt_local_t *local = NULL; + clnt_args_t *args = NULL; + gfs3_opendir_req req = {0,}; + int ret = 0; + int op_errno = ESTALE; + + if (!frame || !this || !prog || !data) + goto unwind; + + args = data; + + local = GF_CALLOC (1, sizeof (*local), gf_client_mt_clnt_local_t); + if (!local) { + op_errno = ENOMEM; + goto unwind; + } + local->fd = fd_ref (args->fd); + loc_copy (&local->loc, args->loc); + frame->local = local; + + ret = inode_ctx_get2 (args->loc->inode, this, &req.ino, &req.gen); + if (args->loc->inode->ino && ret < 0) { + gf_log (this->name, GF_LOG_DEBUG, + "OPEN %"PRId64" (%s): " + "failed to get remote inode number", + args->loc->inode->ino, args->loc->path); + goto unwind; + } + req.path = (char *)args->loc->path; + + client_submit_request (this, &req, frame,prog, GFS3_OP_OPENDIR, + NULL, xdr_from_opendir_req); + + return 0; +unwind: + frame->local = NULL; + STACK_UNWIND_STRICT (opendir, frame, -1, op_errno, NULL); + if (local) + client_local_wipe (local); + return 0; +} + + + +int32_t +client3_1_fsyncdir (call_frame_t *frame, xlator_t *this, rpc_clnt_prog_t *prog, + void *data) + +{ + clnt_args_t *args = NULL; + clnt_fd_ctx_t *fdctx = NULL; + clnt_conf_t *conf = NULL; + int op_errno = ESTALE; + gfs3_fsyncdir_req req = {0,}; + + if (!frame || !this || !prog || !data) + goto unwind; + + args = data; + conf = this->private; + + pthread_mutex_lock (&conf->lock); + { + fdctx = this_fd_get_ctx (args->fd, this); + } + pthread_mutex_unlock (&conf->lock); + + if (fdctx == NULL) { + gf_log (this->name, GF_LOG_DEBUG, + "(%"PRId64"): failed to get fd ctx. EBADFD", + args->fd->inode->ino); + op_errno = EBADFD; + goto unwind; + } + + if (fdctx->remote_fd == -1) { + gf_log (this->name, GF_LOG_DEBUG, "(%"PRId64"): failed to get" + " fd ctx. EBADFD", args->fd->inode->ino); + op_errno = EBADFD; + goto unwind; + } + + req.fd = fdctx->remote_fd; + req.data = args->flags; + + client_submit_request (this, &req, frame,prog, GFS3_OP_FSYNCDIR, + NULL, xdr_from_fsyncdir_req); + + return 0; +unwind: + STACK_UNWIND_STRICT (fsyncdir, frame, -1, op_errno); + return 0; +} + + + +int32_t +client3_1_statfs (call_frame_t *frame, xlator_t *this, rpc_clnt_prog_t *prog, + void *data) +{ + clnt_args_t *args = NULL; + gfs3_statfs_req req = {0,}; + int ret = 0; + int op_errno = ESTALE; + + if (!frame || !this || !prog || !data) + goto unwind; + + args = data; + + if (args->loc->inode) { + ret = inode_ctx_get2 (args->loc->inode, this, + &req.ino, &req.gen); + if (args->loc->inode->ino && ret < 0) { + gf_log (this->name, GF_LOG_TRACE, + "STATFS %"PRId64" (%s): " + "failed to get remote inode number", + args->loc->inode->ino, args->loc->path); + goto unwind; + } + } + req.path = (char *)args->loc->path; + + client_submit_request (this, &req, frame,prog, GFS3_OP_STATFS, + NULL, xdr_from_statfs_req); + + return 0; +unwind: + STACK_UNWIND_STRICT (statfs, frame, -1, op_errno, NULL); + return 0; +} + + + +int32_t +client3_1_setxattr (call_frame_t *frame, xlator_t *this, rpc_clnt_prog_t *prog, + void *data) +{ + clnt_args_t *args = NULL; + gfs3_setxattr_req req = {0,}; + int ret = 0; + size_t dict_len = 0; + int op_errno = ESTALE; + + if (!frame || !this || !prog || !data) + goto unwind; + + args = data; + + ret = inode_ctx_get2 (args->loc->inode, this, &req.ino, &req.gen); + if (args->loc->inode->ino && ret < 0) { + gf_log (this->name, GF_LOG_DEBUG, + "SETXATTR %"PRId64" (%s): " + "failed to get remote inode number", + args->loc->inode->ino, args->loc->path); + goto unwind; + } + if (args->dict) { + ret = dict_allocate_and_serialize (args->dict, + &req.dict.dict_val, + &dict_len); + if (ret < 0) { + gf_log (this->name, GF_LOG_DEBUG, + "failed to get serialized dict"); + op_errno = EINVAL; + goto unwind; + } + req.dict.dict_len = dict_len; + } + req.flags = args->flags; + req.path = (char *)args->loc->path; + + client_submit_request (this, &req, frame,prog, GFS3_OP_SETXATTR, + NULL, xdr_from_setxattr_req); + + if (req.dict.dict_val) { + GF_FREE (req.dict.dict_val); + } + + return 0; +unwind: + STACK_UNWIND_STRICT (setxattr, frame, -1, op_errno); + if (req.dict.dict_val) { + GF_FREE (req.dict.dict_val); + } + return 0; +} + + + +int32_t +client3_1_fsetxattr (call_frame_t *frame, xlator_t *this, rpc_clnt_prog_t *prog, + void *data) +{ + clnt_args_t *args = NULL; + clnt_fd_ctx_t *fdctx = NULL; + clnt_conf_t *conf = NULL; + gfs3_fsetxattr_req req = {0,}; + int op_errno = ESTALE; + int ret = 0; + size_t dict_len = 0; + + if (!frame || !this || !prog || !data) + goto unwind; + + args = data; + conf = this->private; + + pthread_mutex_lock (&conf->lock); + { + fdctx = this_fd_get_ctx (args->fd, this); + } + pthread_mutex_unlock (&conf->lock); + + if (fdctx == NULL) { + gf_log (this->name, GF_LOG_DEBUG, + "(%"PRId64"): failed to get fd ctx. EBADFD", + args->fd->inode->ino); + op_errno = EBADFD; + goto unwind; + } + + if (fdctx->remote_fd == -1) { + gf_log (this->name, GF_LOG_DEBUG, "(%"PRId64"): failed to get" + " fd ctx. EBADFD", args->fd->inode->ino); + op_errno = EBADFD; + goto unwind; + } + + req.fd = fdctx->remote_fd; + req.flags = args->flags; + req.ino = args->fd->inode->ino; + + if (args->dict) { + ret = dict_allocate_and_serialize (args->dict, + &req.dict.dict_val, + &dict_len); + if (ret < 0) { + gf_log (this->name, GF_LOG_DEBUG, + "failed to get serialized dict"); + goto unwind; + } + req.dict.dict_len = dict_len; + } + + client_submit_request (this, &req, frame,prog, GFS3_OP_FSETXATTR, + NULL, xdr_from_fsetxattr_req); + + if (req.dict.dict_val) { + GF_FREE (req.dict.dict_val); + } + + return 0; +unwind: + STACK_UNWIND_STRICT (fsetxattr, frame, -1, op_errno); + if (req.dict.dict_val) { + GF_FREE (req.dict.dict_val); + } + return 0; +} + + + + +int32_t +client3_1_fgetxattr (call_frame_t *frame, xlator_t *this, rpc_clnt_prog_t *prog, + void *data) +{ + clnt_args_t *args = NULL; + clnt_fd_ctx_t *fdctx = NULL; + clnt_conf_t *conf = NULL; + gfs3_fgetxattr_req req = {0,}; + int op_errno = ESTALE; + + if (!frame || !this || !prog || !data) + goto unwind; + + args = data; + conf = this->private; + + pthread_mutex_lock (&conf->lock); + { + fdctx = this_fd_get_ctx (args->fd, this); + } + pthread_mutex_unlock (&conf->lock); + + if (fdctx == NULL) { + gf_log (this->name, GF_LOG_DEBUG, + "(%"PRId64"): failed to get fd ctx. EBADFD", + args->fd->inode->ino); + op_errno = EBADFD; + goto unwind; + } + + if (fdctx->remote_fd == -1) { + gf_log (this->name, GF_LOG_DEBUG, "(%"PRId64"): failed to get" + " fd ctx. EBADFD", args->fd->inode->ino); + op_errno = EBADFD; + goto unwind; + } + + req.namelen = 1; /* Use it as a flag */ + req.fd = fdctx->remote_fd; + req.name = (char *)args->name; + if (!req.name) { + req.name = ""; + req.namelen = 0; + } + + client_submit_request (this, &req, frame,prog, GFS3_OP_FGETXATTR, + NULL, xdr_from_fgetxattr_req); + + return 0; +unwind: + STACK_UNWIND_STRICT (fgetxattr, frame, -1, op_errno, NULL); + return 0; +} + + + +int32_t +client3_1_getxattr (call_frame_t *frame, xlator_t *this, rpc_clnt_prog_t *prog, + void *data) +{ + clnt_args_t *args = NULL; + gfs3_getxattr_req req = {0,}; + int ret = 0; + int op_errno = ESTALE; + + if (!frame || !this || !prog || !data) + goto unwind; + + args = data; + + ret = inode_ctx_get2 (args->loc->inode, this, &req.ino, &req.gen); + if (args->loc->inode->ino && ret < 0) { + gf_log (this->name, GF_LOG_TRACE, + "STAT %"PRId64" (%s): " + "failed to get remote inode number", + args->loc->inode->ino, args->loc->path); + goto unwind; + } + + req.namelen = 1; /* Use it as a flag */ + req.path = (char *)args->loc->path; + req.name = (char *)args->name; + if (!req.name) { + req.name = ""; + req.namelen = 0; + } + + client_submit_request (this, &req, frame,prog, GFS3_OP_GETXATTR, + NULL, xdr_from_getxattr_req); + + return 0; +unwind: + STACK_UNWIND_STRICT (getxattr, frame, -1, op_errno, NULL); + return 0; +} + + + +int32_t +client3_1_xattrop (call_frame_t *frame, xlator_t *this, rpc_clnt_prog_t *prog, + void *data) +{ + clnt_args_t *args = NULL; + gfs3_xattrop_req req = {0,}; + int ret = 0; + size_t dict_len = 0; + int op_errno = ESTALE; + + if (!frame || !this || !prog || !data) + goto unwind; + + args = data; + + ret = inode_ctx_get2 (args->loc->inode, this, &req.ino, &req.gen); + if (args->loc->inode->ino && ret < 0) { + gf_log (this->name, GF_LOG_DEBUG, + "SETXATTR %"PRId64" (%s): " + "failed to get remote inode number", + args->loc->inode->ino, args->loc->path); + goto unwind; + } + if (args->dict) { + ret = dict_allocate_and_serialize (args->dict, + &req.dict.dict_val, + &dict_len); + if (ret < 0) { + gf_log (this->name, GF_LOG_DEBUG, + "failed to get serialized dict"); + op_errno = EINVAL; + goto unwind; + } + req.dict.dict_len = dict_len; + } + req.flags = args->flags; + req.path = (char *)args->loc->path; + + client_submit_request (this, &req, frame,prog, GFS3_OP_XATTROP, + NULL, xdr_from_xattrop_req); + + if (req.dict.dict_val) { + GF_FREE (req.dict.dict_val); + } + return 0; +unwind: + STACK_UNWIND_STRICT (xattrop, frame, -1, op_errno, NULL); + if (req.dict.dict_val) { + GF_FREE (req.dict.dict_val); + } + return 0; +} + + + +int32_t +client3_1_fxattrop (call_frame_t *frame, xlator_t *this, rpc_clnt_prog_t *prog, + void *data) +{ + clnt_args_t *args = NULL; + clnt_fd_ctx_t *fdctx = NULL; + clnt_conf_t *conf = NULL; + gfs3_fxattrop_req req = {0,}; + int op_errno = ESTALE; + int ret = 0; + size_t dict_len = 0; + + if (!frame || !this || !prog || !data) + goto unwind; + + args = data; + conf = this->private; + + pthread_mutex_lock (&conf->lock); + { + fdctx = this_fd_get_ctx (args->fd, this); + } + pthread_mutex_unlock (&conf->lock); + + if (fdctx == NULL) { + gf_log (this->name, GF_LOG_DEBUG, + "(%"PRId64"): failed to get fd ctx. EBADFD", + args->fd->inode->ino); + op_errno = EBADFD; + goto unwind; + } + + if (fdctx->remote_fd == -1) { + gf_log (this->name, GF_LOG_DEBUG, "(%"PRId64"): failed to get" + " fd ctx. EBADFD", args->fd->inode->ino); + op_errno = EBADFD; + goto unwind; + } + + req.fd = fdctx->remote_fd; + req.flags = args->flags; + req.ino = args->fd->inode->ino; + + if (args->dict) { + ret = dict_allocate_and_serialize (args->dict, + &req.dict.dict_val, + &dict_len); + if (ret < 0) { + gf_log (this->name, GF_LOG_DEBUG, + "failed to get serialized dict"); + goto unwind; + } + req.dict.dict_len = dict_len; + } + + client_submit_request (this, &req, frame,prog, GFS3_OP_FXATTROP, + NULL, xdr_from_fxattrop_req); + if (req.dict.dict_val) { + GF_FREE (req.dict.dict_val); + } + + return 0; +unwind: + STACK_UNWIND_STRICT (fxattrop, frame, -1, op_errno, NULL); + if (req.dict.dict_val) { + GF_FREE (req.dict.dict_val); + } + return 0; +} + + + +int32_t +client3_1_removexattr (call_frame_t *frame, xlator_t *this, rpc_clnt_prog_t *prog, + void *data) +{ + clnt_args_t *args = NULL; + gfs3_removexattr_req req = {0,}; + int ret = 0; + int op_errno = ESTALE; + + if (!frame || !this || !prog || !data) + goto unwind; + + args = data; + + ret = inode_ctx_get2 (args->loc->inode, this, &req.ino, &req.gen); + if (args->loc->inode->ino && ret < 0) { + gf_log (this->name, GF_LOG_TRACE, + "REMOVEXATTR %"PRId64" (%s): " + "failed to get remote inode number", + args->loc->inode->ino, args->loc->path); + goto unwind; + } + req.path = (char *)args->loc->path; + req.name = (char *)args->name; + + client_submit_request (this, &req, frame,prog, GFS3_OP_REMOVEXATTR, + NULL, xdr_from_removexattr_req); + + return 0; +unwind: + STACK_UNWIND_STRICT (removexattr, frame, -1, op_errno); + return 0; +} + + +int32_t +client3_1_lk (call_frame_t *frame, xlator_t *this, rpc_clnt_prog_t *prog, + void *data) +{ + clnt_args_t *args = NULL; + gfs3_lk_req req = {0,}; + int32_t gf_cmd = 0; + int32_t gf_type = 0; + clnt_fd_ctx_t *fdctx = NULL; + clnt_conf_t *conf = NULL; + int op_errno = ESTALE; + + if (!frame || !this || !prog || !data) + goto unwind; + + args = data; + conf = this->private; + + pthread_mutex_lock (&conf->lock); + { + fdctx = this_fd_get_ctx (args->fd, this); + } + pthread_mutex_unlock (&conf->lock); + + if (fdctx == NULL) { + gf_log (this->name, GF_LOG_DEBUG, + "(%"PRId64"): failed to get fd ctx. EBADFD", + args->fd->inode->ino); + op_errno = EBADFD; + goto unwind; + } + + if (fdctx->remote_fd == -1) { + gf_log (this->name, GF_LOG_DEBUG, "(%"PRId64"): failed to get" + " fd ctx. EBADFD", args->fd->inode->ino); + op_errno = EBADFD; + goto unwind; + } + + if (args->cmd == F_GETLK || args->cmd == F_GETLK64) + gf_cmd = GF_LK_GETLK; + else if (args->cmd == F_SETLK || args->cmd == F_SETLK64) + gf_cmd = GF_LK_SETLK; + else if (args->cmd == F_SETLKW || args->cmd == F_SETLKW64) + gf_cmd = GF_LK_SETLKW; + else { + gf_log (this->name, GF_LOG_DEBUG, + "Unknown cmd (%d)!", gf_cmd); + goto unwind; + } + + switch (args->flock->l_type) { + case F_RDLCK: + gf_type = GF_LK_F_RDLCK; + break; + case F_WRLCK: + gf_type = GF_LK_F_WRLCK; + break; + case F_UNLCK: + gf_type = GF_LK_F_UNLCK; + break; + } + + req.fd = fdctx->remote_fd; + req.cmd = gf_cmd; + req.type = gf_type; + gf_flock_from_flock (&req.flock, args->flock); + + client_submit_request (this, &req, frame,prog, GFS3_OP_LK, + NULL, xdr_from_lk_req); + + return 0; +unwind: + STACK_UNWIND_STRICT (lk, frame, -1, op_errno, NULL); + return 0; +} + + +int32_t +client3_1_inodelk (call_frame_t *frame, xlator_t *this, rpc_clnt_prog_t *prog, + void *data) +{ + clnt_args_t *args = NULL; + gfs3_inodelk_req req = {0,}; + int ret = 0; + int32_t gf_cmd = 0; + int32_t gf_type = 0; + int op_errno = ESTALE; + + if (!frame || !this || !prog || !data) + goto unwind; + + args = data; + ret = inode_ctx_get2 (args->loc->inode, this, &req.ino, &req.gen); + if (args->loc->inode->ino && ret < 0) { + gf_log (this->name, GF_LOG_TRACE, + "INODELK %"PRId64" (%s): " + "failed to get remote inode number", + args->loc->inode->ino, args->loc->path); + goto unwind; + } + + if (args->cmd == F_GETLK || args->cmd == F_GETLK64) + gf_cmd = GF_LK_GETLK; + else if (args->cmd == F_SETLK || args->cmd == F_SETLK64) + gf_cmd = GF_LK_SETLK; + else if (args->cmd == F_SETLKW || args->cmd == F_SETLKW64) + gf_cmd = GF_LK_SETLKW; + else { + gf_log (this->name, GF_LOG_DEBUG, + "Unknown cmd (%d)!", gf_cmd); + op_errno = EINVAL; + goto unwind; + } + + switch (args->flock->l_type) { + case F_RDLCK: + gf_type = GF_LK_F_RDLCK; + break; + case F_WRLCK: + gf_type = GF_LK_F_WRLCK; + break; + case F_UNLCK: + gf_type = GF_LK_F_UNLCK; + break; + } + + req.path = (char *)args->loc->path; + req.volume = (char *)args->volume; + req.cmd = gf_cmd; + req.type = gf_type; + gf_flock_from_flock (&req.flock, args->flock); + + client_submit_request (this, &req, frame, prog, GFS3_OP_INODELK, + NULL, xdr_from_inodelk_req); + + return 0; +unwind: + STACK_UNWIND_STRICT (inodelk, frame, -1, op_errno); + return 0; +} + + + +int32_t +client3_1_finodelk (call_frame_t *frame, xlator_t *this, rpc_clnt_prog_t *prog, + void *data) +{ + clnt_args_t *args = NULL; + gfs3_finodelk_req req = {0,}; + int32_t gf_cmd = 0; + int32_t gf_type = 0; + clnt_fd_ctx_t *fdctx = NULL; + clnt_conf_t *conf = NULL; + int op_errno = ESTALE; + + if (!frame || !this || !prog || !data) + goto unwind; + + args = data; + conf = this->private; + + pthread_mutex_lock (&conf->lock); + { + fdctx = this_fd_get_ctx (args->fd, this); + } + pthread_mutex_unlock (&conf->lock); + + if (fdctx == NULL) { + gf_log (this->name, GF_LOG_DEBUG, + "(%"PRId64"): failed to get fd ctx. EBADFD", + args->fd->inode->ino); + op_errno = EBADFD; + goto unwind; + } + + if (fdctx->remote_fd == -1) { + gf_log (this->name, GF_LOG_DEBUG, "(%"PRId64"): failed to get" + " fd ctx. EBADFD", args->fd->inode->ino); + op_errno = EBADFD; + goto unwind; + } + + if (args->cmd == F_GETLK || args->cmd == F_GETLK64) + gf_cmd = GF_LK_GETLK; + else if (args->cmd == F_SETLK || args->cmd == F_SETLK64) + gf_cmd = GF_LK_SETLK; + else if (args->cmd == F_SETLKW || args->cmd == F_SETLKW64) + gf_cmd = GF_LK_SETLKW; + else { + gf_log (this->name, GF_LOG_DEBUG, + "Unknown cmd (%d)!", gf_cmd); + goto unwind; + } + + switch (args->flock->l_type) { + case F_RDLCK: + gf_type = GF_LK_F_RDLCK; + break; + case F_WRLCK: + gf_type = GF_LK_F_WRLCK; + break; + case F_UNLCK: + gf_type = GF_LK_F_UNLCK; + break; + } + + req.volume = (char *)args->volume; + req.fd = fdctx->remote_fd; + req.cmd = gf_cmd; + req.type = gf_type; + gf_flock_from_flock (&req.flock, args->flock); + + client_submit_request (this, &req, frame,prog, GFS3_OP_FINODELK, + NULL, xdr_from_finodelk_req); + + return 0; +unwind: + STACK_UNWIND_STRICT (finodelk, frame, -1, op_errno); + return 0; +} + + +int32_t +client3_1_entrylk (call_frame_t *frame, xlator_t *this, rpc_clnt_prog_t *prog, + void *data) +{ + clnt_args_t *args = NULL; + gfs3_entrylk_req req = {0,}; + int ret = 0; + int op_errno = ESTALE; + + if (!frame || !this || !prog || !data) + goto unwind; + + args = data; + + ret = inode_ctx_get2 (args->loc->inode, this, &req.ino, &req.gen); + if (args->loc->inode->ino && ret < 0) { + gf_log (this->name, GF_LOG_TRACE, + "STAT %"PRId64" (%s): " + "failed to get remote inode number", + args->loc->inode->ino, args->loc->path); + goto unwind; + } + req.path = (char *)args->loc->path; + req.cmd = args->cmd_entrylk; + req.type = args->type; + req.volume = (char *)args->volume; + req.name = ""; + if (args->basename) { + req.name = (char *)args->basename; + req.namelen = 1; + } + + client_submit_request (this, &req, frame,prog, GFS3_OP_ENTRYLK, + NULL, xdr_from_entrylk_req); + + return 0; +unwind: + STACK_UNWIND_STRICT (entrylk, frame, -1, op_errno); + return 0; +} + + + +int32_t +client3_1_fentrylk (call_frame_t *frame, xlator_t *this, rpc_clnt_prog_t *prog, + void *data) +{ + clnt_args_t *args = NULL; + gfs3_fentrylk_req req = {0,}; + clnt_fd_ctx_t *fdctx = NULL; + clnt_conf_t *conf = NULL; + int op_errno = ESTALE; + + if (!frame || !this || !prog || !data) + goto unwind; + + args = data; + conf = this->private; + + pthread_mutex_lock (&conf->lock); + { + fdctx = this_fd_get_ctx (args->fd, this); + } + pthread_mutex_unlock (&conf->lock); + + if (fdctx == NULL) { + gf_log (this->name, GF_LOG_DEBUG, + "(%"PRId64"): failed to get fd ctx. EBADFD", + args->fd->inode->ino); + op_errno = EBADFD; + goto unwind; + } + + if (fdctx->remote_fd == -1) { + gf_log (this->name, GF_LOG_DEBUG, "(%"PRId64"): failed to get" + " fd ctx. EBADFD", args->fd->inode->ino); + op_errno = EBADFD; + goto unwind; + } + + req.fd = fdctx->remote_fd; + req.cmd = args->cmd_entrylk; + req.type = args->type; + req.volume = (char *)args->volume; + req.name = ""; + if (args->basename) { + req.name = (char *)args->basename; + req.namelen = 1; + } + + client_submit_request (this, &req, frame,prog, GFS3_OP_FENTRYLK, + NULL, xdr_from_fentrylk_req); + + return 0; +unwind: + STACK_UNWIND_STRICT (fentrylk, frame, -1, op_errno); + return 0; +} + + + + +int32_t +client3_1_checksum (call_frame_t *frame, xlator_t *this, rpc_clnt_prog_t *prog, + void *data) +{ + clnt_args_t *args = NULL; + gfs3_checksum_req req = {0,}; + int ret = 0; + int op_errno = ESTALE; + + if (!frame || !this || !prog || !data) + goto unwind; + + args = data; + + ret = inode_ctx_get2 (args->loc->inode, this, &req.ino, &req.gen); + if (args->loc->inode->ino && ret < 0) { + gf_log (this->name, GF_LOG_TRACE, + "STAT %"PRId64" (%s): " + "failed to get remote inode number", + args->loc->inode->ino, args->loc->path); + goto unwind; + } + req.path = (char *)args->loc->path; + req.flag = args->flags; + + client_submit_request (this, &req, frame,prog, GFS3_OP_CHECKSUM, + NULL, xdr_from_checksum_req); + + return 0; +unwind: + STACK_UNWIND_STRICT (checksum, frame, -1, op_errno, NULL, NULL); + return 0; +} + + + +int32_t +client3_1_rchecksum (call_frame_t *frame, xlator_t *this, rpc_clnt_prog_t *prog, + void *data) +{ + clnt_args_t *args = NULL; + clnt_fd_ctx_t *fdctx = NULL; + clnt_conf_t *conf = NULL; + gfs3_rchecksum_req req = {0,}; + int op_errno = ESTALE; + + if (!frame || !this || !prog || !data) + goto unwind; + + args = data; + conf = this->private; + + pthread_mutex_lock (&conf->lock); + { + fdctx = this_fd_get_ctx (args->fd, this); + } + pthread_mutex_unlock (&conf->lock); + + if (fdctx == NULL) { + gf_log (this->name, GF_LOG_DEBUG, + "(%"PRId64"): failed to get fd ctx. EBADFD", + args->fd->inode->ino); + op_errno = EBADFD; + goto unwind; + } + + if (fdctx->remote_fd == -1) { + gf_log (this->name, GF_LOG_DEBUG, "(%"PRId64"): failed to get" + " fd ctx. EBADFD", args->fd->inode->ino); + op_errno = EBADFD; + goto unwind; + } + + req.len = args->len; + req.offset = args->offset; + req.fd = fdctx->remote_fd; + + client_submit_request (this, &req, frame,prog, GFS3_OP_RCHECKSUM, + NULL, xdr_from_rchecksum_req); + + return 0; +unwind: + STACK_UNWIND_STRICT (rchecksum, frame, -1, op_errno, 0, NULL); + return 0; +} + + + +int32_t +client3_1_readdir (call_frame_t *frame, xlator_t *this, rpc_clnt_prog_t *prog, + void *data) +{ + clnt_args_t *args = NULL; + clnt_fd_ctx_t *fdctx = NULL; + clnt_conf_t *conf = NULL; + gfs3_readdir_req req = {0,}; + int op_errno = ESTALE; + + if (!frame || !this || !prog || !data) + goto unwind; + + args = data; + conf = this->private; + + pthread_mutex_lock (&conf->lock); + { + fdctx = this_fd_get_ctx (args->fd, this); + } + pthread_mutex_unlock (&conf->lock); + + if (fdctx == NULL) { + gf_log (this->name, GF_LOG_DEBUG, + "(%"PRId64"): failed to get fd ctx. EBADFD", + args->fd->inode->ino); + op_errno = EBADFD; + goto unwind; + } + + if (fdctx->remote_fd == -1) { + gf_log (this->name, GF_LOG_DEBUG, "(%"PRId64"): failed to get" + " fd ctx. EBADFD", args->fd->inode->ino); + op_errno = EBADFD; + goto unwind; + } + + req.size = args->size; + req.offset = args->offset; + req.fd = fdctx->remote_fd; + + client_submit_request (this, &req, frame,prog, GFS3_OP_READDIR, + NULL, xdr_from_readdir_req); + + return 0; +unwind: + STACK_UNWIND_STRICT (readdir, frame, -1, op_errno, NULL); + return 0; +} + + +int32_t +client3_1_readdirp (call_frame_t *frame, xlator_t *this, rpc_clnt_prog_t *prog, + void *data) +{ + clnt_args_t *args = NULL; + gfs3_readdirp_req req = {0,}; + clnt_fd_ctx_t *fdctx = NULL; + clnt_conf_t *conf = NULL; + int op_errno = ESTALE; + + if (!frame || !this || !prog || !data) + goto unwind; + + args = data; + conf = this->private; + + pthread_mutex_lock (&conf->lock); + { + fdctx = this_fd_get_ctx (args->fd, this); + } + pthread_mutex_unlock (&conf->lock); + + if (fdctx == NULL) { + gf_log (this->name, GF_LOG_DEBUG, + "(%"PRId64"): failed to get fd ctx. EBADFD", + args->fd->inode->ino); + op_errno = EBADFD; + goto unwind; + } + + if (fdctx->remote_fd == -1) { + gf_log (this->name, GF_LOG_DEBUG, "(%"PRId64"): failed to get" + " fd ctx. EBADFD", args->fd->inode->ino); + op_errno = EBADFD; + goto unwind; + } + + req.size = args->size; + req.offset = args->offset; + req.fd = fdctx->remote_fd; + + client_submit_request (this, &req, frame,prog, GFS3_OP_READDIRP, + NULL, xdr_from_readdirp_req); + + return 0; +unwind: + STACK_UNWIND_STRICT (readdirp, frame, -1, op_errno, NULL); + return 0; +} + + +int32_t +client3_1_setattr (call_frame_t *frame, xlator_t *this, rpc_clnt_prog_t *prog, + void *data) +{ + clnt_args_t *args = NULL; + gfs3_setattr_req req = {0,}; + int ret = 0; + int op_errno = ESTALE; + + if (!frame || !this || !prog || !data) + goto unwind; + + args = data; + + ret = inode_ctx_get2 (args->loc->inode, this, &req.ino, &req.gen); + if (args->loc->inode->ino && ret < 0) { + gf_log (this->name, GF_LOG_TRACE, + "STAT %"PRId64" (%s): " + "failed to get remote inode number", + args->loc->inode->ino, args->loc->path); + goto unwind; + } + req.path = (char *)args->loc->path; + req.valid = args->valid; + gf_stat_from_iatt (&req.stbuf, args->stbuf); + + client_submit_request (this, &req, frame,prog, GFS3_OP_SETATTR, + NULL, xdr_from_setattr_req); + + return 0; +unwind: + STACK_UNWIND_STRICT (setattr, frame, -1, op_errno, NULL, NULL); + return 0; +} + +int32_t +client3_1_fsetattr (call_frame_t *frame, xlator_t *this, rpc_clnt_prog_t *prog, + void *data) +{ + clnt_args_t *args = NULL; + clnt_fd_ctx_t *fdctx = NULL; + clnt_conf_t *conf = NULL; + gfs3_fsetattr_req req = {0,}; + int op_errno = ESTALE; + + if (!frame || !this || !prog || !data) + goto unwind; + + args = data; + conf = this->private; + + pthread_mutex_lock (&conf->lock); + { + fdctx = this_fd_get_ctx (args->fd, this); + } + pthread_mutex_unlock (&conf->lock); + + if (fdctx == NULL) { + gf_log (this->name, GF_LOG_DEBUG, + "(%"PRId64"): failed to get fd ctx. EBADFD", + args->fd->inode->ino); + op_errno = EBADFD; + goto unwind; + } + + if (fdctx->remote_fd == -1) { + gf_log (this->name, GF_LOG_DEBUG, "(%"PRId64"): failed to get" + " fd ctx. EBADFD", args->fd->inode->ino); + op_errno = EBADFD; + goto unwind; + } + + req.fd = fdctx->remote_fd; + req.valid = args->valid; + gf_stat_from_iatt (&req.stbuf, args->stbuf); + + client_submit_request (this, &req, frame,prog, GFS3_OP_FSETATTR, + NULL, xdr_from_fsetattr_req); + + return 0; +unwind: + STACK_UNWIND_STRICT (fsetattr, frame, -1, op_errno, NULL, NULL); + return 0; +} + +/* CBK */ +int +client3_1_release_cbk (struct rpc_req *req, struct iovec *iov, int count, + void *myframe) +{ + call_frame_t *frame = NULL; + + frame = myframe; + STACK_DESTROY (frame->root); + return 0; +} +int +client3_1_releasedir_cbk (struct rpc_req *req, struct iovec *iov, int count, + void *myframe) +{ + call_frame_t *frame = NULL; + + frame = myframe; + STACK_DESTROY (frame->root); + return 0; +} + + +int +client3_1_symlink_cbk (struct rpc_req *req, struct iovec *iov, int count, + void *myframe) +{ + call_frame_t *frame = NULL; + gfs3_symlink_rsp rsp = {0,}; + struct iatt stbuf = {0,}; + struct iatt preparent = {0,}; + struct iatt postparent = {0,}; + int ret = 0; + clnt_local_t *local = NULL; + inode_t *inode = NULL; + + frame = myframe; + + local = frame->local; + frame->local = NULL; + inode = local->loc.inode; + + if (-1 == req->rpc_status) { + rsp.op_ret = -1; + rsp.op_errno = ENOTCONN; + goto out; + } + ret = xdr_to_symlink_rsp (*iov, &rsp); + if (ret < 0) { + gf_log ("", GF_LOG_ERROR, "error"); + rsp.op_ret = -1; + rsp.op_errno = EINVAL; + goto out; + } + + if (-1 != rsp.op_ret) { + gf_stat_to_iatt (&rsp.stat, &stbuf); + + ret = inode_ctx_put2 (inode, frame->this, + stbuf.ia_ino, stbuf.ia_gen); + if (ret < 0) { + gf_log (frame->this->name, GF_LOG_DEBUG, + "SYMLINK %"PRId64"/%s (%s): failed to set " + "remote inode number to inode ctx", + local->loc.parent->ino, local->loc.name, + local->loc.path); + } + + gf_stat_to_iatt (&rsp.preparent, &preparent); + gf_stat_to_iatt (&rsp.postparent, &postparent); + } + +out: + frame->local = NULL; + STACK_UNWIND_STRICT (symlink, frame, rsp.op_ret, + gf_error_to_errno (rsp.op_errno), inode, &stbuf, + &preparent, &postparent); + + if (local) + client_local_wipe (local); + + return 0; +} + + +int +client3_1_mknod_cbk (struct rpc_req *req, struct iovec *iov, int count, + void *myframe) +{ + call_frame_t *frame = NULL; + gfs3_mknod_rsp rsp = {0,}; + struct iatt stbuf = {0,}; + struct iatt preparent = {0,}; + struct iatt postparent = {0,}; + int ret = 0; + clnt_local_t *local = NULL; + inode_t *inode = NULL; + + frame = myframe; + + local = frame->local; + frame->local = NULL; + inode = local->loc.inode; + + if (-1 == req->rpc_status) { + rsp.op_ret = -1; + rsp.op_errno = ENOTCONN; + goto out; + } + ret = xdr_to_mknod_rsp (*iov, &rsp); + if (ret < 0) { + gf_log ("", GF_LOG_ERROR, "error"); + rsp.op_ret = -1; + rsp.op_errno = EINVAL; + goto out; + } + + if (-1 != rsp.op_ret) { + gf_stat_to_iatt (&rsp.stat, &stbuf); + + ret = inode_ctx_put2 (inode, frame->this, + stbuf.ia_ino, stbuf.ia_gen); + if (ret < 0) { + gf_log (frame->this->name, GF_LOG_DEBUG, + "MKNOD %"PRId64"/%s (%s): failed to set " + "remote inode number to inode ctx", + local->loc.parent->ino, local->loc.name, + local->loc.path); + } + + gf_stat_to_iatt (&rsp.preparent, &preparent); + gf_stat_to_iatt (&rsp.postparent, &postparent); + } + +out: + frame->local = NULL; + STACK_UNWIND_STRICT (mknod, frame, rsp.op_ret, + gf_error_to_errno (rsp.op_errno), inode, + &stbuf, &preparent, &postparent); + + if (local) + client_local_wipe (local); + + return 0; +} + +int +client3_1_mkdir_cbk (struct rpc_req *req, struct iovec *iov, int count, + void *myframe) +{ + call_frame_t *frame = NULL; + gfs3_mkdir_rsp rsp = {0,}; + struct iatt stbuf = {0,}; + struct iatt preparent = {0,}; + struct iatt postparent = {0,}; + int ret = 0; + clnt_local_t *local = NULL; + inode_t *inode = NULL; + + frame = myframe; + + local = frame->local; + frame->local = NULL; + inode = local->loc.inode; + + if (-1 == req->rpc_status) { + rsp.op_ret = -1; + rsp.op_errno = ENOTCONN; + goto out; + } + ret = xdr_to_mkdir_rsp (*iov, &rsp); + if (ret < 0) { + gf_log ("", GF_LOG_ERROR, "error"); + rsp.op_ret = -1; + rsp.op_errno = EINVAL; + goto out; + } + + if (-1 != rsp.op_ret) { + gf_stat_to_iatt (&rsp.stat, &stbuf); + + ret = inode_ctx_put2 (inode, frame->this, + stbuf.ia_ino, stbuf.ia_gen); + if (ret < 0) { + gf_log (frame->this->name, GF_LOG_DEBUG, + "MKDIR %"PRId64"/%s (%s): failed to set " + "remote inode number to inode ctx", + local->loc.parent->ino, local->loc.name, + local->loc.path); + } + + gf_stat_to_iatt (&rsp.preparent, &preparent); + gf_stat_to_iatt (&rsp.postparent, &postparent); + } + +out: + frame->local = NULL; + STACK_UNWIND_STRICT (mkdir, frame, rsp.op_ret, + gf_error_to_errno (rsp.op_errno), inode, + &stbuf, &preparent, &postparent); + + if (local) + client_local_wipe (local); + + return 0; +} + +int +client3_1_open_cbk (struct rpc_req *req, struct iovec *iov, int count, + void *myframe) +{ + clnt_local_t *local = NULL; + clnt_conf_t *conf = NULL; + clnt_fd_ctx_t *fdctx = NULL; + call_frame_t *frame = NULL; + fd_t *fd = NULL; + ino_t ino = 0; + uint64_t gen = 0; + int ret = 0; + gfs3_open_rsp rsp = {0,}; + + frame = myframe; + local = frame->local; + + if (local->op) { + local->op (req, iov, 1, myframe); + return 0; + } + + frame->local = NULL; + conf = frame->this->private; + fd = local->fd; + + if (-1 == req->rpc_status) { + rsp.op_ret = -1; + rsp.op_errno = ENOTCONN; + goto out; + } + ret = xdr_to_open_rsp (*iov, &rsp); + if (ret < 0) { + gf_log ("", GF_LOG_ERROR, "error"); + rsp.op_ret = -1; + rsp.op_errno = EINVAL; + goto out; + } + + if (-1 != rsp.op_ret) { + fdctx = GF_CALLOC (1, sizeof (*fdctx), + gf_client_mt_clnt_fdctx_t); + if (!fdctx) { + rsp.op_ret = -1; + rsp.op_errno = ENOMEM; + goto out; + } + + inode_ctx_get2 (fd->inode, frame->this, &ino, &gen); + + fdctx->remote_fd = rsp.fd; + fdctx->inode = inode_ref (fd->inode); + fdctx->ino = ino; + fdctx->gen = gen; + fdctx->flags = local->flags; + fdctx->wbflags = local->wbflags; + + INIT_LIST_HEAD (&fdctx->sfd_pos); + + this_fd_set_ctx (fd, frame->this, &local->loc, fdctx); + + pthread_mutex_lock (&conf->lock); + { + list_add_tail (&fdctx->sfd_pos, &conf->saved_fds); + } + pthread_mutex_unlock (&conf->lock); + } + +out: + frame->local = NULL; + STACK_UNWIND_STRICT (open, frame, rsp.op_ret, + gf_error_to_errno (rsp.op_errno), fd); + + client_local_wipe (local); + + return 0; +} + + +int +client3_1_stat_cbk (struct rpc_req *req, struct iovec *iov, int count, + void *myframe) +{ + gfs3_stat_rsp rsp = {0,}; + call_frame_t *frame = NULL; + struct iatt iatt = {0,}; + int ret = 0; + + frame = myframe; + + if (-1 == req->rpc_status) { + rsp.op_ret = -1; + rsp.op_errno = ENOTCONN; + goto out; + } + ret = xdr_to_stat_rsp (*iov, &rsp); + if (ret < 0) { + gf_log ("", GF_LOG_ERROR, "error"); + rsp.op_ret = -1; + rsp.op_errno = EINVAL; + goto out; + } + + if (-1 != rsp.op_ret) { + gf_stat_to_iatt (&rsp.stat, &iatt); + } + +out: + STACK_UNWIND_STRICT (stat, frame, rsp.op_ret, + gf_error_to_errno (rsp.op_errno), &iatt); + + return 0; +} + +int +client3_1_readlink_cbk (struct rpc_req *req, struct iovec *iov, int count, + void *myframe) +{ + gfs3_readlink_rsp rsp = {0,}; + call_frame_t *frame = NULL; + struct iatt iatt = {0,}; + int ret = 0; + + frame = myframe; + + if (-1 == req->rpc_status) { + rsp.op_ret = -1; + rsp.op_errno = ENOTCONN; + goto out; + } + ret = xdr_to_readlink_rsp (*iov, &rsp); + if (ret < 0) { + gf_log ("", GF_LOG_ERROR, "error"); + rsp.op_ret = -1; + rsp.op_errno = EINVAL; + goto out; + } + + if (-1 != rsp.op_ret) { + gf_stat_to_iatt (&rsp.buf, &iatt); + } + +out: + STACK_UNWIND_STRICT (readlink, frame, rsp.op_ret, + gf_error_to_errno (rsp.op_errno), rsp.path, &iatt); + + /* This is allocated by the libc while decoding RPC msg */ + /* Hence no 'GF_FREE', but just 'free' */ + if (rsp.path) + free (rsp.path); + + return 0; +} + +int +client3_1_unlink_cbk (struct rpc_req *req, struct iovec *iov, int count, + void *myframe) +{ + call_frame_t *frame = NULL; + gfs3_unlink_rsp rsp = {0,}; + struct iatt preparent = {0,}; + struct iatt postparent = {0,}; + int ret = 0; + + frame = myframe; + + if (-1 == req->rpc_status) { + rsp.op_ret = -1; + rsp.op_errno = ENOTCONN; + goto out; + } + ret = xdr_to_unlink_rsp (*iov, &rsp); + if (ret < 0) { + gf_log ("", GF_LOG_ERROR, "error"); + rsp.op_ret = -1; + rsp.op_errno = EINVAL; + goto out; + } + + if (-1 != rsp.op_ret) { + gf_stat_to_iatt (&rsp.preparent, &preparent); + gf_stat_to_iatt (&rsp.postparent, &postparent); + } + +out: + STACK_UNWIND_STRICT (unlink, frame, rsp.op_ret, + gf_error_to_errno (rsp.op_errno), &preparent, + &postparent); + + return 0; +} + +int +client3_1_rmdir_cbk (struct rpc_req *req, struct iovec *iov, int count, + void *myframe) +{ + gfs3_rmdir_rsp rsp = {0,}; + call_frame_t *frame = NULL; + struct iatt preparent = {0,}; + struct iatt postparent = {0,}; + int ret = 0; + + frame = myframe; + + if (-1 == req->rpc_status) { + rsp.op_ret = -1; + rsp.op_errno = ENOTCONN; + goto out; + } + ret = xdr_to_rmdir_rsp (*iov, &rsp); + if (ret < 0) { + gf_log ("", GF_LOG_ERROR, "error"); + rsp.op_ret = -1; + rsp.op_errno = EINVAL; + goto out; + } + + if (-1 != rsp.op_ret) { + gf_stat_to_iatt (&rsp.preparent, &preparent); + gf_stat_to_iatt (&rsp.postparent, &postparent); + } + +out: + STACK_UNWIND_STRICT (rmdir, frame, rsp.op_ret, + gf_error_to_errno (rsp.op_errno), &preparent, + &postparent); + + return 0; +} + + +int +client3_1_truncate_cbk (struct rpc_req *req, struct iovec *iov, int count, + void *myframe) +{ + gfs3_truncate_rsp rsp = {0,}; + call_frame_t *frame = NULL; + struct iatt prestat = {0,}; + struct iatt poststat = {0,}; + int ret = 0; + + frame = myframe; + + if (-1 == req->rpc_status) { + rsp.op_ret = -1; + rsp.op_errno = ENOTCONN; + goto out; + } + ret = xdr_to_truncate_rsp (*iov, &rsp); + if (ret < 0) { + gf_log ("", GF_LOG_ERROR, "error"); + rsp.op_ret = -1; + rsp.op_errno = EINVAL; + goto out; + } + + if (-1 != rsp.op_ret) { + gf_stat_to_iatt (&rsp.prestat, &prestat); + gf_stat_to_iatt (&rsp.poststat, &poststat); + } + +out: + STACK_UNWIND_STRICT (truncate, frame, rsp.op_ret, + gf_error_to_errno (rsp.op_errno), &prestat, + &poststat); + + return 0; +} + + +int +client3_1_statfs_cbk (struct rpc_req *req, struct iovec *iov, int count, + void *myframe) +{ + gfs3_statfs_rsp rsp = {0,}; + call_frame_t *frame = NULL; + struct statvfs statfs = {0,}; + int ret = 0; + + frame = myframe; + + if (-1 == req->rpc_status) { + rsp.op_ret = -1; + rsp.op_errno = ENOTCONN; + goto out; + } + ret = xdr_to_statfs_rsp (*iov, &rsp); + if (ret < 0) { + gf_log ("", GF_LOG_ERROR, "error"); + rsp.op_ret = -1; + rsp.op_errno = EINVAL; + goto out; + } + + if (-1 != rsp.op_ret) { + gf_statfs_to_statfs (&rsp.statfs, &statfs); + } + +out: + STACK_UNWIND_STRICT (statfs, frame, rsp.op_ret, + gf_error_to_errno (rsp.op_errno), &statfs); + + return 0; +} + + +int +client3_1_writev_cbk (struct rpc_req *req, struct iovec *iov, int count, + void *myframe) +{ + gfs3_write_rsp rsp = {0,}; + call_frame_t *frame = NULL; + struct iatt prestat = {0,}; + struct iatt poststat = {0,}; + int ret = 0; + + frame = myframe; + + if (-1 == req->rpc_status) { + rsp.op_ret = -1; + rsp.op_errno = ENOTCONN; + goto out; + } + + ret = xdr_to_truncate_rsp (*iov, &rsp); + if (ret < 0) { + gf_log ("", GF_LOG_ERROR, "error"); + rsp.op_ret = -1; + rsp.op_errno = EINVAL; + goto out; + } + + if (-1 != rsp.op_ret) { + gf_stat_to_iatt (&rsp.prestat, &prestat); + gf_stat_to_iatt (&rsp.poststat, &poststat); + } + +out: + STACK_UNWIND_STRICT (writev, frame, rsp.op_ret, + gf_error_to_errno (rsp.op_errno), &prestat, + &poststat); + + return 0; +} + +int +client3_1_flush_cbk (struct rpc_req *req, struct iovec *iov, int count, + void *myframe) +{ + call_frame_t *frame = NULL; + gf_common_rsp rsp = {0,}; + int ret = 0; + + frame = myframe; + + if (-1 == req->rpc_status) { + rsp.op_ret = -1; + rsp.op_errno = ENOTCONN; + goto out; + } + ret = xdr_to_common_rsp (*iov, &rsp); + if (ret < 0) { + gf_log ("", GF_LOG_ERROR, "error"); + rsp.op_ret = -1; + rsp.op_errno = EINVAL; + goto out; + } + +out: + STACK_UNWIND_STRICT (flush, frame, rsp.op_ret, + gf_error_to_errno (rsp.op_errno)); + + return 0; +} + +int +client3_1_fsync_cbk (struct rpc_req *req, struct iovec *iov, int count, + void *myframe) +{ + gfs3_fsync_rsp rsp = {0,}; + call_frame_t *frame = NULL; + struct iatt prestat = {0,}; + struct iatt poststat = {0,}; + int ret = 0; + + frame = myframe; + + if (-1 == req->rpc_status) { + rsp.op_ret = -1; + rsp.op_errno = ENOTCONN; + goto out; + } + + ret = xdr_to_truncate_rsp (*iov, &rsp); + if (ret < 0) { + gf_log ("", GF_LOG_ERROR, "error"); + rsp.op_ret = -1; + rsp.op_errno = EINVAL; + goto out; + } + + if (-1 != rsp.op_ret) { + gf_stat_to_iatt (&rsp.prestat, &prestat); + gf_stat_to_iatt (&rsp.poststat, &poststat); + } + +out: + STACK_UNWIND_STRICT (fsync, frame, rsp.op_ret, + gf_error_to_errno (rsp.op_errno), &prestat, + &poststat); + + return 0; +} + +int +client3_1_setxattr_cbk (struct rpc_req *req, struct iovec *iov, int count, + void *myframe) +{ + call_frame_t *frame = NULL; + gf_common_rsp rsp = {0,}; + int ret = 0; + + frame = myframe; + + if (-1 == req->rpc_status) { + rsp.op_ret = -1; + rsp.op_errno = ENOTCONN; + goto out; + } + + ret = xdr_to_common_rsp (*iov, &rsp); + if (ret < 0) { + gf_log ("", GF_LOG_ERROR, "error"); + rsp.op_ret = -1; + rsp.op_errno = EINVAL; + goto out; + } + +out: + STACK_UNWIND_STRICT (setxattr, frame, rsp.op_ret, + gf_error_to_errno (rsp.op_errno)); + + return 0; +} + +int +client3_1_getxattr_cbk (struct rpc_req *req, struct iovec *iov, int count, + void *myframe) +{ + call_frame_t *frame = NULL; + dict_t *dict = NULL; + char *buf = NULL; + int dict_len = 0; + int op_ret = 0; + int op_errno = 0; + gfs3_getxattr_rsp rsp = {0,}; + int ret = 0; + + frame = myframe; + + if (-1 == req->rpc_status) { + op_ret = -1; + op_errno = ENOTCONN; + goto out; + } + + ret = xdr_to_getxattr_rsp (*iov, &rsp); + if (ret < 0) { + gf_log ("", GF_LOG_ERROR, "error"); + op_ret = -1; + op_errno = EINVAL; + goto out; + } + + op_errno = gf_error_to_errno (rsp.op_errno); + op_ret = rsp.op_ret; + if (-1 != op_ret) { + op_ret = -1; + dict_len = rsp.dict.dict_len; + + if (dict_len > 0) { + dict = dict_new(); + buf = memdup (rsp.dict.dict_val, rsp.dict.dict_len); + + GF_VALIDATE_OR_GOTO (frame->this->name, dict, out); + GF_VALIDATE_OR_GOTO (frame->this->name, buf, out); + + ret = dict_unserialize (buf, dict_len, &dict); + if (ret < 0) { + gf_log (frame->this->name, GF_LOG_DEBUG, + "failed to unserialize xattr dict"); + op_errno = EINVAL; + goto out; + } + dict->extra_free = buf; + buf = NULL; + } + op_ret = 0; + } + +out: + STACK_UNWIND_STRICT (getxattr, frame, op_ret, op_errno, dict); + + if (rsp.dict.dict_val) { + /* don't use GF_FREE, this memory was allocated by libc + */ + free (rsp.dict.dict_val); + rsp.dict.dict_val = NULL; + } + + if (buf) + GF_FREE (buf); + + if (dict) + dict_unref (dict); + + return 0; +} + +int +client3_1_fgetxattr_cbk (struct rpc_req *req, struct iovec *iov, int count, + void *myframe) +{ + call_frame_t *frame = NULL; + char *buf = NULL; + dict_t *dict = NULL; + gfs3_fgetxattr_rsp rsp = {0,}; + int ret = 0; + int dict_len = 0; + int op_ret = 0; + int op_errno = 0; + + frame = myframe; + + if (-1 == req->rpc_status) { + op_ret = -1; + op_errno = ENOTCONN; + goto out; + } + ret = xdr_to_fgetxattr_rsp (*iov, &rsp); + if (ret < 0) { + gf_log ("", GF_LOG_ERROR, "error"); + op_ret = -1; + op_errno = EINVAL; + goto out; + } + + op_errno = gf_error_to_errno (rsp.op_errno); + op_ret = rsp.op_ret; + if (-1 != op_ret) { + op_ret = -1; + dict_len = rsp.dict.dict_len; + + if (dict_len > 0) { + dict = dict_new(); + GF_VALIDATE_OR_GOTO (frame->this->name, dict, out); + buf = memdup (rsp.dict.dict_val, rsp.dict.dict_len); + GF_VALIDATE_OR_GOTO (frame->this->name, buf, out); + + ret = dict_unserialize (buf, dict_len, &dict); + if (ret < 0) { + gf_log (frame->this->name, GF_LOG_DEBUG, + "failed to unserialize xattr dict"); + op_errno = EINVAL; + goto out; + } + dict->extra_free = buf; + buf = NULL; + } + op_ret = 0; + } +out: + STACK_UNWIND_STRICT (fgetxattr, frame, op_ret, op_errno, dict); + if (rsp.dict.dict_val) { + /* don't use GF_FREE, this memory was allocated by libc + */ + free (rsp.dict.dict_val); + rsp.dict.dict_val = NULL; + } + + if (buf) + GF_FREE (buf); + + if (dict) + dict_unref (dict); + + return 0; +} + +int +client3_1_removexattr_cbk (struct rpc_req *req, struct iovec *iov, int count, + void *myframe) +{ + call_frame_t *frame = NULL; + gf_common_rsp rsp = {0,}; + int ret = 0; + + frame = myframe; + + if (-1 == req->rpc_status) { + rsp.op_ret = -1; + rsp.op_errno = ENOTCONN; + goto out; + } + + ret = xdr_to_common_rsp (*iov, &rsp); + if (ret < 0) { + gf_log ("", GF_LOG_ERROR, "error"); + rsp.op_ret = -1; + rsp.op_errno = EINVAL; + goto out; + } + +out: + STACK_UNWIND_STRICT (removexattr, frame, rsp.op_ret, + gf_error_to_errno (rsp.op_errno)); + + return 0; +} + +int +client3_1_fsyncdir_cbk (struct rpc_req *req, struct iovec *iov, int count, + void *myframe) +{ + call_frame_t *frame = NULL; + gf_common_rsp rsp = {0,}; + int ret = 0; + + frame = myframe; + + if (-1 == req->rpc_status) { + rsp.op_ret = -1; + rsp.op_errno = ENOTCONN; + goto out; + } + ret = xdr_to_common_rsp (*iov, &rsp); + if (ret < 0) { + gf_log ("", GF_LOG_ERROR, "error"); + rsp.op_ret = -1; + rsp.op_errno = EINVAL; + goto out; + } + +out: + STACK_UNWIND_STRICT (fsyncdir, frame, rsp.op_ret, + gf_error_to_errno (rsp.op_errno)); + + return 0; +} + +int +client3_1_access_cbk (struct rpc_req *req, struct iovec *iov, int count, + void *myframe) +{ + call_frame_t *frame = NULL; + gf_common_rsp rsp = {0,}; + int ret = 0; + + frame = myframe; + + if (-1 == req->rpc_status) { + rsp.op_ret = -1; + rsp.op_errno = ENOTCONN; + goto out; + } + ret = xdr_to_common_rsp (*iov, &rsp); + if (ret < 0) { + gf_log ("", GF_LOG_ERROR, "error"); + rsp.op_ret = -1; + rsp.op_errno = EINVAL; + goto out; + } + +out: + STACK_UNWIND_STRICT (access, frame, rsp.op_ret, + gf_error_to_errno (rsp.op_errno)); + + return 0; +} + + +int +client3_1_ftruncate_cbk (struct rpc_req *req, struct iovec *iov, int count, + void *myframe) +{ + gfs3_ftruncate_rsp rsp = {0,}; + call_frame_t *frame = NULL; + struct iatt prestat = {0,}; + struct iatt poststat = {0,}; + int ret = 0; + + frame = myframe; + + if (-1 == req->rpc_status) { + rsp.op_ret = -1; + rsp.op_errno = ENOTCONN; + goto out; + } + ret = xdr_to_ftruncate_rsp (*iov, &rsp); + if (ret < 0) { + gf_log ("", GF_LOG_ERROR, "error"); + rsp.op_ret = -1; + rsp.op_errno = EINVAL; + goto out; + } + + if (-1 != rsp.op_ret) { + gf_stat_to_iatt (&rsp.prestat, &prestat); + gf_stat_to_iatt (&rsp.poststat, &poststat); + } + +out: + STACK_UNWIND_STRICT (ftruncate, frame, rsp.op_ret, + gf_error_to_errno (rsp.op_errno), &prestat, + &poststat); + + return 0; +} + +int +client3_1_fstat_cbk (struct rpc_req *req, struct iovec *iov, int count, + void *myframe) +{ + gfs3_fstat_rsp rsp = {0,}; + call_frame_t *frame = NULL; + struct iatt stat = {0,}; + int ret = 0; + + frame = myframe; + + if (-1 == req->rpc_status) { + rsp.op_ret = -1; + rsp.op_errno = ENOTCONN; + goto out; + } + ret = xdr_to_fstat_rsp (*iov, &rsp); + if (ret < 0) { + gf_log ("", GF_LOG_ERROR, "error"); + rsp.op_ret = -1; + rsp.op_errno = EINVAL; + goto out; + } + + if (-1 != rsp.op_ret) { + gf_stat_to_iatt (&rsp.stat, &stat); + } + +out: + STACK_UNWIND_STRICT (fstat, frame, rsp.op_ret, + gf_error_to_errno (rsp.op_errno), &stat); + + return 0; +} + + +int +client3_1_inodelk_cbk (struct rpc_req *req, struct iovec *iov, int count, + void *myframe) +{ + call_frame_t *frame = NULL; + gf_common_rsp rsp = {0,}; + int ret = 0; + + frame = myframe; + + if (-1 == req->rpc_status) { + rsp.op_ret = -1; + rsp.op_errno = ENOTCONN; + goto out; + } + ret = xdr_to_common_rsp (*iov, &rsp); + if (ret < 0) { + gf_log ("", GF_LOG_ERROR, "error"); + rsp.op_ret = -1; + rsp.op_errno = EINVAL; + goto out; + } + +out: + STACK_UNWIND_STRICT (inodelk, frame, rsp.op_ret, + gf_error_to_errno (rsp.op_errno)); + + return 0; +} + +int +client3_1_finodelk_cbk (struct rpc_req *req, struct iovec *iov, int count, + void *myframe) +{ + call_frame_t *frame = NULL; + gf_common_rsp rsp = {0,}; + int ret = 0; + + frame = myframe; + + if (-1 == req->rpc_status) { + rsp.op_ret = -1; + rsp.op_errno = ENOTCONN; + goto out; + } + ret = xdr_to_common_rsp (*iov, &rsp); + if (ret < 0) { + gf_log ("", GF_LOG_ERROR, "error"); + rsp.op_ret = -1; + rsp.op_errno = EINVAL; + goto out; + } + +out: + STACK_UNWIND_STRICT (finodelk, frame, rsp.op_ret, + gf_error_to_errno (rsp.op_errno)); + + return 0; +} + +int +client3_1_entrylk_cbk (struct rpc_req *req, struct iovec *iov, int count, + void *myframe) +{ + call_frame_t *frame = NULL; + gf_common_rsp rsp = {0,}; + int ret = 0; + + frame = myframe; + + if (-1 == req->rpc_status) { + rsp.op_ret = -1; + rsp.op_errno = ENOTCONN; + goto out; + } + ret = xdr_to_common_rsp (*iov, &rsp); + if (ret < 0) { + gf_log ("", GF_LOG_ERROR, "error"); + rsp.op_ret = -1; + rsp.op_errno = EINVAL; + goto out; + } + +out: + + STACK_UNWIND_STRICT (entrylk, frame, rsp.op_ret, + gf_error_to_errno (rsp.op_errno)); + + return 0; +} + +int +client3_1_fentrylk_cbk (struct rpc_req *req, struct iovec *iov, int count, + void *myframe) +{ + call_frame_t *frame = NULL; + gf_common_rsp rsp = {0,}; + int ret = 0; + + frame = myframe; + + if (-1 == req->rpc_status) { + rsp.op_ret = -1; + rsp.op_errno = ENOTCONN; + goto out; + } + ret = xdr_to_common_rsp (*iov, &rsp); + if (ret < 0) { + gf_log ("", GF_LOG_ERROR, "error"); + rsp.op_ret = -1; + rsp.op_errno = EINVAL; + goto out; + } + +out: + STACK_UNWIND_STRICT (fentrylk, frame, rsp.op_ret, + gf_error_to_errno (rsp.op_errno)); + + return 0; +} + +int +client3_1_xattrop_cbk (struct rpc_req *req, struct iovec *iov, int count, + void *myframe) +{ + call_frame_t *frame = NULL; + dict_t *dict = NULL; + char *buf = NULL; + gfs3_xattrop_rsp rsp = {0,}; + int ret = 0; + int op_ret = 0; + int dict_len = 0; + int op_errno = 0; + + frame = myframe; + + if (-1 == req->rpc_status) { + op_ret = -1; + op_errno = ENOTCONN; + goto out; + } + ret = xdr_to_xattrop_rsp (*iov, &rsp); + if (ret < 0) { + gf_log ("", GF_LOG_ERROR, "error"); + op_ret = -1; + op_errno = EINVAL; + goto out; + } + + op_ret = rsp.op_ret; + if (-1 != op_ret) { + op_ret = -1; + dict_len = rsp.dict.dict_len; + + if (dict_len > 0) { + dict = dict_new(); + GF_VALIDATE_OR_GOTO (frame->this->name, dict, out); + + buf = memdup (rsp.dict.dict_val, rsp.dict.dict_len); + GF_VALIDATE_OR_GOTO (frame->this->name, buf, out); + op_ret = dict_unserialize (buf, dict_len, &dict); + if (op_ret < 0) { + gf_log (frame->this->name, GF_LOG_DEBUG, + "failed to unserialize xattr dict"); + op_errno = EINVAL; + goto out; + } + dict->extra_free = buf; + buf = NULL; + } + op_ret = 0; + } + +out: + + STACK_UNWIND_STRICT (xattrop, frame, op_ret, + gf_error_to_errno (rsp.op_errno), dict); + + if (rsp.dict.dict_val) { + /* don't use GF_FREE, this memory was allocated by libc + */ + free (rsp.dict.dict_val); + rsp.dict.dict_val = NULL; + } + + if (buf) + GF_FREE (buf); + + if (dict) + dict_unref (dict); + + return 0; +} + +int +client3_1_fxattrop_cbk (struct rpc_req *req, struct iovec *iov, int count, + void *myframe) +{ + call_frame_t *frame = NULL; + dict_t *dict = NULL; + char *buf = NULL; + gfs3_fxattrop_rsp rsp = {0,}; + int ret = 0; + int op_ret = 0; + int dict_len = 0; + int op_errno = 0; + + frame = myframe; + + if (-1 == req->rpc_status) { + op_ret = -1; + op_errno = ENOTCONN; + goto out; + } + + ret = xdr_to_fxattrop_rsp (*iov, &rsp); + if (ret < 0) { + op_ret = -1; + op_errno = EINVAL; + gf_log ("", GF_LOG_ERROR, "error"); + goto out; + } + + op_ret = rsp.op_ret; + if (-1 != op_ret) { + op_ret = -1; + dict_len = rsp.dict.dict_len; + + if (dict_len > 0) { + dict = dict_new(); + GF_VALIDATE_OR_GOTO (frame->this->name, dict, out); + + buf = memdup (rsp.dict.dict_val, rsp.dict.dict_len); + GF_VALIDATE_OR_GOTO (frame->this->name, buf, out); + op_ret = dict_unserialize (buf, dict_len, &dict); + if (op_ret < 0) { + gf_log (frame->this->name, GF_LOG_DEBUG, + "failed to unserialize xattr dict"); + op_errno = EINVAL; + goto out; + } + dict->extra_free = buf; + buf = NULL; + } + op_ret = 0; + } + +out: + + STACK_UNWIND_STRICT (fxattrop, frame, op_ret, + gf_error_to_errno (rsp.op_errno), dict); + + if (rsp.dict.dict_val) { + /* don't use GF_FREE, this memory was allocated by libc + */ + free (rsp.dict.dict_val); + rsp.dict.dict_val = NULL; + } + + if (buf) + GF_FREE (buf); + + if (dict) + dict_unref (dict); + + return 0; +} + +int +client3_1_fsetxattr_cbk (struct rpc_req *req, struct iovec *iov, int count, + void *myframe) +{ + call_frame_t *frame = NULL; + gf_common_rsp rsp = {0,}; + int ret = 0; + + frame = myframe; + + if (-1 == req->rpc_status) { + rsp.op_ret = -1; + rsp.op_errno = ENOTCONN; + goto out; + } + ret = xdr_to_common_rsp (*iov, &rsp); + if (ret < 0) { + gf_log ("", GF_LOG_ERROR, "error"); + rsp.op_ret = -1; + rsp.op_errno = EINVAL; + goto out; + } + +out: + STACK_UNWIND_STRICT (fsetxattr, frame, rsp.op_ret, + gf_error_to_errno (rsp.op_errno)); + + return 0; +} + +int +client3_1_fsetattr_cbk (struct rpc_req *req, struct iovec *iov, int count, + void *myframe) +{ + call_frame_t *frame = NULL; + gfs3_fsetattr_rsp rsp = {0,}; + struct iatt prestat = {0,}; + struct iatt poststat = {0,}; + int ret = 0; + + frame = myframe; + + if (-1 == req->rpc_status) { + rsp.op_ret = -1; + rsp.op_errno = ENOTCONN; + goto out; + } + ret = xdr_to_fsetattr_rsp (*iov, &rsp); + if (ret < 0) { + gf_log ("", GF_LOG_ERROR, "error"); + rsp.op_ret = -1; + rsp.op_errno = EINVAL; + goto out; + } + + if (-1 != rsp.op_ret) { + gf_stat_to_iatt (&rsp.statpre, &prestat); + gf_stat_to_iatt (&rsp.statpost, &poststat); + } + +out: + STACK_UNWIND_STRICT (fsetattr, frame, rsp.op_ret, + gf_error_to_errno (rsp.op_errno), &prestat, + &poststat); + + return 0; +} + + +int +client3_1_setattr_cbk (struct rpc_req *req, struct iovec *iov, int count, + void *myframe) +{ + call_frame_t *frame = NULL; + gfs3_setattr_rsp rsp = {0,}; + struct iatt prestat = {0,}; + struct iatt poststat = {0,}; + int ret = 0; + + frame = myframe; + + if (-1 == req->rpc_status) { + rsp.op_ret = -1; + rsp.op_errno = ENOTCONN; + goto out; + } + + ret = xdr_to_setattr_rsp (*iov, &rsp); + if (ret < 0) { + gf_log ("", GF_LOG_ERROR, "error"); + rsp.op_ret = -1; + rsp.op_errno = EINVAL; + goto out; + } + + if (-1 != rsp.op_ret) { + gf_stat_to_iatt (&rsp.statpre, &prestat); + gf_stat_to_iatt (&rsp.statpost, &poststat); + } + +out: + STACK_UNWIND_STRICT (setattr, frame, rsp.op_ret, + gf_error_to_errno (rsp.op_errno), &prestat, + &poststat); + + return 0; +} + +int +client3_1_create_cbk (struct rpc_req *req, struct iovec *iov, int count, + void *myframe) +{ + call_frame_t *frame = NULL; + fd_t *fd = NULL; + inode_t *inode = NULL; + struct iatt stbuf = {0, }; + struct iatt preparent = {0, }; + struct iatt postparent = {0, }; + int32_t ret = -1; + clnt_local_t *local = NULL; + clnt_conf_t *conf = NULL; + clnt_fd_ctx_t *fdctx = NULL; + gfs3_create_rsp rsp = {0,}; + + frame = myframe; + local = frame->local; frame->local = NULL; + conf = frame->this->private; + fd = local->fd; + inode = local->loc.inode; + + if (-1 == req->rpc_status) { + rsp.op_ret = -1; + rsp.op_errno = ENOTCONN; + goto out; + } + + ret = xdr_to_create_rsp (*iov, &rsp); + if (ret < 0) { + gf_log ("", GF_LOG_ERROR, "error"); + rsp.op_ret = -1; + rsp.op_errno = EINVAL; + goto out; + } + + if (-1 != rsp.op_ret) { + gf_stat_to_iatt (&rsp.stat, &stbuf); + + ret = inode_ctx_put2 (inode, frame->this, + stbuf.ia_ino, stbuf.ia_gen); + if (ret < 0) { + gf_log (frame->this->name, GF_LOG_DEBUG, + "CREATE %"PRId64"/%s (%s): failed to set " + "remote inode number to inode ctx", + local->loc.parent->ino, local->loc.name, + local->loc.path); + } + + gf_stat_to_iatt (&rsp.preparent, &preparent); + gf_stat_to_iatt (&rsp.postparent, &postparent); + + fdctx = GF_CALLOC (1, sizeof (*fdctx), + gf_client_mt_clnt_fdctx_t); + if (!fdctx) { + rsp.op_ret = -1; + rsp.op_errno = ENOMEM; + goto out; + } + + fdctx->remote_fd = rsp.fd; + fdctx->inode = inode_ref (inode); + fdctx->ino = stbuf.ia_ino; + fdctx->gen = stbuf.ia_gen; + fdctx->flags = local->flags; + + INIT_LIST_HEAD (&fdctx->sfd_pos); + + this_fd_set_ctx (fd, frame->this, &local->loc, fdctx); + + pthread_mutex_lock (&conf->lock); + { + list_add_tail (&fdctx->sfd_pos, &conf->saved_fds); + } + pthread_mutex_unlock (&conf->lock); + } + +out: + frame->local = NULL; + STACK_UNWIND_STRICT (create, frame, rsp.op_ret, + gf_error_to_errno (rsp.op_errno), fd, inode, + &stbuf, &preparent, &postparent); + + client_local_wipe (local); + return 0; +} + + +int +client3_1_rchecksum_cbk (struct rpc_req *req, struct iovec *iov, int count, + void *myframe) +{ + call_frame_t *frame = NULL; + gfs3_rchecksum_rsp rsp = {0,}; + int ret = 0; + + frame = myframe; + + if (-1 == req->rpc_status) { + rsp.op_ret = -1; + rsp.op_errno = ENOTCONN; + goto out; + } + + ret = xdr_to_rchecksum_rsp (*iov, &rsp); + if (ret < 0) { + gf_log ("", GF_LOG_ERROR, "error"); + rsp.op_ret = -1; + rsp.op_errno = EINVAL; + goto out; + } + +out: + STACK_UNWIND_STRICT (rchecksum, frame, rsp.op_ret, + gf_error_to_errno (rsp.op_errno), + rsp.weak_checksum, + (uint8_t *)rsp.strong_checksum.strong_checksum_val); + + if (rsp.strong_checksum.strong_checksum_val) { + /* This is allocated by the libc while decoding RPC msg */ + /* Hence no 'GF_FREE', but just 'free' */ + free (rsp.strong_checksum.strong_checksum_val); + } + + return 0; +} + +int +client3_1_checksum_cbk (struct rpc_req *req, struct iovec *iov, int count, + void *myframe) +{ + call_frame_t *frame = NULL; + gfs3_checksum_rsp rsp = {0,}; + int ret = 0; + + frame = myframe; + + if (-1 == req->rpc_status) { + rsp.op_ret = -1; + rsp.op_errno = ENOTCONN; + goto out; + } + + ret = xdr_to_checksum_rsp (*iov, &rsp); + if (ret < 0) { + gf_log ("", GF_LOG_ERROR, "error"); + rsp.op_ret = -1; + rsp.op_errno = EINVAL; + goto out; + } + +out: + STACK_UNWIND_STRICT (checksum, frame, rsp.op_ret, + gf_error_to_errno (rsp.op_errno), + (uint8_t *)rsp.fchecksum.fchecksum_val, + (uint8_t *)rsp.dchecksum.dchecksum_val); + + /* This is allocated by the libc while decoding RPC msg */ + /* Hence no 'GF_FREE', but just 'free' */ + if (rsp.fchecksum.fchecksum_val) { + free (rsp.fchecksum.fchecksum_val); + } + if (rsp.dchecksum.dchecksum_val) { + free (rsp.dchecksum.dchecksum_val); + } + return 0; +} + +int +client3_1_lk_cbk (struct rpc_req *req, struct iovec *iov, int count, + void *myframe) +{ + call_frame_t *frame = NULL; + struct flock lock = {0,}; + gfs3_lk_rsp rsp = {0,}; + int ret = 0; + + frame = myframe; + + if (-1 == req->rpc_status) { + rsp.op_ret = -1; + rsp.op_errno = ENOTCONN; + goto out; + } + + ret = xdr_to_lk_rsp (*iov, &rsp); + if (ret < 0) { + gf_log ("", GF_LOG_ERROR, "error"); + rsp.op_ret = -1; + rsp.op_errno = EINVAL; + goto out; + } + + if (rsp.op_ret >= 0) { + gf_flock_to_flock (&rsp.flock, &lock); + } + +out: + STACK_UNWIND_STRICT (lk, frame, rsp.op_ret, + gf_error_to_errno (rsp.op_errno), &lock); + + return 0; +} + +int +client3_1_readdir_cbk (struct rpc_req *req, struct iovec *iov, int count, + void *myframe) +{ + call_frame_t *frame = NULL; + gfs3_readdir_rsp rsp = {0,}; + int32_t ret = 0; + gf_dirent_t entries; + + frame = myframe; + + if (-1 == req->rpc_status) { + rsp.op_ret = -1; + rsp.op_errno = ENOTCONN; + goto out; + } + + ret = xdr_to_readdir_rsp (*iov, &rsp); + if (ret < 0) { + gf_log ("", GF_LOG_ERROR, "error"); + rsp.op_ret = -1; + rsp.op_errno = EINVAL; + goto out; + } + + INIT_LIST_HEAD (&entries.list); + if (rsp.op_ret > 0) { + gf_dirent_unserialize (&entries, rsp.buf.buf_val, + rsp.buf.buf_len); + } + +out: + STACK_UNWIND_STRICT (readdir, frame, rsp.op_ret, + gf_error_to_errno (rsp.op_errno), &entries); + + if (rsp.op_ret != -1) { + gf_dirent_free (&entries); + } + + /* This is allocated by the libc while decoding RPC msg */ + /* Hence no 'GF_FREE', but just 'free' */ + if (rsp.buf.buf_val) + free (rsp.buf.buf_val); + + return 0; +} + + +int +client3_1_readdirp_cbk (struct rpc_req *req, struct iovec *iov, int count, + void *myframe) +{ + call_frame_t *frame = NULL; + gfs3_readdirp_rsp rsp = {0,}; + int32_t ret = 0; + gf_dirent_t entries; + + frame = myframe; + + if (-1 == req->rpc_status) { + rsp.op_ret = -1; + rsp.op_errno = ENOTCONN; + goto out; + } + + ret = xdr_to_readdirp_rsp (*iov, &rsp); + if (ret < 0) { + gf_log ("", GF_LOG_ERROR, "error"); + rsp.op_ret = -1; + rsp.op_errno = EINVAL; + goto out; + } + + INIT_LIST_HEAD (&entries.list); + if (rsp.op_ret > 0) { + gf_dirent_unserialize (&entries, rsp.buf.buf_val, + rsp.buf.buf_len); + } + +out: + STACK_UNWIND_STRICT (readdirp, frame, rsp.op_ret, + gf_error_to_errno (rsp.op_errno), &entries); + + if (rsp.op_ret != -1) { + gf_dirent_free (&entries); + } + + if (rsp.buf.buf_val) { + /* don't use GF_FREE as this memory was allocated by libc */ + free (rsp.buf.buf_val); + } + + return 0; +} + + +int +client3_1_rename_cbk (struct rpc_req *req, struct iovec *iov, int count, + void *myframe) +{ + call_frame_t *frame = NULL; + gfs3_rename_rsp rsp = {0,}; + struct iatt stbuf = {0,}; + struct iatt preoldparent = {0,}; + struct iatt postoldparent = {0,}; + struct iatt prenewparent = {0,}; + struct iatt postnewparent = {0,}; + int ret = 0; + + frame = myframe; + + if (-1 == req->rpc_status) { + rsp.op_ret = -1; + rsp.op_errno = ENOTCONN; + goto out; + } + + ret = xdr_to_rename_rsp (*iov, &rsp); + if (ret < 0) { + gf_log ("", GF_LOG_ERROR, "error"); + rsp.op_ret = -1; + rsp.op_errno = EINVAL; + goto out; + } + + if (-1 != rsp.op_ret) { + gf_stat_to_iatt (&rsp.stat, &stbuf); + + gf_stat_to_iatt (&rsp.preoldparent, &preoldparent); + gf_stat_to_iatt (&rsp.postoldparent, &postoldparent); + + gf_stat_to_iatt (&rsp.prenewparent, &prenewparent); + gf_stat_to_iatt (&rsp.postnewparent, &postnewparent); + } + +out: + STACK_UNWIND_STRICT (rename, frame, rsp.op_ret, + gf_error_to_errno (rsp.op_errno), + &stbuf, &preoldparent, &postoldparent, + &preoldparent, &postoldparent); + + return 0; +} + +int +client3_1_link_cbk (struct rpc_req *req, struct iovec *iov, int count, + void *myframe) +{ + call_frame_t *frame = NULL; + gfs3_link_rsp rsp = {0,}; + struct iatt stbuf = {0,}; + struct iatt preparent = {0,}; + struct iatt postparent = {0,}; + int ret = 0; + clnt_local_t *local = NULL; + inode_t *inode = NULL; + + frame = myframe; + + local = frame->local; + frame->local = NULL; + inode = local->loc.inode; + + if (-1 == req->rpc_status) { + rsp.op_ret = -1; + rsp.op_errno = ENOTCONN; + goto out; + } + + ret = xdr_to_link_rsp (*iov, &rsp); + if (ret < 0) { + gf_log ("", GF_LOG_ERROR, "error"); + rsp.op_ret = -1; + rsp.op_errno = EINVAL; + goto out; + } + + if (-1 != rsp.op_ret) { + gf_stat_to_iatt (&rsp.stat, &stbuf); + + gf_stat_to_iatt (&rsp.preparent, &preparent); + gf_stat_to_iatt (&rsp.postparent, &postparent); + } + +out: + frame->local = NULL; + STACK_UNWIND_STRICT (link, frame, rsp.op_ret, + gf_error_to_errno (rsp.op_errno), inode, + &stbuf, &preparent, &postparent); + + client_local_wipe (local); + return 0; +} + + +int +client3_1_opendir_cbk (struct rpc_req *req, struct iovec *iov, int count, + void *myframe) +{ + clnt_local_t *local = NULL; + clnt_conf_t *conf = NULL; + clnt_fd_ctx_t *fdctx = NULL; + ino_t ino = 0; + uint64_t gen = 0; + call_frame_t *frame = NULL; + fd_t *fd = NULL; + int ret = 0; + gfs3_opendir_rsp rsp = {0,}; + + frame = myframe; + local = frame->local; + + if (local->op) { + local->op (req, iov, 1, myframe); + return 0; + } + + frame->local = NULL; + conf = frame->this->private; + fd = local->fd; + + if (-1 == req->rpc_status) { + rsp.op_ret = -1; + rsp.op_errno = ENOTCONN; + goto out; + } + + ret = xdr_to_opendir_rsp (*iov, &rsp); + if (ret < 0) { + gf_log ("", GF_LOG_ERROR, "error"); + rsp.op_ret = -1; + rsp.op_errno = EINVAL; + goto out; + } + + if (-1 != rsp.op_ret) { + fdctx = GF_CALLOC (1, sizeof (*fdctx), + gf_client_mt_clnt_fdctx_t); + if (!fdctx) { + rsp.op_ret = -1; + rsp.op_errno = ENOMEM; + goto out; + } + + inode_ctx_get2 (fd->inode, frame->this, &ino, &gen); + + fdctx->remote_fd = rsp.fd; + fdctx->inode = inode_ref (fd->inode); + fdctx->ino = ino; + fdctx->gen = gen; + + fdctx->is_dir = 1; + + INIT_LIST_HEAD (&fdctx->sfd_pos); + + this_fd_set_ctx (fd, frame->this, &local->loc, fdctx); + + pthread_mutex_lock (&conf->lock); + { + list_add_tail (&fdctx->sfd_pos, &conf->saved_fds); + } + pthread_mutex_unlock (&conf->lock); + } + +out: + frame->local = NULL; + STACK_UNWIND_STRICT (opendir, frame, rsp.op_ret, + gf_error_to_errno (rsp.op_errno), fd); + + client_local_wipe (local); + + return 0; +} + + +int +client3_1_lookup_cbk (struct rpc_req *req, struct iovec *iov, int count, + void *myframe) +{ + clnt_local_t *local = NULL; + call_frame_t *frame = NULL; + int ret = 0; + gfs3_lookup_rsp rsp = {0,}; + struct iatt stbuf = {0,}; + struct iatt postparent = {0,}; + int op_errno = 0; + ino_t oldino = 0; + uint64_t oldgen = 0; + dict_t *xattr = NULL; + inode_t *inode = NULL; + char *buf = NULL; + + frame = myframe; + local = frame->local; + inode = local->loc.inode; + frame->local = NULL; + + if (-1 == req->rpc_status) { + rsp.op_ret = -1; + rsp.op_errno = ENOTCONN; + goto out; + } + + ret = xdr_to_lookup_rsp (*iov, &rsp); + if (ret < 0) { + gf_log ("", GF_LOG_ERROR, "error"); + rsp.op_ret = -1; + rsp.op_errno = EINVAL; + goto out; + } + + op_errno = gf_error_to_errno (rsp.op_errno); + gf_stat_to_iatt (&rsp.postparent, &postparent); + + if (rsp.op_ret == 0) { + rsp.op_ret = -1; + gf_stat_to_iatt (&rsp.stat, &stbuf); + + ret = inode_ctx_get2 (inode, frame->this, &oldino, &oldgen); + if (oldino != stbuf.ia_ino || oldgen != stbuf.ia_gen) { + if (oldino) { + gf_log (frame->this->name, GF_LOG_DEBUG, + "LOOKUP %"PRId64"/%s (%s): " + "inode number changed from " + "{%"PRId64",%"PRId64"} to {%"PRId64",%"PRId64"}", + local->loc.parent ? + local->loc.parent->ino : (uint64_t) 0, + local->loc.name, + local->loc.path, + oldgen, oldino, stbuf.ia_gen, stbuf.ia_ino); + op_errno = ESTALE; + goto out; + } + + ret = inode_ctx_put2 (inode, frame->this, + stbuf.ia_ino, stbuf.ia_gen); + if (ret < 0) { + gf_log (frame->this->name, GF_LOG_DEBUG, + "LOOKUP %"PRId64"/%s (%s) : " + "failed to set remote inode " + "number to inode ctx", + local->loc.parent ? + local->loc.parent->ino : (uint64_t) 0, + local->loc.name, + local->loc.path); + } + } + + if (rsp.dict.dict_len > 0) { + xattr = dict_new(); + GF_VALIDATE_OR_GOTO (frame->this->name, xattr, out); + + buf = memdup (rsp.dict.dict_val, rsp.dict.dict_len); + GF_VALIDATE_OR_GOTO (frame->this->name, buf, out); + + ret = dict_unserialize (buf, rsp.dict.dict_len, &xattr); + if (ret < 0) { + gf_log (frame->this->name, GF_LOG_DEBUG, + "%s (%"PRId64"): failed to " + "unserialize dictionary", + local->loc.path, inode->ino); + op_errno = EINVAL; + goto out; + } + + xattr->extra_free = buf; + buf = NULL; + } + + rsp.op_ret = 0; + } + +out: + frame->local = NULL; + STACK_UNWIND_STRICT (lookup, frame, rsp.op_ret, rsp.op_errno, inode, + &stbuf, xattr, &postparent); + + client_local_wipe (local); + + if (xattr) + dict_unref (xattr); + + if (rsp.dict.dict_val) { + /* don't use GF_FREE, this memory was allocated by libc + */ + free (rsp.dict.dict_val); + rsp.dict.dict_val = NULL; + } + + if (buf) { + GF_FREE (buf); + } + + return 0; +} + +int +client3_1_readv_cbk (struct rpc_req *req, struct iovec *iov, int count, + void *myframe) +{ + call_frame_t *frame = NULL; + struct iobref *iobref = NULL; + struct iovec vector = {0,}; + struct iatt stat = {0,}; + gfs3_read_rsp rsp = {0,}; + int ret = 0; + + frame = myframe; + + if (-1 == req->rpc_status) { + rsp.op_ret = -1; + rsp.op_errno = ENOTCONN; + goto out; + } + + ret = xdr_to_readv_rsp (*iov, &rsp); + if (ret < 0) { + gf_log ("", GF_LOG_ERROR, "error"); + rsp.op_ret = -1; + rsp.op_errno = EINVAL; + goto out; + } + + if (rsp.op_ret != -1) { + iobref = iobref_new (); + gf_stat_to_iatt (&rsp.stat, &stat); + vector.iov_len = rsp.op_ret; + + if (rsp.op_ret > 0) { + vector.iov_base = req->rsp_procpayload->ptr; + iobref_add (iobref, req->rsp_procpayload); + } + } +out: + STACK_UNWIND_STRICT (readv, frame, rsp.op_ret, + gf_error_to_errno (rsp.op_errno), &vector, 1, + &stat, iobref); + + if (iobref) { + iobref_unref (iobref); + } + + return 0; +} + +/* Table Specific to FOPS */ + + +rpc_clnt_procedure_t clnt3_1_fop_actors[GF_FOP_MAXVALUE] = { + [GF_FOP_NULL] = {"NULL", NULL, NULL }, + [GF_FOP_STAT] = { "STAT", client3_1_stat, client3_1_stat_cbk }, + [GF_FOP_READLINK] = { "READLINK", client3_1_readlink, client3_1_readlink_cbk }, + [GF_FOP_MKNOD] = { "MKNOD", client3_1_mknod, client3_1_mknod_cbk }, + [GF_FOP_MKDIR] = { "MKDIR", client3_1_mkdir, client3_1_mkdir_cbk }, + [GF_FOP_UNLINK] = { "UNLINK", client3_1_unlink, client3_1_unlink_cbk }, + [GF_FOP_RMDIR] = { "RMDIR", client3_1_rmdir, client3_1_rmdir_cbk }, + [GF_FOP_SYMLINK] = { "SYMLINK", client3_1_symlink, client3_1_symlink_cbk }, + [GF_FOP_RENAME] = { "RENAME", client3_1_rename, client3_1_rename_cbk }, + [GF_FOP_LINK] = { "LINK", client3_1_link, client3_1_link_cbk }, + [GF_FOP_TRUNCATE] = { "TRUNCATE", client3_1_truncate, client3_1_truncate_cbk }, + [GF_FOP_OPEN] = { "OPEN", client3_1_open, client3_1_open_cbk }, + [GF_FOP_READ] = { "READ", client3_1_readv, client3_1_readv_cbk }, + [GF_FOP_WRITE] = { "WRITE", client3_1_writev, client3_1_writev_cbk }, + [GF_FOP_STATFS] = { "STATFS", client3_1_statfs, client3_1_statfs_cbk }, + [GF_FOP_FLUSH] = { "FLUSH", client3_1_flush, client3_1_flush_cbk }, + [GF_FOP_FSYNC] = { "FSYNC", client3_1_fsync, client3_1_fsync_cbk }, + [GF_FOP_SETXATTR] = { "SETXATTR", client3_1_setxattr, client3_1_setxattr_cbk }, + [GF_FOP_GETXATTR] = { "GETXATTR", client3_1_getxattr, client3_1_getxattr_cbk }, + [GF_FOP_REMOVEXATTR] = { "REMOVEXATTR", client3_1_removexattr, client3_1_removexattr_cbk }, + [GF_FOP_OPENDIR] = { "OPENDIR", client3_1_opendir, client3_1_opendir_cbk }, + [GF_FOP_FSYNCDIR] = { "FSYNCDIR", client3_1_fsyncdir, client3_1_fsyncdir_cbk }, + [GF_FOP_ACCESS] = { "ACCESS", client3_1_access, client3_1_access_cbk }, + [GF_FOP_CREATE] = { "CREATE", client3_1_create, client3_1_create_cbk }, + [GF_FOP_FTRUNCATE] = { "FTRUNCATE", client3_1_ftruncate, client3_1_ftruncate_cbk }, + [GF_FOP_FSTAT] = { "FSTAT", client3_1_fstat, client3_1_fstat_cbk }, + [GF_FOP_LK] = { "LK", client3_1_lk, client3_1_lk_cbk }, + [GF_FOP_LOOKUP] = { "LOOKUP", client3_1_lookup, client3_1_lookup_cbk }, + [GF_FOP_READDIR] = { "READDIR", client3_1_readdir, client3_1_readdir_cbk }, + [GF_FOP_INODELK] = { "INODELK", client3_1_inodelk, client3_1_inodelk_cbk }, + [GF_FOP_FINODELK] = { "FINODELK", client3_1_finodelk, client3_1_finodelk_cbk }, + [GF_FOP_ENTRYLK] = { "ENTRYLK", client3_1_entrylk, client3_1_entrylk_cbk }, + [GF_FOP_FENTRYLK] = { "FENTRYLK", client3_1_fentrylk, client3_1_fentrylk_cbk }, + [GF_FOP_CHECKSUM] = { "CHECKSUM", client3_1_checksum, client3_1_checksum_cbk }, + [GF_FOP_XATTROP] = { "XATTROP", client3_1_xattrop, client3_1_xattrop_cbk }, + [GF_FOP_FXATTROP] = { "FXATTROP", client3_1_fxattrop, client3_1_fxattrop_cbk }, + [GF_FOP_FGETXATTR] = { "FGETXATTR", client3_1_fgetxattr, client3_1_fgetxattr_cbk }, + [GF_FOP_FSETXATTR] = { "FSETXATTR", client3_1_fsetxattr, client3_1_fsetxattr_cbk }, + [GF_FOP_RCHECKSUM] = { "RCHECKSUM", client3_1_rchecksum, client3_1_rchecksum_cbk }, + [GF_FOP_SETATTR] = { "SETATTR", client3_1_setattr, client3_1_setattr_cbk }, + [GF_FOP_FSETATTR] = { "FSETATTR", client3_1_fsetattr, client3_1_fsetattr_cbk }, + [GF_FOP_READDIRP] = { "READDIRP", client3_1_readdirp, client3_1_readdirp_cbk }, + [GF_FOP_FORGET] = { "FORGET", NULL, client3_1_release_cbk }, + [GF_FOP_RELEASE] = { "RELEASE", client3_1_release, client3_1_release_cbk }, + [GF_FOP_RELEASEDIR] = { "RELEASEDIR", client3_1_releasedir, client3_1_releasedir_cbk }, +// [GF_FOP_GETSPEC] = { "GETSPEC", client_getspec, client_getspec_cbk }, +}; + +rpc_clnt_prog_t clnt3_1_fop_prog = { + .progname = "GlusterFS 3.1", + .prognum = GLUSTER3_1_FOP_PROGRAM, + .progver = GLUSTER3_1_FOP_VERSION, + .numproc = GLUSTER3_1_FOP_PROCCNT, + .actor = clnt3_1_fop_actors, +}; + +rpc_clnt_procedure_t clnt3_1_mgmt_actors[] = { + {0,} +}; + +rpc_clnt_prog_t clnt3_1_mgmt_prog = { + .progname = "Mgmt 3.1", + .prognum = GLUSTER1_MGMT_PROGRAM, + .progver = GLUSTER1_MGMT_VERSION, + .actor = clnt3_1_mgmt_actors, + .numproc = (sizeof (*clnt3_1_mgmt_actors) / + sizeof (rpc_clnt_procedure_t)), +}; |