summaryrefslogtreecommitdiffstats
path: root/xlators/protocol/client
diff options
context:
space:
mode:
authorAmar Tumballi <amar@gluster.com>2010-06-21 07:00:04 +0000
committerAnand V. Avati <avati@dev.gluster.com>2010-06-21 20:21:10 -0700
commitfdd20492638fe98a62b5e6d5e82f18cf4799fd1a (patch)
tree98082d7bfdc66157f40666f2070d3a45b582327a /xlators/protocol/client
parentb9b8734a9496ccf5f8ed5527dc7714930a59948b (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.am1
-rw-r--r--xlators/protocol/client/src/Makefile.am16
-rw-r--r--xlators/protocol/client/src/client-handshake.c738
-rw-r--r--xlators/protocol/client/src/client-helpers.c109
-rw-r--r--xlators/protocol/client/src/client-mem-types.h32
-rw-r--r--xlators/protocol/client/src/client.c1791
-rw-r--r--xlators/protocol/client/src/client.h125
-rw-r--r--xlators/protocol/client/src/client3_1-fops.c4662
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 (&current, 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)),
+};