summaryrefslogtreecommitdiffstats
path: root/xlators/protocol
diff options
context:
space:
mode:
Diffstat (limited to 'xlators/protocol')
-rw-r--r--xlators/protocol/Makefile.am3
-rw-r--r--xlators/protocol/client/Makefile.am3
-rw-r--r--xlators/protocol/client/src/Makefile.am16
-rw-r--r--xlators/protocol/client/src/client-protocol.c6671
-rw-r--r--xlators/protocol/client/src/client-protocol.h173
-rw-r--r--xlators/protocol/client/src/saved-frames.c178
-rw-r--r--xlators/protocol/client/src/saved-frames.h74
-rw-r--r--xlators/protocol/server/Makefile.am3
-rw-r--r--xlators/protocol/server/src/Makefile.am18
-rw-r--r--xlators/protocol/server/src/server-dentry.c413
-rw-r--r--xlators/protocol/server/src/server-helpers.c586
-rw-r--r--xlators/protocol/server/src/server-helpers.h77
-rw-r--r--xlators/protocol/server/src/server-protocol.c7984
-rw-r--r--xlators/protocol/server/src/server-protocol.h143
14 files changed, 16342 insertions, 0 deletions
diff --git a/xlators/protocol/Makefile.am b/xlators/protocol/Makefile.am
new file mode 100644
index 00000000000..745e277c2a6
--- /dev/null
+++ b/xlators/protocol/Makefile.am
@@ -0,0 +1,3 @@
+SUBDIRS = client server
+
+CLEANFILES =
diff --git a/xlators/protocol/client/Makefile.am b/xlators/protocol/client/Makefile.am
new file mode 100644
index 00000000000..d471a3f9243
--- /dev/null
+++ b/xlators/protocol/client/Makefile.am
@@ -0,0 +1,3 @@
+SUBDIRS = src
+
+CLEANFILES =
diff --git a/xlators/protocol/client/src/Makefile.am b/xlators/protocol/client/src/Makefile.am
new file mode 100644
index 00000000000..fb720942cc6
--- /dev/null
+++ b/xlators/protocol/client/src/Makefile.am
@@ -0,0 +1,16 @@
+
+xlator_LTLIBRARIES = client.la
+xlatordir = $(libdir)/glusterfs/$(PACKAGE_VERSION)/xlator/protocol
+
+client_la_LDFLAGS = -module -avoidversion
+
+client_la_SOURCES = client-protocol.c saved-frames.c
+client_la_LIBADD = $(top_builddir)/libglusterfs/src/libglusterfs.la
+
+noinst_HEADERS = client-protocol.h saved-frames.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)
+
+CLEANFILES =
+
diff --git a/xlators/protocol/client/src/client-protocol.c b/xlators/protocol/client/src/client-protocol.c
new file mode 100644
index 00000000000..5c93bd6f135
--- /dev/null
+++ b/xlators/protocol/client/src/client-protocol.c
@@ -0,0 +1,6671 @@
+/*
+ Copyright (c) 2006, 2007, 2008, 2009 Z RESEARCH, Inc. <http://www.zresearch.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 <inttypes.h>
+
+
+#include "glusterfs.h"
+#include "client-protocol.h"
+#include "compat.h"
+#include "dict.h"
+#include "protocol.h"
+#include "transport.h"
+#include "xlator.h"
+#include "logging.h"
+#include "timer.h"
+#include "defaults.h"
+#include "compat.h"
+#include "compat-errno.h"
+
+#include <sys/resource.h>
+#include <inttypes.h>
+
+/* for default_*_cbk functions */
+#include "defaults.c"
+#include "saved-frames.h"
+
+
+int protocol_client_cleanup (transport_t *trans);
+int protocol_client_interpret (xlator_t *this, transport_t *trans,
+ char *hdr_p, size_t hdrlen,
+ char *buf_p, size_t buflen);
+int
+protocol_client_xfer (call_frame_t *frame, xlator_t *this, transport_t *trans,
+ int type, int op,
+ gf_hdr_common_t *hdr, size_t hdrlen,
+ struct iovec *vector, int count,
+ dict_t *refs);
+
+static gf_op_t gf_fops[];
+static gf_op_t gf_mops[];
+static gf_op_t gf_cbks[];
+
+
+static ino_t
+this_ino_get_from_inode (inode_t *inode, xlator_t *this)
+{
+ ino_t ino = 0;
+ int32_t ret = 0;
+
+ GF_VALIDATE_OR_GOTO ("client", this, out);
+ GF_VALIDATE_OR_GOTO (this->name, inode, out);
+
+ if (inode->ino == 1) {
+ ino = 1;
+ goto out;
+ }
+
+ ret = inode_ctx_get (inode, this, &ino);
+
+ if (inode->ino && ret < 0) {
+ gf_log (this->name, GF_LOG_ERROR,
+ "(%"PRId64"): failed to get remote inode number",
+ inode->ino);
+ }
+
+out:
+ return ino;
+}
+
+
+static ino_t
+this_ino_get (loc_t *loc, xlator_t *this, int32_t which)
+{
+ ino_t ino = 0;
+ int32_t ret = 0;
+ inode_t *inode = NULL;
+
+ GF_VALIDATE_OR_GOTO ("client", this, out);
+
+ if (which == GF_CLIENT_INODE_SELF) {
+ inode = loc->inode;
+ } else if (which == GF_CLIENT_INODE_PARENT) {
+ inode = loc->parent;
+ }
+ GF_VALIDATE_OR_GOTO (this->name, inode, out);
+
+ if (inode->ino == 1) {
+ ino = 1;
+ goto out;
+ }
+
+ ret = inode_ctx_get (inode, this, &ino);
+
+ if (inode->ino && ret < 0) {
+ gf_log (this->name, GF_LOG_ERROR,
+ "%s(%s - %"PRId64") failed to get remote inode number",
+ loc->path,
+ (which == GF_CLIENT_INODE_SELF? "self" : "parent"),
+ inode->ino);
+ }
+
+out:
+ return ino;
+}
+
+
+static void
+this_ino_set (loc_t *loc, xlator_t *this, ino_t ino)
+{
+ ino_t old_ino = 0;
+ int32_t ret = -1;
+ inode_t *inode = NULL;
+
+ GF_VALIDATE_OR_GOTO ("client", this, out);
+
+ inode = loc->inode;
+ GF_VALIDATE_OR_GOTO (this->name, inode, out);
+
+ ret = inode_ctx_get (inode, this, &old_ino);
+
+ if (old_ino != ino) {
+ if (old_ino)
+ gf_log (this->name, GF_LOG_DEBUG,
+ "%s: inode number changed from %"PRId64" "
+ "to %"PRId64,
+ loc->path, old_ino, ino);
+
+ ret = inode_ctx_put (inode, this, ino);
+ if (ret < 0) {
+ gf_log (this->name, GF_LOG_ERROR,
+ "%s (%"PRId64"): failed to set remote "
+ "inode number to inode ctx",
+ loc->path, ino);
+ }
+ }
+out:
+ return;
+}
+
+
+static int
+this_fd_get (fd_t *file, xlator_t *this, int64_t *remote_fd)
+{
+ int ret = 0;
+ int dict_ret = -1;
+ uint64_t tmp_fd = 0;
+
+ GF_VALIDATE_OR_GOTO ("client", this, out);
+ GF_VALIDATE_OR_GOTO (this->name, file, out);
+ GF_VALIDATE_OR_GOTO (this->name, remote_fd, out);
+
+ dict_ret = fd_ctx_get (file, this, &tmp_fd);
+
+ if (dict_ret < 0) {
+ ret = -1;
+ }
+ *remote_fd = (int64_t)tmp_fd;
+out:
+ return ret;
+}
+
+
+static void
+this_fd_set (fd_t *file, xlator_t *this, loc_t *loc, int64_t fd)
+{
+ uint64_t old_fd = 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, &old_fd);
+ if (ret >= 0) {
+ gf_log (this->name, GF_LOG_WARNING,
+ "%s (%"PRId64"): trying duplicate remote fd set. "
+ "%"PRId64" over-rides %"PRId64,
+ loc->path, loc->inode->ino, fd, old_fd);
+ }
+
+ ret = fd_ctx_set (file, this, (uint64_t)fd);
+ if (ret < 0) {
+ gf_log (this->name, GF_LOG_ERROR,
+ "%s (%"PRId64"): failed to set remote fd",
+ loc->path, loc->inode->ino);
+ }
+out:
+ return;
+}
+
+
+static int
+client_local_wipe (client_local_t *local)
+{
+ if (local) {
+ loc_wipe (&local->loc);
+
+ if (local->fd)
+ fd_unref (local->fd);
+
+ free (local);
+ }
+
+ return 0;
+}
+
+/*
+ * lookup_frame - lookup call frame corresponding to a given callid
+ * @trans: transport object
+ * @callid: call id of the frame
+ *
+ * not for external reference
+ */
+
+static call_frame_t *
+lookup_frame (transport_t *trans, int32_t op, int8_t type, int64_t callid)
+{
+ client_connection_t *conn = NULL;
+ call_frame_t *frame = NULL;
+
+ conn = trans->xl_private;
+
+ pthread_mutex_lock (&conn->lock);
+ {
+ frame = saved_frames_get (conn->saved_frames,
+ op, type, callid);
+ }
+ pthread_mutex_unlock (&conn->lock);
+
+ return frame;
+}
+
+
+static void
+call_bail (void *data)
+{
+ client_connection_t *conn = NULL;
+ struct timeval current;
+ int32_t bail_out = 0;
+ transport_t *trans = NULL;
+
+ GF_VALIDATE_OR_GOTO("client", data, out);
+ trans = data;
+
+ conn = trans->xl_private;
+
+ gettimeofday (&current, NULL);
+ pthread_mutex_lock (&conn->lock);
+ {
+ /* Chaining to get call-always functionality from
+ call-once timer */
+ if (conn->timer) {
+ struct timeval timeout = {0,};
+ gf_timer_cbk_t timer_cbk = conn->timer->cbk;
+
+ timeout.tv_sec = 10;
+ timeout.tv_usec = 0;
+
+ gf_timer_call_cancel (trans->xl->ctx, conn->timer);
+ conn->timer = gf_timer_call_after (trans->xl->ctx,
+ timeout,
+ timer_cbk,
+ trans);
+ if (conn->timer == NULL) {
+ gf_log (trans->xl->name, GF_LOG_DEBUG,
+ "Cannot create bailout timer");
+ }
+ }
+
+ if (((conn->saved_frames->count > 0) &&
+ (RECEIVE_TIMEOUT(conn, current)) &&
+ (SEND_TIMEOUT(conn, current)))) {
+
+ struct tm last_sent_tm, last_received_tm;
+ char last_sent[32] = {0,}, last_received[32] = {0,};
+
+ bail_out = 1;
+
+ localtime_r (&conn->last_sent.tv_sec,
+ &last_sent_tm);
+ localtime_r (&conn->last_received.tv_sec,
+ &last_received_tm);
+
+ strftime (last_sent, 32,
+ "%Y-%m-%d %H:%M:%S", &last_sent_tm);
+ strftime (last_received, 32,
+ "%Y-%m-%d %H:%M:%S", &last_received_tm);
+
+ gf_log (trans->xl->name, GF_LOG_ERROR,
+ "activating bail-out. pending frames = %d. "
+ "last sent = %s. last received = %s. "
+ "transport-timeout = %d",
+ (int32_t) conn->saved_frames->count,
+ last_sent, last_received,
+ conn->transport_timeout);
+ }
+ }
+
+ if (bail_out) {
+ conn->ping_started = 0;
+ }
+
+ pthread_mutex_unlock (&conn->lock);
+
+ if (bail_out) {
+ gf_log (trans->xl->name, GF_LOG_CRITICAL,
+ "bailing transport");
+ transport_disconnect (trans);
+ }
+out:
+ return;
+}
+
+
+void
+save_frame (transport_t *trans, call_frame_t *frame,
+ int32_t op, int8_t type, uint64_t callid)
+{
+ client_connection_t *conn = NULL;
+ struct timeval timeout = {0, };
+
+
+ conn = trans->xl_private;
+
+ saved_frames_put (conn->saved_frames, frame, op, type, callid);
+
+ if (conn->timer == NULL) {
+ timeout.tv_sec = 10;
+ timeout.tv_usec = 0;
+ conn->timer = gf_timer_call_after (trans->xl->ctx, timeout,
+ call_bail, (void *) trans);
+ }
+}
+
+
+int
+client_get_forgets (xlator_t *this, client_forget_t *forget)
+{
+ call_frame_t *fr = NULL;
+ gf_hdr_common_t *hdr = NULL;
+ size_t hdrlen = 0;
+ gf_cbk_forget_req_t *req = NULL;
+ int ret = -1;
+ client_conf_t *conf = NULL;
+ int count = 0;
+ int index = 0;
+
+ conf = this->private;
+
+ if (conf->forget.count > 0) {
+ count = conf->forget.count;
+
+ hdrlen = gf_hdr_len (req, (count * sizeof (int64_t)));
+ hdr = gf_hdr_new (req, (count * sizeof (int64_t)));
+ GF_VALIDATE_OR_GOTO (this->name, hdr, out);
+
+ req = gf_param (hdr);
+
+ req->count = hton32 (count);
+ for (index = 0; index < count; index++) {
+ req->ino_array[index] =
+ hton64 (conf->forget.ino_array[index]);
+ }
+
+ fr = create_frame (this, this->ctx->pool);
+ GF_VALIDATE_OR_GOTO (this->name, fr, out);
+
+ conf->forget.frames_in_transit++;
+
+ forget->frame = fr;
+ forget->hdr = hdr;
+ forget->hdrlen = hdrlen;
+
+ ret = count;
+
+ conf->forget.count = 0;
+ }
+ out:
+ return ret;
+}
+
+
+void
+client_ping_timer_expired (void *data)
+{
+ xlator_t *this = NULL;
+ transport_t *trans = NULL;
+ client_conf_t *conf = NULL;
+ client_connection_t *conn = NULL;
+
+ trans = data;
+ this = trans->xl;
+ conf = this->private;
+ conn = trans->xl_private;
+
+ gf_log (this->name, GF_LOG_ERROR,
+ "ping timer expired! bailing transport");
+
+ pthread_mutex_lock (&conn->lock);
+ {
+ if (conn->ping_timer)
+ gf_timer_call_cancel (trans->xl->ctx,
+ conn->ping_timer);
+
+ conn->ping_started = 0;
+ conn->ping_timer = NULL;
+ }
+ pthread_mutex_unlock (&conn->lock);
+ transport_disconnect (trans);
+}
+
+
+void
+client_start_ping (void *data)
+{
+ xlator_t *this = NULL;
+ transport_t *trans = NULL;
+ client_conf_t *conf = NULL;
+ client_connection_t *conn = NULL;
+ int32_t ret = -1;
+ gf_hdr_common_t *hdr = NULL;
+ struct timeval timeout = {0, };
+ call_frame_t *dummy_frame = NULL;
+ size_t hdrlen = -1;
+ gf_mop_ping_req_t *req = NULL;
+
+
+ trans = data;
+ this = trans->xl;
+ conf = this->private;
+ conn = trans->xl_private;
+
+ pthread_mutex_lock (&conn->lock);
+ {
+ if ((conn->saved_frames->count == 0) ||
+ !conn->connected) {
+ /* using goto looked ugly here,
+ * hence getting out this way */
+ if (conn->ping_timer)
+ gf_timer_call_cancel (trans->xl->ctx,
+ conn->ping_timer);
+ conn->ping_timer = NULL;
+ conn->ping_started = 0;
+ /* unlock */
+ pthread_mutex_unlock (&conn->lock);
+ return;
+ }
+
+ if (conn->saved_frames->count < 0) {
+ gf_log (this->name, GF_LOG_ERROR,
+ "saved_frames->count is %"PRId64,
+ conn->saved_frames->count);
+ conn->saved_frames->count = 0;
+ }
+ timeout.tv_sec = conn->ping_timeout;
+ timeout.tv_usec = 0;
+
+ conn->ping_timer =
+ gf_timer_call_after (trans->xl->ctx, timeout,
+ client_ping_timer_expired,
+ (void *) trans);
+
+ if (conn->ping_timer == NULL) {
+ gf_log (this->name, GF_LOG_ERROR,
+ "unable to setup timer");
+ } else
+ conn->ping_started = 1;
+ }
+ pthread_mutex_unlock (&conn->lock);
+
+ hdrlen = gf_hdr_len (req, 0);
+ hdr = gf_hdr_new (req, 0);
+
+ dummy_frame = create_frame (this, this->ctx->pool);
+ dummy_frame->local = trans;
+
+ ret = protocol_client_xfer (dummy_frame, this, trans,
+ GF_OP_TYPE_MOP_REQUEST, GF_MOP_PING,
+ hdr, hdrlen, NULL, 0, NULL);
+}
+
+
+int
+client_ping_cbk (call_frame_t *frame, gf_hdr_common_t *hdr, size_t hdrlen,
+ char *buf, size_t buflen)
+{
+ xlator_t *this = NULL;
+ transport_t *trans = NULL;
+ client_conf_t *conf = NULL;
+ client_connection_t *conn = NULL;
+ struct timeval timeout = {0, };
+ int op_ret = 0;
+
+ trans = frame->local; frame->local = NULL;
+ this = trans->xl;
+ conf = this->private;
+ conn = trans->xl_private;
+
+ op_ret = ntoh32 (hdr->rsp.op_ret);
+
+ if (op_ret == -1) {
+ /* timer expired and transport bailed out */
+ gf_log (this->name, GF_LOG_ERROR, "timer must have expired");
+ goto out;
+ }
+
+ pthread_mutex_lock (&conn->lock);
+ {
+ timeout.tv_sec = conn->ping_timeout;
+ timeout.tv_usec = 0;
+
+ gf_timer_call_cancel (trans->xl->ctx,
+ conn->ping_timer);
+
+ conn->ping_timer =
+ gf_timer_call_after (trans->xl->ctx, timeout,
+ client_start_ping, (void *)trans);
+ if (conn->ping_timer == NULL)
+ gf_log (this->name, GF_LOG_ERROR,
+ "gf_timer_call_after() returned NULL");
+ }
+ pthread_mutex_unlock (&conn->lock);
+out:
+ STACK_DESTROY (frame->root);
+ return 0;
+}
+
+
+int
+protocol_client_xfer (call_frame_t *frame, xlator_t *this, transport_t *trans,
+ int type, int op,
+ gf_hdr_common_t *hdr, size_t hdrlen,
+ struct iovec *vector, int count,
+ dict_t *refs)
+{
+ client_conf_t *conf = NULL;
+ client_connection_t *conn = NULL;
+ uint64_t callid = 0;
+ int32_t ret = -1;
+ int start_ping = 0;
+ gf_hdr_common_t rsphdr = {0, };
+ client_forget_t forget = {0, };
+ uint8_t send_forget = 0;
+
+
+ conf = this->private;
+
+ if (!trans) {
+ /* default to bulk op since it is 'safer' */
+ trans = conf->transport[CHANNEL_BULK];
+ }
+ conn = trans->xl_private;
+
+ if (!((type == GF_OP_TYPE_CBK_REQUEST) &&
+ (op == GF_CBK_FORGET)))
+ {
+ LOCK (&conf->forget.lock);
+ {
+ ret = client_get_forgets (this, &forget);
+ if (ret <= 0)
+ send_forget = 0;
+ else
+ send_forget = 1;
+ }
+ UNLOCK (&conf->forget.lock);
+
+ if (send_forget) {
+ ret = protocol_client_xfer (forget.frame, this, NULL,
+ GF_OP_TYPE_CBK_REQUEST,
+ GF_CBK_FORGET,
+ forget.hdr, forget.hdrlen,
+ NULL, 0, NULL);
+ }
+ }
+
+ pthread_mutex_lock (&conn->lock);
+ {
+ callid = ++conn->callid;
+
+ hdr->callid = hton64 (callid);
+ hdr->op = hton32 (op);
+ hdr->type = hton32 (type);
+
+ if (frame) {
+ hdr->req.uid = hton32 (frame->root->uid);
+ hdr->req.gid = hton32 (frame->root->gid);
+ hdr->req.pid = hton32 (frame->root->pid);
+ }
+
+ if (conn->connected == 0)
+ transport_connect (trans);
+
+ ret = -1;
+
+ if (conn->connected ||
+ ((type == GF_OP_TYPE_MOP_REQUEST) &&
+ (op == GF_MOP_SETVOLUME))) {
+ ret = transport_submit (trans, (char *)hdr, hdrlen,
+ vector, count, refs);
+ }
+
+ if ((ret >= 0) && frame) {
+ /* TODO: check this logic */
+ gettimeofday (&conn->last_sent, NULL);
+ save_frame (trans, frame, op, type, callid);
+ }
+
+ if (!conn->ping_started && (ret >= 0)) {
+ start_ping = 1;
+ }
+ }
+ pthread_mutex_unlock (&conn->lock);
+
+ if (start_ping)
+ client_start_ping ((void *) trans);
+
+ if (frame && (ret < 0)) {
+ rsphdr.op = op;
+ rsphdr.rsp.op_ret = hton32 (-1);
+ rsphdr.rsp.op_errno = hton32 (ENOTCONN);
+
+ if (type == GF_OP_TYPE_FOP_REQUEST) {
+ rsphdr.type = GF_OP_TYPE_FOP_REPLY;
+ gf_fops[op] (frame, &rsphdr, sizeof (rsphdr), NULL, 0);
+ } else if (type == GF_OP_TYPE_MOP_REQUEST) {
+ rsphdr.type = GF_OP_TYPE_MOP_REPLY;
+ gf_mops[op] (frame, &rsphdr, sizeof (rsphdr), NULL, 0);
+ } else {
+ rsphdr.type = GF_OP_TYPE_CBK_REPLY;
+ gf_cbks[op] (frame, &rsphdr, sizeof (rsphdr), NULL, 0);
+ }
+ }
+
+ return ret;
+}
+
+
+
+/**
+ * client_create - create function for client protocol
+ * @frame: call frame
+ * @this: this translator structure
+ * @path: complete path to file
+ * @flags: create flags
+ * @mode: create mode
+ *
+ * external reference through client_protocol_xlator->fops->create
+ */
+
+int
+client_create (call_frame_t *frame, xlator_t *this,
+ loc_t *loc, int32_t flags,
+ mode_t mode, fd_t *fd)
+{
+ gf_hdr_common_t *hdr = NULL;
+ gf_fop_create_req_t *req = NULL;
+ size_t hdrlen = 0;
+ size_t pathlen = 0;
+ size_t baselen = 0;
+ int32_t ret = -1;
+ ino_t par = 0;
+ client_conf_t *conf = NULL;
+ client_local_t *local = NULL;
+
+
+ conf = this->private;
+
+ if (conf->child) {
+ STACK_WIND (frame, default_create_cbk,
+ conf->child,
+ conf->child->fops->create,
+ loc, flags, mode, fd);
+ return 0;
+ }
+
+ local = calloc (1, sizeof (*local));
+ GF_VALIDATE_OR_GOTO(this->name, local, unwind);
+
+ local->fd = fd_ref (fd);
+ loc_copy (&local->loc, loc);
+
+ frame->local = local;
+
+ pathlen = STRLEN_0(loc->path);
+ baselen = STRLEN_0(loc->name);
+ par = this_ino_get (loc, this, GF_CLIENT_INODE_PARENT);
+
+ hdrlen = gf_hdr_len (req, pathlen + baselen);
+ hdr = gf_hdr_new (req, pathlen + baselen);
+ GF_VALIDATE_OR_GOTO(this->name, hdr, unwind);
+
+ req = gf_param (hdr);
+
+ req->flags = hton32 (flags);
+ req->mode = hton32 (mode);
+ req->par = hton64 (par);
+ strcpy (req->path, loc->path);
+ strcpy (req->bname + pathlen, loc->name);
+
+ ret = protocol_client_xfer (frame, this,
+ CLIENT_CHANNEL (this, CHANNEL_LOWLAT),
+ GF_OP_TYPE_FOP_REQUEST, GF_FOP_CREATE,
+ hdr, hdrlen, NULL, 0, NULL);
+ return ret;
+unwind:
+ if (hdr)
+ free (hdr);
+ STACK_UNWIND(frame, -1, EINVAL, fd, NULL, NULL);
+ return 0;
+
+}
+
+/**
+ * client_open - open function for client protocol
+ * @frame: call frame
+ * @this: this translator structure
+ * @loc: location of file
+ * @flags: open flags
+ * @mode: open modes
+ *
+ * external reference through client_protocol_xlator->fops->open
+ */
+int
+client_open (call_frame_t *frame, xlator_t *this,
+ loc_t *loc, int32_t flags, fd_t *fd)
+{
+ int ret = -1;
+ gf_hdr_common_t *hdr = NULL;
+ size_t hdrlen = 0;
+ gf_fop_open_req_t *req = NULL;
+ size_t pathlen = 0;
+ ino_t ino = 0;
+ client_conf_t *conf = NULL;
+ client_local_t *local = NULL;
+
+ conf = this->private;
+ if (conf->child) {
+ /* */
+ STACK_WIND (frame, default_open_cbk,
+ conf->child,
+ conf->child->fops->open,
+ loc, flags, fd);
+
+ return 0;
+ }
+
+ local = calloc (1, sizeof (*local));
+ GF_VALIDATE_OR_GOTO(this->name, local, unwind);
+
+ local->fd = fd_ref (fd);
+ loc_copy (&local->loc, loc);
+
+ frame->local = local;
+
+ pathlen = STRLEN_0(loc->path);
+ ino = this_ino_get (loc, this, GF_CLIENT_INODE_SELF);
+
+ hdrlen = gf_hdr_len (req, pathlen);
+ hdr = gf_hdr_new (req, pathlen);
+ GF_VALIDATE_OR_GOTO(this->name, hdr, unwind);
+
+ req = gf_param (hdr);
+
+ req->ino = hton64 (ino);
+ req->flags = hton32 (flags);
+ strcpy (req->path, loc->path);
+
+ ret = protocol_client_xfer (frame, this,
+ CLIENT_CHANNEL (this, CHANNEL_LOWLAT),
+ GF_OP_TYPE_FOP_REQUEST, GF_FOP_OPEN,
+ hdr, hdrlen, NULL, 0, NULL);
+
+ return ret;
+unwind:
+ if (hdr)
+ free (hdr);
+ STACK_UNWIND(frame, -1, EINVAL, fd);
+ return 0;
+
+}
+
+
+/**
+ * client_stat - stat function for client protocol
+ * @frame: call frame
+ * @this: this translator structure
+ * @loc: location
+ *
+ * external reference through client_protocol_xlator->fops->stat
+ */
+int32_t
+client_stat (call_frame_t *frame,
+ xlator_t *this,
+ loc_t *loc)
+{
+ gf_hdr_common_t *hdr = NULL;
+ gf_fop_stat_req_t *req = NULL;
+ size_t hdrlen = -1;
+ int32_t ret = -1;
+ size_t pathlen = 0;
+ ino_t ino = 0;
+ client_conf_t *conf = this->private;
+
+ if (conf->child) {
+ /* */
+ STACK_WIND (frame,
+ default_stat_cbk,
+ conf->child,
+ conf->child->fops->stat,
+ loc);
+
+ return 0;
+ }
+
+ pathlen = STRLEN_0(loc->path);
+ ino = this_ino_get (loc, this, GF_CLIENT_INODE_SELF);
+
+ hdrlen = gf_hdr_len (req, pathlen);
+ hdr = gf_hdr_new (req, pathlen);
+ GF_VALIDATE_OR_GOTO(this->name, hdr, unwind);
+
+ req = gf_param (hdr);
+
+ req->ino = hton64 (ino);
+ strcpy (req->path, loc->path);
+
+ ret = protocol_client_xfer (frame, this,
+ CLIENT_CHANNEL (this, CHANNEL_LOWLAT),
+ GF_OP_TYPE_FOP_REQUEST, GF_FOP_STAT,
+ hdr, hdrlen, NULL, 0, NULL);
+
+ return ret;
+unwind:
+ if (hdr)
+ free (hdr);
+ STACK_UNWIND(frame, -1, EINVAL, NULL);
+ return 0;
+
+}
+
+
+/**
+ * client_readlink - readlink function for client protocol
+ * @frame: call frame
+ * @this: this translator structure
+ * @loc: location
+ * @size:
+ *
+ * external reference through client_protocol_xlator->fops->readlink
+ */
+int32_t
+client_readlink (call_frame_t *frame,
+ xlator_t *this,
+ loc_t *loc,
+ size_t size)
+{
+ gf_hdr_common_t *hdr = NULL;
+ gf_fop_readlink_req_t *req = NULL;
+ size_t hdrlen = -1;
+ int ret = -1;
+ size_t pathlen = 0;
+ ino_t ino = 0;
+ client_conf_t *conf = this->private;
+
+ if (conf->child) {
+ /* */
+ STACK_WIND (frame,
+ default_readlink_cbk,
+ conf->child,
+ conf->child->fops->readlink,
+ loc,
+ size);
+
+ return 0;
+ }
+
+ pathlen = STRLEN_0(loc->path);
+ ino = this_ino_get (loc, this, GF_CLIENT_INODE_SELF);
+
+ hdrlen = gf_hdr_len (req, pathlen);
+ hdr = gf_hdr_new (req, pathlen);
+ GF_VALIDATE_OR_GOTO(this->name, hdr, unwind);
+
+ req = gf_param (hdr);
+
+ req->ino = hton64 (ino);
+ req->size = hton32 (size);
+ strcpy (req->path, loc->path);
+
+ ret = protocol_client_xfer (frame, this,
+ CLIENT_CHANNEL (this, CHANNEL_LOWLAT),
+ GF_OP_TYPE_FOP_REQUEST, GF_FOP_READLINK,
+ hdr, hdrlen, NULL, 0, NULL);
+
+ return ret;
+unwind:
+ if (hdr)
+ free (hdr);
+ STACK_UNWIND(frame, -1, EINVAL, NULL);
+ return 0;
+
+}
+
+
+/**
+ * client_mknod - mknod function for client protocol
+ * @frame: call frame
+ * @this: this translator structure
+ * @path: pathname of node
+ * @mode:
+ * @dev:
+ *
+ * external reference through client_protocol_xlator->fops->mknod
+ */
+int32_t
+client_mknod (call_frame_t *frame,
+ xlator_t *this,
+ loc_t *loc,
+ mode_t mode,
+ dev_t dev)
+{
+ gf_hdr_common_t *hdr = NULL;
+ gf_fop_mknod_req_t *req = NULL;
+ size_t hdrlen = -1;
+ int ret = -1;
+ size_t pathlen = 0;
+ size_t baselen = 0;
+ ino_t par = 0;
+ client_conf_t *conf = this->private;
+ client_local_t *local = NULL;
+
+ if (conf->child) {
+ /* */
+ STACK_WIND (frame,
+ default_mknod_cbk,
+ conf->child,
+ conf->child->fops->mknod,
+ loc, mode, dev);
+
+ return 0;
+ }
+
+ local = calloc (1, sizeof (*local));
+ GF_VALIDATE_OR_GOTO(this->name, local, unwind);
+
+ loc_copy (&local->loc, loc);
+
+ frame->local = local;
+
+ pathlen = STRLEN_0(loc->path);
+ baselen = STRLEN_0(loc->name);
+ par = this_ino_get (loc, this, GF_CLIENT_INODE_PARENT);
+
+ hdrlen = gf_hdr_len (req, pathlen + baselen);
+ hdr = gf_hdr_new (req, pathlen + baselen);
+ GF_VALIDATE_OR_GOTO(this->name, hdr, unwind);
+
+ req = gf_param (hdr);
+
+ req->par = hton64 (par);
+ req->mode = hton32 (mode);
+ req->dev = hton64 (dev);
+ strcpy (req->path, loc->path);
+ strcpy (req->bname + pathlen, loc->name);
+
+ ret = protocol_client_xfer (frame, this,
+ CLIENT_CHANNEL (this, CHANNEL_LOWLAT),
+ GF_OP_TYPE_FOP_REQUEST, GF_FOP_MKNOD,
+ hdr, hdrlen, NULL, 0, NULL);
+
+ return ret;
+unwind:
+ if (hdr)
+ free (hdr);
+ STACK_UNWIND(frame, -1, EINVAL, loc->inode, NULL);
+ return 0;
+
+}
+
+
+/**
+ * client_mkdir - mkdir function for client protocol
+ * @frame: call frame
+ * @this: this translator structure
+ * @path: pathname of directory
+ * @mode:
+ *
+ * external reference through client_protocol_xlator->fops->mkdir
+ */
+int32_t
+client_mkdir (call_frame_t *frame,
+ xlator_t *this,
+ loc_t *loc,
+ mode_t mode)
+{
+ gf_hdr_common_t *hdr = NULL;
+ gf_fop_mkdir_req_t *req = NULL;
+ size_t hdrlen = -1;
+ int ret = -1;
+ size_t pathlen = 0;
+ size_t baselen = 0;
+ ino_t par = 0;
+ client_conf_t *conf = this->private;
+ client_local_t *local = NULL;
+
+ if (conf->child) {
+ /* */
+ STACK_WIND (frame,
+ default_mkdir_cbk,
+ conf->child,
+ conf->child->fops->mkdir,
+ loc, mode);
+
+ return 0;
+ }
+
+ local = calloc (1, sizeof (*local));
+ GF_VALIDATE_OR_GOTO(this->name, local, unwind);
+
+ loc_copy (&local->loc, loc);
+
+ frame->local = local;
+
+ pathlen = STRLEN_0(loc->path);
+ baselen = STRLEN_0(loc->name);
+ par = this_ino_get (loc, this, GF_CLIENT_INODE_PARENT);
+
+ hdrlen = gf_hdr_len (req, pathlen + baselen);
+ hdr = gf_hdr_new (req, pathlen + baselen);
+ GF_VALIDATE_OR_GOTO(this->name, hdr, unwind);
+
+ req = gf_param (hdr);
+
+ req->par = hton64 (par);
+ req->mode = hton32 (mode);
+ strcpy (req->path, loc->path);
+ strcpy (req->bname + pathlen, loc->name);
+
+ ret = protocol_client_xfer (frame, this,
+ CLIENT_CHANNEL (this, CHANNEL_LOWLAT),
+ GF_OP_TYPE_FOP_REQUEST, GF_FOP_MKDIR,
+ hdr, hdrlen, NULL, 0, NULL);
+
+ return ret;
+unwind:
+ if (hdr)
+ free (hdr);
+ STACK_UNWIND(frame, -1, EINVAL, loc->inode, NULL);
+ return 0;
+
+}
+
+
+
+/**
+ * client_unlink - unlink function for client protocol
+ * @frame: call frame
+ * @this: this translator structure
+ * @loc: location of file
+ *
+ * external reference through client_protocol_xlator->fops->unlink
+ */
+int32_t
+client_unlink (call_frame_t *frame,
+ xlator_t *this,
+ loc_t *loc)
+{
+ gf_hdr_common_t *hdr = NULL;
+ gf_fop_unlink_req_t *req = NULL;
+ size_t hdrlen = -1;
+ int ret = -1;
+ size_t pathlen = 0;
+ size_t baselen = 0;
+ ino_t par = 0;
+ client_conf_t *conf = this->private;
+
+ if (conf->child) {
+ /* */
+ STACK_WIND (frame,
+ default_unlink_cbk,
+ conf->child,
+ conf->child->fops->unlink,
+ loc);
+
+ return 0;
+ }
+
+ pathlen = STRLEN_0(loc->path);
+ baselen = STRLEN_0(loc->name);
+ par = this_ino_get (loc, this, GF_CLIENT_INODE_PARENT);
+
+ hdrlen = gf_hdr_len (req, pathlen + baselen);
+ hdr = gf_hdr_new (req, pathlen + baselen);
+ GF_VALIDATE_OR_GOTO(this->name, hdr, unwind);
+
+ req = gf_param (hdr);
+
+ req->par = hton64 (par);
+ strcpy (req->path, loc->path);
+ strcpy (req->bname + pathlen, loc->name);
+
+ ret = protocol_client_xfer (frame, this,
+ CLIENT_CHANNEL (this, CHANNEL_BULK),
+ GF_OP_TYPE_FOP_REQUEST, GF_FOP_UNLINK,
+ hdr, hdrlen, NULL, 0, NULL);
+
+ return ret;
+unwind:
+ if (hdr)
+ free (hdr);
+ STACK_UNWIND(frame, -1, EINVAL);
+ return 0;
+
+}
+
+/**
+ * client_rmdir - rmdir function for client protocol
+ * @frame: call frame
+ * @this: this translator structure
+ * @loc: location
+ *
+ * external reference through client_protocol_xlator->fops->rmdir
+ */
+int32_t
+client_rmdir (call_frame_t *frame,
+ xlator_t *this,
+ loc_t *loc)
+{
+ gf_hdr_common_t *hdr = NULL;
+ gf_fop_rmdir_req_t *req = NULL;
+ size_t hdrlen = -1;
+ int ret = -1;
+ size_t pathlen = 0;
+ size_t baselen = 0;
+ ino_t par = 0;
+ client_conf_t *conf = this->private;
+
+ if (conf->child) {
+ /* */
+ STACK_WIND (frame,
+ default_rmdir_cbk,
+ conf->child,
+ conf->child->fops->rmdir,
+ loc);
+
+ return 0;
+ }
+
+ pathlen = STRLEN_0(loc->path);
+ baselen = STRLEN_0(loc->name);
+ par = this_ino_get (loc, this, GF_CLIENT_INODE_PARENT);
+
+ hdrlen = gf_hdr_len (req, pathlen + baselen);
+ hdr = gf_hdr_new (req, pathlen + baselen);
+ GF_VALIDATE_OR_GOTO(this->name, hdr, unwind);
+
+ req = gf_param (hdr);
+
+ req->par = hton64 (par);
+ strcpy (req->path, loc->path);
+ strcpy (req->bname + pathlen, loc->name);
+
+ ret = protocol_client_xfer (frame, this,
+ CLIENT_CHANNEL (this, CHANNEL_BULK),
+ GF_OP_TYPE_FOP_REQUEST, GF_FOP_RMDIR,
+ hdr, hdrlen, NULL, 0, NULL);
+
+ return ret;
+unwind:
+ if (hdr)
+ free (hdr);
+ STACK_UNWIND(frame, -1, EINVAL);
+ return 0;
+
+}
+
+
+
+/**
+ * client_symlink - symlink function for client protocol
+ * @frame: call frame
+ * @this: this translator structure
+ * @oldpath: pathname of target
+ * @newpath: pathname of symlink
+ *
+ * external reference through client_protocol_xlator->fops->symlink
+ */
+int32_t
+client_symlink (call_frame_t *frame,
+ xlator_t *this,
+ const char *linkname,
+ loc_t *loc)
+{
+ int ret = -1;
+ gf_hdr_common_t *hdr = NULL;
+ gf_fop_symlink_req_t *req = NULL;
+ size_t hdrlen = 0;
+ size_t pathlen = 0;
+ size_t newlen = 0;
+ size_t baselen = 0;
+ ino_t par = 0;
+ client_conf_t *conf = this->private;
+ client_local_t *local = NULL;
+
+ if (conf->child) {
+ /* */
+ STACK_WIND (frame,
+ default_symlink_cbk,
+ conf->child,
+ conf->child->fops->symlink,
+ linkname, loc);
+
+ return 0;
+ }
+
+ local = calloc (1, sizeof (*local));
+ GF_VALIDATE_OR_GOTO(this->name, local, unwind);
+
+ loc_copy (&local->loc, loc);
+
+ frame->local = local;
+
+ pathlen = STRLEN_0 (loc->path);
+ baselen = STRLEN_0 (loc->name);
+ newlen = STRLEN_0 (linkname);
+ par = this_ino_get (loc, this, GF_CLIENT_INODE_PARENT);
+
+ hdrlen = gf_hdr_len (req, pathlen + baselen + newlen);
+ hdr = gf_hdr_new (req, pathlen + baselen + newlen);
+ GF_VALIDATE_OR_GOTO(this->name, hdr, unwind);
+
+ req = gf_param (hdr);
+
+ req->par = hton64 (par);
+ strcpy (req->path, loc->path);
+ strcpy (req->bname + pathlen, loc->name);
+ strcpy (req->linkname + pathlen + baselen, linkname);
+
+ ret = protocol_client_xfer (frame, this,
+ CLIENT_CHANNEL (this, CHANNEL_LOWLAT),
+ GF_OP_TYPE_FOP_REQUEST, GF_FOP_SYMLINK,
+ hdr, hdrlen, NULL, 0, NULL);
+ return ret;
+unwind:
+ if (hdr)
+ free (hdr);
+ STACK_UNWIND(frame, -1, EINVAL, loc->inode, NULL);
+ return 0;
+
+}
+
+
+/**
+ * client_rename - rename function for client protocol
+ * @frame: call frame
+ * @this: this translator structure
+ * @oldloc: location of old pathname
+ * @newloc: location of new pathname
+ *
+ * external reference through client_protocol_xlator->fops->rename
+ */
+int32_t
+client_rename (call_frame_t *frame,
+ xlator_t *this,
+ loc_t *oldloc,
+ loc_t *newloc)
+{
+ int ret = -1;
+ gf_hdr_common_t *hdr = NULL;
+ gf_fop_rename_req_t *req = NULL;
+ size_t hdrlen = 0;
+ size_t oldpathlen = 0;
+ size_t oldbaselen = 0;
+ size_t newpathlen = 0;
+ size_t newbaselen = 0;
+ ino_t oldpar = 0;
+ ino_t newpar = 0;
+ client_conf_t *conf = this->private;
+
+ if (conf->child) {
+ /* */
+ STACK_WIND (frame,
+ default_rename_cbk,
+ conf->child,
+ conf->child->fops->rename,
+ oldloc, newloc);
+
+ return 0;
+ }
+
+ oldpathlen = STRLEN_0(oldloc->path);
+ oldbaselen = STRLEN_0(oldloc->name);
+ newpathlen = STRLEN_0(newloc->path);
+ newbaselen = STRLEN_0(newloc->name);
+ oldpar = this_ino_get (oldloc, this, GF_CLIENT_INODE_PARENT);
+ newpar = this_ino_get (newloc, this, GF_CLIENT_INODE_PARENT);
+
+ hdrlen = gf_hdr_len (req, (oldpathlen + oldbaselen +
+ newpathlen + newbaselen));
+ hdr = gf_hdr_new (req, (oldpathlen + oldbaselen +
+ newpathlen + newbaselen));
+
+ GF_VALIDATE_OR_GOTO(this->name, hdr, unwind);
+
+ req = gf_param (hdr);
+
+ req->oldpar = hton64 (oldpar);
+ req->newpar = hton64 (newpar);
+
+ strcpy (req->oldpath, oldloc->path);
+ strcpy (req->oldbname + oldpathlen, oldloc->name);
+ strcpy (req->newpath + oldpathlen + oldbaselen, newloc->path);
+ strcpy (req->newbname + oldpathlen + oldbaselen + newpathlen,
+ newloc->name);
+
+ ret = protocol_client_xfer (frame, this,
+ CLIENT_CHANNEL (this, CHANNEL_LOWLAT),
+ GF_OP_TYPE_FOP_REQUEST, GF_FOP_RENAME,
+ hdr, hdrlen, NULL, 0, NULL);
+ return ret;
+unwind:
+ if (hdr)
+ free (hdr);
+ STACK_UNWIND(frame, -1, EINVAL, NULL);
+ return 0;
+
+}
+
+
+
+/**
+ * client_link - link function for client protocol
+ * @frame: call frame
+ * @this: this translator structure
+ * @oldloc: location of old pathname
+ * @newpath: new pathname
+ *
+ * external reference through client_protocol_xlator->fops->link
+ */
+
+int32_t
+client_link (call_frame_t *frame,
+ xlator_t *this,
+ loc_t *oldloc,
+ loc_t *newloc)
+{
+ int ret = -1;
+ gf_hdr_common_t *hdr = NULL;
+ gf_fop_link_req_t *req = NULL;
+ size_t hdrlen = 0;
+ size_t oldpathlen = 0;
+ size_t newpathlen = 0;
+ size_t newbaselen = 0;
+ ino_t oldino = 0;
+ ino_t newpar = 0;
+ client_conf_t *conf = this->private;
+ client_local_t *local = NULL;
+
+ if (conf->child) {
+ /* */
+ STACK_WIND (frame,
+ default_link_cbk,
+ conf->child,
+ conf->child->fops->link,
+ oldloc, newloc);
+
+ return 0;
+ }
+
+ local = calloc (1, sizeof (*local));
+ GF_VALIDATE_OR_GOTO(this->name, local, unwind);
+
+ loc_copy (&local->loc, oldloc);
+
+ frame->local = local;
+
+ oldpathlen = STRLEN_0(oldloc->path);
+ newpathlen = STRLEN_0(newloc->path);
+ newbaselen = STRLEN_0(newloc->name);
+ oldino = this_ino_get (oldloc, this, GF_CLIENT_INODE_SELF);
+ newpar = this_ino_get (newloc, this, GF_CLIENT_INODE_PARENT);
+
+ hdrlen = gf_hdr_len (req, oldpathlen + newpathlen + newbaselen);
+ hdr = gf_hdr_new (req, oldpathlen + newpathlen + newbaselen);
+ GF_VALIDATE_OR_GOTO(this->name, hdr, unwind);
+
+ req = gf_param (hdr);
+
+ strcpy (req->oldpath, oldloc->path);
+ strcpy (req->newpath + oldpathlen, newloc->path);
+ strcpy (req->newbname + oldpathlen + newpathlen, newloc->name);
+
+ req->oldino = hton64 (oldino);
+ req->newpar = hton64 (newpar);
+
+ ret = protocol_client_xfer (frame, this,
+ CLIENT_CHANNEL (this, CHANNEL_LOWLAT),
+ GF_OP_TYPE_FOP_REQUEST, GF_FOP_LINK,
+ hdr, hdrlen, NULL, 0, NULL);
+ return ret;
+unwind:
+ if (hdr)
+ free (hdr);
+ STACK_UNWIND(frame, -1, EINVAL, oldloc->inode, NULL);
+ return 0;
+}
+
+
+
+/**
+ * client_chmod - chmod function for client protocol
+ * @frame: call frame
+ * @this: this translator structure
+ * @loc: location
+ * @mode:
+ *
+ * external reference through client_protocol_xlator->fops->chmod
+ */
+int32_t
+client_chmod (call_frame_t *frame,
+ xlator_t *this,
+ loc_t *loc,
+ mode_t mode)
+{
+ gf_hdr_common_t *hdr = NULL;
+ gf_fop_chmod_req_t *req = NULL;
+ size_t hdrlen = -1;
+ int ret = -1;
+ size_t pathlen = 0;
+ ino_t ino = 0;
+ client_conf_t *conf = this->private;
+
+ if (conf->child) {
+ /* */
+ STACK_WIND (frame,
+ default_chmod_cbk,
+ conf->child,
+ conf->child->fops->chmod,
+ loc,
+ mode);
+
+ return 0;
+ }
+
+ pathlen = STRLEN_0(loc->path);
+ ino = this_ino_get (loc, this, GF_CLIENT_INODE_SELF);
+
+ hdrlen = gf_hdr_len (req, pathlen);
+ hdr = gf_hdr_new (req, pathlen);
+ GF_VALIDATE_OR_GOTO(this->name, hdr, unwind);
+
+ req = gf_param (hdr);
+
+ req->ino = hton64 (ino);
+ req->mode = hton32 (mode);
+ strcpy (req->path, loc->path);
+
+ ret = protocol_client_xfer (frame, this,
+ CLIENT_CHANNEL (this, CHANNEL_LOWLAT),
+ GF_OP_TYPE_FOP_REQUEST, GF_FOP_CHMOD,
+ hdr, hdrlen, NULL, 0, NULL);
+
+ return ret;
+unwind:
+ if (hdr)
+ free (hdr);
+ STACK_UNWIND(frame, -1, EINVAL, NULL);
+ return 0;
+
+}
+
+
+/**
+ * client_chown - chown function for client protocol
+ * @frame: call frame
+ * @this: this translator structure
+ * @loc: location
+ * @uid: uid of new owner
+ * @gid: gid of new owner group
+ *
+ * external reference through client_protocol_xlator->fops->chown
+ */
+int32_t
+client_chown (call_frame_t *frame,
+ xlator_t *this,
+ loc_t *loc,
+ uid_t uid,
+ gid_t gid)
+{
+ gf_hdr_common_t *hdr = NULL;
+ gf_fop_chown_req_t *req = NULL;
+ size_t hdrlen = -1;
+ int ret = -1;
+ size_t pathlen = 0;
+ ino_t ino = 0;
+ client_conf_t *conf = this->private;
+
+ if (conf->child) {
+ /* */
+ STACK_WIND (frame,
+ default_chown_cbk,
+ conf->child,
+ conf->child->fops->chown,
+ loc,
+ uid,
+ gid);
+
+ return 0;
+ }
+
+ pathlen = STRLEN_0(loc->path);
+ ino = this_ino_get (loc, this, GF_CLIENT_INODE_SELF);
+
+ hdrlen = gf_hdr_len (req, pathlen);
+ hdr = gf_hdr_new (req, pathlen);
+ GF_VALIDATE_OR_GOTO(this->name, hdr, unwind);
+
+ req = gf_param (hdr);
+
+ req->ino = hton64 (ino);
+ req->uid = hton32 (uid);
+ req->gid = hton32 (gid);
+ strcpy (req->path, loc->path);
+
+ ret = protocol_client_xfer (frame, this,
+ CLIENT_CHANNEL (this, CHANNEL_LOWLAT),
+ GF_OP_TYPE_FOP_REQUEST, GF_FOP_CHOWN,
+ hdr, hdrlen, NULL, 0, NULL);
+
+ return ret;
+unwind:
+ if (hdr)
+ free (hdr);
+ STACK_UNWIND(frame, -1, EINVAL, NULL);
+ return 0;
+
+}
+
+/**
+ * client_truncate - truncate function for client protocol
+ * @frame: call frame
+ * @this: this translator structure
+ * @loc: location
+ * @offset:
+ *
+ * external reference through client_protocol_xlator->fops->truncate
+ */
+int32_t
+client_truncate (call_frame_t *frame,
+ xlator_t *this,
+ loc_t *loc,
+ off_t offset)
+{
+ gf_hdr_common_t *hdr = NULL;
+ gf_fop_truncate_req_t *req = NULL;
+ size_t hdrlen = -1;
+ int ret = -1;
+ size_t pathlen = 0;
+ ino_t ino = 0;
+ client_conf_t *conf = this->private;
+
+ if (conf->child) {
+ /* */
+ STACK_WIND (frame,
+ default_truncate_cbk,
+ conf->child,
+ conf->child->fops->truncate,
+ loc,
+ offset);
+
+ return 0;
+ }
+
+ pathlen = STRLEN_0(loc->path);
+ ino = this_ino_get (loc, this, GF_CLIENT_INODE_SELF);
+
+ hdrlen = gf_hdr_len (req, pathlen);
+ hdr = gf_hdr_new (req, pathlen);
+ GF_VALIDATE_OR_GOTO(this->name, hdr, unwind);
+
+ req = gf_param (hdr);
+
+ req->ino = hton64 (ino);
+ req->offset = hton64 (offset);
+ strcpy (req->path, loc->path);
+
+ ret = protocol_client_xfer (frame, this,
+ CLIENT_CHANNEL (this, CHANNEL_BULK),
+ GF_OP_TYPE_FOP_REQUEST, GF_FOP_TRUNCATE,
+ hdr, hdrlen, NULL, 0, NULL);
+
+ return ret;
+unwind:
+ if (hdr)
+ free (hdr);
+ STACK_UNWIND(frame, -1, EINVAL, NULL);
+ return 0;
+
+}
+
+
+
+/**
+ * client_utimes - utimes function for client protocol
+ * @frame: call frame
+ * @this: this translator structure
+ * @loc: location
+ * @tvp:
+ *
+ * external reference through client_protocol_xlator->fops->utimes
+ */
+int32_t
+client_utimens (call_frame_t *frame,
+ xlator_t *this,
+ loc_t *loc,
+ struct timespec *tvp)
+{
+ gf_hdr_common_t *hdr = NULL;
+ gf_fop_utimens_req_t *req = NULL;
+ size_t hdrlen = -1;
+ int ret = -1;
+ size_t pathlen = 0;
+ ino_t ino = 0;
+ client_conf_t *conf = this->private;
+
+ if (conf->child) {
+ /* */
+ STACK_WIND (frame,
+ default_utimens_cbk,
+ conf->child,
+ conf->child->fops->utimens,
+ loc,
+ tvp);
+
+ return 0;
+ }
+
+ pathlen = STRLEN_0(loc->path);
+ ino = this_ino_get (loc, this, GF_CLIENT_INODE_SELF);
+
+ hdrlen = gf_hdr_len (req, pathlen);
+ hdr = gf_hdr_new (req, pathlen);
+ GF_VALIDATE_OR_GOTO(this->name, hdr, unwind);
+
+ req = gf_param (hdr);
+
+ req->ino = hton64 (ino);
+ gf_timespec_from_timespec (req->tv, tvp);
+ strcpy (req->path, loc->path);
+
+ ret = protocol_client_xfer (frame, this,
+ CLIENT_CHANNEL (this, CHANNEL_LOWLAT),
+ GF_OP_TYPE_FOP_REQUEST, GF_FOP_UTIMENS,
+ hdr, hdrlen, NULL, 0, NULL);
+
+ return ret;
+unwind:
+ if (hdr)
+ free (hdr);
+ STACK_UNWIND(frame, -1, EINVAL, NULL);
+ return 0;
+
+}
+
+
+
+/**
+ * client_readv - readv function for client protocol
+ * @frame: call frame
+ * @this: this translator structure
+ * @fd: file descriptor structure
+ * @size:
+ * @offset:
+ *
+ * external reference through client_protocol_xlator->fops->readv
+ */
+int32_t
+client_readv (call_frame_t *frame,
+ xlator_t *this,
+ fd_t *fd,
+ size_t size,
+ off_t offset)
+{
+ gf_hdr_common_t *hdr = NULL;
+ gf_fop_read_req_t *req = NULL;
+ size_t hdrlen = 0;
+ int64_t remote_fd = -1;
+ int ret = -1;
+ client_conf_t *conf = this->private;
+
+ if (conf->child) {
+ /* */
+ STACK_WIND (frame,
+ default_readv_cbk,
+ conf->child,
+ conf->child->fops->readv,
+ fd,
+ size,
+ offset);
+
+ return 0;
+ }
+
+ ret = this_fd_get (fd, this, &remote_fd);
+ if (ret == -1) {
+ gf_log (this->name, GF_LOG_DEBUG,
+ "(%"PRId64"): failed to get remote fd, returning EBADFD",
+ fd->inode->ino);
+ STACK_UNWIND (frame, -1, EBADFD, NULL, 0, NULL);
+ return 0;
+ }
+
+ hdrlen = gf_hdr_len (req, 0);
+ hdr = gf_hdr_new (req, 0);
+ GF_VALIDATE_OR_GOTO(this->name, hdr, unwind);
+
+ req = gf_param (hdr);
+
+ req->fd = hton64 (remote_fd);
+ req->size = hton32 (size);
+ req->offset = hton64 (offset);
+
+ ret = protocol_client_xfer (frame, this,
+ CLIENT_CHANNEL (this, CHANNEL_BULK),
+ GF_OP_TYPE_FOP_REQUEST, GF_FOP_READ,
+ hdr, hdrlen, NULL, 0, NULL);
+
+ return 0;
+unwind:
+ if (hdr)
+ free (hdr);
+ STACK_UNWIND(frame, -1, EINVAL, NULL, 0, NULL);
+ return 0;
+
+}
+
+
+/**
+ * client_writev - writev function for client protocol
+ * @frame: call frame
+ * @this: this translator structure
+ * @fd: file descriptor structure
+ * @vector:
+ * @count:
+ * @offset:
+ *
+ * external reference through client_protocol_xlator->fops->writev
+ */
+int32_t
+client_writev (call_frame_t *frame,
+ xlator_t *this,
+ fd_t *fd,
+ struct iovec *vector,
+ int32_t count,
+ off_t offset)
+{
+ gf_hdr_common_t *hdr = NULL;
+ gf_fop_write_req_t *req = NULL;
+ size_t hdrlen = 0;
+ int64_t remote_fd = -1;
+ int ret = -1;
+ client_conf_t *conf = this->private;
+
+ if (conf->child) {
+ /* */
+ STACK_WIND (frame,
+ default_writev_cbk,
+ conf->child,
+ conf->child->fops->writev,
+ fd,
+ vector,
+ count,
+ offset);
+
+ return 0;
+ }
+
+ ret = this_fd_get (fd, this, &remote_fd);
+ if (ret == -1) {
+ gf_log (this->name, GF_LOG_DEBUG,
+ "(%"PRId64"): failed to get remote fd. returning EBADFD",
+ fd->inode->ino);
+ STACK_UNWIND (frame, -1, EBADFD, NULL);
+ return 0;
+ }
+
+ hdrlen = gf_hdr_len (req, 0);
+ hdr = gf_hdr_new (req, 0);
+ GF_VALIDATE_OR_GOTO(this->name, hdr, unwind);
+
+ req = gf_param (hdr);
+
+ req->fd = hton64 (remote_fd);
+ req->size = hton32 (iov_length (vector, count));
+ req->offset = hton64 (offset);
+
+ ret = protocol_client_xfer (frame, this,
+ CLIENT_CHANNEL (this, CHANNEL_BULK),
+ GF_OP_TYPE_FOP_REQUEST, GF_FOP_WRITE,
+ hdr, hdrlen, vector, count,
+ frame->root->req_refs);
+
+ return ret;
+unwind:
+ if (hdr)
+ free (hdr);
+ STACK_UNWIND(frame, -1, EINVAL, NULL);
+ return 0;
+
+}
+
+
+/**
+ * client_statfs - statfs function for client protocol
+ * @frame: call frame
+ * @this: this translator structure
+ * @loc: location
+ *
+ * external reference through client_protocol_xlator->fops->statfs
+ */
+int32_t
+client_statfs (call_frame_t *frame,
+ xlator_t *this,
+ loc_t *loc)
+{
+ gf_hdr_common_t *hdr = NULL;
+ gf_fop_statfs_req_t *req = NULL;
+ size_t hdrlen = -1;
+ int ret = -1;
+ size_t pathlen = 0;
+ ino_t ino = 0;
+ client_conf_t *conf = this->private;
+
+ if (conf->child) {
+ /* */
+ STACK_WIND (frame,
+ default_statfs_cbk,
+ conf->child,
+ conf->child->fops->statfs,
+ loc);
+
+ return 0;
+ }
+
+ pathlen = STRLEN_0(loc->path);
+ ino = this_ino_get (loc, this, GF_CLIENT_INODE_SELF);
+
+ hdrlen = gf_hdr_len (req, pathlen);
+ hdr = gf_hdr_new (req, pathlen);
+ GF_VALIDATE_OR_GOTO(this->name, hdr, unwind);
+
+ req = gf_param (hdr);
+
+ req->ino = hton64 (ino);
+ strcpy (req->path, loc->path);
+
+ ret = protocol_client_xfer (frame, this,
+ CLIENT_CHANNEL (this, CHANNEL_LOWLAT),
+ GF_OP_TYPE_FOP_REQUEST, GF_FOP_STATFS,
+ hdr, hdrlen, NULL, 0, NULL);
+
+ return ret;
+unwind:
+ if (hdr)
+ free (hdr);
+ STACK_UNWIND(frame, -1, EINVAL, NULL);
+ return 0;
+
+}
+
+
+/**
+ * client_flush - flush function for client protocol
+ * @frame: call frame
+ * @this: this translator structure
+ * @fd: file descriptor structure
+ *
+ * external reference through client_protocol_xlator->fops->flush
+ */
+
+int32_t
+client_flush (call_frame_t *frame,
+ xlator_t *this,
+ fd_t *fd)
+{
+ gf_hdr_common_t *hdr = NULL;
+ gf_fop_flush_req_t *req = NULL;
+ size_t hdrlen = 0;
+ int64_t remote_fd = -1;
+ int ret = -1;
+ client_conf_t *conf = this->private;
+
+ if (conf->child) {
+ /* */
+ STACK_WIND (frame,
+ default_flush_cbk,
+ conf->child,
+ conf->child->fops->flush,
+ fd);
+
+ return 0;
+ }
+
+ ret = this_fd_get (fd, this, &remote_fd);
+ if (ret == -1) {
+ gf_log (this->name, GF_LOG_DEBUG,
+ "(%"PRId64"): failed to get remote fd. returning EBADFD",
+ fd->inode->ino);
+ STACK_UNWIND (frame, -1, EBADFD);
+ return 0;
+ }
+
+ hdrlen = gf_hdr_len (req, 0);
+ hdr = gf_hdr_new (req, 0);
+ GF_VALIDATE_OR_GOTO(this->name, hdr, unwind);
+
+ req = gf_param (hdr);
+
+ req->fd = hton64 (remote_fd);
+
+ ret = protocol_client_xfer (frame, this,
+ CLIENT_CHANNEL (this, CHANNEL_BULK),
+ GF_OP_TYPE_FOP_REQUEST, GF_FOP_FLUSH,
+ hdr, hdrlen, NULL, 0, NULL);
+
+ return 0;
+unwind:
+ if (hdr)
+ free (hdr);
+ STACK_UNWIND(frame, -1, EINVAL);
+ return 0;
+
+}
+
+
+
+
+/**
+ * client_fsync - fsync function for client protocol
+ * @frame: call frame
+ * @this: this translator structure
+ * @fd: file descriptor structure
+ * @flags:
+ *
+ * external reference through client_protocol_xlator->fops->fsync
+ */
+
+int32_t
+client_fsync (call_frame_t *frame,
+ xlator_t *this,
+ fd_t *fd,
+ int32_t flags)
+{
+ gf_hdr_common_t *hdr = NULL;
+ gf_fop_fsync_req_t *req = NULL;
+ size_t hdrlen = 0;
+ int64_t remote_fd = -1;
+ int32_t ret = -1;
+ client_conf_t *conf = this->private;
+
+ if (conf->child) {
+ /* */
+ STACK_WIND (frame,
+ default_fsync_cbk,
+ conf->child,
+ conf->child->fops->fsync,
+ fd,
+ flags);
+
+ return 0;
+ }
+
+ ret = this_fd_get (fd, this, &remote_fd);
+ if (ret == -1) {
+ gf_log (this->name, GF_LOG_DEBUG,
+ "(%"PRId64"): failed to get remote fd. returning EBADFD",
+ fd->inode->ino);
+ STACK_UNWIND(frame, -1, EBADFD);
+ return 0;
+ }
+
+ hdrlen = gf_hdr_len (req, 0);
+ hdr = gf_hdr_new (req, 0);
+ GF_VALIDATE_OR_GOTO(this->name, hdr, unwind);
+
+ req = gf_param (hdr);
+
+ req->fd = hton64 (remote_fd);
+ req->data = hton32 (flags);
+
+ ret = protocol_client_xfer (frame, this,
+ CLIENT_CHANNEL (this, CHANNEL_BULK),
+ GF_OP_TYPE_FOP_REQUEST, GF_FOP_FSYNC,
+ hdr, hdrlen, NULL, 0, NULL);
+
+ return ret;
+unwind:
+ if (hdr)
+ free (hdr);
+ STACK_UNWIND(frame, -1, EINVAL);
+ return 0;
+
+}
+
+int32_t
+client_xattrop (call_frame_t *frame,
+ xlator_t *this,
+ loc_t *loc,
+ gf_xattrop_flags_t flags,
+ dict_t *dict)
+{
+ gf_hdr_common_t *hdr = NULL;
+ gf_fop_xattrop_req_t *req = NULL;
+ size_t hdrlen = 0;
+ size_t dict_len = 0;
+ int32_t ret = -1;
+ size_t pathlen = 0;
+ ino_t ino = 0;
+ client_conf_t *conf = NULL;
+
+ GF_VALIDATE_OR_GOTO("client", this, unwind);
+
+ conf = this->private;
+ if (conf->child) {
+ /* */
+ STACK_WIND (frame,
+ default_xattrop_cbk,
+ conf->child,
+ conf->child->fops->xattrop,
+ loc,
+ flags,
+ dict);
+
+ return 0;
+ }
+
+ GF_VALIDATE_OR_GOTO(this->name, loc, unwind);
+
+ if (dict) {
+ dict_len = dict_serialized_length (dict);
+ if (dict_len < 0) {
+ gf_log (this->name, GF_LOG_ERROR,
+ "failed to get serialized length of dict(%p)",
+ dict);
+ goto unwind;
+ }
+ }
+
+ pathlen = STRLEN_0(loc->path);
+ ino = this_ino_get (loc, this, GF_CLIENT_INODE_SELF);
+
+ hdrlen = gf_hdr_len (req, dict_len + pathlen);
+ hdr = gf_hdr_new (req, dict_len + pathlen);
+ GF_VALIDATE_OR_GOTO(this->name, hdr, unwind);
+
+ req = gf_param (hdr);
+
+ req->flags = hton32 (flags);
+ req->dict_len = hton32 (dict_len);
+ if (dict) {
+ ret = dict_serialize (dict, req->dict);
+ if (ret < 0) {
+ gf_log (this->name, GF_LOG_ERROR,
+ "failed to serialize dictionary(%p)",
+ dict);
+ goto unwind;
+ }
+ }
+ req->ino = hton64 (ino);
+ strcpy (req->path + dict_len, loc->path);
+
+ ret = protocol_client_xfer (frame, this,
+ CLIENT_CHANNEL (this, CHANNEL_BULK),
+ GF_OP_TYPE_FOP_REQUEST, GF_FOP_XATTROP,
+ hdr, hdrlen, NULL, 0, NULL);
+ return ret;
+unwind:
+ if (hdr)
+ free (hdr);
+
+ STACK_UNWIND(frame, -1, EINVAL, 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)
+{
+ gf_hdr_common_t *hdr = NULL;
+ gf_fop_fxattrop_req_t *req = NULL;
+ size_t hdrlen = 0;
+ size_t dict_len = 0;
+ int64_t remote_fd = -1;
+ int32_t ret = -1;
+ ino_t ino = 0;
+ client_conf_t *conf = this->private;
+
+ if (conf->child) {
+ /* */
+ STACK_WIND (frame,
+ default_fxattrop_cbk,
+ conf->child,
+ conf->child->fops->fxattrop,
+ fd,
+ flags,
+ dict);
+
+ return 0;
+ }
+
+ if (dict) {
+ dict_len = dict_serialized_length (dict);
+ if (dict_len < 0) {
+ gf_log (this->name, GF_LOG_ERROR,
+ "failed to get serialized length of dict(%p)",
+ dict);
+ goto unwind;
+ }
+ }
+
+ if (fd) {
+ ret = this_fd_get (fd, this, &remote_fd);
+ if (ret == -1) {
+ gf_log (this->name, GF_LOG_DEBUG,
+ "(%"PRId64"): failed to get remote fd. returning EBADFD",
+ fd->inode->ino);
+ goto unwind;
+ }
+ ino = fd->inode->ino;
+ }
+
+ hdrlen = gf_hdr_len (req, dict_len);
+ hdr = gf_hdr_new (req, dict_len);
+ GF_VALIDATE_OR_GOTO(this->name, hdr, unwind);
+
+ req = gf_param (hdr);
+
+ req->flags = hton32 (flags);
+ req->dict_len = hton32 (dict_len);
+ if (dict) {
+ ret = dict_serialize (dict, req->dict);
+ if (ret < 0) {
+ gf_log (this->name, GF_LOG_ERROR,
+ "failed to serialize dictionary(%p)",
+ dict);
+ goto unwind;
+ }
+ }
+ req->fd = hton64 (remote_fd);
+ req->ino = hton64 (ino);
+
+ ret = protocol_client_xfer (frame, this,
+ CLIENT_CHANNEL (this, CHANNEL_BULK),
+ GF_OP_TYPE_FOP_REQUEST, GF_FOP_FXATTROP,
+ hdr, hdrlen, NULL, 0, NULL);
+ return ret;
+unwind:
+ if (hdr)
+ free (hdr);
+
+ STACK_UNWIND (frame, -1, EBADFD, NULL);
+ return 0;
+
+}
+
+
+/**
+ * client_setxattr - setxattr function for client protocol
+ * @frame: call frame
+ * @this: this translator structure
+ * @loc: location
+ * @dict: dictionary which contains key:value to be set.
+ * @flags:
+ *
+ * external reference through client_protocol_xlator->fops->setxattr
+ */
+int32_t
+client_setxattr (call_frame_t *frame,
+ xlator_t *this,
+ loc_t *loc,
+ dict_t *dict,
+ int32_t flags)
+{
+ gf_hdr_common_t *hdr = NULL;
+ gf_fop_setxattr_req_t *req = NULL;
+ size_t hdrlen = 0;
+ size_t dict_len = 0;
+ int ret = -1;
+ size_t pathlen = 0;
+ ino_t ino = 0;
+ client_conf_t *conf = this->private;
+
+ if (conf->child) {
+ /* */
+ STACK_WIND (frame,
+ default_setxattr_cbk,
+ conf->child,
+ conf->child->fops->setxattr,
+ loc,
+ dict,
+ flags);
+
+ return 0;
+ }
+
+ dict_len = dict_serialized_length (dict);
+ if (dict_len < 0) {
+ gf_log (this->name, GF_LOG_ERROR,
+ "failed to get serialized length of dict(%p)",
+ dict);
+ goto unwind;
+ }
+
+ pathlen = STRLEN_0(loc->path);
+ ino = this_ino_get (loc, this, GF_CLIENT_INODE_SELF);
+
+ hdrlen = gf_hdr_len (req, dict_len + pathlen);
+ hdr = gf_hdr_new (req, dict_len + pathlen);
+ GF_VALIDATE_OR_GOTO(this->name, hdr, unwind);
+
+ req = gf_param (hdr);
+
+ req->ino = hton64 (ino);
+ req->flags = hton32 (flags);
+ req->dict_len = hton32 (dict_len);
+
+ ret = dict_serialize (dict, req->dict);
+ if (ret < 0) {
+ gf_log (this->name, GF_LOG_ERROR,
+ "failed to serialize dictionary(%p)",
+ dict);
+ goto unwind;
+ }
+
+ strcpy (req->path + dict_len, loc->path);
+
+ ret = protocol_client_xfer (frame, this,
+ CLIENT_CHANNEL (this, CHANNEL_BULK),
+ GF_OP_TYPE_FOP_REQUEST, GF_FOP_SETXATTR,
+ hdr, hdrlen, NULL, 0, NULL);
+ return ret;
+unwind:
+ if (hdr)
+ free (hdr);
+
+ STACK_UNWIND(frame, -1, EINVAL);
+ return 0;
+}
+
+/**
+ * client_getxattr - getxattr function for client protocol
+ * @frame: call frame
+ * @this: this translator structure
+ * @loc: location structure
+ *
+ * external reference through client_protocol_xlator->fops->getxattr
+ */
+int32_t
+client_getxattr (call_frame_t *frame,
+ xlator_t *this,
+ loc_t *loc,
+ const char *name)
+{
+ int ret = -1;
+ gf_hdr_common_t *hdr = NULL;
+ gf_fop_getxattr_req_t *req = NULL;
+ size_t hdrlen = 0;
+ size_t pathlen = 0;
+ size_t namelen = 0;
+ ino_t ino = 0;
+ client_conf_t *conf = this->private;
+
+ if (conf->child) {
+ /* */
+ STACK_WIND (frame,
+ default_getxattr_cbk,
+ conf->child,
+ conf->child->fops->getxattr,
+ loc,
+ name);
+
+ return 0;
+ }
+
+ pathlen = STRLEN_0(loc->path);
+ if (name)
+ namelen = STRLEN_0(name);
+
+ ino = this_ino_get (loc, this, GF_CLIENT_INODE_SELF);
+
+ hdrlen = gf_hdr_len (req, pathlen + namelen);
+ hdr = gf_hdr_new (req, pathlen + namelen);
+ GF_VALIDATE_OR_GOTO(frame->this->name, hdr, unwind);
+
+ req = gf_param (hdr);
+
+ req->ino = hton64 (ino);
+ req->namelen = hton32 (namelen);
+ strcpy (req->path, loc->path);
+ if (name)
+ strcpy (req->name + pathlen, name);
+
+ ret = protocol_client_xfer (frame, this,
+ CLIENT_CHANNEL (this, CHANNEL_LOWLAT),
+ GF_OP_TYPE_FOP_REQUEST, GF_FOP_GETXATTR,
+ hdr, hdrlen, NULL, 0, NULL);
+ return ret;
+unwind:
+ if (hdr)
+ free (hdr);
+
+ STACK_UNWIND(frame, -1, EINVAL, NULL);
+ return 0;
+}
+
+/**
+ * client_removexattr - removexattr function for client protocol
+ * @frame: call frame
+ * @this: this translator structure
+ * @loc: location structure
+ * @name:
+ *
+ * external reference through client_protocol_xlator->fops->removexattr
+ */
+int32_t
+client_removexattr (call_frame_t *frame,
+ xlator_t *this,
+ loc_t *loc,
+ const char *name)
+{
+ int ret = -1;
+ gf_hdr_common_t *hdr = NULL;
+ gf_fop_removexattr_req_t *req = NULL;
+ size_t hdrlen = 0;
+ size_t namelen = 0;
+ size_t pathlen = 0;
+ ino_t ino = 0;
+ client_conf_t *conf = this->private;
+
+ if (conf->child) {
+ /* */
+ STACK_WIND (frame,
+ default_removexattr_cbk,
+ conf->child,
+ conf->child->fops->removexattr,
+ loc,
+ name);
+
+ return 0;
+ }
+
+ pathlen = STRLEN_0(loc->path);
+ namelen = STRLEN_0(name);
+ ino = this_ino_get (loc, this, GF_CLIENT_INODE_SELF);
+
+ hdrlen = gf_hdr_len (req, pathlen + namelen);
+ hdr = gf_hdr_new (req, pathlen + namelen);
+ GF_VALIDATE_OR_GOTO(frame->this->name, hdr, unwind);
+
+ req = gf_param (hdr);
+
+ req->ino = hton64 (ino);
+ strcpy (req->path, loc->path);
+ strcpy (req->name + pathlen, name);
+
+ ret = protocol_client_xfer (frame, this,
+ CLIENT_CHANNEL (this, CHANNEL_LOWLAT),
+ GF_OP_TYPE_FOP_REQUEST, GF_FOP_REMOVEXATTR,
+ hdr, hdrlen, NULL, 0, NULL);
+ return ret;
+unwind:
+ if (hdr)
+ free (hdr);
+ STACK_UNWIND(frame, -1, EINVAL);
+ return 0;
+}
+
+
+/**
+ * client_opendir - opendir function for client protocol
+ * @frame: call frame
+ * @this: this translator structure
+ * @loc: location structure
+ *
+ * external reference through client_protocol_xlator->fops->opendir
+ */
+int32_t
+client_opendir (call_frame_t *frame,
+ xlator_t *this,
+ loc_t *loc,
+ fd_t *fd)
+{
+ gf_fop_opendir_req_t *req = NULL;
+ gf_hdr_common_t *hdr = NULL;
+ size_t hdrlen = 0;
+ int ret = -1;
+ ino_t ino = 0;
+ size_t pathlen = 0;
+ client_conf_t *conf = this->private;
+ client_local_t *local = NULL;
+
+ if (conf->child) {
+ /* */
+ STACK_WIND (frame,
+ default_opendir_cbk,
+ conf->child,
+ conf->child->fops->opendir,
+ loc, fd);
+
+ return 0;
+ }
+
+ local = calloc (1, sizeof (*local));
+ GF_VALIDATE_OR_GOTO(this->name, local, unwind);
+
+ loc_copy (&local->loc, loc);
+ local->fd = fd_ref (fd);
+
+ frame->local = local;
+
+ ino = this_ino_get (loc, this, GF_CLIENT_INODE_SELF);
+ pathlen = STRLEN_0(loc->path);
+
+ hdrlen = gf_hdr_len (req, pathlen);
+ hdr = gf_hdr_new (req, pathlen);
+ GF_VALIDATE_OR_GOTO(frame->this->name, hdr, unwind);
+
+ req = gf_param (hdr);
+
+ req->ino = hton64 (ino);
+ strcpy (req->path, loc->path);
+
+ ret = protocol_client_xfer (frame, this,
+ CLIENT_CHANNEL (this, CHANNEL_LOWLAT),
+ GF_OP_TYPE_FOP_REQUEST, GF_FOP_OPENDIR,
+ hdr, hdrlen, NULL, 0, NULL);
+
+ return ret;
+unwind:
+ if (hdr)
+ free (hdr);
+ STACK_UNWIND(frame, -1, EINVAL, fd);
+ return 0;
+
+}
+
+
+/**
+ * client_readdir - readdir function for client protocol
+ * @frame: call frame
+ * @this: this translator structure
+ *
+ * external reference through client_protocol_xlator->fops->readdir
+ */
+
+int32_t
+client_getdents (call_frame_t *frame,
+ xlator_t *this,
+ fd_t *fd,
+ size_t size,
+ off_t offset,
+ int32_t flag)
+{
+ gf_hdr_common_t *hdr = NULL;
+ gf_fop_getdents_req_t *req = NULL;
+ size_t hdrlen = 0;
+ int64_t remote_fd = -1;
+ int ret = -1;
+ client_conf_t *conf = this->private;
+
+ if (conf->child) {
+ /* */
+ STACK_WIND (frame,
+ default_getdents_cbk,
+ conf->child,
+ conf->child->fops->getdents,
+ fd,
+ size,
+ offset,
+ flag);
+
+ return 0;
+ }
+
+ ret = this_fd_get (fd, this, &remote_fd);
+ if (ret == -1) {
+ gf_log (this->name, GF_LOG_DEBUG,
+ "(%"PRId64"): failed to get remote fd. returning EBADFD",
+ fd->inode->ino);
+ STACK_UNWIND (frame, -1, EBADFD, NULL);
+ return 0;
+ }
+
+ hdrlen = gf_hdr_len (req, 0);
+ hdr = gf_hdr_new (req, 0);
+ GF_VALIDATE_OR_GOTO(frame->this->name, hdr, unwind);
+
+ req = gf_param (hdr);
+ GF_VALIDATE_OR_GOTO(frame->this->name, hdr, unwind);
+
+ req->fd = hton64 (remote_fd);
+ req->size = hton32 (size);
+ req->offset = hton64 (offset);
+ req->flags = hton32 (flag);
+
+ ret = protocol_client_xfer (frame, this,
+ CLIENT_CHANNEL (this, CHANNEL_BULK),
+ GF_OP_TYPE_FOP_REQUEST, GF_FOP_GETDENTS,
+ hdr, hdrlen, NULL, 0, NULL);
+
+ return 0;
+unwind:
+ STACK_UNWIND(frame, -1, EINVAL, NULL, 0);
+ return 0;
+}
+
+/**
+ * client_readdir - readdir function for client protocol
+ * @frame: call frame
+ * @this: this translator structure
+ *
+ * external reference through client_protocol_xlator->fops->readdir
+ */
+
+int32_t
+client_readdir (call_frame_t *frame,
+ xlator_t *this,
+ fd_t *fd,
+ size_t size,
+ off_t offset)
+{
+ gf_hdr_common_t *hdr = NULL;
+ gf_fop_readdir_req_t *req = NULL;
+ size_t hdrlen = 0;
+ int64_t remote_fd = -1;
+ int ret = -1;
+ client_conf_t *conf = this->private;
+
+ if (conf->child) {
+ /* */
+ STACK_WIND (frame,
+ default_readdir_cbk,
+ conf->child,
+ conf->child->fops->readdir,
+ fd, size, offset);
+
+ return 0;
+ }
+
+ ret = this_fd_get (fd, this, &remote_fd);
+ if (ret == -1) {
+ gf_log (this->name, GF_LOG_DEBUG,
+ "(%"PRId64"): failed to get remote fd. returning EBADFD",
+ fd->inode->ino);
+ goto unwind;
+ }
+
+ hdrlen = gf_hdr_len (req, 0);
+ hdr = gf_hdr_new (req, 0);
+ GF_VALIDATE_OR_GOTO(this->name, hdr, unwind);
+
+ req = gf_param (hdr);
+ GF_VALIDATE_OR_GOTO(this->name, hdr, unwind);
+
+ req->fd = hton64 (remote_fd);
+ req->size = hton32 (size);
+ req->offset = hton64 (offset);
+
+ ret = protocol_client_xfer (frame, this,
+ CLIENT_CHANNEL (this, CHANNEL_LOWLAT),
+ GF_OP_TYPE_FOP_REQUEST, GF_FOP_READDIR,
+ hdr, hdrlen, NULL, 0, NULL);
+
+ return 0;
+unwind:
+ if (hdr)
+ free (hdr);
+ STACK_UNWIND (frame, -1, EBADFD, NULL);
+ return 0;
+
+}
+
+
+
+/**
+ * client_fsyncdir - fsyncdir function for client protocol
+ * @frame: call frame
+ * @this: this translator structure
+ * @fd: file descriptor structure
+ * @flags:
+ *
+ * external reference through client_protocol_xlator->fops->fsyncdir
+ */
+
+int32_t
+client_fsyncdir (call_frame_t *frame,
+ xlator_t *this,
+ fd_t *fd,
+ int32_t flags)
+{
+ gf_hdr_common_t *hdr = NULL;
+ gf_fop_fsyncdir_req_t *req = NULL;
+ size_t hdrlen = 0;
+ int64_t remote_fd = -1;
+ int32_t ret = -1;
+ client_conf_t *conf = this->private;
+
+ if (conf->child) {
+ /* */
+ STACK_WIND (frame,
+ default_fsyncdir_cbk,
+ conf->child,
+ conf->child->fops->fsyncdir,
+ fd,
+ flags);
+
+ return 0;
+ }
+
+ ret = this_fd_get (fd, this, &remote_fd);
+ if (ret == -1) {
+ gf_log (this->name, GF_LOG_DEBUG,
+ "(%"PRId64"): failed to get remote fd. returning EBADFD",
+ fd->inode->ino);
+ goto unwind;
+ }
+
+ hdrlen = gf_hdr_len (req, 0);
+ hdr = gf_hdr_new (req, 0);
+ GF_VALIDATE_OR_GOTO(this->name, hdr, unwind);
+
+ req = gf_param (hdr);
+
+ req->data = hton32 (flags);
+ req->fd = hton64 (remote_fd);
+
+ ret = protocol_client_xfer (frame, this,
+ CLIENT_CHANNEL (this, CHANNEL_BULK),
+ GF_OP_TYPE_FOP_REQUEST, GF_FOP_FSYNCDIR,
+ hdr, hdrlen, NULL, 0, NULL);
+
+ return ret;
+unwind:
+ STACK_UNWIND (frame, -1, EBADFD);
+ return 0;
+}
+
+
+/**
+ * client_access - access function for client protocol
+ * @frame: call frame
+ * @this: this translator structure
+ * @loc: location structure
+ * @mode:
+ *
+ * external reference through client_protocol_xlator->fops->access
+ */
+int32_t
+client_access (call_frame_t *frame,
+ xlator_t *this,
+ loc_t *loc,
+ int32_t mask)
+{
+ gf_hdr_common_t *hdr = NULL;
+ gf_fop_access_req_t *req = NULL;
+ size_t hdrlen = -1;
+ int ret = -1;
+ ino_t ino = 0;
+ size_t pathlen = 0;
+ client_conf_t *conf = this->private;
+
+ if (conf->child) {
+ /* */
+ STACK_WIND (frame,
+ default_access_cbk,
+ conf->child,
+ conf->child->fops->access,
+ loc,
+ mask);
+
+ return 0;
+ }
+
+ ino = this_ino_get (loc, this, GF_CLIENT_INODE_SELF);
+ pathlen = STRLEN_0(loc->path);
+
+ hdrlen = gf_hdr_len (req, pathlen);
+ hdr = gf_hdr_new (req, pathlen);
+ GF_VALIDATE_OR_GOTO(this->name, hdr, unwind);
+
+ req = gf_param (hdr);
+
+ req->ino = hton64 (ino);
+ req->mask = hton32 (mask);
+ strcpy (req->path, loc->path);
+
+ ret = protocol_client_xfer (frame, this,
+ CLIENT_CHANNEL (this, CHANNEL_LOWLAT),
+ GF_OP_TYPE_FOP_REQUEST, GF_FOP_ACCESS,
+ hdr, hdrlen, NULL, 0, NULL);
+
+ return ret;
+unwind:
+ if (hdr)
+ free (hdr);
+
+ STACK_UNWIND(frame, -1, EINVAL);
+ return 0;
+
+}
+
+
+/**
+ * client_ftrucate - ftruncate function for client protocol
+ * @frame: call frame
+ * @this: this translator structure
+ * @fd: file descriptor structure
+ * @offset: offset to truncate to
+ *
+ * external reference through client_protocol_xlator->fops->ftruncate
+ */
+
+int32_t
+client_ftruncate (call_frame_t *frame,
+ xlator_t *this,
+ fd_t *fd,
+ off_t offset)
+{
+ gf_hdr_common_t *hdr = NULL;
+ gf_fop_ftruncate_req_t *req = NULL;
+ int64_t remote_fd = -1;
+ size_t hdrlen = -1;
+ int ret = -1;
+ client_conf_t *conf = this->private;
+
+ if (conf->child) {
+ /* */
+ STACK_WIND (frame,
+ default_ftruncate_cbk,
+ conf->child,
+ conf->child->fops->ftruncate,
+ fd,
+ offset);
+
+ return 0;
+ }
+
+ ret = this_fd_get (fd, this, &remote_fd);
+ if (ret == -1) {
+ gf_log (this->name, GF_LOG_DEBUG,
+ "(%"PRId64"): failed to get remote fd. returning EBADFD",
+ fd->inode->ino);
+ STACK_UNWIND (frame, -1, EBADFD, NULL);
+ return 0;
+ }
+
+ hdrlen = gf_hdr_len (req, 0);
+ hdr = gf_hdr_new (req, 0);
+ GF_VALIDATE_OR_GOTO(this->name, hdr, unwind);
+
+ req = gf_param (hdr);
+
+ req->fd = hton64 (remote_fd);
+ req->offset = hton64 (offset);
+
+ ret = protocol_client_xfer (frame, this,
+ CLIENT_CHANNEL (this, CHANNEL_BULK),
+ GF_OP_TYPE_FOP_REQUEST, GF_FOP_FTRUNCATE,
+ hdr, hdrlen, NULL, 0, NULL);
+
+ return ret;
+unwind:
+ if (hdr)
+ free (hdr);
+
+ STACK_UNWIND(frame, -1, EINVAL, NULL);
+ return 0;
+
+}
+
+
+/**
+ * client_fstat - fstat function for client protocol
+ * @frame: call frame
+ * @this: this translator structure
+ * @fd: file descriptor structure
+ *
+ * external reference through client_protocol_xlator->fops->fstat
+ */
+
+int32_t
+client_fstat (call_frame_t *frame,
+ xlator_t *this,
+ fd_t *fd)
+{
+ gf_hdr_common_t *hdr = NULL;
+ gf_fop_fstat_req_t *req = NULL;
+ int64_t remote_fd = -1;
+ size_t hdrlen = -1;
+ int ret = -1;
+ client_conf_t *conf = this->private;
+
+ if (conf->child) {
+ /* */
+ STACK_WIND (frame,
+ default_fstat_cbk,
+ conf->child,
+ conf->child->fops->fstat,
+ fd);
+
+ return 0;
+ }
+
+ ret = this_fd_get (fd, this, &remote_fd);
+ if (ret == -1) {
+ gf_log (this->name, GF_LOG_DEBUG,
+ "(%"PRId64"): failed to get remote fd. returning EBADFD",
+ fd->inode->ino);
+ STACK_UNWIND (frame, -1, EBADFD, NULL);
+ return 0;
+ }
+
+ hdrlen = gf_hdr_len (req, 0);
+ hdr = gf_hdr_new (req, 0);
+ GF_VALIDATE_OR_GOTO(this->name, hdr, unwind);
+
+ req = gf_param (hdr);
+
+ req->fd = hton64 (remote_fd);
+
+ ret = protocol_client_xfer (frame, this,
+ CLIENT_CHANNEL (this, CHANNEL_BULK),
+ GF_OP_TYPE_FOP_REQUEST, GF_FOP_FSTAT,
+ hdr, hdrlen, NULL, 0, NULL);
+
+ return ret;
+unwind:
+ if (hdr)
+ free (hdr);
+
+ STACK_UNWIND(frame, -1, EINVAL, NULL);
+ return 0;
+
+}
+
+
+/**
+ * client_lk - lk function for client protocol
+ * @frame: call frame
+ * @this: this translator structure
+ * @fd: file descriptor structure
+ * @cmd: lock command
+ * @lock:
+ *
+ * external reference through client_protocol_xlator->fops->lk
+ */
+int32_t
+client_lk (call_frame_t *frame,
+ xlator_t *this,
+ fd_t *fd,
+ int32_t cmd,
+ struct flock *flock)
+{
+ int ret = -1;
+ gf_hdr_common_t *hdr = NULL;
+ gf_fop_lk_req_t *req = NULL;
+ size_t hdrlen = 0;
+ int64_t remote_fd = -1;
+ int32_t gf_cmd = 0;
+ int32_t gf_type = 0;
+ client_conf_t *conf = this->private;
+
+ if (conf->child) {
+ /* */
+ STACK_WIND (frame,
+ default_lk_cbk,
+ conf->child,
+ conf->child->fops->lk,
+ fd,
+ cmd,
+ flock);
+
+ return 0;
+ }
+
+ ret = this_fd_get (fd, this, &remote_fd);
+ if (ret == -1) {
+ gf_log (this->name, GF_LOG_DEBUG,
+ "(%"PRId64"): failed to get remote fd. returning EBADFD",
+ fd->inode->ino);
+ STACK_UNWIND(frame, -1, EBADFD, NULL);
+ return 0;
+ }
+
+ if (cmd == F_GETLK || cmd == F_GETLK64)
+ gf_cmd = GF_LK_GETLK;
+ else if (cmd == F_SETLK || cmd == F_SETLK64)
+ gf_cmd = GF_LK_SETLK;
+ else if (cmd == F_SETLKW || cmd == F_SETLKW64)
+ gf_cmd = GF_LK_SETLKW;
+ else {
+ gf_log (this->name, GF_LOG_ERROR,
+ "Unknown cmd (%d)!", gf_cmd);
+ goto unwind;
+ }
+
+ switch (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;
+ }
+
+ hdrlen = gf_hdr_len (req, 0);
+ hdr = gf_hdr_new (req, 0);
+ GF_VALIDATE_OR_GOTO(this->name, hdr, unwind);
+
+ req = gf_param (hdr);
+
+ req->fd = hton64 (remote_fd);
+ req->cmd = hton32 (gf_cmd);
+ req->type = hton32 (gf_type);
+ gf_flock_from_flock (&req->flock, flock);
+
+ ret = protocol_client_xfer (frame, this,
+ CLIENT_CHANNEL (this, CHANNEL_BULK),
+ GF_OP_TYPE_FOP_REQUEST, GF_FOP_LK,
+ hdr, hdrlen, NULL, 0, NULL);
+ return ret;
+unwind:
+ if (hdr)
+ free (hdr);
+
+ STACK_UNWIND(frame, -1, EINVAL, NULL);
+ return 0;
+}
+
+
+/**
+ * client_inodelk - inodelk function for client protocol
+ * @frame: call frame
+ * @this: this translator structure
+ * @inode: inode structure
+ * @cmd: lock command
+ * @lock: flock struct
+ *
+ * external reference through client_protocol_xlator->fops->inodelk
+ */
+int32_t
+client_inodelk (call_frame_t *frame,
+ xlator_t *this,
+ loc_t *loc,
+ int32_t cmd,
+ struct flock *flock)
+{
+ int ret = -1;
+ gf_hdr_common_t *hdr = NULL;
+ gf_fop_inodelk_req_t *req = NULL;
+ size_t hdrlen = 0;
+ int32_t gf_cmd = 0;
+ int32_t gf_type = 0;
+ ino_t ino = 0;
+ size_t pathlen = 0;
+ client_conf_t *conf = this->private;
+
+ if (conf->child) {
+ /* */
+ STACK_WIND (frame,
+ default_inodelk_cbk,
+ conf->child,
+ conf->child->fops->inodelk,
+ loc, cmd, flock);
+
+ return 0;
+ }
+
+ pathlen = STRLEN_0(loc->path);
+ ino = this_ino_get (loc, this, GF_CLIENT_INODE_SELF);
+
+ if (cmd == F_GETLK || cmd == F_GETLK64)
+ gf_cmd = GF_LK_GETLK;
+ else if (cmd == F_SETLK || cmd == F_SETLK64)
+ gf_cmd = GF_LK_SETLK;
+ else if (cmd == F_SETLKW || cmd == F_SETLKW64)
+ gf_cmd = GF_LK_SETLKW;
+ else {
+ gf_log (this->name, GF_LOG_ERROR,
+ "Unknown cmd (%d)!", gf_cmd);
+ goto unwind;
+ }
+
+ switch (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;
+ }
+
+ hdrlen = gf_hdr_len (req, pathlen);
+ hdr = gf_hdr_new (req, pathlen);
+ GF_VALIDATE_OR_GOTO(this->name, hdr, unwind);
+
+ req = gf_param (hdr);
+
+ strcpy (req->path, loc->path);
+
+ req->ino = hton64 (ino);
+
+ req->cmd = hton32 (gf_cmd);
+ req->type = hton32 (gf_type);
+ gf_flock_from_flock (&req->flock, flock);
+
+
+ ret = protocol_client_xfer (frame, this,
+ CLIENT_CHANNEL (this, CHANNEL_BULK),
+ GF_OP_TYPE_FOP_REQUEST,
+ GF_FOP_INODELK,
+ hdr, hdrlen, NULL, 0, NULL);
+ return ret;
+unwind:
+ if (hdr)
+ free (hdr);
+
+ STACK_UNWIND(frame, -1, EINVAL);
+ return 0;
+
+}
+
+
+/**
+ * client_finodelk - finodelk function for client protocol
+ * @frame: call frame
+ * @this: this translator structure
+ * @inode: inode structure
+ * @cmd: lock command
+ * @lock: flock struct
+ *
+ * external reference through client_protocol_xlator->fops->finodelk
+ */
+int32_t
+client_finodelk (call_frame_t *frame,
+ xlator_t *this,
+ fd_t *fd,
+ int32_t cmd,
+ struct flock *flock)
+{
+ int ret = -1;
+ gf_hdr_common_t *hdr = NULL;
+ gf_fop_finodelk_req_t *req = NULL;
+ size_t hdrlen = 0;
+ int32_t gf_cmd = 0;
+ int32_t gf_type = 0;
+ int64_t remote_fd = -1;
+ client_conf_t *conf = this->private;
+
+ if (conf->child) {
+ /* */
+ STACK_WIND (frame,
+ default_finodelk_cbk,
+ conf->child,
+ conf->child->fops->finodelk,
+ fd, cmd, flock);
+
+ return 0;
+ }
+
+ ret = this_fd_get (fd, this, &remote_fd);
+ if (ret == -1) {
+ gf_log (this->name, GF_LOG_DEBUG,
+ "(%"PRId64"): failed to get remote fd. returning EBADFD",
+ fd->inode->ino);
+ STACK_UNWIND(frame, -1, EBADFD);
+ return 0;
+ }
+
+ if (cmd == F_GETLK || cmd == F_GETLK64)
+ gf_cmd = GF_LK_GETLK;
+ else if (cmd == F_SETLK || cmd == F_SETLK64)
+ gf_cmd = GF_LK_SETLK;
+ else if (cmd == F_SETLKW || cmd == F_SETLKW64)
+ gf_cmd = GF_LK_SETLKW;
+ else {
+ gf_log (this->name, GF_LOG_ERROR,
+ "Unknown cmd (%d)!", gf_cmd);
+ goto unwind;
+ }
+
+ switch (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;
+ }
+
+ hdrlen = gf_hdr_len (req, 0);
+ hdr = gf_hdr_new (req, 0);
+ GF_VALIDATE_OR_GOTO(this->name, hdr, unwind);
+
+ req = gf_param (hdr);
+
+ req->fd = hton64 (remote_fd);
+
+ req->cmd = hton32 (gf_cmd);
+ req->type = hton32 (gf_type);
+ gf_flock_from_flock (&req->flock, flock);
+
+ ret = protocol_client_xfer (frame, this,
+ CLIENT_CHANNEL (this, CHANNEL_BULK),
+ GF_OP_TYPE_FOP_REQUEST,
+ GF_FOP_FINODELK,
+ hdr, hdrlen, NULL, 0, NULL);
+ return ret;
+unwind:
+ if (hdr)
+ free (hdr);
+
+ STACK_UNWIND(frame, -1, EINVAL);
+ return 0;
+}
+
+
+int32_t
+client_entrylk (call_frame_t *frame,
+ xlator_t *this,
+ loc_t *loc,
+ const char *name,
+ entrylk_cmd cmd,
+ entrylk_type type)
+{
+ gf_hdr_common_t *hdr = NULL;
+ gf_fop_entrylk_req_t *req = NULL;
+ size_t pathlen = 0;
+ size_t hdrlen = -1;
+ int ret = -1;
+ ino_t ino = 0;
+ size_t namelen = 0;
+ client_conf_t *conf = this->private;
+
+ if (conf->child) {
+ /* */
+ STACK_WIND (frame, default_entrylk_cbk,
+ conf->child,
+ conf->child->fops->entrylk,
+ loc, name, cmd, type);
+
+ return 0;
+ }
+
+ pathlen = STRLEN_0(loc->path);
+ if (name)
+ namelen = STRLEN_0(name);
+
+ ino = this_ino_get (loc, this, GF_CLIENT_INODE_SELF);
+
+ hdrlen = gf_hdr_len (req, pathlen + namelen);
+ hdr = gf_hdr_new (req, pathlen + namelen);
+ GF_VALIDATE_OR_GOTO(this->name, hdr, unwind);
+
+ req = gf_param (hdr);
+
+ req->ino = hton64 (ino);
+ req->namelen = hton64 (namelen);
+
+ strcpy (req->path, loc->path);
+ if (name)
+ strcpy (req->name + pathlen, name);
+
+ req->cmd = hton32 (cmd);
+ req->type = hton32 (type);
+
+ ret = protocol_client_xfer (frame, this,
+ CLIENT_CHANNEL (this, CHANNEL_LOWLAT),
+ GF_OP_TYPE_FOP_REQUEST, GF_FOP_ENTRYLK,
+ hdr, hdrlen, NULL, 0, NULL);
+
+ return ret;
+unwind:
+ if (hdr)
+ free (hdr);
+
+ STACK_UNWIND(frame, -1, EINVAL);
+ return 0;
+
+}
+
+
+int32_t
+client_fentrylk (call_frame_t *frame,
+ xlator_t *this,
+ fd_t *fd,
+ const char *name,
+ entrylk_cmd cmd,
+ entrylk_type type)
+{
+ gf_hdr_common_t *hdr = NULL;
+ gf_fop_fentrylk_req_t *req = NULL;
+ int64_t remote_fd = -1;
+ size_t namelen = 0;
+ size_t hdrlen = -1;
+ int ret = -1;
+ client_conf_t *conf = this->private;
+
+ if (conf->child) {
+ /* */
+ STACK_WIND (frame, default_fentrylk_cbk,
+ conf->child,
+ conf->child->fops->fentrylk,
+ fd, name, cmd, type);
+
+ return 0;
+ }
+
+ if (name)
+ namelen = STRLEN_0(name);
+
+ ret = this_fd_get (fd, this, &remote_fd);
+ if (ret == -1) {
+ gf_log (this->name, GF_LOG_DEBUG,
+ "(%"PRId64"): failed to get remote fd. returning EBADFD",
+ fd->inode->ino);
+ STACK_UNWIND(frame, -1, EBADFD);
+ return 0;
+ }
+
+ hdrlen = gf_hdr_len (req, namelen);
+ hdr = gf_hdr_new (req, namelen);
+ GF_VALIDATE_OR_GOTO(this->name, hdr, unwind);
+
+ req = gf_param (hdr);
+
+ req->fd = hton64 (remote_fd);
+ req->namelen = hton64 (namelen);
+
+ if (name)
+ strcpy (req->name, name);
+
+ req->cmd = hton32 (cmd);
+ req->type = hton32 (type);
+
+ ret = protocol_client_xfer (frame, this,
+ CLIENT_CHANNEL (this, CHANNEL_LOWLAT),
+ GF_OP_TYPE_FOP_REQUEST, GF_FOP_FENTRYLK,
+ hdr, hdrlen, NULL, 0, NULL);
+
+ return ret;
+unwind:
+ if (hdr)
+ free (hdr);
+
+ STACK_UNWIND(frame, -1, EINVAL);
+ return 0;
+}
+
+
+/*
+ * client_lookup - lookup function for client protocol
+ * @frame: call frame
+ * @this:
+ * @loc: location
+ *
+ * not for external reference
+ */
+int32_t
+client_lookup (call_frame_t *frame,
+ xlator_t *this,
+ loc_t *loc,
+ dict_t *xattr_req)
+{
+ gf_hdr_common_t *hdr = NULL;
+ gf_fop_lookup_req_t *req = NULL;
+ size_t hdrlen = -1;
+ int ret = -1;
+ ino_t ino = 0;
+ ino_t par = 0;
+ size_t dictlen = 0;
+ size_t pathlen = 0;
+ size_t baselen = 0;
+ int32_t op_ret = -1;
+ int32_t op_errno = EINVAL;
+ client_conf_t *conf = this->private;
+ client_local_t *local = NULL;
+
+ if (conf->child) {
+ /* */
+ STACK_WIND (frame,
+ default_lookup_cbk,
+ conf->child,
+ conf->child->fops->lookup,
+ loc,
+ xattr_req);
+
+ return 0;
+ }
+
+ local = calloc (1, sizeof (*local));
+ GF_VALIDATE_OR_GOTO(this->name, local, unwind);
+
+ loc_copy (&local->loc, loc);
+
+ frame->local = local;
+
+ GF_VALIDATE_OR_GOTO (this->name, loc, unwind);
+ GF_VALIDATE_OR_GOTO (this->name, loc->path, unwind);
+
+ if (loc->ino != 1) {
+ par = this_ino_get (loc, this, GF_CLIENT_INODE_PARENT);
+ GF_VALIDATE_OR_GOTO (this->name, loc->name, unwind);
+ baselen = STRLEN_0(loc->name);
+ } else {
+ ino = 1;
+ }
+
+ pathlen = STRLEN_0(loc->path);
+
+ if (xattr_req) {
+ dictlen = dict_serialized_length (xattr_req);
+ if (dictlen < 0) {
+ gf_log (this->name, GF_LOG_ERROR,
+ "failed to get serialized length of dict(%p)",
+ xattr_req);
+ ret = dictlen;
+ goto unwind;
+ }
+ }
+
+ hdrlen = gf_hdr_len (req, pathlen + baselen + dictlen);
+ hdr = gf_hdr_new (req, pathlen + baselen + dictlen);
+ GF_VALIDATE_OR_GOTO (this->name, hdr, unwind);
+
+ req = gf_param (hdr);
+
+ req->ino = hton64 (ino);
+ req->par = hton64 (par);
+ strcpy (req->path, loc->path);
+ if (baselen)
+ strcpy (req->path + pathlen, loc->name);
+
+ if (dictlen) {
+ ret = dict_serialize (xattr_req, req->dict + baselen + pathlen);
+ if (ret < 0) {
+ gf_log (this->name, GF_LOG_ERROR,
+ "failed to serialize dictionary(%p)",
+ xattr_req);
+ goto unwind;
+ }
+ }
+
+ req->dictlen = hton32 (dictlen);
+
+ ret = protocol_client_xfer (frame, this,
+ CLIENT_CHANNEL (this, CHANNEL_LOWLAT),
+ GF_OP_TYPE_FOP_REQUEST, GF_FOP_LOOKUP,
+ hdr, hdrlen, NULL, 0, NULL);
+ return ret;
+
+unwind:
+ STACK_UNWIND (frame, op_ret, op_errno, loc->inode, NULL, NULL);
+ return ret;
+}
+
+
+
+/*
+ * client_fchmod
+ *
+ */
+int32_t
+client_fchmod (call_frame_t *frame,
+ xlator_t *this,
+ fd_t *fd,
+ mode_t mode)
+{
+ gf_hdr_common_t *hdr = NULL;
+ gf_fop_fchmod_req_t *req = NULL;
+ int64_t remote_fd = -1;
+ size_t hdrlen = -1;
+ int ret = -1;
+ int32_t op_errno = EINVAL;
+ int32_t op_ret = -1;
+ client_conf_t *conf = this->private;
+
+ if (conf->child) {
+ /* */
+ STACK_WIND (frame,
+ default_fchmod_cbk,
+ conf->child,
+ conf->child->fops->fchmod,
+ fd,
+ mode);
+
+ return 0;
+ }
+
+ GF_VALIDATE_OR_GOTO (this->name, fd, unwind);
+
+ ret = this_fd_get (fd, this, &remote_fd);
+ if (ret == -1) {
+ op_errno = EBADFD;
+ gf_log (this->name, GF_LOG_DEBUG,
+ "(%"PRId64"): failed to get remote fd. returning EBADFD",
+ fd->inode->ino);
+ goto unwind;
+ }
+
+ hdrlen = gf_hdr_len (req, 0);
+ hdr = gf_hdr_new (req, 0);
+ GF_VALIDATE_OR_GOTO (this->name, hdr, unwind);
+
+ req = gf_param (hdr);
+
+ req->fd = hton64 (remote_fd);
+ req->mode = hton32 (mode);
+
+ ret = protocol_client_xfer (frame, this,
+ CLIENT_CHANNEL (this, CHANNEL_LOWLAT),
+ GF_OP_TYPE_FOP_REQUEST, GF_FOP_FCHMOD,
+ hdr, hdrlen, NULL, 0, NULL);
+
+ return 0;
+
+unwind:
+ STACK_UNWIND (frame, op_ret, op_errno, NULL);
+ return 0;
+}
+
+
+/*
+ * client_fchown -
+ *
+ * @frame:
+ * @this:
+ * @fd:
+ * @uid:
+ * @gid:
+ *
+ */
+int32_t
+client_fchown (call_frame_t *frame,
+ xlator_t *this,
+ fd_t *fd,
+ uid_t uid,
+ gid_t gid)
+{
+ gf_hdr_common_t *hdr = NULL;
+ gf_fop_fchown_req_t *req = NULL;
+ int64_t remote_fd = 0;
+ size_t hdrlen = -1;
+ int32_t op_ret = -1;
+ int32_t op_errno = EINVAL;
+ int32_t ret = -1;
+ client_conf_t *conf = this->private;
+
+ if (conf->child) {
+ /* */
+ STACK_WIND (frame,
+ default_fchown_cbk,
+ conf->child,
+ conf->child->fops->fchown,
+ fd,
+ uid,
+ gid);
+
+ return 0;
+ }
+
+ GF_VALIDATE_OR_GOTO (this->name, fd, unwind);
+
+ ret = this_fd_get (fd, this, &remote_fd);
+ if (ret == -1) {
+ op_errno = EBADFD;
+ gf_log (this->name, GF_LOG_DEBUG,
+ "(%"PRId64"): failed to get remote fd. returning EBADFD",
+ fd->inode->ino);
+ goto unwind;
+ }
+
+ hdrlen = gf_hdr_len (req, 0);
+ hdr = gf_hdr_new (req, 0);
+ GF_VALIDATE_OR_GOTO (this->name, hdr, unwind);
+
+ req = gf_param (hdr);
+
+ req->fd = hton64 (remote_fd);
+ req->uid = hton32 (uid);
+ req->gid = hton32 (gid);
+
+ ret = protocol_client_xfer (frame, this,
+ CLIENT_CHANNEL (this, CHANNEL_LOWLAT),
+ GF_OP_TYPE_FOP_REQUEST, GF_FOP_FCHOWN,
+ hdr, hdrlen, NULL, 0, NULL);
+
+ return 0;
+
+unwind:
+ STACK_UNWIND (frame, op_ret, op_errno, NULL);
+ return 0;
+
+}
+
+/**
+ * client_setdents -
+ */
+int32_t
+client_setdents (call_frame_t *frame,
+ xlator_t *this,
+ fd_t *fd,
+ int32_t flags,
+ dir_entry_t *entries,
+ int32_t count)
+{
+ gf_hdr_common_t *hdr = NULL;
+ gf_fop_setdents_req_t *req = NULL;
+ int64_t remote_fd = 0;
+ char *buffer = NULL;
+ char *ptr = NULL;
+ data_t *buf_data = NULL;
+ dict_t *reply_dict = NULL;
+ dir_entry_t *trav = NULL;
+ uint32_t len = 0;
+ int32_t buf_len = 0;
+ int32_t ret = -1;
+ int32_t op_ret = -1;
+ int32_t op_errno = EINVAL;
+ int32_t vec_count = 0;
+ size_t hdrlen = -1;
+ struct iovec vector[1];
+ client_conf_t *conf = this->private;
+
+ if (conf->child) {
+ /* */
+ STACK_WIND (frame,
+ default_setdents_cbk,
+ conf->child,
+ conf->child->fops->setdents,
+ fd,
+ flags,
+ entries,
+ count);
+
+ return 0;
+ }
+
+ GF_VALIDATE_OR_GOTO (this->name, fd, unwind);
+
+ ret = this_fd_get (fd, this, &remote_fd);
+ if (ret == -1) {
+ gf_log (this->name, GF_LOG_DEBUG,
+ "(%"PRId64"): failed to get remote fd. returning EBADFD",
+ fd->inode->ino);
+ op_errno = EBADFD;
+ goto unwind;
+ }
+
+ GF_VALIDATE_OR_GOTO (this->name, entries, unwind);
+ GF_VALIDATE_OR_GOTO (this->name, count, unwind);
+
+ trav = entries->next;
+ while (trav) {
+ len += strlen (trav->name);
+ len += 1;
+ len += strlen (trav->link);
+ len += 1;
+ len += 256; // max possible for statbuf;
+ trav = trav->next;
+ }
+ buffer = CALLOC (1, len);
+ GF_VALIDATE_OR_GOTO (this->name, buffer, unwind);
+
+ ptr = buffer;
+
+ trav = entries->next;
+ while (trav) {
+ int32_t this_len = 0;
+ char *tmp_buf = NULL;
+ struct stat *stbuf = &trav->buf;
+ {
+ /* Convert the stat buf to string */
+ uint64_t dev = stbuf->st_dev;
+ uint64_t ino = stbuf->st_ino;
+ uint32_t mode = stbuf->st_mode;
+ uint32_t nlink = stbuf->st_nlink;
+ uint32_t uid = stbuf->st_uid;
+ uint32_t gid = stbuf->st_gid;
+ uint64_t rdev = stbuf->st_rdev;
+ uint64_t size = stbuf->st_size;
+ uint32_t blksize = stbuf->st_blksize;
+ uint64_t blocks = stbuf->st_blocks;
+
+ uint32_t atime = stbuf->st_atime;
+ uint32_t mtime = stbuf->st_mtime;
+ uint32_t ctime = stbuf->st_ctime;
+
+ uint32_t atime_nsec = ST_ATIM_NSEC(stbuf);
+ uint32_t mtime_nsec = ST_MTIM_NSEC(stbuf);
+ uint32_t ctime_nsec = ST_CTIM_NSEC(stbuf);
+
+ asprintf (&tmp_buf,
+ GF_STAT_PRINT_FMT_STR,
+ dev,
+ ino,
+ mode,
+ nlink,
+ uid,
+ gid,
+ rdev,
+ size,
+ blksize,
+ blocks,
+ atime,
+ atime_nsec,
+ mtime,
+ mtime_nsec,
+ ctime,
+ ctime_nsec);
+ }
+ this_len = sprintf (ptr, "%s/%s%s\n",
+ trav->name,
+ tmp_buf,
+ trav->link);
+
+ FREE (tmp_buf);
+ trav = trav->next;
+ ptr += this_len;
+ }
+ buf_len = strlen (buffer);
+
+ hdrlen = gf_hdr_len (req, 0);
+ hdr = gf_hdr_new (req, 0);
+ GF_VALIDATE_OR_GOTO (this->name, hdr, unwind);
+
+ req = gf_param (hdr);
+
+ req->fd = hton64 (remote_fd);
+ req->flags = hton32 (flags);
+ req->count = hton32 (count);
+
+ {
+ buf_data = get_new_data ();
+ GF_VALIDATE_OR_GOTO (this->name, buf_data, unwind);
+ reply_dict = get_new_dict();
+ GF_VALIDATE_OR_GOTO (this->name, reply_dict, unwind);
+
+ buf_data->data = buffer;
+ buf_data->len = buf_len;
+ dict_set (reply_dict, NULL, buf_data);
+ frame->root->rsp_refs = dict_ref (reply_dict);
+ vector[0].iov_base = buffer;
+ vector[0].iov_len = buf_len;
+ vec_count = 1;
+ }
+
+ ret = protocol_client_xfer (frame, this,
+ CLIENT_CHANNEL (this, CHANNEL_BULK),
+ GF_OP_TYPE_FOP_REQUEST, GF_FOP_SETDENTS,
+ hdr, hdrlen, vector, vec_count,
+ frame->root->rsp_refs);
+
+ return ret;
+unwind:
+ STACK_UNWIND (frame, op_ret, op_errno);
+ return 0;
+}
+
+
+/*
+ * CBKs
+ */
+/*
+ * client_forget - forget function for client protocol
+ * @this:
+ * @inode:
+ *
+ * not for external reference
+ */
+int32_t
+client_forget (xlator_t *this,
+ inode_t *inode)
+{
+ ino_t ino = 0;
+ client_conf_t *conf = NULL;
+ client_forget_t forget = {0,};
+ uint8_t send_forget = 0;
+ int32_t ret = -1;
+
+ GF_VALIDATE_OR_GOTO ("client", this, out);
+ conf = this->private;
+
+ if (conf->child) {
+ /* */
+ /* Yenu beda */
+ return 0;
+ }
+
+ GF_VALIDATE_OR_GOTO (this->name, inode, out);
+ ino = this_ino_get_from_inode (inode, this);
+
+ LOCK (&conf->forget.lock);
+ {
+ conf->forget.ino_array[conf->forget.count++] = ino;
+
+ if ((!conf->forget.frames_in_transit) ||
+ (conf->forget.count >= CLIENT_PROTO_FORGET_LIMIT)) {
+ ret = client_get_forgets (this, &forget);
+ if (ret <= 0)
+ send_forget = 0;
+ else
+ send_forget = 1;
+ }
+ }
+ UNLOCK (&conf->forget.lock);
+
+ if (send_forget) {
+ ret = protocol_client_xfer (forget.frame, this,
+ CLIENT_CHANNEL (this,CHANNEL_BULK),
+ GF_OP_TYPE_CBK_REQUEST,
+ GF_CBK_FORGET,
+ forget.hdr, forget.hdrlen,
+ NULL, 0, NULL);
+ }
+out:
+ return 0;
+}
+
+/**
+ * client_releasedir - releasedir function for client protocol
+ * @this: this translator structure
+ * @fd: file descriptor structure
+ *
+ * external reference through client_protocol_xlator->cbks->releasedir
+ */
+
+int32_t
+client_releasedir (xlator_t *this, fd_t *fd)
+{
+ call_frame_t *fr = NULL;
+ int32_t ret = -1;
+ int64_t remote_fd = 0;
+ char key[32] = {0,};
+ gf_hdr_common_t *hdr = NULL;
+ size_t hdrlen = 0;
+ gf_cbk_releasedir_req_t *req = NULL;
+ client_conf_t *conf = NULL;
+
+
+ GF_VALIDATE_OR_GOTO ("client", this, out);
+ GF_VALIDATE_OR_GOTO (this->name, fd, out);
+
+ conf = this->private;
+ if (conf->child) {
+ return 0;
+ }
+
+ ret = this_fd_get (fd, this, &remote_fd);
+ if (ret == -1){
+ gf_log (this->name, GF_LOG_DEBUG,
+ "(%"PRId64"): failed to get remote fd.",
+ fd->inode->ino);
+ goto out;
+ }
+
+ hdrlen = gf_hdr_len (req, 0);
+ hdr = gf_hdr_new (req, 0);
+ GF_VALIDATE_OR_GOTO (this->name, hdr, out);
+
+ req = gf_param (hdr);
+
+ req->fd = hton64 (remote_fd);
+
+ {
+ sprintf (key, "%p", fd);
+
+ pthread_mutex_lock (&conf->mutex);
+ {
+ dict_del (conf->saved_fds, key);
+ }
+ pthread_mutex_unlock (&conf->mutex);
+ }
+
+ fr = create_frame (this, this->ctx->pool);
+ GF_VALIDATE_OR_GOTO (this->name, fr, out);
+
+ ret = protocol_client_xfer (fr, this,
+ CLIENT_CHANNEL (this, CHANNEL_BULK),
+ GF_OP_TYPE_CBK_REQUEST, GF_CBK_RELEASEDIR,
+ hdr, hdrlen, NULL, 0, NULL);
+out:
+ return ret;
+}
+
+
+/**
+ * client_release - release function for client protocol
+ * @this: this translator structure
+ * @fd: file descriptor structure
+ *
+ * external reference through client_protocol_xlator->cbks->release
+ *
+ */
+int
+client_release (xlator_t *this, fd_t *fd)
+{
+ call_frame_t *fr = NULL;
+ int32_t ret = -1;
+ int64_t remote_fd = 0;
+ char key[32] = {0,};
+ gf_hdr_common_t *hdr = NULL;
+ size_t hdrlen = 0;
+ gf_cbk_release_req_t *req = NULL;
+ client_conf_t *conf = NULL;
+
+ GF_VALIDATE_OR_GOTO ("client", this, out);
+ GF_VALIDATE_OR_GOTO (this->name, fd, out);
+
+ conf = this->private;
+
+ if (conf->child) {
+ return 0;
+ }
+
+ ret = this_fd_get (fd, this, &remote_fd);
+ if (ret == -1) {
+ gf_log (this->name, GF_LOG_DEBUG,
+ "(%"PRId64"): failed to get remote fd.",
+ fd->inode->ino);
+ goto out;
+ }
+
+ hdrlen = gf_hdr_len (req, 0);
+ hdr = gf_hdr_new (req, 0);
+ GF_VALIDATE_OR_GOTO (this->name, hdr, out);
+ req = gf_param (hdr);
+
+ req->fd = hton64 (remote_fd);
+
+ {
+ sprintf (key, "%p", fd);
+
+ pthread_mutex_lock (&conf->mutex);
+ {
+ dict_del (conf->saved_fds, key);
+ }
+ pthread_mutex_unlock (&conf->mutex);
+ }
+
+ fr = create_frame (this, this->ctx->pool);
+ GF_VALIDATE_OR_GOTO (this->name, fr, out);
+
+ ret = protocol_client_xfer (fr, this,
+ CLIENT_CHANNEL (this, CHANNEL_BULK),
+ GF_OP_TYPE_CBK_REQUEST, GF_CBK_RELEASE,
+ hdr, hdrlen, NULL, 0, NULL);
+out:
+ return ret;
+}
+
+/*
+ * MGMT_OPS
+ */
+
+/**
+ * client_stats - stats function for client protocol
+ * @frame: call frame
+ * @this: this translator structure
+ * @flags:
+ *
+ * external reference through client_protocol_xlator->mops->stats
+ */
+
+int32_t
+client_stats (call_frame_t *frame,
+ xlator_t *this,
+ int32_t flags)
+{
+ gf_hdr_common_t *hdr = NULL;
+ gf_mop_stats_req_t *req = NULL;
+ size_t hdrlen = -1;
+ int ret = -1;
+ client_conf_t *conf = NULL;
+
+ GF_VALIDATE_OR_GOTO ("client", this, unwind);
+
+ conf = this->private;
+ if (conf->child) {
+ /* */
+ STACK_WIND (frame,
+ default_stats_cbk,
+ conf->child,
+ conf->child->mops->stats,
+ flags);
+
+ return 0;
+ }
+
+
+ hdrlen = gf_hdr_len (req, 0);
+ hdr = gf_hdr_new (req, 0);
+ GF_VALIDATE_OR_GOTO (this->name, hdr, unwind);
+
+ req = gf_param (hdr);
+
+ req->flags = hton32 (flags);
+
+ ret = protocol_client_xfer (frame, this,
+ CLIENT_CHANNEL (this, CHANNEL_BULK),
+ GF_OP_TYPE_MOP_REQUEST, GF_MOP_STATS,
+ hdr, hdrlen, NULL, 0, NULL);
+
+ return ret;
+unwind:
+ STACK_UNWIND (frame, -1, EINVAL, NULL);
+ return 0;
+}
+
+
+/* Callbacks */
+
+int32_t
+client_fxattrop_cbk (call_frame_t *frame,
+ gf_hdr_common_t *hdr, size_t hdrlen,
+ char *buf, size_t buflen)
+{
+ gf_fop_xattrop_rsp_t *rsp = NULL;
+ int32_t op_ret = 0;
+ int32_t gf_errno = 0;
+ int32_t op_errno = 0;
+ int32_t dict_len = 0;
+ dict_t *dict = NULL;
+ int32_t ret = -1;
+ char *dictbuf = NULL;
+
+ rsp = gf_param (hdr);
+ GF_VALIDATE_OR_GOTO(frame->this->name, rsp, fail);
+
+ op_ret = ntoh32 (hdr->rsp.op_ret);
+
+ if (op_ret >= 0) {
+ op_ret = -1;
+ dict_len = ntoh32 (rsp->dict_len);
+
+ if (dict_len > 0) {
+ dictbuf = memdup (rsp->dict, dict_len);
+ GF_VALIDATE_OR_GOTO(frame->this->name, dictbuf, fail);
+
+ dict = dict_new();
+ GF_VALIDATE_OR_GOTO(frame->this->name, dict, fail);
+
+ ret = dict_unserialize (dictbuf, dict_len, &dict);
+ if (ret < 0) {
+ gf_log (frame->this->name, GF_LOG_ERROR,
+ "failed to serialize dictionary(%p)",
+ dict);
+ op_errno = -ret;
+ goto fail;
+ } else {
+ dict->extra_free = dictbuf;
+ dictbuf = NULL;
+ }
+ }
+ op_ret = 0;
+ }
+ gf_errno = ntoh32 (hdr->rsp.op_errno);
+ op_errno = gf_error_to_errno (gf_errno);
+
+fail:
+ STACK_UNWIND (frame, op_ret, op_errno, dict);
+
+ if (dictbuf)
+ free (dictbuf);
+
+ if (dict)
+ dict_unref (dict);
+
+ return 0;
+}
+
+int32_t
+client_xattrop_cbk (call_frame_t *frame,
+ gf_hdr_common_t *hdr, size_t hdrlen,
+ char *buf, size_t buflen)
+{
+ gf_fop_xattrop_rsp_t *rsp = NULL;
+ int32_t op_ret = -1;
+ int32_t gf_errno = EINVAL;
+ int32_t op_errno = 0;
+ int32_t dict_len = 0;
+ dict_t *dict = NULL;
+ int32_t ret = -1;
+ char *dictbuf = NULL;
+
+ rsp = gf_param (hdr);
+ GF_VALIDATE_OR_GOTO(frame->this->name, rsp, fail);
+
+ op_ret = ntoh32 (hdr->rsp.op_ret);
+ if (op_ret >= 0) {
+ op_ret = -1;
+ dict_len = ntoh32 (rsp->dict_len);
+
+ if (dict_len > 0) {
+ dictbuf = memdup (rsp->dict, dict_len);
+ GF_VALIDATE_OR_GOTO(frame->this->name, dictbuf, fail);
+
+ dict = get_new_dict();
+ GF_VALIDATE_OR_GOTO(frame->this->name, dict, fail);
+ dict_ref (dict);
+
+ ret = dict_unserialize (dictbuf, dict_len, &dict);
+ if (ret < 0) {
+ gf_log (frame->this->name, GF_LOG_ERROR,
+ "failed to serialize dictionary(%p)",
+ dict);
+ goto fail;
+ } else {
+ dict->extra_free = dictbuf;
+ dictbuf = NULL;
+ }
+ }
+ op_ret = 0;
+ }
+ gf_errno = ntoh32 (hdr->rsp.op_errno);
+ op_errno = gf_error_to_errno (gf_errno);
+
+
+fail:
+ STACK_UNWIND (frame, op_ret, op_errno, dict);
+
+ if (dictbuf)
+ free (dictbuf);
+ if (dict)
+ dict_unref (dict);
+
+ return 0;
+}
+
+/*
+ * client_chown_cbk -
+ *
+ * @frame:
+ * @args:
+ *
+ * not for external reference
+ */
+int32_t
+client_fchown_cbk (call_frame_t *frame,
+ gf_hdr_common_t *hdr, size_t hdrlen,
+ char *buf, size_t buflen)
+{
+ struct stat stbuf = {0, };
+ gf_fop_fchown_rsp_t *rsp = NULL;
+ int32_t op_ret = 0;
+ int32_t op_errno = 0;
+
+ rsp = gf_param (hdr);
+
+ op_ret = ntoh32 (hdr->rsp.op_ret);
+ op_errno = gf_error_to_errno (ntoh32 (hdr->rsp.op_errno));
+
+ if (op_ret == 0) {
+ gf_stat_to_stat (&rsp->stat, &stbuf);
+ }
+
+ STACK_UNWIND (frame, op_ret, op_errno, &stbuf);
+
+ return 0;
+}
+
+
+/*
+ * client_fchmod_cbk
+ *
+ * @frame:
+ * @args:
+ *
+ * not for external reference
+ */
+int32_t
+client_fchmod_cbk (call_frame_t *frame,
+ gf_hdr_common_t *hdr, size_t hdrlen,
+ char *buf, size_t buflen)
+{
+ struct stat stbuf = {0, };
+ gf_fop_fchmod_rsp_t *rsp = NULL;
+ int32_t op_ret = 0;
+ int32_t op_errno = 0;
+
+ rsp = gf_param (hdr);
+
+ op_ret = ntoh32 (hdr->rsp.op_ret);
+ op_errno = gf_error_to_errno (ntoh32 (hdr->rsp.op_errno));
+
+ if (op_ret == 0) {
+ gf_stat_to_stat (&rsp->stat, &stbuf);
+ }
+
+ STACK_UNWIND (frame, op_ret, op_errno, &stbuf);
+
+ return 0;
+}
+
+
+/*
+ * client_create_cbk - create callback function for client protocol
+ * @frame: call frame
+ * @args: arguments in dictionary
+ *
+ * not for external reference
+ */
+
+int
+client_create_cbk (call_frame_t *frame,
+ gf_hdr_common_t *hdr, size_t hdrlen,
+ char *buf, size_t buflen)
+{
+ gf_fop_create_rsp_t *rsp = NULL;
+ int32_t op_ret = 0;
+ int32_t op_errno = 0;
+ fd_t *fd = NULL;
+ inode_t *inode = NULL;
+ struct stat stbuf = {0, };
+ int64_t remote_fd = 0;
+ char key[32] = {0, };
+ int32_t ret = -1;
+ client_local_t *local = NULL;
+ client_conf_t *conf = NULL;
+
+
+ local = frame->local; frame->local = NULL;
+ conf = frame->this->private;
+ fd = local->fd;
+ inode = local->loc.inode;
+
+ rsp = gf_param (hdr);
+
+ op_ret = ntoh32 (hdr->rsp.op_ret);
+ op_errno = ntoh32 (hdr->rsp.op_errno);
+
+ if (op_ret >= 0) {
+ remote_fd = ntoh64 (rsp->fd);
+ gf_stat_to_stat (&rsp->stat, &stbuf);
+ }
+
+ if (op_ret >= 0) {
+ this_ino_set (&local->loc, frame->this, stbuf.st_ino);
+ this_fd_set (fd, frame->this, &local->loc, remote_fd);
+
+ sprintf (key, "%p", fd);
+
+ pthread_mutex_lock (&conf->mutex);
+ {
+ ret = dict_set_str (conf->saved_fds, key, "");
+ }
+ pthread_mutex_unlock (&conf->mutex);
+
+ if (ret < 0) {
+ free (key);
+ gf_log (frame->this->name, GF_LOG_ERROR,
+ "%s (%"PRId64"): failed to save remote fd",
+ local->loc.path, stbuf.st_ino);
+ }
+ }
+
+ STACK_UNWIND (frame, op_ret, op_errno, fd, inode, &stbuf);
+
+ client_local_wipe (local);
+
+ return 0;
+}
+
+
+/*
+ * client_open_cbk - open callback for client protocol
+ * @frame: call frame
+ * @args: argument dictionary
+ *
+ * not for external reference
+ */
+int32_t
+client_open_cbk (call_frame_t *frame,
+ gf_hdr_common_t *hdr, size_t hdrlen,
+ char *buf, size_t buflen)
+{
+ int32_t op_ret = -1;
+ int32_t op_errno = ENOTCONN;
+ fd_t *fd = NULL;
+ int64_t remote_fd = 0;
+ gf_fop_open_rsp_t *rsp = NULL;
+ char key[32] = {0,};
+ int32_t ret = -1;
+ client_local_t *local = NULL;
+ client_conf_t *conf = NULL;
+
+
+ local = frame->local; frame->local = NULL;
+ conf = frame->this->private;
+ fd = local->fd;
+
+ rsp = gf_param (hdr);
+
+ op_ret = ntoh32 (hdr->rsp.op_ret);
+ op_errno = ntoh32 (hdr->rsp.op_errno);
+
+ if (op_ret >= 0) {
+ remote_fd = ntoh64 (rsp->fd);
+ }
+
+ if (op_ret >= 0) {
+ this_fd_set (fd, frame->this, &local->loc, remote_fd);
+
+ sprintf (key, "%p", fd);
+
+ pthread_mutex_lock (&conf->mutex);
+ {
+ ret = dict_set_str (conf->saved_fds, key, "");
+ }
+ pthread_mutex_unlock (&conf->mutex);
+
+ if (ret < 0) {
+ gf_log (frame->this->name, GF_LOG_ERROR,
+ "%s (%"PRId64"): failed to save remote fd",
+ local->loc.path, local->loc.inode->ino);
+ free (key);
+ }
+
+ }
+
+ STACK_UNWIND (frame, op_ret, op_errno, fd);
+
+ client_local_wipe (local);
+
+ return 0;
+}
+
+/*
+ * client_stat_cbk - stat callback for client protocol
+ * @frame: call frame
+ * @args: arguments dictionary
+ *
+ * not for external reference
+ */
+int
+client_stat_cbk (call_frame_t *frame,
+ gf_hdr_common_t *hdr, size_t hdrlen,
+ char *buf, size_t buflen)
+{
+ struct stat stbuf = {0, };
+ gf_fop_stat_rsp_t *rsp = NULL;
+ int32_t op_ret = 0;
+ int32_t op_errno = 0;
+
+ rsp = gf_param (hdr);
+
+ op_ret = ntoh32 (hdr->rsp.op_ret);
+ op_errno = gf_error_to_errno (ntoh32 (hdr->rsp.op_errno));
+
+ if (op_ret == 0) {
+ gf_stat_to_stat (&rsp->stat, &stbuf);
+ }
+
+ STACK_UNWIND (frame, op_ret, op_errno, &stbuf);
+
+ return 0;
+}
+
+/*
+ * client_utimens_cbk - utimens callback for client protocol
+ * @frame: call frame
+ * @args: argument dictionary
+ *
+ * not for external reference
+ */
+
+int32_t
+client_utimens_cbk (call_frame_t *frame,
+ gf_hdr_common_t *hdr, size_t hdrlen,
+ char *buf, size_t buflen)
+{
+ struct stat stbuf = {0, };
+ gf_fop_utimens_rsp_t *rsp = NULL;
+ int32_t op_ret = 0;
+ int32_t op_errno = 0;
+
+ rsp = gf_param (hdr);
+
+ op_ret = ntoh32 (hdr->rsp.op_ret);
+ op_errno = gf_error_to_errno (ntoh32 (hdr->rsp.op_errno));
+
+ if (op_ret == 0) {
+ gf_stat_to_stat (&rsp->stat, &stbuf);
+ }
+
+ STACK_UNWIND (frame, op_ret, op_errno, &stbuf);
+
+ return 0;
+}
+
+/*
+ * client_chmod_cbk - chmod for client protocol
+ * @frame: call frame
+ * @args: argument dictionary
+ *
+ * not for external reference
+ */
+int32_t
+client_chmod_cbk (call_frame_t *frame,
+ gf_hdr_common_t *hdr, size_t hdrlen,
+ char *buf, size_t buflen)
+{
+ struct stat stbuf = {0, };
+ gf_fop_chmod_rsp_t *rsp = NULL;
+ int32_t op_ret = 0;
+ int32_t op_errno = 0;
+
+ rsp = gf_param (hdr);
+
+ op_ret = ntoh32 (hdr->rsp.op_ret);
+ op_errno = gf_error_to_errno (ntoh32 (hdr->rsp.op_errno));
+
+ if (op_ret == 0) {
+ gf_stat_to_stat (&rsp->stat, &stbuf);
+ }
+
+ STACK_UNWIND (frame, op_ret, op_errno, &stbuf);
+
+ return 0;
+}
+
+/*
+ * client_chown_cbk - chown for client protocol
+ * @frame: call frame
+ * @args: argument dictionary
+ *
+ * not for external reference
+ */
+int32_t
+client_chown_cbk (call_frame_t *frame,
+ gf_hdr_common_t *hdr, size_t hdrlen,
+ char *buf, size_t buflen)
+{
+ struct stat stbuf = {0, };
+ gf_fop_chown_rsp_t *rsp = NULL;
+ int32_t op_ret = 0;
+ int32_t op_errno = 0;
+
+ rsp = gf_param (hdr);
+
+ op_ret = ntoh32 (hdr->rsp.op_ret);
+ op_errno = gf_error_to_errno (ntoh32 (hdr->rsp.op_errno));
+
+ if (op_ret == 0) {
+ gf_stat_to_stat (&rsp->stat, &stbuf);
+ }
+
+ STACK_UNWIND (frame, op_ret, op_errno, &stbuf);
+
+ return 0;
+}
+
+/*
+ * client_mknod_cbk - mknod callback for client protocol
+ * @frame: call frame
+ * @args: argument dictionary
+ *
+ * not for external reference
+ */
+int32_t
+client_mknod_cbk (call_frame_t *frame,
+ gf_hdr_common_t *hdr, size_t hdrlen,
+ char *buf, size_t buflen)
+{
+ gf_fop_mknod_rsp_t *rsp = NULL;
+ int32_t op_ret = 0;
+ int32_t op_errno = 0;
+ struct stat stbuf = {0, };
+ inode_t *inode = NULL;
+ client_local_t *local = NULL;
+
+ local = frame->local;
+ frame->local = NULL;
+ inode = local->loc.inode;
+
+ rsp = gf_param (hdr);
+
+ op_ret = ntoh32 (hdr->rsp.op_ret);
+ op_errno = gf_error_to_errno (ntoh32 (hdr->rsp.op_errno));
+
+ if (op_ret >= 0) {
+ gf_stat_to_stat (&rsp->stat, &stbuf);
+ this_ino_set (&local->loc, frame->this, stbuf.st_ino);
+ }
+
+ STACK_UNWIND (frame, op_ret, op_errno, inode, &stbuf);
+
+ client_local_wipe (local);
+
+ return 0;
+}
+
+/*
+ * client_symlink_cbk - symlink callback for client protocol
+ * @frame: call frame
+ * @args: argument dictionary
+ *
+ * not for external reference
+ */
+int32_t
+client_symlink_cbk (call_frame_t *frame,
+ gf_hdr_common_t *hdr, size_t hdrlen,
+ char *buf, size_t buflen)
+{
+ gf_fop_symlink_rsp_t *rsp = NULL;
+ int32_t op_ret = 0;
+ int32_t op_errno = 0;
+ struct stat stbuf = {0, };
+ inode_t *inode = NULL;
+ client_local_t *local = NULL;
+
+ local = frame->local;
+ frame->local = NULL;
+ inode = local->loc.inode;
+
+ rsp = gf_param (hdr);
+
+ op_ret = ntoh32 (hdr->rsp.op_ret);
+ op_errno = gf_error_to_errno (ntoh32 (hdr->rsp.op_errno));
+
+ if (op_ret >= 0) {
+ gf_stat_to_stat (&rsp->stat, &stbuf);
+ this_ino_set (&local->loc, frame->this, stbuf.st_ino);
+ }
+
+ STACK_UNWIND (frame, op_ret, op_errno, inode, &stbuf);
+
+ client_local_wipe (local);
+
+ return 0;
+}
+
+/*
+ * client_link_cbk - link callback for client protocol
+ * @frame: call frame
+ * @args: argument dictionary
+ *
+ * not for external reference
+ */
+int32_t
+client_link_cbk (call_frame_t *frame,
+ gf_hdr_common_t *hdr, size_t hdrlen,
+ char *buf, size_t buflen)
+{
+ gf_fop_link_rsp_t *rsp = NULL;
+ int32_t op_ret = 0;
+ int32_t op_errno = 0;
+ struct stat stbuf = {0, };
+ inode_t *inode = NULL;
+ client_local_t *local = NULL;
+
+ local = frame->local;
+ frame->local = NULL;
+ inode = local->loc.inode;
+
+ rsp = gf_param (hdr);
+
+ op_ret = ntoh32 (hdr->rsp.op_ret);
+ op_errno = gf_error_to_errno (ntoh32 (hdr->rsp.op_errno));
+
+ if (op_ret >= 0) {
+ gf_stat_to_stat (&rsp->stat, &stbuf);
+ }
+
+ STACK_UNWIND (frame, op_ret, op_errno, inode, &stbuf);
+
+ client_local_wipe (local);
+
+ return 0;
+}
+
+/*
+ * client_truncate_cbk - truncate callback for client protocol
+ * @frame: call frame
+ * @args: argument dictionary
+ *
+ * not for external reference
+ */
+
+int32_t
+client_truncate_cbk (call_frame_t *frame,
+ gf_hdr_common_t *hdr, size_t hdrlen,
+ char *buf, size_t buflen)
+{
+ struct stat stbuf = {0, };
+ gf_fop_truncate_rsp_t *rsp = NULL;
+ int32_t op_ret = 0;
+ int32_t op_errno = 0;
+
+ rsp = gf_param (hdr);
+
+ op_ret = ntoh32 (hdr->rsp.op_ret);
+ op_errno = gf_error_to_errno (ntoh32 (hdr->rsp.op_errno));
+
+ if (op_ret == 0) {
+ gf_stat_to_stat (&rsp->stat, &stbuf);
+ }
+
+ STACK_UNWIND (frame, op_ret, op_errno, &stbuf);
+
+ return 0;
+}
+
+/* client_fstat_cbk - fstat callback for client protocol
+ * @frame: call frame
+ * @args: argument dictionary
+ *
+ * not for external reference
+ */
+
+int32_t
+client_fstat_cbk (call_frame_t *frame,
+ gf_hdr_common_t *hdr, size_t hdrlen,
+ char *buf, size_t buflen)
+{
+ struct stat stbuf = {0, };
+ gf_fop_fstat_rsp_t *rsp = NULL;
+ int32_t op_ret = 0;
+ int32_t op_errno = 0;
+
+ rsp = gf_param (hdr);
+
+ op_ret = ntoh32 (hdr->rsp.op_ret);
+ op_errno = gf_error_to_errno (ntoh32 (hdr->rsp.op_errno));
+
+ if (op_ret == 0) {
+ gf_stat_to_stat (&rsp->stat, &stbuf);
+ }
+
+ STACK_UNWIND (frame, op_ret, op_errno, &stbuf);
+
+ return 0;
+}
+
+/*
+ * client_ftruncate_cbk - ftruncate callback for client protocol
+ * @frame: call frame
+ * @args: argument dictionary
+ *
+ * not for external reference
+ */
+int32_t
+client_ftruncate_cbk (call_frame_t *frame,
+ gf_hdr_common_t *hdr, size_t hdrlen,
+ char *buf, size_t buflen)
+{
+ struct stat stbuf = {0, };
+ gf_fop_ftruncate_rsp_t *rsp = NULL;
+ int32_t op_ret = 0;
+ int32_t op_errno = 0;
+
+ rsp = gf_param (hdr);
+
+ op_ret = ntoh32 (hdr->rsp.op_ret);
+ op_errno = gf_error_to_errno (ntoh32 (hdr->rsp.op_errno));
+
+ if (op_ret == 0) {
+ gf_stat_to_stat (&rsp->stat, &stbuf);
+ }
+
+ STACK_UNWIND (frame, op_ret, op_errno, &stbuf);
+
+ return 0;
+}
+
+/* client_readv_cbk - readv callback for client protocol
+ * @frame: call frame
+ * @args: argument dictionary
+ *
+ * not for external referece
+ */
+
+int32_t
+client_readv_cbk (call_frame_t *frame,
+ gf_hdr_common_t *hdr, size_t hdrlen,
+ char *buf, size_t buflen)
+{
+ gf_fop_read_rsp_t *rsp = NULL;
+ int32_t op_ret = 0;
+ int32_t op_errno = 0;
+ struct iovec vector = {0, };
+ struct stat stbuf = {0, };
+ dict_t *refs = NULL;
+
+ rsp = gf_param (hdr);
+
+ op_ret = ntoh32 (hdr->rsp.op_ret);
+ op_errno = gf_error_to_errno (ntoh32 (hdr->rsp.op_errno));
+
+ if (op_ret != -1) {
+ gf_stat_to_stat (&rsp->stat, &stbuf);
+ vector.iov_base = buf;
+ vector.iov_len = buflen;
+
+ refs = get_new_dict ();
+ dict_set (refs, NULL, data_from_dynptr (buf, 0));
+ frame->root->rsp_refs = dict_ref (refs);
+ }
+
+ STACK_UNWIND (frame, op_ret, op_errno, &vector, 1, &stbuf);
+
+ if (refs)
+ dict_unref (refs);
+
+ return 0;
+}
+
+/*
+ * client_write_cbk - write callback for client protocol
+ * @frame: cal frame
+ * @args: argument dictionary
+ *
+ * not for external reference
+ */
+
+int32_t
+client_write_cbk (call_frame_t *frame,
+ gf_hdr_common_t *hdr, size_t hdrlen,
+ char *buf, size_t buflen)
+{
+ gf_fop_write_rsp_t *rsp = NULL;
+ int32_t op_ret = 0;
+ int32_t op_errno = 0;
+ struct stat stbuf = {0, };
+
+ rsp = gf_param (hdr);
+
+ op_ret = ntoh32 (hdr->rsp.op_ret);
+ op_errno = gf_error_to_errno (ntoh32 (hdr->rsp.op_errno));
+
+ if (op_ret >= 0)
+ gf_stat_to_stat (&rsp->stat, &stbuf);
+
+ STACK_UNWIND (frame, op_ret, op_errno, &stbuf);
+
+ return 0;
+}
+
+
+int32_t
+client_readdir_cbk (call_frame_t *frame,
+ gf_hdr_common_t *hdr, size_t hdrlen,
+ char *buf, size_t buflen)
+{
+ gf_fop_readdir_rsp_t *rsp = NULL;
+ int32_t op_ret = 0;
+ int32_t op_errno = 0;
+ uint32_t buf_size = 0;
+ gf_dirent_t entries;
+
+ rsp = gf_param (hdr);
+
+ op_ret = ntoh32 (hdr->rsp.op_ret);
+ op_errno = ntoh32 (hdr->rsp.op_errno);
+
+ INIT_LIST_HEAD (&entries.list);
+ if (op_ret > 0) {
+ buf_size = ntoh32 (rsp->size);
+ gf_dirent_unserialize (&entries, rsp->buf, buf_size);
+ }
+
+ STACK_UNWIND (frame, op_ret, op_errno, &entries);
+
+ gf_dirent_free (&entries);
+
+ return 0;
+}
+
+/*
+ * client_fsync_cbk - fsync callback for client protocol
+ *
+ * @frame: call frame
+ * @args: argument dictionary
+ *
+ * not for external reference
+ */
+int32_t
+client_fsync_cbk (call_frame_t *frame,
+ gf_hdr_common_t *hdr, size_t hdrlen,
+ char *buf, size_t buflen)
+{
+ struct stat stbuf = {0, };
+ gf_fop_fsync_rsp_t *rsp = NULL;
+ int32_t op_ret = 0;
+ int32_t op_errno = 0;
+
+ rsp = gf_param (hdr);
+
+ op_ret = ntoh32 (hdr->rsp.op_ret);
+ op_errno = gf_error_to_errno (ntoh32 (hdr->rsp.op_errno));
+
+ STACK_UNWIND (frame, op_ret, op_errno, &stbuf);
+
+ return 0;
+}
+
+
+/*
+ * client_unlink_cbk - unlink callback for client protocol
+ * @frame: call frame
+ * @args: argument dictionary
+ *
+ * not for external reference
+ */
+int32_t
+client_unlink_cbk (call_frame_t *frame,
+ gf_hdr_common_t *hdr, size_t hdrlen,
+ char *buf, size_t buflen)
+{
+ gf_fop_unlink_rsp_t *rsp = NULL;
+ int32_t op_ret = 0;
+ int32_t op_errno = 0;
+
+ rsp = gf_param (hdr);
+
+ op_ret = ntoh32 (hdr->rsp.op_ret);
+ op_errno = gf_error_to_errno (ntoh32 (hdr->rsp.op_errno));
+
+ STACK_UNWIND (frame, op_ret, op_errno);
+
+ return 0;
+}
+
+/*
+ * client_rename_cbk - rename callback for client protocol
+ * @frame: call frame
+ * @args: argument dictionary
+ *
+ * not for external reference
+ */
+int32_t
+client_rename_cbk (call_frame_t *frame,
+ gf_hdr_common_t *hdr, size_t hdrlen,
+ char *buf, size_t buflen)
+{
+ struct stat stbuf = {0, };
+ gf_fop_rename_rsp_t *rsp = NULL;
+ int32_t op_ret = 0;
+ int32_t op_errno = 0;
+
+ rsp = gf_param (hdr);
+
+ op_ret = ntoh32 (hdr->rsp.op_ret);
+ op_errno = gf_error_to_errno (ntoh32 (hdr->rsp.op_errno));
+
+ if (op_ret == 0) {
+ gf_stat_to_stat (&rsp->stat, &stbuf);
+ }
+
+ STACK_UNWIND (frame, op_ret, op_errno, &stbuf);
+
+ return 0;
+}
+
+
+/*
+ * client_readlink_cbk - readlink callback for client protocol
+ *
+ * @frame: call frame
+ * @args: argument dictionary
+ *
+ * not for external reference
+ */
+int32_t
+client_readlink_cbk (call_frame_t *frame,
+ gf_hdr_common_t *hdr, size_t hdrlen,
+ char *buf, size_t buflen)
+{
+ gf_fop_readlink_rsp_t *rsp = NULL;
+ int32_t op_ret = 0;
+ int32_t op_errno = 0;
+ char *link = NULL;
+
+ rsp = gf_param (hdr);
+
+ op_ret = ntoh32 (hdr->rsp.op_ret);
+ op_errno = gf_error_to_errno (ntoh32 (hdr->rsp.op_errno));
+
+ if (op_ret > 0) {
+ link = rsp->path;
+ }
+
+ STACK_UNWIND (frame, op_ret, op_errno, link);
+ return 0;
+}
+
+/*
+ * client_mkdir_cbk - mkdir callback for client protocol
+ * @frame: call frame
+ * @args: argument dictionary
+ *
+ * not for external reference
+ */
+int32_t
+client_mkdir_cbk (call_frame_t *frame,
+ gf_hdr_common_t *hdr, size_t hdrlen,
+ char *buf, size_t buflen)
+{
+ gf_fop_mkdir_rsp_t *rsp = NULL;
+ int32_t op_ret = 0;
+ int32_t op_errno = 0;
+ struct stat stbuf = {0, };
+ inode_t *inode = NULL;
+ client_local_t *local = NULL;
+
+ local = frame->local;
+ inode = local->loc.inode;
+ frame->local = NULL;
+
+ rsp = gf_param (hdr);
+
+ op_ret = ntoh32 (hdr->rsp.op_ret);
+ op_errno = gf_error_to_errno (ntoh32 (hdr->rsp.op_errno));
+
+ if (op_ret >= 0) {
+ gf_stat_to_stat (&rsp->stat, &stbuf);
+ this_ino_set (&local->loc, frame->this, stbuf.st_ino);
+ }
+
+ STACK_UNWIND (frame, op_ret, op_errno, inode, &stbuf);
+
+ client_local_wipe (local);
+
+ return 0;
+}
+
+/*
+ * client_flush_cbk - flush callback for client protocol
+ *
+ * @frame: call frame
+ * @args: argument dictionary
+ *
+ * not for external reference
+ */
+
+int32_t
+client_flush_cbk (call_frame_t *frame,
+ gf_hdr_common_t *hdr, size_t hdrlen,
+ char *buf, size_t buflen)
+{
+ int32_t op_ret = 0;
+ int32_t op_errno = 0;
+
+ op_ret = ntoh32 (hdr->rsp.op_ret);
+ op_errno = gf_error_to_errno (ntoh32 (hdr->rsp.op_errno));
+
+ STACK_UNWIND (frame, op_ret, op_errno);
+
+ return 0;
+}
+
+
+/*
+ * client_opendir_cbk - opendir callback for client protocol
+ * @frame: call frame
+ * @args: argument dictionary
+ *
+ * not for external reference
+ */
+int
+client_opendir_cbk (call_frame_t *frame,
+ gf_hdr_common_t *hdr, size_t hdrlen,
+ char *buf, size_t buflen)
+{
+ int32_t op_ret = -1;
+ int32_t op_errno = ENOTCONN;
+ fd_t *fd = NULL;
+ int64_t remote_fd = 0;
+ gf_fop_opendir_rsp_t *rsp = NULL;
+ char key[32] = {0,};
+ int32_t ret = -1;
+ client_local_t *local = NULL;
+ client_conf_t *conf = NULL;
+
+
+ local = frame->local; frame->local = NULL;
+ conf = frame->this->private;
+ fd = local->fd;
+
+ rsp = gf_param (hdr);
+
+ op_ret = ntoh32 (hdr->rsp.op_ret);
+ op_errno = ntoh32 (hdr->rsp.op_errno);
+
+ if (op_ret >= 0) {
+ remote_fd = ntoh64 (rsp->fd);
+ }
+
+ if (op_ret >= 0) {
+ this_fd_set (fd, frame->this, &local->loc, remote_fd);
+
+ sprintf (key, "%p", fd);
+
+ pthread_mutex_lock (&conf->mutex);
+ {
+ ret = dict_set_str (conf->saved_fds, key, "");
+ }
+ pthread_mutex_unlock (&conf->mutex);
+
+ if (ret < 0) {
+ free (key);
+ gf_log (frame->this->name, GF_LOG_ERROR,
+ "%s (%"PRId64"): failed to save remote fd",
+ local->loc.path, local->loc.inode->ino);
+ }
+ }
+
+ STACK_UNWIND (frame, op_ret, op_errno, fd);
+
+ client_local_wipe (local);
+
+ return 0;
+}
+
+
+/*
+ * client_rmdir_cbk - rmdir callback for client protocol
+ * @frame: call frame
+ * @args: argument dictionary
+ *
+ * not for external reference
+ */
+
+int
+client_rmdir_cbk (call_frame_t *frame,
+ gf_hdr_common_t *hdr, size_t hdrlen,
+ char *buf, size_t buflen)
+{
+ gf_fop_rmdir_rsp_t *rsp = NULL;
+ int32_t op_ret = 0;
+ int32_t op_errno = 0;
+
+ rsp = gf_param (hdr);
+
+ op_ret = ntoh32 (hdr->rsp.op_ret);
+ op_errno = gf_error_to_errno (ntoh32 (hdr->rsp.op_errno));
+
+ STACK_UNWIND (frame, op_ret, op_errno);
+
+ return 0;
+}
+
+/*
+ * client_access_cbk - access callback for client protocol
+ * @frame: call frame
+ * @args: argument dictionary
+ *
+ * not for external reference
+ */
+int32_t
+client_access_cbk (call_frame_t *frame,
+ gf_hdr_common_t *hdr, size_t hdrlen,
+ char *buf, size_t buflen)
+{
+ gf_fop_access_rsp_t *rsp = NULL;
+ int32_t op_ret = 0;
+ int32_t op_errno = 0;
+
+ rsp = gf_param (hdr);
+
+ op_ret = ntoh32 (hdr->rsp.op_ret);
+ op_errno = gf_error_to_errno (ntoh32 (hdr->rsp.op_errno));
+
+ STACK_UNWIND (frame, op_ret, op_errno);
+
+ return 0;
+}
+
+
+
+/*
+ * client_lookup_cbk - lookup callback for client protocol
+ *
+ * @frame: call frame
+ * @args: arguments dictionary
+ *
+ * not for external reference
+ */
+int32_t
+client_lookup_cbk (call_frame_t *frame,
+ gf_hdr_common_t *hdr, size_t hdrlen,
+ char *buf, size_t buflen)
+{
+ struct stat stbuf = {0, };
+ inode_t *inode = NULL;
+ dict_t *xattr = NULL;
+ gf_fop_lookup_rsp_t *rsp = NULL;
+ int32_t op_ret = 0;
+ int32_t op_errno = 0;
+ size_t dict_len = 0;
+ char *dictbuf = NULL;
+ int32_t ret = -1;
+ int32_t gf_errno = 0;
+ client_local_t *local = NULL;
+
+ local = frame->local;
+ inode = local->loc.inode;
+ frame->local = NULL;
+
+ rsp = gf_param (hdr);
+
+ op_ret = ntoh32 (hdr->rsp.op_ret);
+
+ if (op_ret == 0) {
+ op_ret = -1;
+ gf_stat_to_stat (&rsp->stat, &stbuf);
+ this_ino_set (&local->loc, frame->this, stbuf.st_ino);
+
+ dict_len = ntoh32 (rsp->dict_len);
+
+ if (dict_len > 0) {
+ dictbuf = memdup (rsp->dict, dict_len);
+ GF_VALIDATE_OR_GOTO(frame->this->name, dictbuf, fail);
+
+ xattr = dict_new();
+ GF_VALIDATE_OR_GOTO(frame->this->name, xattr, fail);
+
+ ret = dict_unserialize (dictbuf, dict_len, &xattr);
+ if (ret < 0) {
+ gf_log (frame->this->name, GF_LOG_ERROR,
+ "%s (%"PRId64"): failed to unserialize dictionary",
+ local->loc.path, inode->ino);
+ goto fail;
+ } else {
+ xattr->extra_free = dictbuf;
+ dictbuf = NULL;
+ }
+ }
+ op_ret = 0;
+ }
+ gf_errno = ntoh32 (hdr->rsp.op_errno);
+ op_errno = gf_error_to_errno (gf_errno);
+
+fail:
+ STACK_UNWIND (frame, op_ret, op_errno, inode, &stbuf, xattr);
+
+ client_local_wipe (local);
+
+ if (dictbuf)
+ free (dictbuf);
+
+ if (xattr)
+ dict_unref (xattr);
+
+ return 0;
+}
+
+static dir_entry_t *
+gf_bin_to_direntry (char *buf, size_t count)
+{
+ int32_t idx = 0, bread = 0;
+ size_t rcount = 0;
+ char *ender = NULL, *buffer = NULL;
+ char tmp_buf[512] = {0,};
+ dir_entry_t *trav = NULL, *prev = NULL;
+ dir_entry_t *thead = NULL, *head = NULL;
+
+ thead = CALLOC (1, sizeof (dir_entry_t));
+ GF_VALIDATE_OR_GOTO("client-protocol", thead, fail);
+
+ buffer = buf;
+ prev = thead;
+
+ for (idx = 0; idx < count ; idx++) {
+ bread = 0;
+ trav = CALLOC (1, sizeof (dir_entry_t));
+ GF_VALIDATE_OR_GOTO("client-protocol", trav, fail);
+
+ ender = strchr (buffer, '/');
+ if (!ender)
+ break;
+ rcount = ender - buffer;
+ trav->name = CALLOC (1, rcount + 2);
+ GF_VALIDATE_OR_GOTO("client-protocol", trav->name, fail);
+
+ strncpy (trav->name, buffer, rcount);
+ bread = rcount + 1;
+ buffer += bread;
+
+ ender = strchr (buffer, '\n');
+ if (!ender)
+ break;
+ rcount = ender - buffer;
+ strncpy (tmp_buf, buffer, rcount);
+ bread = rcount + 1;
+ buffer += bread;
+
+ gf_string_to_stat (tmp_buf, &trav->buf);
+
+ ender = strchr (buffer, '\n');
+ if (!ender)
+ break;
+ rcount = ender - buffer;
+ *ender = '\0';
+ if (S_ISLNK (trav->buf.st_mode))
+ trav->link = strdup (buffer);
+ else
+ trav->link = "";
+
+ bread = rcount + 1;
+ buffer += bread;
+
+ prev->next = trav;
+ prev = trav;
+ }
+
+ head = thead;
+fail:
+ return head;
+}
+
+int32_t
+gf_free_direntry(dir_entry_t *head)
+{
+ dir_entry_t *prev = NULL, *trav = NULL;
+
+ prev = head;
+ GF_VALIDATE_OR_GOTO("client-protocol", prev, fail);
+
+ trav = head->next;
+ while (trav) {
+ prev->next = trav->next;
+ FREE (trav->name);
+ if (S_ISLNK (trav->buf.st_mode))
+ FREE (trav->link);
+ FREE (trav);
+ trav = prev->next;
+ }
+ FREE (head);
+fail:
+ return 0;
+}
+/*
+ * client_getdents_cbk - readdir callback for client protocol
+ * @frame: call frame
+ * @args: argument dictionary
+ *
+ * not for external reference
+ */
+int32_t
+client_getdents_cbk (call_frame_t *frame,
+ gf_hdr_common_t *hdr, size_t hdrlen,
+ char *buf, size_t buflen)
+{
+ gf_fop_getdents_rsp_t *rsp = NULL;
+ int32_t op_ret = 0;
+ int32_t op_errno = 0;
+ int32_t gf_errno = 0;
+ int32_t nr_count = 0;
+ dir_entry_t *entry = NULL;
+
+ rsp = gf_param (hdr);
+
+ op_ret = ntoh32 (hdr->rsp.op_ret);
+ gf_errno = ntoh32 (hdr->rsp.op_errno);
+ op_errno = gf_error_to_errno (gf_errno);
+
+ if (op_ret >= 0) {
+ nr_count = ntoh32 (rsp->count);
+ entry = gf_bin_to_direntry(buf, nr_count);
+ if (entry == NULL) {
+ op_ret = -1;
+ op_errno = EINVAL;
+ }
+ }
+
+ STACK_UNWIND (frame, op_ret, op_errno, entry, nr_count);
+
+ if (op_ret >= 0) {
+ /* Free the buffer */
+ FREE (buf);
+ gf_free_direntry(entry);
+ }
+
+ return 0;
+}
+
+/*
+ * client_statfs_cbk - statfs callback for client protocol
+ * @frame: call frame
+ * @args: argument dictionary
+ *
+ * not for external reference
+ */
+int32_t
+client_statfs_cbk (call_frame_t *frame,
+ gf_hdr_common_t *hdr, size_t hdrlen,
+ char *buf, size_t buflen)
+{
+ struct statvfs stbuf = {0, };
+ gf_fop_statfs_rsp_t *rsp = NULL;
+ int32_t op_ret = 0;
+ int32_t op_errno = 0;
+
+ rsp = gf_param (hdr);
+
+ op_ret = ntoh32 (hdr->rsp.op_ret);
+ op_errno = gf_error_to_errno (ntoh32 (hdr->rsp.op_errno));
+
+ if (op_ret == 0)
+ {
+ gf_statfs_to_statfs (&rsp->statfs, &stbuf);
+ }
+
+ STACK_UNWIND (frame, op_ret, op_errno, &stbuf);
+
+ return 0;
+}
+
+/*
+ * client_fsyncdir_cbk - fsyncdir callback for client protocol
+ * @frame: call frame
+ * @args: argument dictionary
+ *
+ * not for external reference
+ */
+int32_t
+client_fsyncdir_cbk (call_frame_t *frame,
+ gf_hdr_common_t *hdr, size_t hdrlen,
+ char *buf, size_t buflen)
+{
+ int32_t op_ret = 0;
+ int32_t op_errno = 0;
+
+ op_ret = ntoh32 (hdr->rsp.op_ret);
+ op_errno = gf_error_to_errno (ntoh32 (hdr->rsp.op_errno));
+
+ STACK_UNWIND (frame, op_ret, op_errno);
+
+ return 0;
+}
+
+/*
+ * client_setxattr_cbk - setxattr callback for client protocol
+ * @frame: call frame
+ * @args: argument dictionary
+ *
+ * not for external reference
+ */
+int32_t
+client_setxattr_cbk (call_frame_t *frame,
+ gf_hdr_common_t *hdr, size_t hdrlen,
+ char *buf, size_t buflen)
+{
+ gf_fop_setxattr_rsp_t *rsp = NULL;
+ int32_t op_ret = 0;
+ int32_t op_errno = 0;
+
+ rsp = gf_param (hdr);
+
+ op_ret = ntoh32 (hdr->rsp.op_ret);
+ op_errno = gf_error_to_errno (ntoh32 (hdr->rsp.op_errno));
+
+ STACK_UNWIND (frame, op_ret, op_errno);
+
+ return 0;
+}
+
+/*
+ * client_getxattr_cbk - getxattr callback for client protocol
+ * @frame: call frame
+ * @args: argument dictionary
+ *
+ * not for external reference
+ */
+int32_t
+client_getxattr_cbk (call_frame_t *frame,
+ gf_hdr_common_t *hdr, size_t hdrlen,
+ char *buf, size_t buflen)
+{
+ gf_fop_getxattr_rsp_t *rsp = NULL;
+ int32_t op_ret = 0;
+ int32_t gf_errno = 0;
+ int32_t op_errno = 0;
+ int32_t dict_len = 0;
+ dict_t *dict = NULL;
+ int32_t ret = -1;
+ char *dictbuf = NULL;
+ client_local_t *local = NULL;
+
+ local = frame->local;
+ frame->local = NULL;
+
+ rsp = gf_param (hdr);
+ GF_VALIDATE_OR_GOTO(frame->this->name, rsp, fail);
+
+ op_ret = ntoh32 (hdr->rsp.op_ret);
+
+ if (op_ret >= 0) {
+ op_ret = -1;
+ dict_len = ntoh32 (rsp->dict_len);
+
+ if (dict_len > 0) {
+ dictbuf = memdup (rsp->dict, dict_len);
+ GF_VALIDATE_OR_GOTO(frame->this->name, dictbuf, fail);
+
+ dict = dict_new();
+ GF_VALIDATE_OR_GOTO(frame->this->name, dict, fail);
+
+ ret = dict_unserialize (dictbuf, dict_len, &dict);
+ if (ret < 0) {
+ gf_log (frame->this->name, GF_LOG_ERROR,
+ "%s (%"PRId64"): failed to "
+ "unserialize xattr dictionary",
+ local->loc.path, local->loc.inode->ino);
+ goto fail;
+ } else {
+ dict->extra_free = dictbuf;
+ dictbuf = NULL;
+ }
+ }
+ op_ret = 0;
+ }
+ gf_errno = ntoh32 (hdr->rsp.op_errno);
+ op_errno = gf_error_to_errno (gf_errno);
+fail:
+ STACK_UNWIND (frame, op_ret, op_errno, dict);
+
+ client_local_wipe (local);
+
+ if (dictbuf)
+ free (dictbuf);
+
+ if (dict)
+ dict_unref (dict);
+
+ return 0;
+}
+
+/*
+ * client_removexattr_cbk - removexattr callback for client protocol
+ * @frame: call frame
+ * @args: argument dictionary
+ *
+ * not for external reference
+ */
+int32_t
+client_removexattr_cbk (call_frame_t *frame,
+ gf_hdr_common_t *hdr, size_t hdrlen,
+ char *buf, size_t buflen)
+{
+ int32_t op_ret = 0;
+ int32_t op_errno = 0;
+
+ op_ret = ntoh32 (hdr->rsp.op_ret);
+ op_errno = gf_error_to_errno (ntoh32 (hdr->rsp.op_errno));
+
+ STACK_UNWIND (frame, op_ret, op_errno);
+
+ return 0;
+}
+
+/*
+ * client_lk_cbk - lk callback for client protocol
+ * @frame: call frame
+ * @args: argument dictionary
+ *
+ * not for external reference
+ */
+int32_t
+client_lk_common_cbk (call_frame_t *frame,
+ gf_hdr_common_t *hdr, size_t hdrlen,
+ char *buf, size_t buflen)
+{
+ struct flock lock = {0,};
+ gf_fop_lk_rsp_t *rsp = NULL;
+ int32_t op_ret = 0;
+ int32_t op_errno = 0;
+
+ rsp = gf_param (hdr);
+
+ op_ret = ntoh32 (hdr->rsp.op_ret);
+ op_errno = gf_error_to_errno (ntoh32 (hdr->rsp.op_errno));
+
+ if (op_ret >= 0) {
+ gf_flock_to_flock (&rsp->flock, &lock);
+ }
+
+ STACK_UNWIND (frame, op_ret, op_errno, &lock);
+ return 0;
+}
+
+
+/*
+ * client_gf_file_lk_cbk - gf_file_lk callback for client protocol
+ * @frame: call frame
+ * @args: argument dictionary
+ *
+ * not for external reference
+ */
+int32_t
+client_inodelk_cbk (call_frame_t *frame,
+ gf_hdr_common_t *hdr, size_t hdrlen,
+ char *buf, size_t buflen)
+{
+ gf_fop_inodelk_rsp_t *rsp = NULL;
+ int32_t op_ret = 0;
+ int32_t op_errno = 0;
+
+ rsp = gf_param (hdr);
+
+ op_ret = ntoh32 (hdr->rsp.op_ret);
+ op_errno = gf_error_to_errno (ntoh32 (hdr->rsp.op_errno));
+
+ STACK_UNWIND (frame, op_ret, op_errno);
+ return 0;
+}
+
+
+int32_t
+client_finodelk_cbk (call_frame_t *frame,
+ gf_hdr_common_t *hdr, size_t hdrlen,
+ char *buf, size_t buflen)
+{
+ gf_fop_finodelk_rsp_t *rsp = NULL;
+ int32_t op_ret = 0;
+ int32_t op_errno = 0;
+
+ rsp = gf_param (hdr);
+
+ op_ret = ntoh32 (hdr->rsp.op_ret);
+ op_errno = gf_error_to_errno (ntoh32 (hdr->rsp.op_errno));
+
+ STACK_UNWIND (frame, op_ret, op_errno);
+ return 0;
+}
+
+
+/*
+ * client_entrylk_cbk - entrylk callback for client protocol
+ * @frame: call frame
+ * @args: argument dictionary
+ *
+ * not for external reference
+ */
+int32_t
+client_entrylk_cbk (call_frame_t *frame,
+ gf_hdr_common_t *hdr, size_t hdrlen,
+ char *buf, size_t buflen)
+{
+ gf_fop_entrylk_rsp_t *rsp = NULL;
+ int32_t op_ret = 0;
+ int32_t op_errno = 0;
+
+ rsp = gf_param (hdr);
+
+ op_ret = ntoh32 (hdr->rsp.op_ret);
+ op_errno = gf_error_to_errno (ntoh32 (hdr->rsp.op_errno));
+
+ STACK_UNWIND (frame, op_ret, op_errno);
+ return 0;
+}
+
+int32_t
+client_fentrylk_cbk (call_frame_t *frame,
+ gf_hdr_common_t *hdr, size_t hdrlen,
+ char *buf, size_t buflen)
+{
+ gf_fop_fentrylk_rsp_t *rsp = NULL;
+ int32_t op_ret = 0;
+ int32_t op_errno = 0;
+
+ rsp = gf_param (hdr);
+
+ op_ret = ntoh32 (hdr->rsp.op_ret);
+ op_errno = gf_error_to_errno (ntoh32 (hdr->rsp.op_errno));
+
+ STACK_UNWIND (frame, op_ret, op_errno);
+ return 0;
+}
+
+
+/**
+ * client_writedir_cbk -
+ *
+ * @frame:
+ * @args:
+ *
+ * not for external reference
+ */
+int32_t
+client_setdents_cbk (call_frame_t *frame,
+ gf_hdr_common_t *hdr, size_t hdrlen,
+ char *buf, size_t buflen)
+{
+ int32_t op_ret = 0;
+ int32_t op_errno = 0;
+
+ op_ret = ntoh32 (hdr->rsp.op_ret);
+ op_errno = gf_error_to_errno (ntoh32 (hdr->rsp.op_errno));
+
+ STACK_UNWIND (frame, op_ret, op_errno);
+
+ return 0;
+}
+
+
+
+/*
+ * client_stats_cbk - stats callback for client protocol
+ *
+ * @frame: call frame
+ * @args: argument dictionary
+ *
+ * not for external reference
+ */
+
+int32_t
+client_stats_cbk (call_frame_t *frame,
+ gf_hdr_common_t *hdr, size_t hdrlen,
+ char *buf, size_t buflen)
+{
+ struct xlator_stats stats = {0,};
+ gf_mop_stats_rsp_t *rsp = NULL;
+ char *buffer = NULL;
+ int32_t op_ret = 0;
+ int32_t op_errno = 0;
+
+ rsp = gf_param (hdr);
+
+ op_ret = ntoh32 (hdr->rsp.op_ret);
+ op_errno = gf_error_to_errno (ntoh32 (hdr->rsp.op_errno));
+
+ if (op_ret >= 0)
+ {
+ buffer = rsp->buf;
+
+ sscanf (buffer, "%"SCNx64",%"SCNx64",%"SCNx64",%"SCNx64
+ ",%"SCNx64",%"SCNx64",%"SCNx64",%"SCNx64"\n",
+ &stats.nr_files,
+ &stats.disk_usage,
+ &stats.free_disk,
+ &stats.total_disk_size,
+ &stats.read_usage,
+ &stats.write_usage,
+ &stats.disk_speed,
+ &stats.nr_clients);
+ }
+
+ STACK_UNWIND (frame, op_ret, op_errno, &stats);
+ return 0;
+}
+
+/*
+ * client_getspec - getspec function for client protocol
+ * @frame: call frame
+ * @this: client protocol xlator structure
+ * @flag:
+ *
+ * external reference through client_protocol_xlator->fops->getspec
+ */
+int32_t
+client_getspec (call_frame_t *frame,
+ xlator_t *this,
+ const char *key,
+ int32_t flag)
+{
+ gf_hdr_common_t *hdr = NULL;
+ gf_mop_getspec_req_t *req = NULL;
+ size_t hdrlen = -1;
+ int keylen = 0;
+ int ret = -1;
+
+ if (key)
+ keylen = STRLEN_0(key);
+
+ hdrlen = gf_hdr_len (req, keylen);
+ hdr = gf_hdr_new (req, keylen);
+ GF_VALIDATE_OR_GOTO(this->name, hdr, unwind);
+
+ req = gf_param (hdr);
+ req->flags = hton32 (flag);
+ req->keylen = hton32 (keylen);
+ if (keylen)
+ strcpy (req->key, key);
+
+ ret = protocol_client_xfer (frame, this,
+ CLIENT_CHANNEL (this, CHANNEL_BULK),
+ GF_OP_TYPE_MOP_REQUEST, GF_MOP_GETSPEC,
+ hdr, hdrlen, NULL, 0, NULL);
+
+ return ret;
+unwind:
+ if (hdr)
+ free (hdr);
+ STACK_UNWIND(frame, -1, EINVAL, NULL);
+ return 0;
+}
+
+
+/*
+ * client_getspec_cbk - getspec callback for client protocol
+ *
+ * @frame: call frame
+ * @args: argument dictionary
+ *
+ * not for external reference
+ */
+
+int32_t
+client_getspec_cbk (call_frame_t *frame,
+ gf_hdr_common_t *hdr, size_t hdrlen,
+ char *buf, size_t buflen)
+{
+ gf_mop_getspec_rsp_t *rsp = NULL;
+ char *spec_data = NULL;
+ int32_t op_ret = 0;
+ int32_t op_errno = 0;
+ int32_t gf_errno = 0;
+
+ op_ret = ntoh32 (hdr->rsp.op_ret);
+ gf_errno = ntoh32 (hdr->rsp.op_errno);
+ op_errno = gf_error_to_errno (gf_errno);
+ rsp = gf_param (hdr);
+
+ if (op_ret >= 0) {
+ spec_data = rsp->spec;
+ }
+
+ STACK_UNWIND (frame, op_ret, op_errno, spec_data);
+ return 0;
+}
+
+int32_t
+client_checksum (call_frame_t *frame,
+ xlator_t *this,
+ loc_t *loc,
+ int32_t flag)
+{
+ gf_hdr_common_t *hdr = NULL;
+ gf_fop_checksum_req_t *req = NULL;
+ size_t hdrlen = -1;
+ int ret = -1;
+ client_conf_t *conf = this->private;
+ ino_t ino = 0;
+
+ if (conf->child) {
+ STACK_WIND (frame,
+ default_checksum_cbk,
+ conf->child,
+ conf->child->fops->checksum,
+ loc,
+ flag);
+
+ return 0;
+ }
+
+ hdrlen = gf_hdr_len (req, strlen (loc->path) + 1);
+ hdr = gf_hdr_new (req, strlen (loc->path) + 1);
+ req = gf_param (hdr);
+
+ ino = this_ino_get (loc, this, GF_CLIENT_INODE_SELF);
+ req->ino = hton64 (ino);
+ req->flag = hton32 (flag);
+ strcpy (req->path, loc->path);
+
+ ret = protocol_client_xfer (frame, this,
+ CLIENT_CHANNEL (this, CHANNEL_BULK),
+ GF_OP_TYPE_FOP_REQUEST, GF_FOP_CHECKSUM,
+ hdr, hdrlen, NULL, 0, NULL);
+
+ return ret;
+}
+
+int32_t
+client_checksum_cbk (call_frame_t *frame,
+ gf_hdr_common_t *hdr, size_t hdrlen,
+ char *buf, size_t buflen)
+{
+ gf_fop_checksum_rsp_t *rsp = NULL;
+ int32_t op_ret = 0;
+ int32_t op_errno = 0;
+ int32_t gf_errno = 0;
+ unsigned char *fchecksum = NULL;
+ unsigned char *dchecksum = NULL;
+
+ rsp = gf_param (hdr);
+
+ op_ret = ntoh32 (hdr->rsp.op_ret);
+ gf_errno = ntoh32 (hdr->rsp.op_errno);
+ op_errno = gf_error_to_errno (gf_errno);
+
+ if (op_ret >= 0) {
+ fchecksum = rsp->fchecksum;
+ dchecksum = rsp->dchecksum + ZR_FILENAME_MAX;
+ }
+
+ STACK_UNWIND (frame, op_ret, op_errno, fchecksum, dchecksum);
+ return 0;
+}
+
+
+/*
+ * client_setspec_cbk - setspec callback for client protocol
+ * @frame: call frame
+ * @args: argument dictionary
+ *
+ * not for external reference
+ */
+
+int32_t
+client_setspec_cbk (call_frame_t *frame,
+ gf_hdr_common_t *hdr, size_t hdrlen,
+ char *buf, size_t buflen)
+{
+ int32_t op_ret = 0;
+ int32_t op_errno = 0;
+
+ op_ret = ntoh32 (hdr->rsp.op_ret);
+ op_errno = gf_error_to_errno (ntoh32 (hdr->rsp.op_errno));
+
+ STACK_UNWIND (frame, op_ret, op_errno);
+
+ return 0;
+}
+
+/*
+ * client_setvolume_cbk - setvolume callback for client protocol
+ * @frame: call frame
+ * @args: argument dictionary
+ *
+ * not for external reference
+ */
+int
+client_setvolume_cbk (call_frame_t *frame,
+ gf_hdr_common_t *hdr, size_t hdrlen,
+ char *buf, size_t buflen)
+{
+ gf_mop_setvolume_rsp_t *rsp = NULL;
+ client_connection_t *conn = NULL;
+ client_conf_t *conf = NULL;
+ glusterfs_ctx_t *ctx = NULL;
+ xlator_t *this = NULL;
+ xlator_list_t *parent = NULL;
+ transport_t *trans = NULL;
+ dict_t *reply = NULL;
+ char *remote_subvol = NULL;
+ char *remote_error = NULL;
+ char *process_uuid = NULL;
+ int32_t ret = -1;
+ int32_t op_ret = -1;
+ int32_t op_errno = EINVAL;
+ int32_t dict_len = 0;
+
+
+ trans = frame->local; frame->local = NULL;
+ this = frame->this;
+ conf = this->private;
+ conn = trans->xl_private;
+
+ rsp = gf_param (hdr);
+
+ op_ret = ntoh32 (hdr->rsp.op_ret);
+ op_errno = gf_error_to_errno (ntoh32 (hdr->rsp.op_errno));
+
+ if (op_ret < 0 && op_errno == ENOTCONN) {
+ gf_log (this->name, GF_LOG_ERROR,
+ "setvolume failed (%s)",
+ strerror (op_errno));
+ goto out;
+ }
+
+ reply = dict_new ();
+ GF_VALIDATE_OR_GOTO(this->name, reply, out);
+
+ dict_len = ntoh32 (rsp->dict_len);
+ ret = dict_unserialize (rsp->buf, dict_len, &reply);
+ if (ret < 0) {
+ gf_log (frame->this->name, GF_LOG_ERROR,
+ "failed to unserialize buffer(%p) to dictionary",
+ rsp->buf);
+ goto out;
+ }
+
+ ret = dict_get_str (reply, "ERROR", &remote_error);
+ if (ret < 0) {
+ gf_log (this->name, GF_LOG_ERROR,
+ "failed to get ERROR string from reply dictionary");
+ }
+
+ 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 dictionary");
+ }
+
+ if (op_ret < 0) {
+ gf_log (trans->xl->name, GF_LOG_ERROR,
+ "SETVOLUME on remote-host failed: %s",
+ remote_error ? remote_error : strerror (op_errno));
+ errno = op_errno;
+ if (op_errno == ENOTCONN)
+ goto out;
+ } else {
+ ctx = get_global_ctx_ptr ();
+ if (process_uuid && !strcmp (ctx->process_uuid,process_uuid)) {
+ ret = dict_get_str (this->options, "remote-subvolume",
+ &remote_subvol);
+ if (!remote_subvol)
+ goto out;
+
+ gf_log (this->name, GF_LOG_WARNING,
+ "attaching to the local volume '%s'",
+ remote_subvol);
+
+ /* TODO: */
+ conf->child = xlator_search_by_name (this,
+ remote_subvol);
+ }
+ gf_log (trans->xl->name, GF_LOG_INFO,
+ "connection and handshake succeeded");
+
+ pthread_mutex_lock (&(conn->lock));
+ {
+ conn->connected = 1;
+ }
+ pthread_mutex_unlock (&(conn->lock));
+
+ parent = trans->xl->parents;
+ while (parent) {
+ parent->xlator->notify (parent->xlator,
+ GF_EVENT_CHILD_UP,
+ trans->xl);
+ parent = parent->next;
+ }
+ }
+
+out:
+ STACK_DESTROY (frame->root);
+
+ if (reply)
+ dict_unref (reply);
+
+ return op_ret;
+}
+
+/*
+ * client_enosys_cbk -
+ * @frame: call frame
+ *
+ * not for external reference
+ */
+int
+client_enosys_cbk (call_frame_t *frame,
+ gf_hdr_common_t *hdr, size_t hdrlen,
+ char *buf, size_t buflen)
+{
+ STACK_DESTROY (frame->root);
+ return 0;
+}
+
+
+void
+client_protocol_reconnect (void *trans_ptr)
+{
+ transport_t *trans = NULL;
+ client_connection_t *conn = NULL;
+ struct timeval tv = {0, 0};
+
+ trans = trans_ptr;
+ conn = trans->xl_private;
+ pthread_mutex_lock (&conn->lock);
+ {
+ if (conn->reconnect)
+ gf_timer_call_cancel (trans->xl->ctx,
+ conn->reconnect);
+ conn->reconnect = 0;
+
+ if (conn->connected == 0) {
+ tv.tv_sec = 10;
+
+ gf_log (trans->xl->name, GF_LOG_DEBUG,
+ "attempting reconnect");
+ transport_connect (trans);
+
+ conn->reconnect =
+ gf_timer_call_after (trans->xl->ctx, tv,
+ client_protocol_reconnect,
+ trans);
+ } else {
+ gf_log (trans->xl->name, GF_LOG_DEBUG,
+ "breaking reconnect chain");
+ }
+ }
+ pthread_mutex_unlock (&conn->lock);
+}
+
+/*
+ * client_protocol_cleanup - cleanup function
+ * @trans: transport object
+ *
+ */
+int
+protocol_client_cleanup (transport_t *trans)
+{
+ client_connection_t *conn = NULL;
+ struct saved_frames *saved_frames = NULL;
+
+ conn = trans->xl_private;
+
+ gf_log (trans->xl->name, GF_LOG_DEBUG,
+ "cleaning up state in transport object %p", trans);
+
+ pthread_mutex_lock (&conn->lock);
+ {
+ saved_frames = conn->saved_frames;
+ conn->saved_frames = saved_frames_new ();
+
+/*
+ trav = conn->saved_fds->members_list;
+ this = trans->xl;
+
+ while (trav) {
+ fd_t *fd_tmp = (fd_t *)(long) strtoul (trav->key,
+ NULL, 0);
+ fd_ctx_del (fd_tmp, this, NULL);
+ trav = trav->next;
+ }
+
+ dict_destroy (conn->saved_fds);
+
+ conn->saved_fds = get_new_dict_full (64);
+*/
+ /* bailout logic cleanup */
+ memset (&(conn->last_sent), 0,
+ sizeof (conn->last_sent));
+
+ memset (&(conn->last_received), 0,
+ sizeof (conn->last_received));
+
+ if (conn->timer) {
+ gf_timer_call_cancel (trans->xl->ctx, conn->timer);
+ conn->timer = NULL;
+ }
+
+ if (conn->reconnect == NULL) {
+ /* :O This part is empty.. any thing missing? */
+ }
+ }
+ pthread_mutex_unlock (&conn->lock);
+
+ saved_frames_destroy (trans->xl, saved_frames,
+ gf_fops, gf_mops, gf_cbks);
+
+ return 0;
+}
+
+
+/* cbk callbacks */
+int
+client_releasedir_cbk (call_frame_t *frame,
+ gf_hdr_common_t *hdr, size_t hdrlen,
+ char *buf, size_t buflen)
+{
+ STACK_DESTROY (frame->root);
+ return 0;
+}
+
+
+int
+client_release_cbk (call_frame_t *frame,
+ gf_hdr_common_t *hdr, size_t hdrlen,
+ char *buf, size_t buflen)
+{
+ STACK_DESTROY (frame->root);
+ return 0;
+}
+
+
+int
+client_forget_cbk (call_frame_t *frame,
+ gf_hdr_common_t *hdr, size_t hdrlen,
+ char *buf, size_t buflen)
+{
+ client_conf_t *conf = NULL;
+ client_forget_t forget = {0, };
+ uint8_t send_forget = 0;
+ int32_t ret = -1;
+
+
+ conf = frame->this->private;
+ LOCK (&conf->forget.lock);
+ {
+ conf->forget.frames_in_transit--;
+
+ ret = client_get_forgets (frame->this, &forget);
+ if (ret <= 0)
+ send_forget = 0;
+ else
+ send_forget = 1;
+ }
+ UNLOCK (&conf->forget.lock);
+
+ if (send_forget) {
+ ret = protocol_client_xfer (forget.frame, frame->this,
+ CLIENT_CHANNEL (frame->this,
+ CHANNEL_BULK),
+ GF_OP_TYPE_CBK_REQUEST,
+ GF_CBK_FORGET,
+ forget.hdr, forget.hdrlen,
+ NULL, 0, NULL);
+ }
+
+ STACK_DESTROY (frame->root);
+ return 0;
+}
+
+
+static gf_op_t gf_fops[] = {
+ [GF_FOP_STAT] = client_stat_cbk,
+ [GF_FOP_READLINK] = client_readlink_cbk,
+ [GF_FOP_MKNOD] = client_mknod_cbk,
+ [GF_FOP_MKDIR] = client_mkdir_cbk,
+ [GF_FOP_UNLINK] = client_unlink_cbk,
+ [GF_FOP_RMDIR] = client_rmdir_cbk,
+ [GF_FOP_SYMLINK] = client_symlink_cbk,
+ [GF_FOP_RENAME] = client_rename_cbk,
+ [GF_FOP_LINK] = client_link_cbk,
+ [GF_FOP_CHMOD] = client_chmod_cbk,
+ [GF_FOP_CHOWN] = client_chown_cbk,
+ [GF_FOP_TRUNCATE] = client_truncate_cbk,
+ [GF_FOP_OPEN] = client_open_cbk,
+ [GF_FOP_READ] = client_readv_cbk,
+ [GF_FOP_WRITE] = client_write_cbk,
+ [GF_FOP_STATFS] = client_statfs_cbk,
+ [GF_FOP_FLUSH] = client_flush_cbk,
+ [GF_FOP_FSYNC] = client_fsync_cbk,
+ [GF_FOP_SETXATTR] = client_setxattr_cbk,
+ [GF_FOP_GETXATTR] = client_getxattr_cbk,
+ [GF_FOP_REMOVEXATTR] = client_removexattr_cbk,
+ [GF_FOP_OPENDIR] = client_opendir_cbk,
+ [GF_FOP_GETDENTS] = client_getdents_cbk,
+ [GF_FOP_FSYNCDIR] = client_fsyncdir_cbk,
+ [GF_FOP_ACCESS] = client_access_cbk,
+ [GF_FOP_CREATE] = client_create_cbk,
+ [GF_FOP_FTRUNCATE] = client_ftruncate_cbk,
+ [GF_FOP_FSTAT] = client_fstat_cbk,
+ [GF_FOP_LK] = client_lk_common_cbk,
+ [GF_FOP_UTIMENS] = client_utimens_cbk,
+ [GF_FOP_FCHMOD] = client_fchmod_cbk,
+ [GF_FOP_FCHOWN] = client_fchown_cbk,
+ [GF_FOP_LOOKUP] = client_lookup_cbk,
+ [GF_FOP_SETDENTS] = client_setdents_cbk,
+ [GF_FOP_READDIR] = client_readdir_cbk,
+ [GF_FOP_INODELK] = client_inodelk_cbk,
+ [GF_FOP_FINODELK] = client_finodelk_cbk,
+ [GF_FOP_ENTRYLK] = client_entrylk_cbk,
+ [GF_FOP_FENTRYLK] = client_fentrylk_cbk,
+ [GF_FOP_CHECKSUM] = client_checksum_cbk,
+ [GF_FOP_XATTROP] = client_xattrop_cbk,
+ [GF_FOP_FXATTROP] = client_fxattrop_cbk,
+};
+
+static gf_op_t gf_mops[] = {
+ [GF_MOP_SETVOLUME] = client_setvolume_cbk,
+ [GF_MOP_GETVOLUME] = client_enosys_cbk,
+ [GF_MOP_STATS] = client_stats_cbk,
+ [GF_MOP_SETSPEC] = client_setspec_cbk,
+ [GF_MOP_GETSPEC] = client_getspec_cbk,
+ [GF_MOP_PING] = client_ping_cbk,
+};
+
+static gf_op_t gf_cbks[] = {
+ [GF_CBK_FORGET] = client_forget_cbk,
+ [GF_CBK_RELEASE] = client_release_cbk,
+ [GF_CBK_RELEASEDIR] = client_releasedir_cbk
+};
+
+/*
+ * client_protocol_interpret - protocol interpreter
+ * @trans: transport object
+ * @blk: data block
+ *
+ */
+int
+protocol_client_interpret (xlator_t *this, transport_t *trans,
+ char *hdr_p, size_t hdrlen,
+ char *buf_p, size_t buflen)
+{
+ int ret = -1;
+ call_frame_t *frame = NULL;
+ gf_hdr_common_t *hdr = NULL;
+ uint64_t callid = 0;
+ int type = -1;
+ int op = -1;
+
+
+ hdr = (gf_hdr_common_t *)hdr_p;
+
+ type = ntoh32 (hdr->type);
+ op = ntoh32 (hdr->op);
+ callid = ntoh64 (hdr->callid);
+
+ frame = lookup_frame (trans, op, type, callid);
+ if (frame == NULL) {
+ gf_log (this->name, GF_LOG_ERROR,
+ "no frame for callid=%"PRId64" type=%d op=%d",
+ callid, type, op);
+ return 0;
+ }
+
+ switch (type) {
+ case GF_OP_TYPE_FOP_REPLY:
+ if ((op > GF_FOP_MAXVALUE) ||
+ (op < 0)) {
+ gf_log (trans->xl->name, GF_LOG_WARNING,
+ "invalid fop '%d'", op);
+ } else {
+ ret = gf_fops[op] (frame, hdr, hdrlen, buf_p, buflen);
+ }
+ break;
+ case GF_OP_TYPE_MOP_REPLY:
+ if ((op > GF_MOP_MAXVALUE) ||
+ (op < 0)) {
+ gf_log (trans->xl->name, GF_LOG_WARNING,
+ "invalid fop '%d'", op);
+ } else {
+ ret = gf_mops[op] (frame, hdr, hdrlen, buf_p, buflen);
+ }
+ break;
+ case GF_OP_TYPE_CBK_REPLY:
+ if ((op > GF_CBK_MAXVALUE) ||
+ (op < 0)) {
+ gf_log (trans->xl->name, GF_LOG_WARNING,
+ "invalid cbk '%d'", op);
+ } else {
+ ret = gf_cbks[op] (frame, hdr, hdrlen, buf_p, buflen);
+ }
+ break;
+ default:
+ gf_log (trans->xl->name, GF_LOG_ERROR,
+ "invalid packet type: %d", type);
+ break;
+ }
+
+ return ret;
+}
+
+/*
+ * init - initiliazation function. called during loading of client protocol
+ * @this:
+ *
+ */
+int32_t
+init (xlator_t *this)
+{
+ transport_t *trans = NULL;
+ client_conf_t *conf = NULL;
+ client_connection_t *conn = NULL;
+ int32_t transport_timeout = 0;
+ int32_t ping_timeout = 0;
+ data_t *remote_subvolume = NULL;
+ int32_t ret = -1;
+ int i = 0;
+
+ if (this->children) {
+ gf_log (this->name, GF_LOG_ERROR,
+ "FATAL: client protocol translator cannot have "
+ "subvolumes");
+ goto out;
+ }
+
+ if (!this->parents) {
+ gf_log (this->name, GF_LOG_WARNING,
+ "dangling volume. check volfile ");
+ }
+
+ remote_subvolume = dict_get (this->options, "remote-subvolume");
+ if (remote_subvolume == NULL) {
+ gf_log (this->name, GF_LOG_ERROR,
+ "missing 'option remote-subvolume'.");
+ goto out;
+ }
+
+ ret = dict_get_int32 (this->options, "transport-timeout",
+ &transport_timeout);
+ if (ret >= 0) {
+ gf_log (this->name, GF_LOG_DEBUG,
+ "setting transport-timeout to %d", transport_timeout);
+ } else {
+ gf_log (this->name, GF_LOG_DEBUG,
+ "defaulting transport-timeout to 42");
+ transport_timeout = 42;
+ }
+
+ ret = dict_get_int32 (this->options, "ping-timeout",
+ &ping_timeout);
+ if (ret >= 0) {
+ gf_log (this->name, GF_LOG_DEBUG,
+ "setting ping-timeout to %d", ping_timeout);
+ } else {
+ gf_log (this->name, GF_LOG_DEBUG,
+ "defaulting ping-timeout to 10");
+ ping_timeout = 10;
+ }
+
+ conf = CALLOC (1, sizeof (client_conf_t));
+
+ LOCK_INIT (&conf->forget.lock);
+ pthread_mutex_init (&conf->mutex, NULL);
+ conf->saved_fds = get_new_dict_full (64);
+
+ this->private = conf;
+
+ for (i = 0; i < CHANNEL_MAX; i++) {
+ trans = transport_load (this->options, this);
+ if (trans == NULL) {
+ gf_log (this->name, GF_LOG_ERROR,
+ "Failed to load transport");
+ ret = -1;
+ goto out;
+ }
+
+ conn = CALLOC (1, sizeof (*conn));
+
+ conn->saved_frames = saved_frames_new ();
+
+ conn->callid = 1;
+
+ memset (&(conn->last_sent), 0, sizeof (conn->last_sent));
+ memset (&(conn->last_received), 0,
+ sizeof (conn->last_received));
+
+ conn->transport_timeout = transport_timeout;
+ conn->ping_timeout = ping_timeout;
+
+ pthread_mutex_init (&conn->lock, NULL);
+
+ trans->xl_private = conn;
+ conf->transport[i] = transport_ref (trans);
+ }
+
+#ifndef GF_DARWIN_HOST_OS
+ {
+ struct rlimit lim;
+
+ lim.rlim_cur = 1048576;
+ lim.rlim_max = 1048576;
+
+ ret = setrlimit (RLIMIT_NOFILE, &lim);
+ if (ret == -1) {
+ gf_log (this->name, GF_LOG_WARNING,
+ "WARNING: Failed to set 'ulimit -n 1M': %s",
+ strerror(errno));
+ lim.rlim_cur = 65536;
+ lim.rlim_max = 65536;
+
+ ret = setrlimit (RLIMIT_NOFILE, &lim);
+ if (ret == -1) {
+ gf_log (this->name, GF_LOG_ERROR,
+ "Failed to set max open fd to 64k: %s",
+ strerror(errno));
+ } else {
+ gf_log (this->name, GF_LOG_ERROR,
+ "max open fd set to 64k");
+ }
+
+ }
+ }
+#endif
+ ret = 0;
+out:
+ return ret;
+}
+
+/*
+ * fini - finish function called during unloading of client protocol
+ * @this:
+ *
+ */
+void
+fini (xlator_t *this)
+{
+ /* TODO: Check if its enough.. how to call transport's fini () */
+ client_conf_t *conf = NULL;
+
+ conf = this->private;
+ this->private = NULL;
+
+ if (conf) {
+ LOCK_DESTROY (&conf->forget.lock);
+ FREE (conf);
+ }
+ return;
+}
+
+
+int
+protocol_client_handshake (xlator_t *this, transport_t *trans)
+{
+ gf_hdr_common_t *hdr = NULL;
+ gf_mop_setvolume_req_t *req = NULL;
+ dict_t *options = NULL;
+ int32_t ret = -1;
+ int hdrlen = 0;
+ int dict_len = 0;
+ call_frame_t *fr = NULL;
+ char *process_uuid_xl;
+
+ options = this->options;
+ ret = dict_set_str (options, "version", PACKAGE_VERSION);
+ if (ret < 0) {
+ gf_log (this->name, GF_LOG_ERROR,
+ "failed to set version(%s) in options dictionary",
+ PACKAGE_VERSION);
+ }
+
+ asprintf (&process_uuid_xl, "%s-%s", this->ctx->process_uuid,
+ this->name);
+ 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 options dictionary",
+ PACKAGE_VERSION);
+ }
+
+ dict_len = dict_serialized_length (options);
+ if (dict_len < 0) {
+ gf_log (this->name, GF_LOG_ERROR,
+ "failed to get serialized length of dict(%p)",
+ options);
+ ret = dict_len;
+ goto fail;
+ }
+
+ hdrlen = gf_hdr_len (req, dict_len);
+ hdr = gf_hdr_new (req, dict_len);
+ GF_VALIDATE_OR_GOTO(this->name, hdr, fail);
+
+ req = gf_param (hdr);
+
+ ret = dict_serialize (options, req->buf);
+ if (ret < 0) {
+ gf_log (this->name, GF_LOG_ERROR,
+ "failed to serialize dictionary(%p)",
+ options);
+ goto fail;
+ }
+
+ req->dict_len = hton32 (dict_len);
+ fr = create_frame (this, this->ctx->pool);
+ GF_VALIDATE_OR_GOTO(this->name, fr, fail);
+
+ fr->local = trans;
+ ret = protocol_client_xfer (fr, this, trans,
+ GF_OP_TYPE_MOP_REQUEST, GF_MOP_SETVOLUME,
+ hdr, hdrlen, NULL, 0, NULL);
+ return ret;
+fail:
+ if (hdr)
+ free (hdr);
+ return ret;
+}
+
+
+int
+protocol_client_pollout (xlator_t *this, transport_t *trans)
+{
+ client_connection_t *conn = NULL;
+
+ conn = trans->xl_private;
+
+ pthread_mutex_lock (&conn->lock);
+ {
+ gettimeofday (&conn->last_sent, NULL);
+ }
+ pthread_mutex_unlock (&conn->lock);
+
+ return 0;
+}
+
+
+int
+protocol_client_pollin (xlator_t *this, transport_t *trans)
+{
+ client_connection_t *conn = NULL;
+ int ret = -1;
+ char *buf = NULL;
+ size_t buflen = 0;
+ char *hdr = NULL;
+ size_t hdrlen = 0;
+ int connected = 0;
+
+ conn = trans->xl_private;
+
+ pthread_mutex_lock (&conn->lock);
+ {
+ gettimeofday (&conn->last_received, NULL);
+ connected = conn->connected;
+ }
+ pthread_mutex_unlock (&conn->lock);
+
+ ret = transport_receive (trans, &hdr, &hdrlen, &buf, &buflen);
+
+ if (ret == 0)
+ {
+ ret = protocol_client_interpret (this, trans, hdr, hdrlen,
+ buf, buflen);
+ }
+
+ /* TODO: use mem-pool */
+ FREE (hdr);
+
+ return ret;
+}
+
+
+/*
+ * client_protocol_notify - notify function for client protocol
+ * @this:
+ * @trans: transport object
+ * @event
+ *
+ */
+
+int32_t
+notify (xlator_t *this,
+ int32_t event,
+ void *data,
+ ...)
+{
+ int ret = -1;
+ transport_t *trans = NULL;
+ client_connection_t *conn = NULL;
+
+ trans = data;
+
+ switch (event) {
+ case GF_EVENT_POLLOUT:
+ {
+ ret = protocol_client_pollout (this, trans);
+
+ break;
+ }
+ case GF_EVENT_POLLIN:
+ {
+ ret = protocol_client_pollin (this, trans);
+
+ break;
+ }
+ /* no break for ret check to happen below */
+ case GF_EVENT_POLLERR:
+ {
+ ret = -1;
+ protocol_client_cleanup (trans);
+ }
+
+ conn = trans->xl_private;
+ if (conn->connected) {
+ xlator_list_t *parent = NULL;
+
+ gf_log (this->name, GF_LOG_INFO, "disconnected");
+
+ parent = this->parents;
+ while (parent) {
+ parent->xlator->notify (parent->xlator,
+ GF_EVENT_CHILD_DOWN,
+ this);
+ parent = parent->next;
+ }
+
+ conn->connected = 0;
+ if (conn->reconnect == 0)
+ client_protocol_reconnect (trans);
+ }
+ break;
+
+ case GF_EVENT_PARENT_UP:
+ {
+ xlator_list_t *parent = NULL;
+ client_conf_t *conf = NULL;
+ int i = 0;
+ transport_t *trans = NULL;
+
+ conf = this->private;
+ for (i = 0; i < CHANNEL_MAX; i++) {
+ trans = conf->transport[i];
+ if (!trans) {
+ gf_log (this->name, GF_LOG_DEBUG,
+ "transport init failed");
+ return -1;
+ }
+
+ conn = trans->xl_private;
+
+ gf_log (this->name, GF_LOG_DEBUG,
+ "got GF_EVENT_PARENT_UP, attempting connect "
+ "on transport");
+
+ client_protocol_reconnect (trans);
+ }
+
+ /* Let the connection/re-connection happen in
+ * background, for now, don't hang here,
+ * tell the parents that i am all ok..
+ */
+ parent = trans->xl->parents;
+ while (parent) {
+ parent->xlator->notify (parent->xlator,
+ GF_EVENT_CHILD_CONNECTING,
+ trans->xl);
+ parent = parent->next;
+ }
+ }
+ break;
+
+ case GF_EVENT_CHILD_UP:
+ {
+ char *handshake = NULL;
+
+ ret = dict_get_str (this->options, "disable-handshake",
+ &handshake);
+ gf_log (this->name, GF_LOG_DEBUG,
+ "got GF_EVENT_CHILD_UP");
+ if ((ret < 0) ||
+ (strcasecmp (handshake, "on"))) {
+ ret = protocol_client_handshake (this, trans);
+ } else {
+ conn = trans->xl_private;
+ conn->connected = 1;
+ ret = default_notify (this, event, trans);
+ }
+
+ if (ret)
+ transport_disconnect (trans);
+
+ }
+ break;
+
+ default:
+ gf_log (this->name, GF_LOG_DEBUG,
+ "got %d, calling default_notify ()", event);
+
+ default_notify (this, event, data);
+ break;
+ }
+
+ return ret;
+}
+
+
+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,
+ .chmod = client_chmod,
+ .chown = client_chown,
+ .truncate = client_truncate,
+ .utimens = client_utimens,
+ .open = client_open,
+ .readv = client_readv,
+ .writev = client_writev,
+ .statfs = client_statfs,
+ .flush = client_flush,
+ .fsync = client_fsync,
+ .setxattr = client_setxattr,
+ .getxattr = client_getxattr,
+ .removexattr = client_removexattr,
+ .opendir = client_opendir,
+ .readdir = client_readdir,
+ .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,
+ .fchmod = client_fchmod,
+ .fchown = client_fchown,
+ .setdents = client_setdents,
+ .getdents = client_getdents,
+ .checksum = client_checksum,
+ .xattrop = client_xattrop,
+ .fxattrop = client_fxattrop,
+};
+
+struct xlator_mops mops = {
+ .stats = client_stats,
+ .getspec = client_getspec,
+};
+
+struct xlator_cbks cbks = {
+ .forget = client_forget,
+ .release = client_release,
+ .releasedir = client_releasedir
+};
+
+
+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_ANY
+ },
+ { .key = {"remote-subvolume"},
+ .type = GF_OPTION_TYPE_ANY
+ },
+ { .key = {"transport-timeout"},
+ .type = GF_OPTION_TYPE_TIME,
+ .min = 5,
+ .max = 1013,
+ },
+ { .key = {"ping-timeout"},
+ .type = GF_OPTION_TYPE_TIME,
+ .min = 5,
+ .max = 1013,
+ },
+ { .key = {NULL} },
+};
diff --git a/xlators/protocol/client/src/client-protocol.h b/xlators/protocol/client/src/client-protocol.h
new file mode 100644
index 00000000000..c90cc980d83
--- /dev/null
+++ b/xlators/protocol/client/src/client-protocol.h
@@ -0,0 +1,173 @@
+/*
+ Copyright (c) 2006, 2007 Z RESEARCH, Inc. <http://www.zresearch.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_PROTOCOL_H
+#define _CLIENT_PROTOCOL_H
+
+#ifndef _CONFIG_H
+#define _CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <arpa/inet.h>
+#include "inode.h"
+#include "timer.h"
+#include "byte-order.h"
+
+#define CLIENT_PROTO_FORGET_LIMIT 128
+#define CLIENT_PORT_CIELING 1023
+
+#define GF_CLIENT_INODE_SELF 0
+#define GF_CLIENT_INODE_PARENT 1
+
+#define CLIENT_CONF(this) ((client_conf_t *)(this->private))
+
+#define RECEIVE_TIMEOUT(_cprivate,_current) \
+ ((_cprivate->last_received.tv_sec + \
+ _cprivate->transport_timeout) < \
+ _current.tv_sec)
+
+#define SEND_TIMEOUT(_cprivate,_current) \
+ ((_cprivate->last_sent.tv_sec + \
+ _cprivate->transport_timeout) < \
+ _current.tv_sec)
+
+enum {
+ CHANNEL_BULK = 0,
+ CHANNEL_LOWLAT = 1,
+ CHANNEL_MAX
+};
+#define CLIENT_CHANNEL(xl,id) \
+ (((client_conf_t *)(xl->private))->transport[id])
+
+struct client_connection;
+typedef struct client_connection client_connection_t;
+
+#include "stack.h"
+#include "xlator.h"
+#include "transport.h"
+#include "protocol.h"
+
+struct _client_conf {
+ transport_t *transport[CHANNEL_MAX];
+ xlator_t *child;
+
+ /* enhancement for 'forget', a must required where lot
+ of stats happening */
+ struct {
+ uint64_t ino_array[CLIENT_PROTO_FORGET_LIMIT + 4];
+ uint32_t count;
+ uint32_t frames_in_transit;
+ gf_lock_t lock;
+ } forget;
+ dict_t *saved_fds;
+ pthread_mutex_t mutex;
+};
+typedef struct _client_conf client_conf_t;
+
+/* This will be stored in transport_t->xl_private */
+struct client_connection {
+ pthread_mutex_t lock;
+ uint64_t callid;
+ struct saved_frames *saved_frames;
+ int32_t transport_timeout;
+ int32_t ping_started;
+ int32_t ping_timeout;
+ gf_timer_t *reconnect;
+ char connected;
+ uint64_t max_block_size;
+ struct timeval last_sent;
+ struct timeval last_received;
+ gf_timer_t *timer;
+ gf_timer_t *ping_timer;
+};
+
+typedef struct {
+ loc_t loc;
+ loc_t loc2;
+ fd_t *fd;
+} client_local_t;
+
+typedef struct {
+ gf_hdr_common_t *hdr;
+ size_t hdrlen;
+ call_frame_t *frame;
+} client_forget_t;
+
+static inline void
+gf_string_to_stat(char *string, struct stat *stbuf)
+{
+ uint64_t dev = 0;
+ uint64_t ino = 0;
+ uint32_t mode = 0;
+ uint32_t nlink = 0;
+ uint32_t uid = 0;
+ uint32_t gid = 0;
+ uint64_t rdev = 0;
+ uint64_t size = 0;
+ uint32_t blksize = 0;
+ uint64_t blocks = 0;
+ uint32_t atime = 0;
+ uint32_t atime_nsec = 0;
+ uint32_t mtime = 0;
+ uint32_t mtime_nsec = 0;
+ uint32_t ctime = 0;
+ uint32_t ctime_nsec = 0;
+
+ sscanf (string, GF_STAT_PRINT_FMT_STR,
+ &dev,
+ &ino,
+ &mode,
+ &nlink,
+ &uid,
+ &gid,
+ &rdev,
+ &size,
+ &blksize,
+ &blocks,
+ &atime,
+ &atime_nsec,
+ &mtime,
+ &mtime_nsec,
+ &ctime,
+ &ctime_nsec);
+
+ stbuf->st_dev = dev;
+ stbuf->st_ino = ino;
+ stbuf->st_mode = mode;
+ stbuf->st_nlink = nlink;
+ stbuf->st_uid = uid;
+ stbuf->st_gid = gid;
+ stbuf->st_rdev = rdev;
+ stbuf->st_size = size;
+ stbuf->st_blksize = blksize;
+ stbuf->st_blocks = blocks;
+
+ stbuf->st_atime = atime;
+ stbuf->st_mtime = mtime;
+ stbuf->st_ctime = ctime;
+
+ ST_ATIM_NSEC_SET(stbuf, atime_nsec);
+ ST_MTIM_NSEC_SET(stbuf, mtime_nsec);
+ ST_CTIM_NSEC_SET(stbuf, ctime_nsec);
+
+}
+
+#endif
diff --git a/xlators/protocol/client/src/saved-frames.c b/xlators/protocol/client/src/saved-frames.c
new file mode 100644
index 00000000000..0d1366d8222
--- /dev/null
+++ b/xlators/protocol/client/src/saved-frames.c
@@ -0,0 +1,178 @@
+/*
+ Copyright (c) 2008 Z RESEARCH, Inc. <http://www.zresearch.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/>.
+*/
+
+
+#include "saved-frames.h"
+#include "common-utils.h"
+#include "protocol.h"
+#include "xlator.h"
+
+
+
+struct saved_frames *
+saved_frames_new (void)
+{
+ struct saved_frames *saved_frames = NULL;
+
+ saved_frames = CALLOC (sizeof (*saved_frames), 1);
+ if (!saved_frames) {
+ return NULL;
+ }
+
+ INIT_LIST_HEAD (&saved_frames->fops.list);
+ INIT_LIST_HEAD (&saved_frames->mops.list);
+ INIT_LIST_HEAD (&saved_frames->cbks.list);
+
+ return saved_frames;
+}
+
+
+struct saved_frame *
+get_head_frame_for_type (struct saved_frames *frames, int8_t type)
+{
+ struct saved_frame *head_frame = NULL;
+
+ switch (type) {
+ case GF_OP_TYPE_FOP_REQUEST:
+ case GF_OP_TYPE_FOP_REPLY:
+ head_frame = &frames->fops;
+ break;
+ case GF_OP_TYPE_MOP_REQUEST:
+ case GF_OP_TYPE_MOP_REPLY:
+ head_frame = &frames->mops;
+ break;
+ case GF_OP_TYPE_CBK_REQUEST:
+ case GF_OP_TYPE_CBK_REPLY:
+ head_frame = &frames->cbks;
+ break;
+ }
+
+ return head_frame;
+}
+
+
+int
+saved_frames_put (struct saved_frames *frames, call_frame_t *frame,
+ int32_t op, int8_t type, int64_t callid)
+{
+ struct saved_frame *saved_frame = NULL;
+ struct saved_frame *head_frame = NULL;
+
+ head_frame = get_head_frame_for_type (frames, type);
+
+ saved_frame = CALLOC (sizeof (*saved_frame), 1);
+ if (!saved_frame) {
+ return -ENOMEM;
+ }
+
+ INIT_LIST_HEAD (&saved_frame->list);
+ saved_frame->frame = frame;
+ saved_frame->op = op;
+ saved_frame->type = type;
+ saved_frame->callid = callid;
+
+// gettimeofday (&saved_frame->saved_at, NULL);
+
+ list_add (&saved_frame->list, &head_frame->list);
+ frames->count++;
+
+ return 0;
+}
+
+
+call_frame_t *
+saved_frames_get (struct saved_frames *frames, int32_t op,
+ int8_t type, int64_t callid)
+{
+ struct saved_frame *saved_frame = NULL;
+ struct saved_frame *tmp = NULL;
+ struct saved_frame *head_frame = NULL;
+ call_frame_t *frame = NULL;
+
+ head_frame = get_head_frame_for_type (frames, type);
+
+ list_for_each_entry (tmp, &head_frame->list, list) {
+ if (tmp->callid == callid) {
+ list_del_init (&tmp->list);
+ frames->count--;
+ saved_frame = tmp;
+ break;
+ }
+ }
+
+ if (saved_frame)
+ frame = saved_frame->frame;
+
+ FREE (saved_frame);
+
+ return frame;
+}
+
+
+void
+saved_frames_unwind (xlator_t *this, struct saved_frames *saved_frames,
+ struct saved_frame *head,
+ gf_op_t gf_ops[], char *gf_op_list[])
+{
+ struct saved_frame *trav = NULL;
+ struct saved_frame *tmp = NULL;
+
+ gf_hdr_common_t hdr = {0, };
+ call_frame_t *frame = NULL;
+ dict_t *reply = NULL;
+
+ reply = get_new_dict();
+ dict_ref (reply);
+
+ hdr.rsp.op_ret = hton32 (-1);
+ hdr.rsp.op_errno = hton32 (ENOTCONN);
+
+ list_for_each_entry_safe (trav, tmp, &head->list, list) {
+ gf_log (this->name, GF_LOG_ERROR,
+ "forced unwinding frame type(%d) op(%s)",
+ trav->type, gf_op_list[trav->op]);
+
+ hdr.type = hton32 (trav->type);
+ hdr.op = hton32 (trav->op);
+
+ frame = trav->frame;
+ frame->root->rsp_refs = reply;
+
+ saved_frames->count--;
+
+ gf_ops[trav->op] (frame, &hdr, sizeof (hdr), NULL, 0);
+
+ list_del_init (&trav->list);
+ FREE (trav);
+ }
+
+ dict_unref (reply);
+}
+
+
+void
+saved_frames_destroy (xlator_t *this, struct saved_frames *frames,
+ gf_op_t gf_fops[], gf_op_t gf_mops[], gf_op_t gf_cbks[])
+{
+ saved_frames_unwind (this, frames, &frames->fops, gf_fops, gf_fop_list);
+ saved_frames_unwind (this, frames, &frames->mops, gf_mops, gf_mop_list);
+ saved_frames_unwind (this, frames, &frames->cbks, gf_cbks, gf_cbk_list);
+
+ FREE (frames);
+}
diff --git a/xlators/protocol/client/src/saved-frames.h b/xlators/protocol/client/src/saved-frames.h
new file mode 100644
index 00000000000..e402feba33b
--- /dev/null
+++ b/xlators/protocol/client/src/saved-frames.h
@@ -0,0 +1,74 @@
+/*
+ Copyright (c) 2008 Z RESEARCH, Inc. <http://www.zresearch.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 _SAVED_FRAMES_H
+#define _SAVED_FRAMES_H
+
+#ifndef _CONFIG_H
+#define _CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdint.h>
+#include <sys/time.h>
+#include "stack.h"
+#include "list.h"
+#include "protocol.h"
+
+/* UGLY: have common typedef b/w saved-frames.c and protocol-client.c */
+typedef int32_t (*gf_op_t) (call_frame_t *frame,
+ gf_hdr_common_t *hdr, size_t hdrlen,
+ char *buf, size_t buflen);
+
+
+struct saved_frame {
+ union {
+ struct list_head list;
+ struct {
+ struct saved_frame *frame_next;
+ struct saved_frame *frame_prev;
+ };
+ };
+
+ struct timeval saved_at;
+ call_frame_t *frame;
+ int32_t op;
+ int8_t type;
+ uint64_t callid;
+};
+
+
+struct saved_frames {
+ int64_t count;
+ struct saved_frame fops;
+ struct saved_frame mops;
+ struct saved_frame cbks;
+};
+
+
+struct saved_frames *saved_frames_new ();
+int saved_frames_put (struct saved_frames *frames, call_frame_t *frame,
+ int32_t op, int8_t type, int64_t callid);
+call_frame_t *saved_frames_get (struct saved_frames *frames, int32_t op,
+ int8_t type, int64_t callid);
+void saved_frames_destroy (xlator_t *this, struct saved_frames *frames,
+ gf_op_t gf_fops[], gf_op_t gf_mops[],
+ gf_op_t gf_cbks[]);
+
+#endif /* _SAVED_FRAMES_H */
diff --git a/xlators/protocol/server/Makefile.am b/xlators/protocol/server/Makefile.am
new file mode 100644
index 00000000000..d471a3f9243
--- /dev/null
+++ b/xlators/protocol/server/Makefile.am
@@ -0,0 +1,3 @@
+SUBDIRS = src
+
+CLEANFILES =
diff --git a/xlators/protocol/server/src/Makefile.am b/xlators/protocol/server/src/Makefile.am
new file mode 100644
index 00000000000..dcd92aeedd9
--- /dev/null
+++ b/xlators/protocol/server/src/Makefile.am
@@ -0,0 +1,18 @@
+
+xlator_LTLIBRARIES = server.la
+xlatordir = $(libdir)/glusterfs/$(PACKAGE_VERSION)/xlator/protocol
+
+server_la_LDFLAGS = -module -avoidversion
+
+server_la_SOURCES = server-protocol.c server-dentry.c server-helpers.c
+server_la_LIBADD = $(top_builddir)/libglusterfs/src/libglusterfs.la
+
+noinst_HEADERS = server-protocol.h server-helpers.h
+
+AM_CFLAGS = -fPIC -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE -Wall -D$(GF_HOST_OS) \
+ -I$(top_srcdir)/libglusterfs/src -shared -nostartfiles \
+ -DDATADIR=\"$(localstatedir)\" -DCONFDIR=\"$(sysconfdir)/glusterfs\" \
+ $(GF_CFLAGS)
+
+CLEANFILES =
+
diff --git a/xlators/protocol/server/src/server-dentry.c b/xlators/protocol/server/src/server-dentry.c
new file mode 100644
index 00000000000..d3a69a393fc
--- /dev/null
+++ b/xlators/protocol/server/src/server-dentry.c
@@ -0,0 +1,413 @@
+#include "glusterfs.h"
+#include "xlator.h"
+#include "server-protocol.h"
+#include "server-helpers.h"
+#include <libgen.h>
+
+/* SERVER_DENTRY_STATE_PREPARE - prepare a fresh state for use
+ *
+ * @state - an empty state
+ * @loc - loc_t which needs to resolved
+ * @parent - most immediate parent of @loc available in dentry cache
+ * @resolved - component of @loc->path which has been resolved
+ * through dentry cache
+ */
+#define SERVER_DENTRY_STATE_PREPARE(_state,_loc,_parent,_resolved) do { \
+ size_t pathlen = 0; \
+ size_t resolvedlen = 0; \
+ char *path = NULL; \
+ int pad = 0; \
+ pathlen = strlen (_loc->path) + 1; \
+ path = CALLOC (1, pathlen); \
+ _state->loc.parent = inode_ref (_parent); \
+ _state->loc.inode = inode_new (_state->itable); \
+ if (_resolved) { \
+ resolvedlen = strlen (_resolved); \
+ strncpy (path, _resolved, resolvedlen); \
+ _state->resolved = memdup (path, pathlen); \
+ if (resolvedlen == 1) /* only root resolved */ \
+ pad = 0; \
+ else { \
+ pad = 1; \
+ path[resolvedlen] = '/'; \
+ } \
+ strcpy_till (path + resolvedlen + pad, loc->path + resolvedlen + pad, '/'); \
+ } else { \
+ strncpy (path, _loc->path, pathlen); \
+ } \
+ _state->loc.path = path; \
+ _state->loc.name = strrchr (path, '/'); \
+ if (_state->loc.name) \
+ _state->loc.name++; \
+ _state->path = strdup (_loc->path); \
+ }while (0);
+
+/* SERVER_DENTRY_UPDATE_STATE - update a server_state_t, to prepare state
+ * for new lookup
+ *
+ * @state - state to be updated.
+ */
+#define SERVER_DENTRY_UPDATE_STATE(_state) do { \
+ char *path = NULL; \
+ size_t pathlen = 0; \
+ strcpy (_state->resolved, _state->loc.path); \
+ pathlen = strlen (_state->loc.path); \
+ if (!strcmp (_state->resolved, _state->path)) { \
+ free (_state->resolved); \
+ _state->resolved = NULL; \
+ goto resume; \
+ } \
+ \
+ path = (char *)(_state->loc.path + pathlen); \
+ path[0] = '/'; \
+ strcpy_till (path + 1, \
+ _state->path + pathlen + 1, '/'); \
+ _state->loc.name = strrchr (_state->loc.path, '/'); \
+ if (_state->loc.name) \
+ _state->loc.name++; \
+ inode_unref (_state->loc.parent); \
+ _state->loc.parent = inode_ref (_state->loc.inode); \
+ inode_unref (_state->loc.inode); \
+ _state->loc.inode = inode_new (_state->itable); \
+ }while (0);
+
+/* NOTE: should be used only for a state which was created by __do_path_resolve
+ * using any other state will result in double free corruption.
+ */
+#define SERVER_STATE_CLEANUP(_state) do { \
+ if (_state->resolved) \
+ free (_state->resolved); \
+ if (_state->path) \
+ free (_state->path); \
+ server_loc_wipe (&_state->loc); \
+ free_state (_state); \
+ } while (0);
+
+/* strcpy_till - copy @dname to @dest, until 'delim' is encountered in @dest
+ * @dest - destination string
+ * @dname - source string
+ * @delim - delimiter character
+ *
+ * return - NULL is returned if '0' is encountered in @dname, otherwise returns
+ * a pointer to remaining string begining in @dest.
+ */
+static char *
+strcpy_till (char *dest, const char *dname, char delim)
+{
+ char *src = NULL;
+ int idx = 0;
+ char *ret = NULL;
+
+ src = (char *)dname;
+ while (src[idx] && (src[idx] != delim)) {
+ dest[idx] = src[idx];
+ idx++;
+ }
+
+ dest[idx] = 0;
+
+ if (src[idx] == 0)
+ ret = NULL;
+ else
+ ret = &(src[idx]);
+
+ return ret;
+}
+
+/* __server_path_to_parenti - derive parent inode for @path. if immediate parent is
+ * not available in the dentry cache, return nearest
+ * available parent inode and set @reslv to the path of
+ * the returned directory.
+ *
+ * @itable - inode table
+ * @path - path whose parent has to be looked up.
+ * @reslv - if immediate parent is not available, reslv will be set to path of the
+ * resolved parent.
+ *
+ * return - should never return NULL. should at least return '/' inode.
+ */
+static inode_t *
+__server_path_to_parenti (inode_table_t *itable,
+ const char *path,
+ char **reslv)
+{
+ char *resolved_till = NULL;
+ char *strtokptr = NULL;
+ char *component = NULL;
+ char *next_component = NULL;
+ char *pathdup = NULL;
+ inode_t *curr = NULL;
+ inode_t *parent = NULL;
+ size_t pathlen = 0;
+
+
+ pathlen = STRLEN_0 (path);
+ resolved_till = CALLOC (1, pathlen);
+
+ GF_VALIDATE_OR_GOTO("server-dentry", resolved_till, out);
+ pathdup = strdup (path);
+ GF_VALIDATE_OR_GOTO("server-dentry", pathdup, out);
+
+ parent = inode_ref (itable->root);
+ curr = NULL;
+
+ component = strtok_r (pathdup, "/", &strtokptr);
+
+ while (component) {
+ curr = inode_search (itable, parent->ino, component);
+ if (!curr) {
+ /* if current component was the last component
+ set it to NULL
+ */
+ component = strtok_r (NULL, "/", &strtokptr);
+ break;
+ }
+
+ /* It is OK to append the component even if it is the
+ last component in the path, because, if 'next_component'
+ returns NULL, @parent will remain the same and
+ @resolved_till will not be sent back
+ */
+
+ strcat (resolved_till, "/");
+ strcat (resolved_till, component);
+
+ next_component = strtok_r (NULL, "/", &strtokptr);
+
+ if (next_component) {
+ inode_unref (parent);
+ parent = curr;
+ curr = NULL;
+ } else {
+ /* will break */
+ inode_unref (curr);
+ }
+
+ component = next_component;
+ }
+
+ free (pathdup);
+
+ if (component) {
+ *reslv = resolved_till;
+ } else {
+ free (resolved_till);
+ }
+out:
+ return parent;
+}
+
+
+/* __do_path_resolve_cbk -
+ *
+ * @frame -
+ * @cookie -
+ * @this -
+ * @op_ret -
+ * @op_errno -
+ * @inode -
+ * @stbuf -
+ * @dict -
+ *
+ */
+static int32_t
+__do_path_resolve_cbk (call_frame_t *frame,
+ void *cookie,
+ xlator_t *this,
+ int32_t op_ret,
+ int32_t op_errno,
+ inode_t *inode,
+ struct stat *stbuf,
+ dict_t *dict)
+{
+ server_state_t *state = NULL;
+ call_stub_t *stub = NULL;
+ inode_t *parent = NULL;
+
+ stub = frame->local;
+ state = CALL_STATE(frame);
+
+ parent = state->loc.parent;
+
+ if (op_ret == -1) {
+ if (strcmp (state->path, state->loc.path))
+ parent = NULL;
+
+ server_stub_resume (stub, op_ret, op_errno, NULL, parent);
+ goto cleanup;
+ } else {
+ if (inode->ino == 0) {
+ gf_log (BOUND_XL(frame)->name, GF_LOG_DEBUG,
+ "looked up for %s (%"PRId64"/%s)",
+ state->loc.path, state->loc.parent->ino, state->loc.name);
+ inode_link (inode, state->loc.parent, state->loc.name, stbuf);
+ inode_lookup (inode);
+ }
+
+ if (state->resolved) {
+ SERVER_DENTRY_UPDATE_STATE(state);
+
+ gf_log (BOUND_XL(frame)->name, GF_LOG_DEBUG,
+ "looking up for %s (%"PRId64"/%s)",
+ state->loc.path, state->loc.parent->ino, state->loc.name);
+
+ STACK_WIND (frame,
+ __do_path_resolve_cbk,
+ BOUND_XL(frame),
+ BOUND_XL(frame)->fops->lookup,
+ &(state->loc),
+ 0);
+
+ goto out;
+ }
+ resume:
+ /* we are done, call stub_resume() to do rest of the job */
+ server_stub_resume (stub, op_ret, op_errno, inode, parent);
+ cleanup:
+ SERVER_STATE_CLEANUP(state);
+ /* stub will be freed by stub_resume, leave no traces */
+ frame->local = NULL;
+ STACK_DESTROY (frame->root);
+ }
+out:
+ return 0;
+}
+
+/* __do_path_resolve - resolve @loc->path into @loc->inode and @loc->parent. also
+ * update the dentry cache
+ *
+ * @stub - call stub to resume after resolving @loc->path
+ * @loc - loc to resolve before resuming @stub.
+ *
+ * return - return value of __do_path_resolve doesn't matter to the caller, if @stub
+ * is not NULL.
+ */
+static int32_t
+__do_path_resolve (call_stub_t *stub,
+ const loc_t *loc)
+{
+ int32_t ret = -1;
+ char *resolved = NULL;
+ call_frame_t *new_frame = NULL;
+ server_state_t *state = NULL, *new_state = NULL;
+ inode_t *parent = NULL;
+
+ state = CALL_STATE(stub->frame);
+ parent = loc->parent;
+ if (parent) {
+ inode_ref (parent);
+ gf_log (BOUND_XL(stub->frame)->name, GF_LOG_DEBUG,
+ "loc->parent(%"PRId64") already present. sending lookup "
+ "for %"PRId64"/%s", parent->ino, parent->ino, loc->name);
+ resolved = strdup (loc->path);
+ resolved = dirname (resolved);
+ } else {
+ parent = __server_path_to_parenti (state->itable, loc->path, &resolved);
+ }
+
+ if (parent == NULL) {
+ /* fire in the bush.. run! run!! run!!! */
+ gf_log ("server",
+ GF_LOG_CRITICAL,
+ "failed to get parent inode number");
+ goto panic;
+ }
+
+ if (resolved) {
+ gf_log (BOUND_XL(stub->frame)->name,
+ GF_LOG_DEBUG,
+ "resolved path(%s) till %"PRId64"(%s). "
+ "sending lookup for remaining path",
+ loc->path, parent->ino, resolved);
+ }
+
+ {
+ new_frame = server_copy_frame (stub->frame);
+ new_state = CALL_STATE(new_frame);
+
+ SERVER_DENTRY_STATE_PREPARE(new_state, loc, parent, resolved);
+
+ if (parent)
+ inode_unref (parent); /* __server_path_to_parenti()'s inode_ref */
+ free (resolved);
+ /* now interpret state as:
+ * state->path - compelete pathname to resolve
+ * state->resolved - pathname resolved from dentry cache
+ */
+ new_frame->local = stub;
+ STACK_WIND (new_frame,
+ __do_path_resolve_cbk,
+ BOUND_XL(new_frame),
+ BOUND_XL(new_frame)->fops->lookup,
+ &(new_state->loc),
+ 0);
+ goto out;
+ }
+panic:
+ server_stub_resume (stub, -1, ENOENT, NULL, NULL);
+out:
+ return ret;
+}
+
+
+/*
+ * do_path_lookup - transform a pathname into inode, with the compelete
+ * dentry tree upto inode built.
+ *
+ * @stub - call stub to resume after completing pathname to inode transform
+ * @loc - location. valid fields that do_path_lookup() uses in @loc are
+ * @loc->path - pathname
+ * @loc->ino - inode number
+ *
+ * return - do_path_lookup returns only after complete dentry tree is built
+ * upto @loc->path.
+ */
+int32_t
+do_path_lookup (call_stub_t *stub,
+ const loc_t *loc)
+{
+ char *pathname = NULL;
+ char *directory = NULL;
+ inode_t *inode = NULL;
+ inode_t *parent = NULL;
+ server_state_t *state = NULL;
+
+ state = CALL_STATE(stub->frame);
+
+ inode = inode_from_path (state->itable, loc->path);
+ pathname = strdup (loc->path);
+ directory = dirname (pathname);
+ parent = inode_from_path (state->itable, directory);
+
+ if (inode && parent) {
+ gf_log (BOUND_XL(stub->frame)->name,
+ GF_LOG_DEBUG,
+ "resolved path(%s) to %"PRId64"/%"PRId64"(%s)",
+ loc->path, parent->ino, inode->ino, loc->name);
+ server_stub_resume (stub, 0, 0, inode, parent);
+ inode_unref (inode);
+ inode_unref (parent);
+ } else {
+ gf_log (BOUND_XL(stub->frame)->name,
+ GF_LOG_DEBUG,
+ "resolved path(%s) to %p(%"PRId64")/%p(%"PRId64")",
+ loc->path, parent, (parent ? parent->ino : 0),
+ inode, (inode ? inode->ino : 0));
+ if (parent) {
+ inode_unref (parent);
+ } else if (inode) {
+ inode_unref (inode);
+ gf_log (BOUND_XL(stub->frame)->name,
+ GF_LOG_ERROR,
+ "undesired behaviour. inode(%"PRId64") for %s "
+ "exists without parent (%s)",
+ inode->ino, loc->path, directory);
+ }
+ __do_path_resolve (stub, loc);
+ }
+
+ if (pathname)
+ free (pathname);
+
+ return 0;
+}
diff --git a/xlators/protocol/server/src/server-helpers.c b/xlators/protocol/server/src/server-helpers.c
new file mode 100644
index 00000000000..b51c11aa994
--- /dev/null
+++ b/xlators/protocol/server/src/server-helpers.c
@@ -0,0 +1,586 @@
+/*
+ Copyright (c) 2006, 2007, 2008 Z RESEARCH, Inc. <http://www.zresearch.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 "server-protocol.h"
+#include "server-helpers.h"
+
+
+/* server_loc_fill - derive a loc_t for a given inode number
+ *
+ * NOTE: make sure that @loc is empty, because any pointers it holds with reference will
+ * be leaked after returning from here.
+ */
+int
+server_loc_fill (loc_t *loc, server_state_t *state,
+ ino_t ino, ino_t par,
+ const char *name, const char *path)
+{
+ inode_t *inode = NULL;
+ inode_t *parent = NULL;
+ int32_t ret = -1;
+ char *dentry_path = NULL;
+
+
+ GF_VALIDATE_OR_GOTO ("server", loc, out);
+ GF_VALIDATE_OR_GOTO ("server", state, out);
+ GF_VALIDATE_OR_GOTO ("server", path, out);
+
+ /* anything beyond this point is success */
+ ret = 0;
+ loc->ino = ino;
+ inode = loc->inode;
+ if (inode == NULL) {
+ if (ino)
+ inode = inode_search (state->itable, ino, NULL);
+
+ if ((inode == NULL) &&
+ (par && name))
+ inode = inode_search (state->itable, par, name);
+
+ loc->inode = inode;
+ if (inode)
+ loc->ino = inode->ino;
+ }
+
+ parent = loc->parent;
+ if (parent == NULL) {
+ if (inode)
+ parent = inode_parent (inode, par, name);
+ else
+ parent = inode_search (state->itable, par, NULL);
+ loc->parent = parent;
+ }
+
+ if (name && parent) {
+ ret = inode_path (parent, name, &dentry_path);
+ if (ret < 0) {
+ gf_log (state->bound_xl->name, GF_LOG_DEBUG,
+ "failed to build path for %"PRId64"/%s: %s",
+ parent->ino, name, strerror (-ret));
+ }
+ } else if (inode) {
+ ret = inode_path (inode, NULL, &dentry_path);
+ if (ret < 0) {
+ gf_log (state->bound_xl->name, GF_LOG_DEBUG,
+ "failed to build path for %"PRId64": %s",
+ inode->ino, strerror (-ret));
+
+ inode_unref (loc->inode);
+ loc->inode = NULL;
+ }
+ }
+
+ if (dentry_path) {
+ if (strcmp (dentry_path, path)) {
+ gf_log (state->bound_xl->name, GF_LOG_DEBUG,
+ "paths differ for inode(%"PRId64"): "
+ "client path = %s. dentry path = %s",
+ ino, path, dentry_path);
+ }
+
+ loc->path = dentry_path;
+ loc->name = strrchr (loc->path, '/');
+ if (loc->name)
+ loc->name++;
+ } else {
+ loc->path = strdup (path);
+ loc->name = strrchr (loc->path, '/');
+ if (loc->name)
+ loc->name++;
+ }
+
+out:
+ return ret;
+}
+
+/*
+ * stat_to_str - convert struct stat to a ASCII string
+ * @stbuf: struct stat pointer
+ *
+ * not for external reference
+ */
+char *
+stat_to_str (struct stat *stbuf)
+{
+ char *tmp_buf = NULL;
+
+ uint64_t dev = stbuf->st_dev;
+ uint64_t ino = stbuf->st_ino;
+ uint32_t mode = stbuf->st_mode;
+ uint32_t nlink = stbuf->st_nlink;
+ uint32_t uid = stbuf->st_uid;
+ uint32_t gid = stbuf->st_gid;
+ uint64_t rdev = stbuf->st_rdev;
+ uint64_t size = stbuf->st_size;
+ uint32_t blksize = stbuf->st_blksize;
+ uint64_t blocks = stbuf->st_blocks;
+ uint32_t atime = stbuf->st_atime;
+ uint32_t mtime = stbuf->st_mtime;
+ uint32_t ctime = stbuf->st_ctime;
+
+ uint32_t atime_nsec = ST_ATIM_NSEC(stbuf);
+ uint32_t mtime_nsec = ST_MTIM_NSEC(stbuf);
+ uint32_t ctime_nsec = ST_CTIM_NSEC(stbuf);
+
+
+ asprintf (&tmp_buf,
+ GF_STAT_PRINT_FMT_STR,
+ dev,
+ ino,
+ mode,
+ nlink,
+ uid,
+ gid,
+ rdev,
+ size,
+ blksize,
+ blocks,
+ atime,
+ atime_nsec,
+ mtime,
+ mtime_nsec,
+ ctime,
+ ctime_nsec);
+
+ return tmp_buf;
+}
+
+
+void
+server_loc_wipe (loc_t *loc)
+{
+ if (loc->parent)
+ inode_unref (loc->parent);
+ if (loc->inode)
+ inode_unref (loc->inode);
+ if (loc->path)
+ free ((char *)loc->path);
+}
+
+void
+free_state (server_state_t *state)
+{
+ transport_t *trans = NULL;
+
+ trans = state->trans;
+
+ if (state->fd)
+ fd_unref (state->fd);
+
+ transport_unref (trans);
+
+ if (state->xattr_req)
+ dict_unref (state->xattr_req);
+
+ FREE (state);
+}
+
+
+call_frame_t *
+server_copy_frame (call_frame_t *frame)
+{
+ call_frame_t *new_frame = NULL;
+ server_state_t *state = NULL, *new_state = NULL;
+
+ state = frame->root->state;
+
+ new_frame = copy_frame (frame);
+
+ new_state = CALLOC (1, sizeof (server_state_t));
+
+ new_frame->root->op = frame->root->op;
+ new_frame->root->type = frame->root->type;
+ new_frame->root->trans = state->trans;
+ new_frame->root->state = new_state;
+
+ new_state->bound_xl = state->bound_xl;
+ new_state->trans = transport_ref (state->trans);
+ new_state->itable = state->itable;
+
+ return new_frame;
+}
+
+int32_t
+gf_add_locker (struct _lock_table *table,
+ loc_t *loc,
+ fd_t *fd,
+ pid_t pid)
+{
+ int32_t ret = -1;
+ struct _locker *new = NULL;
+ uint8_t dir = 0;
+
+ new = CALLOC (1, sizeof (struct _locker));
+ if (new == NULL) {
+ gf_log ("server", GF_LOG_ERROR,
+ "failed to allocate memory for \'struct _locker\'");
+ goto out;
+ }
+ INIT_LIST_HEAD (&new->lockers);
+
+ if (fd == NULL) {
+ loc_copy (&new->loc, loc);
+ dir = S_ISDIR (new->loc.inode->st_mode);
+ } else {
+ new->fd = fd_ref (fd);
+ dir = S_ISDIR (fd->inode->st_mode);
+ }
+
+ new->pid = pid;
+
+ LOCK (&table->lock);
+ {
+ if (dir)
+ list_add_tail (&new->lockers, &table->dir_lockers);
+ else
+ list_add_tail (&new->lockers, &table->file_lockers);
+ }
+ UNLOCK (&table->lock);
+out:
+ return ret;
+}
+
+int32_t
+gf_del_locker (struct _lock_table *table,
+ loc_t *loc,
+ fd_t *fd,
+ pid_t pid)
+{
+ struct _locker *locker = NULL, *tmp = NULL;
+ int32_t ret = 0;
+ uint8_t dir = 0;
+ struct list_head *head = NULL;
+ struct list_head del;
+
+ INIT_LIST_HEAD (&del);
+
+ if (fd) {
+ dir = S_ISDIR (fd->inode->st_mode);
+ } else {
+ dir = S_ISDIR (loc->inode->st_mode);
+ }
+
+ LOCK (&table->lock);
+ {
+ if (dir) {
+ head = &table->dir_lockers;
+ } else {
+ head = &table->file_lockers;
+ }
+
+ list_for_each_entry_safe (locker, tmp, head, lockers) {
+ if (locker->fd &&
+ fd &&
+ (locker->fd == fd) && (locker->pid == pid)) {
+ list_move_tail (&locker->lockers, &del);
+ } else if (locker->loc.inode &&
+ loc &&
+ (locker->loc.inode == loc->inode) &&
+ (locker->pid == pid)) {
+ list_move_tail (&locker->lockers, &del);
+ }
+ }
+ }
+ UNLOCK (&table->lock);
+
+ tmp = NULL;
+ locker = NULL;
+
+ list_for_each_entry_safe (locker, tmp, &del, lockers) {
+ list_del_init (&locker->lockers);
+ if (locker->fd)
+ fd_unref (locker->fd);
+ else
+ loc_wipe (&locker->loc);
+
+ free (locker);
+ }
+
+ return ret;
+}
+
+int32_t
+gf_direntry_to_bin (dir_entry_t *head,
+ char **bufferp)
+{
+ dir_entry_t *trav = NULL;
+ uint32_t len = 0;
+ uint32_t this_len = 0;
+ char *buffer = NULL;
+ size_t buflen = -1;
+ char *ptr = NULL;
+ char *tmp_buf = NULL;
+
+ trav = head->next;
+ while (trav) {
+ len += strlen (trav->name);
+ len += 1;
+ len += strlen (trav->link);
+ len += 1; /* for '\n' */
+ len += 256; // max possible for statbuf;
+ trav = trav->next;
+ }
+
+ buffer = CALLOC (1, len);
+ if (buffer == NULL) {
+ gf_log ("server", GF_LOG_ERROR,
+ "failed to allocate memory for buffer");
+ goto out;
+ }
+
+ ptr = buffer;
+ trav = head->next;
+ while (trav) {
+ tmp_buf = stat_to_str (&trav->buf);
+ /* tmp_buf will have \n before \0 */
+
+ this_len = sprintf (ptr, "%s/%s%s\n",
+ trav->name, tmp_buf,
+ trav->link);
+
+ FREE (tmp_buf);
+ trav = trav->next;
+ ptr += this_len;
+ }
+ if (bufferp)
+ *bufferp = buffer;
+ buflen = strlen (buffer);
+
+out:
+ return buflen;
+}
+
+
+static struct _lock_table *
+gf_lock_table_new (void)
+{
+ struct _lock_table *new = NULL;
+
+ new = CALLOC (1, sizeof (struct _lock_table));
+ if (new == NULL) {
+ gf_log ("server-protocol", GF_LOG_CRITICAL,
+ "failed to allocate memory for new lock table");
+ goto out;
+ }
+ INIT_LIST_HEAD (&new->dir_lockers);
+ INIT_LIST_HEAD (&new->file_lockers);
+ LOCK_INIT (&new->lock);
+out:
+ return new;
+}
+
+
+int
+server_connection_destroy (xlator_t *this, server_connection_t *conn)
+{
+
+ call_frame_t *frame = NULL, *tmp_frame = NULL;
+ xlator_t *bound_xl = NULL;
+ int32_t ret = -1;
+ server_state_t *state = NULL;
+ struct list_head file_lockers;
+ struct list_head dir_lockers;
+ struct _lock_table *ltable = NULL;
+ struct _locker *locker = NULL, *tmp = NULL;
+ struct flock flock = {0,};
+
+
+ bound_xl = (xlator_t *) (conn->bound_xl);
+
+ if (bound_xl) {
+ /* trans will have ref_count = 1 after this call, but its
+ ok since this function is called in
+ GF_EVENT_TRANSPORT_CLEANUP */
+ frame = create_frame (this, this->ctx->pool);
+
+ pthread_mutex_lock (&(conn->lock));
+ {
+ if (conn->ltable) {
+ ltable = conn->ltable;
+ conn->ltable = NULL;
+ }
+ }
+ pthread_mutex_unlock (&conn->lock);
+
+ INIT_LIST_HEAD (&file_lockers);
+ INIT_LIST_HEAD (&dir_lockers);
+
+ LOCK (&ltable->lock);
+ {
+ list_splice_init (&ltable->file_lockers,
+ &file_lockers);
+
+ list_splice_init (&ltable->dir_lockers, &dir_lockers);
+ }
+ UNLOCK (&ltable->lock);
+ free (ltable);
+
+ flock.l_type = F_UNLCK;
+ flock.l_start = 0;
+ flock.l_len = 0;
+ list_for_each_entry_safe (locker,
+ tmp, &file_lockers, lockers) {
+ tmp_frame = copy_frame (frame);
+ /*
+ pid = 0 is a special case that tells posix-locks
+ to release all locks from this transport
+ */
+ tmp_frame->root->pid = 0;
+ tmp_frame->root->trans = conn;
+
+ if (locker->fd) {
+ STACK_WIND (tmp_frame, server_nop_cbk,
+ bound_xl,
+ bound_xl->fops->finodelk,
+ locker->fd, F_SETLK, &flock);
+ fd_unref (locker->fd);
+ } else {
+ STACK_WIND (tmp_frame, server_nop_cbk,
+ bound_xl,
+ bound_xl->fops->inodelk,
+ &(locker->loc), F_SETLK, &flock);
+ loc_wipe (&locker->loc);
+ }
+
+ list_del_init (&locker->lockers);
+ free (locker);
+ }
+
+ tmp = NULL;
+ locker = NULL;
+ list_for_each_entry_safe (locker, tmp, &dir_lockers, lockers) {
+ tmp_frame = copy_frame (frame);
+
+ tmp_frame->root->pid = 0;
+ tmp_frame->root->trans = conn;
+
+ if (locker->fd) {
+ STACK_WIND (tmp_frame, server_nop_cbk,
+ bound_xl,
+ bound_xl->fops->fentrylk,
+ locker->fd, NULL,
+ ENTRYLK_UNLOCK, ENTRYLK_WRLCK);
+ fd_unref (locker->fd);
+ } else {
+ STACK_WIND (tmp_frame, server_nop_cbk,
+ bound_xl,
+ bound_xl->fops->entrylk,
+ &(locker->loc), NULL,
+ ENTRYLK_UNLOCK, ENTRYLK_WRLCK);
+ loc_wipe (&locker->loc);
+ }
+
+ list_del_init (&locker->lockers);
+ free (locker);
+ }
+
+ state = CALL_STATE (frame);
+ if (state)
+ free (state);
+ STACK_DESTROY (frame->root);
+
+ pthread_mutex_lock (&(conn->lock));
+ {
+ if (conn->fdtable) {
+ gf_fd_fdtable_destroy (conn->fdtable);
+ conn->fdtable = NULL;
+ }
+ }
+ pthread_mutex_unlock (&conn->lock);
+
+ }
+
+ gf_log (this->name, GF_LOG_INFO, "destroyed connection of %s",
+ conn->id);
+
+ FREE (conn->id);
+ FREE (conn);
+
+ return ret;
+}
+
+
+server_connection_t *
+server_connection_get (xlator_t *this, const char *id)
+{
+ server_connection_t *conn = NULL;
+ server_connection_t *trav = NULL;
+ server_conf_t *conf = NULL;
+
+ conf = this->private;
+
+ pthread_mutex_lock (&conf->mutex);
+ {
+ list_for_each_entry (trav, &conf->conns, list) {
+ if (!strcmp (id, trav->id)) {
+ conn = trav;
+ break;
+ }
+ }
+
+ if (!conn) {
+ conn = (void *) CALLOC (1, sizeof (*conn));
+
+ conn->id = strdup (id);
+ conn->fdtable = gf_fd_fdtable_alloc ();
+ conn->ltable = gf_lock_table_new ();
+
+ pthread_mutex_init (&conn->lock, NULL);
+
+ list_add (&conn->list, &conf->conns);
+ }
+
+ conn->ref++;
+ }
+ pthread_mutex_unlock (&conf->mutex);
+
+ return conn;
+}
+
+
+void
+server_connection_put (xlator_t *this, server_connection_t *conn)
+{
+ server_conf_t *conf = NULL;
+ server_connection_t *todel = NULL;
+
+ conf = this->private;
+
+ pthread_mutex_lock (&conf->mutex);
+ {
+ conn->ref--;
+
+ if (!conn->ref) {
+ list_del_init (&conn->list);
+ todel = conn;
+ }
+ }
+ pthread_mutex_unlock (&conf->mutex);
+
+ if (todel) {
+ server_connection_destroy (this, todel);
+ }
+
+ return;
+}
diff --git a/xlators/protocol/server/src/server-helpers.h b/xlators/protocol/server/src/server-helpers.h
new file mode 100644
index 00000000000..36c0ce98e40
--- /dev/null
+++ b/xlators/protocol/server/src/server-helpers.h
@@ -0,0 +1,77 @@
+/*
+ Copyright (c) 2006, 2007, 2008 Z RESEARCH, Inc. <http://www.zresearch.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 __SERVER_HELPERS_H__
+#define __SERVER_HELPERS_H__
+
+#define CALL_STATE(frame) ((server_state_t *)frame->root->state)
+
+#define BOUND_XL(frame) ((xlator_t *) CALL_STATE(frame)->bound_xl)
+
+#define TRANSPORT_FROM_FRAME(frame) ((transport_t *) CALL_STATE(frame)->trans)
+
+#define SERVER_CONNECTION(frame) \
+ ((server_connection_t *) TRANSPORT_FROM_FRAME(frame)->xl_private)
+
+#define SERVER_CONF(frame) \
+ ((server_conf_t *)TRANSPORT_FROM_FRAME(frame)->xl->private)
+
+#define TRANSPORT_FROM_XLATOR(this) ((((server_conf_t *)this->private))->trans)
+
+#define INODE_LRU_LIMIT(this) \
+ (((server_conf_t *)(this->private))->inode_lru_limit)
+
+#define IS_ROOT_INODE(inode) (inode == inode->table->root)
+
+#define IS_NOT_ROOT(pathlen) ((pathlen > 2)? 1 : 0)
+
+int32_t
+server_loc_fill (loc_t *loc,
+ server_state_t *state,
+ ino_t ino,
+ ino_t par,
+ const char *name,
+ const char *path);
+
+char *
+stat_to_str (struct stat *stbuf);
+
+call_frame_t *
+server_copy_frame (call_frame_t *frame);
+
+void free_state (server_state_t *state);
+
+void server_loc_wipe (loc_t *loc);
+
+int32_t
+gf_add_locker (struct _lock_table *table,
+ loc_t *loc,
+ fd_t *fd,
+ pid_t pid);
+
+int32_t
+gf_del_locker (struct _lock_table *table,
+ loc_t *loc,
+ fd_t *fd,
+ pid_t pid);
+
+int32_t
+gf_direntry_to_bin (dir_entry_t *head,
+ char **bufferp);
+#endif /* __SERVER_HELPERS_H__ */
diff --git a/xlators/protocol/server/src/server-protocol.c b/xlators/protocol/server/src/server-protocol.c
new file mode 100644
index 00000000000..a5198c1ed07
--- /dev/null
+++ b/xlators/protocol/server/src/server-protocol.c
@@ -0,0 +1,7984 @@
+/*
+ Copyright (c) 2006, 2007, 2008 Z RESEARCH, Inc. <http://www.zresearch.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 <time.h>
+#include <sys/uio.h>
+#include <sys/resource.h>
+
+#include <libgen.h>
+
+#include "transport.h"
+#include "fnmatch.h"
+#include "xlator.h"
+#include "protocol.h"
+#include "server-protocol.h"
+#include "server-helpers.h"
+#include "call-stub.h"
+#include "defaults.h"
+#include "list.h"
+#include "dict.h"
+#include "compat.h"
+#include "compat-errno.h"
+
+
+static void
+protocol_server_reply (call_frame_t *frame,
+ int type, int op,
+ gf_hdr_common_t *hdr, size_t hdrlen,
+ struct iovec *vector, int count,
+ dict_t *refs)
+{
+ server_state_t *state = NULL;
+ xlator_t *bound_xl = NULL;
+ transport_t *trans = NULL;
+
+ bound_xl = BOUND_XL(frame);
+ state = CALL_STATE(frame);
+ trans = state->trans;
+
+ hdr->callid = hton64 (frame->root->unique);
+ hdr->type = hton32 (type);
+ hdr->op = hton32 (op);
+
+ transport_submit (trans, (char *)hdr, hdrlen, vector, count, refs);
+ /* TODO: If transport submit fails, there is no reply sent to client,
+ * its bailed out as of now.. loggically, only this frame should fail.
+ */
+
+ STACK_DESTROY (frame->root);
+
+ if (state)
+ free_state (state);
+
+}
+
+
+/*
+ * server_fchmod_cbk
+ */
+int32_t
+server_fchmod_cbk (call_frame_t *frame,
+ void *cookie,
+ xlator_t *this,
+ int32_t op_ret,
+ int32_t op_errno,
+ struct stat *stbuf)
+{
+ gf_hdr_common_t *hdr = NULL;
+ gf_fop_fchmod_rsp_t *rsp = NULL;
+ size_t hdrlen = 0;
+ int32_t gf_errno = 0;
+ server_state_t *state = NULL;
+
+ hdrlen = gf_hdr_len (rsp, 0);
+ hdr = gf_hdr_new (rsp, 0);
+ rsp = gf_param (hdr);
+
+ hdr->rsp.op_ret = hton32 (op_ret);
+ gf_errno = gf_errno_to_error (op_errno);
+ hdr->rsp.op_errno = hton32 (gf_errno);
+
+ if (op_ret == 0) {
+ gf_stat_from_stat (&rsp->stat, stbuf);
+ } else {
+ state = CALL_STATE(frame);
+
+ gf_log (this->name, GF_LOG_DEBUG,
+ "%"PRId64": FCHMOD %"PRId64" (%"PRId64") ==> %"PRId32" (%s)",
+ frame->root->unique, state->fd_no,
+ state->fd ? state->fd->inode->ino : 0, op_ret,
+ strerror (op_errno));
+ }
+
+ protocol_server_reply (frame, GF_OP_TYPE_FOP_REPLY, GF_FOP_FCHMOD,
+ hdr, hdrlen, NULL, 0, NULL);
+
+ return 0;
+}
+
+/*
+ * server_fchmod
+ *
+ */
+int32_t
+server_fchmod (call_frame_t *frame,
+ xlator_t *bound_xl,
+ gf_hdr_common_t *hdr, size_t hdrlen,
+ char *buf, size_t buflen)
+{
+ server_connection_t *conn = NULL;
+ gf_fop_fchmod_req_t *req = NULL;
+ server_state_t *state = NULL;
+
+ conn = SERVER_CONNECTION(frame);
+
+ req = gf_param (hdr);
+ state = CALL_STATE(frame);
+ {
+ state->fd_no = ntoh64 (req->fd);
+ if (state->fd_no >= 0)
+ state->fd = gf_fd_fdptr_get (conn->fdtable,
+ state->fd_no);
+
+ state->mode = ntoh32 (req->mode);
+ }
+
+ GF_VALIDATE_OR_GOTO(bound_xl->name, state->fd, fail);
+
+ STACK_WIND (frame,
+ server_fchmod_cbk,
+ BOUND_XL(frame),
+ BOUND_XL(frame)->fops->fchmod,
+ state->fd,
+ state->mode);
+
+ return 0;
+fail:
+ server_fchmod_cbk (frame, NULL, frame->this,
+ -1, EINVAL, NULL);
+ return 0;
+}
+
+
+/*
+ * server_fchown_cbk
+ */
+int32_t
+server_fchown_cbk (call_frame_t *frame,
+ void *cookie,
+ xlator_t *this,
+ int32_t op_ret,
+ int32_t op_errno,
+ struct stat *stbuf)
+{
+ gf_hdr_common_t *hdr = NULL;
+ gf_fop_fchown_rsp_t *rsp = NULL;
+ size_t hdrlen = 0;
+ int32_t gf_errno = 0;
+ server_state_t *state = NULL;
+
+ hdrlen = gf_hdr_len (rsp, 0);
+ hdr = gf_hdr_new (rsp, 0);
+ rsp = gf_param (hdr);
+
+ hdr->rsp.op_ret = hton32 (op_ret);
+ gf_errno = gf_errno_to_error (op_errno);
+ hdr->rsp.op_errno = hton32 (gf_errno);
+
+ if (op_ret == 0) {
+ gf_stat_from_stat (&rsp->stat, stbuf);
+ } else {
+ state = CALL_STATE(frame);
+
+ gf_log (this->name, GF_LOG_DEBUG,
+ "%"PRId64": FCHOWN %"PRId64" (%"PRId64") ==> %"PRId32" (%s)",
+ frame->root->unique, state->fd_no,
+ state->fd ? state->fd->inode->ino : 0, op_ret,
+ strerror (op_errno));
+ }
+
+ protocol_server_reply (frame, GF_OP_TYPE_FOP_REPLY, GF_FOP_FCHOWN,
+ hdr, hdrlen, NULL, 0, NULL);
+
+ return 0;
+}
+
+/*
+ * server_fchown
+ *
+ */
+int32_t
+server_fchown (call_frame_t *frame,
+ xlator_t *bound_xl,
+ gf_hdr_common_t *hdr, size_t hdrlen,
+ char *buf, size_t buflen)
+{
+ server_connection_t *conn = NULL;
+ gf_fop_fchown_req_t *req = NULL;
+ server_state_t *state = NULL;
+
+ conn = SERVER_CONNECTION(frame);
+
+ req = gf_param (hdr);
+ state = CALL_STATE(frame);
+ {
+ state->fd_no = ntoh64 (req->fd);
+ if (state->fd_no >= 0)
+ state->fd = gf_fd_fdptr_get (conn->fdtable,
+ state->fd_no);
+
+ state->uid = ntoh32 (req->uid);
+ state->gid = ntoh32 (req->gid);
+ }
+
+ GF_VALIDATE_OR_GOTO(bound_xl->name, state->fd, fail);
+
+ STACK_WIND (frame,
+ server_fchown_cbk,
+ BOUND_XL(frame),
+ BOUND_XL(frame)->fops->fchown,
+ state->fd,
+ state->uid,
+ state->gid);
+
+ return 0;
+fail:
+ server_fchown_cbk (frame, NULL, frame->this,
+ -1, EINVAL, NULL);
+ return 0;
+}
+
+/*
+ * server_setdents_cbk - writedir callback for server protocol
+ * @frame: call frame
+ * @cookie:
+ * @this:
+ * @op_ret: return value
+ * @op_errno: errno
+ *
+ * not for external reference
+ */
+int32_t
+server_setdents_cbk (call_frame_t *frame,
+ void *cookie,
+ xlator_t *this,
+ int32_t op_ret,
+ int32_t op_errno)
+{
+ gf_hdr_common_t *hdr = NULL;
+ gf_fop_setdents_rsp_t *rsp = NULL;
+ size_t hdrlen = 0;
+ int32_t gf_errno = 0;
+
+ hdrlen = gf_hdr_len (rsp, 0);
+ hdr = gf_hdr_new (rsp, 0);
+ rsp = gf_param (hdr);
+
+ hdr->rsp.op_ret = hton32 (op_ret);
+ gf_errno = gf_errno_to_error (op_errno);
+ hdr->rsp.op_errno = hton32 (gf_errno);
+
+ protocol_server_reply (frame, GF_OP_TYPE_FOP_REPLY, GF_FOP_SETDENTS,
+ hdr, hdrlen, NULL, 0, NULL);
+
+ return 0;
+}
+
+/*
+ * server_lk_cbk - lk callback for server protocol
+ * @frame: call frame
+ * @cookie:
+ * @this:
+ * @op_ret:
+ * @op_errno:
+ * @lock:
+ *
+ * not for external reference
+ */
+int32_t
+server_lk_cbk (call_frame_t *frame,
+ void *cookie,
+ xlator_t *this,
+ int32_t op_ret,
+ int32_t op_errno,
+ struct flock *lock)
+{
+ gf_hdr_common_t *hdr = NULL;
+ gf_fop_lk_rsp_t *rsp = NULL;
+ size_t hdrlen = 0;
+ int32_t gf_errno = 0;
+ server_state_t *state = NULL;
+
+ hdrlen = gf_hdr_len (rsp, 0);
+ hdr = gf_hdr_new (rsp, 0);
+ rsp = gf_param (hdr);
+
+ hdr->rsp.op_ret = hton32 (op_ret);
+ gf_errno = gf_errno_to_error (op_errno);
+ hdr->rsp.op_errno = hton32 (gf_errno);
+
+ if (op_ret == 0) {
+ gf_flock_from_flock (&rsp->flock, lock);
+ } else if (op_errno != ENOSYS) {
+ state = CALL_STATE(frame);
+
+ gf_log (this->name, GF_LOG_DEBUG,
+ "%"PRId64": LK %"PRId64" (%"PRId64") ==> %"PRId32" (%s)",
+ frame->root->unique, state->fd_no,
+ state->fd ? state->fd->inode->ino : 0, op_ret,
+ strerror (op_errno));
+ }
+
+ protocol_server_reply (frame, GF_OP_TYPE_FOP_REPLY, GF_FOP_LK,
+ hdr, hdrlen, NULL, 0, NULL);
+
+ return 0;
+}
+
+
+int32_t
+server_inodelk_cbk (call_frame_t *frame, void *cookie,
+ xlator_t *this, int32_t op_ret, int32_t op_errno)
+{
+ server_connection_t *conn = NULL;
+ gf_hdr_common_t *hdr = NULL;
+ gf_fop_inodelk_rsp_t *rsp = NULL;
+ server_state_t *state = NULL;
+ size_t hdrlen = 0;
+ int32_t gf_errno = 0;
+
+ conn = SERVER_CONNECTION(frame);
+
+ state = CALL_STATE(frame);
+
+ hdrlen = gf_hdr_len (rsp, 0);
+ hdr = gf_hdr_new (rsp, 0);
+ rsp = gf_param (hdr);
+
+ hdr->rsp.op_ret = hton32 (op_ret);
+ gf_errno = gf_errno_to_error (op_errno);
+ hdr->rsp.op_errno = hton32 (gf_errno);
+
+ if (op_ret >= 0) {
+ if (state->flock.l_type == F_UNLCK)
+ gf_del_locker (conn->ltable,
+ &state->loc, NULL, frame->root->pid);
+ else
+ gf_add_locker (conn->ltable,
+ &state->loc, NULL, frame->root->pid);
+ } else if (op_errno != ENOSYS) {
+ gf_log (this->name, GF_LOG_DEBUG,
+ "%"PRId64": INODELK %s (%"PRId64") ==> %"PRId32" (%s)",
+ frame->root->unique, state->loc.path,
+ state->loc.inode ? state->loc.inode->ino : 0, op_ret,
+ strerror (op_errno));
+ }
+
+ server_loc_wipe (&state->loc);
+
+ protocol_server_reply (frame, GF_OP_TYPE_FOP_REPLY, GF_FOP_INODELK,
+ hdr, hdrlen, NULL, 0, NULL);
+
+ return 0;
+}
+
+
+int32_t
+server_finodelk_cbk (call_frame_t *frame, void *cookie,
+ xlator_t *this, int32_t op_ret, int32_t op_errno)
+{
+ server_connection_t *conn = NULL;
+ gf_hdr_common_t *hdr = NULL;
+ gf_fop_finodelk_rsp_t *rsp = NULL;
+ server_state_t *state = NULL;
+ size_t hdrlen = 0;
+ int32_t gf_errno = 0;
+
+ conn = SERVER_CONNECTION(frame);
+
+ hdrlen = gf_hdr_len (rsp, 0);
+ hdr = gf_hdr_new (rsp, 0);
+ rsp = gf_param (hdr);
+
+ hdr->rsp.op_ret = hton32 (op_ret);
+ gf_errno = gf_errno_to_error (op_errno);
+ hdr->rsp.op_errno = hton32 (gf_errno);
+
+ state = CALL_STATE(frame);
+
+ if (op_ret >= 0) {
+ if (state->flock.l_type == F_UNLCK)
+ gf_del_locker (conn->ltable,
+ NULL, state->fd, frame->root->pid);
+ else
+ gf_add_locker (conn->ltable,
+ NULL, state->fd, frame->root->pid);
+ } else if (op_errno != ENOSYS) {
+ gf_log (this->name, GF_LOG_DEBUG,
+ "%"PRId64": FINODELK %"PRId64" (%"PRId64") ==> %"PRId32" (%s)",
+ frame->root->unique, state->fd_no,
+ state->fd ? state->fd->inode->ino : 0, op_ret,
+ strerror (op_errno));
+ }
+
+ protocol_server_reply (frame, GF_OP_TYPE_FOP_REPLY, GF_FOP_FINODELK,
+ hdr, hdrlen, NULL, 0, NULL);
+
+ return 0;
+}
+
+
+/*
+ * server_entrylk_cbk -
+ * @frame: call frame
+ * @cookie:
+ * @this:
+ * @op_ret:
+ * @op_errno:
+ * @lock:
+ *
+ * not for external reference
+ */
+int32_t
+server_entrylk_cbk (call_frame_t *frame, void *cookie,
+ xlator_t *this, int32_t op_ret, int32_t op_errno)
+{
+ server_connection_t *conn = NULL;
+ gf_hdr_common_t *hdr = NULL;
+ gf_fop_entrylk_rsp_t *rsp = NULL;
+ server_state_t *state = NULL;
+ size_t hdrlen = 0;
+ int32_t gf_errno = 0;
+
+ conn = SERVER_CONNECTION(frame);
+
+ state = CALL_STATE(frame);
+
+ hdrlen = gf_hdr_len (rsp, 0);
+ hdr = gf_hdr_new (rsp, 0);
+ rsp = gf_param (hdr);
+
+ hdr->rsp.op_ret = hton32 (op_ret);
+ gf_errno = gf_errno_to_error (op_errno);
+ hdr->rsp.op_errno = hton32 (gf_errno);
+
+ if (op_ret >= 0) {
+ if (state->cmd == ENTRYLK_UNLOCK)
+ gf_del_locker (conn->ltable,
+ &state->loc, NULL, frame->root->pid);
+ else
+ gf_add_locker (conn->ltable,
+ &state->loc, NULL, frame->root->pid);
+ } else if (op_errno != ENOSYS) {
+ gf_log (this->name, GF_LOG_DEBUG,
+ "%"PRId64": INODELK %s (%"PRId64") ==> %"PRId32" (%s)",
+ frame->root->unique, state->loc.path,
+ state->loc.inode ? state->loc.inode->ino : 0, op_ret,
+ strerror (op_errno));
+ }
+
+ server_loc_wipe (&state->loc);
+
+ protocol_server_reply (frame, GF_OP_TYPE_FOP_REPLY, GF_FOP_ENTRYLK,
+ hdr, hdrlen, NULL, 0, NULL);
+
+ return 0;
+}
+
+
+int32_t
+server_fentrylk_cbk (call_frame_t *frame, void *cookie,
+ xlator_t *this, int32_t op_ret, int32_t op_errno)
+{
+ server_connection_t *conn = NULL;
+ gf_hdr_common_t *hdr = NULL;
+ gf_fop_fentrylk_rsp_t *rsp = NULL;
+ server_state_t *state = NULL;
+ size_t hdrlen = 0;
+ int32_t gf_errno = 0;
+
+ conn = SERVER_CONNECTION(frame);
+
+ hdrlen = gf_hdr_len (rsp, 0);
+ hdr = gf_hdr_new (rsp, 0);
+ rsp = gf_param (hdr);
+
+ hdr->rsp.op_ret = hton32 (op_ret);
+ gf_errno = gf_errno_to_error (op_errno);
+ hdr->rsp.op_errno = hton32 (gf_errno);
+
+ if (op_ret >= 0) {
+ state = CALL_STATE(frame);
+ if (state->cmd == ENTRYLK_UNLOCK)
+ gf_del_locker (conn->ltable,
+ NULL, state->fd, frame->root->pid);
+ else
+ gf_add_locker (conn->ltable,
+ NULL, state->fd, frame->root->pid);
+ } else if (op_errno != ENOSYS) {
+ gf_log (this->name, GF_LOG_DEBUG,
+ "%"PRId64": FENTRYLK %"PRId64" (%"PRId64") ==> %"PRId32" (%s)",
+ frame->root->unique, state->fd_no,
+ state->fd ? state->fd->inode->ino : 0, op_ret,
+ strerror (op_errno));
+ }
+
+ protocol_server_reply (frame, GF_OP_TYPE_FOP_REPLY, GF_FOP_FENTRYLK,
+ hdr, hdrlen, NULL, 0, NULL);
+
+ return 0;
+}
+
+
+/*
+ * server_access_cbk - access callback for server protocol
+ * @frame: call frame
+ * @cookie:
+ * @this:
+ * @op_ret:
+ * @op_errno:
+ *
+ * not for external reference
+ */
+int32_t
+server_access_cbk (call_frame_t *frame,
+ void *cookie,
+ xlator_t *this,
+ int32_t op_ret,
+ int32_t op_errno)
+{
+ gf_hdr_common_t *hdr = NULL;
+ gf_fop_access_rsp_t *rsp = NULL;
+ server_state_t *state = NULL;
+ size_t hdrlen = 0;
+ int32_t gf_errno = 0;
+
+ state = CALL_STATE(frame);
+
+ hdrlen = gf_hdr_len (rsp, 0);
+ hdr = gf_hdr_new (rsp, 0);
+ rsp = gf_param (hdr);
+
+ hdr->rsp.op_ret = hton32 (op_ret);
+ gf_errno = gf_errno_to_error (op_errno);
+ hdr->rsp.op_errno = hton32 (gf_errno);
+
+ server_loc_wipe (&(state->loc));
+
+ protocol_server_reply (frame, GF_OP_TYPE_FOP_REPLY, GF_FOP_ACCESS,
+ hdr, hdrlen, NULL, 0, NULL);
+
+ return 0;
+}
+
+/*
+ * server_utimens_cbk - utimens callback for server protocol
+ * @frame: call frame
+ * @cookie:
+ * @this:
+ * @op_ret:
+ * @op_errno:
+ * @stbuf:
+ *
+ * not for external reference
+ */
+int32_t
+server_utimens_cbk (call_frame_t *frame,
+ void *cookie,
+ xlator_t *this,
+ int32_t op_ret,
+ int32_t op_errno,
+ struct stat *stbuf)
+{
+ gf_hdr_common_t *hdr = NULL;
+ gf_fop_utimens_rsp_t *rsp = NULL;
+ server_state_t *state = NULL;
+ size_t hdrlen = 0;
+ int32_t gf_errno = 0;
+ state = CALL_STATE(frame);
+
+ hdrlen = gf_hdr_len (rsp, 0);
+ hdr = gf_hdr_new (rsp, 0);
+ rsp = gf_param (hdr);
+
+ hdr->rsp.op_ret = hton32 (op_ret);
+ gf_errno = gf_errno_to_error (op_errno);
+ hdr->rsp.op_errno = hton32 (gf_errno);
+
+ if (op_ret == 0)
+ gf_stat_from_stat (&rsp->stat, stbuf);
+
+ server_loc_wipe (&(state->loc));
+
+ protocol_server_reply (frame, GF_OP_TYPE_FOP_REPLY, GF_FOP_UTIMENS,
+ hdr, hdrlen, NULL, 0, NULL);
+
+ return 0;
+}
+
+/*
+ * server_chmod_cbk - chmod callback for server protocol
+ * @frame: call frame
+ * @cookie:
+ * @this:
+ * @op_ret:
+ * @op_errno:
+ * @stbuf:
+ *
+ * not for external reference
+ */
+int32_t
+server_chmod_cbk (call_frame_t *frame,
+ void *cookie,
+ xlator_t *this,
+ int32_t op_ret,
+ int32_t op_errno,
+ struct stat *stbuf)
+{
+ gf_hdr_common_t *hdr = NULL;
+ gf_fop_chmod_rsp_t *rsp = NULL;
+ server_state_t *state = NULL;
+ size_t hdrlen = 0;
+ int32_t gf_errno = 0;
+
+ state = CALL_STATE(frame);
+
+ hdrlen = gf_hdr_len (rsp, 0);
+ hdr = gf_hdr_new (rsp, 0);
+ rsp = gf_param (hdr);
+
+ hdr->rsp.op_ret = hton32 (op_ret);
+ gf_errno = gf_errno_to_error (op_errno);
+ hdr->rsp.op_errno = hton32 (gf_errno);
+
+ if (op_ret == 0)
+ gf_stat_from_stat (&rsp->stat, stbuf);
+
+ server_loc_wipe (&(state->loc));
+
+ protocol_server_reply (frame, GF_OP_TYPE_FOP_REPLY, GF_FOP_CHMOD,
+ hdr, hdrlen, NULL, 0, NULL);
+
+ return 0;
+}
+
+/*
+ * server_chown_cbk - chown callback for server protocol
+ * @frame: call frame
+ * @cookie:
+ * @this:
+ * @op_ret:
+ * @op_errno:
+ * @stbuf:
+ *
+ * not for external reference
+ */
+int32_t
+server_chown_cbk (call_frame_t *frame,
+ void *cookie,
+ xlator_t *this,
+ int32_t op_ret,
+ int32_t op_errno,
+ struct stat *stbuf)
+{
+ gf_hdr_common_t *hdr = NULL;
+ gf_fop_chown_rsp_t *rsp = NULL;
+ server_state_t *state = NULL;
+ int32_t gf_errno = 0;
+ size_t hdrlen = 0;
+
+ state = CALL_STATE(frame);
+
+ hdrlen = gf_hdr_len (rsp, 0);
+ hdr = gf_hdr_new (rsp, 0);
+ rsp = gf_param (hdr);
+
+ hdr->rsp.op_ret = hton32 (op_ret);
+ gf_errno = gf_errno_to_error (op_errno);
+ hdr->rsp.op_errno = hton32 (gf_errno);
+
+ if (op_ret == 0)
+ gf_stat_from_stat (&rsp->stat, stbuf);
+
+ server_loc_wipe (&(state->loc));
+
+ protocol_server_reply (frame, GF_OP_TYPE_FOP_REPLY, GF_FOP_CHOWN,
+ hdr, hdrlen, NULL, 0, NULL);
+
+ return 0;
+}
+
+/*
+ * server_rmdir_cbk - rmdir callback for server protocol
+ * @frame: call frame
+ * @cookie:
+ * @this:
+ * @op_ret:
+ * @op_errno:
+ *
+ * not for external reference
+ */
+int32_t
+server_rmdir_cbk (call_frame_t *frame,
+ void *cookie,
+ xlator_t *this,
+ int32_t op_ret,
+ int32_t op_errno)
+{
+ gf_hdr_common_t *hdr = NULL;
+ gf_fop_rmdir_rsp_t *rsp = NULL;
+ server_state_t *state = NULL;
+ int32_t gf_errno = 0;
+ size_t hdrlen = 0;
+
+ state = CALL_STATE(frame);
+
+ if (op_ret == 0) {
+ inode_unlink (state->loc.inode, state->loc.parent,
+ state->loc.name);
+ } else {
+ gf_log (this->name, GF_LOG_DEBUG,
+ "%"PRId64": RMDIR %s (%"PRId64") ==> %"PRId32" (%s)",
+ frame->root->unique, state->loc.path,
+ state->loc.inode ? state->loc.inode->ino : 0,
+ op_ret, strerror (op_errno));
+ }
+
+ hdrlen = gf_hdr_len (rsp, 0);
+ hdr = gf_hdr_new (rsp, 0);
+ rsp = gf_param (hdr);
+
+ hdr->rsp.op_ret = hton32 (op_ret);
+ gf_errno = gf_errno_to_error (op_errno);
+ hdr->rsp.op_errno = hton32 (gf_errno);
+
+ server_loc_wipe (&(state->loc));
+
+ protocol_server_reply (frame, GF_OP_TYPE_FOP_REPLY, GF_FOP_RMDIR,
+ hdr, hdrlen, NULL, 0, NULL);
+
+ return 0;
+}
+
+/*
+ * server_mkdir_cbk - mkdir callback for server protocol
+ * @frame: call frame
+ * @cookie:
+ * @this:
+ * @op_ret:
+ * @op_errno:
+ * @stbuf:
+ *
+ * not for external reference
+ */
+int32_t
+server_mkdir_cbk (call_frame_t *frame,
+ void *cookie,
+ xlator_t *this,
+ int32_t op_ret,
+ int32_t op_errno,
+ inode_t *inode,
+ struct stat *stbuf)
+{
+ gf_hdr_common_t *hdr = NULL;
+ gf_fop_mkdir_rsp_t *rsp = NULL;
+ server_state_t *state = NULL;
+ size_t hdrlen = 0;
+ int32_t gf_errno = 0;
+
+ state = CALL_STATE(frame);
+
+ hdrlen = gf_hdr_len (rsp, 0);
+ hdr = gf_hdr_new (rsp, 0);
+ rsp = gf_param (hdr);
+
+ hdr->rsp.op_ret = hton32 (op_ret);
+ gf_errno = gf_errno_to_error (op_errno);
+ hdr->rsp.op_errno = hton32 (gf_errno);
+
+ if (op_ret >= 0) {
+ gf_stat_from_stat (&rsp->stat, stbuf);
+ inode_link (inode, state->loc.parent, state->loc.name, stbuf);
+ inode_lookup (inode);
+ } else {
+ gf_log (this->name, GF_LOG_DEBUG,
+ "%"PRId64": MKDIR %s ==> %"PRId32" (%s)",
+ frame->root->unique, state->loc.path,
+ op_ret, strerror (op_errno));
+ }
+
+ server_loc_wipe (&(state->loc));
+
+ protocol_server_reply (frame, GF_OP_TYPE_FOP_REPLY, GF_FOP_MKDIR,
+ hdr, hdrlen, NULL, 0, NULL);
+
+ return 0;
+}
+
+/*
+ * server_mknod_cbk - mknod callback for server protocol
+ * @frame: call frame
+ * @cookie:
+ * @this:
+ * @op_ret:
+ * @op_errno:
+ * @stbuf:
+ *
+ * not for external reference
+ */
+int32_t
+server_mknod_cbk (call_frame_t *frame,
+ void *cookie,
+ xlator_t *this,
+ int32_t op_ret,
+ int32_t op_errno,
+ inode_t *inode,
+ struct stat *stbuf)
+{
+ gf_hdr_common_t *hdr = NULL;
+ gf_fop_mknod_rsp_t *rsp = NULL;
+ server_state_t *state = NULL;
+ int32_t gf_errno = 0;
+ size_t hdrlen = 0;
+
+ state = CALL_STATE(frame);
+
+ hdrlen = gf_hdr_len (rsp, 0);
+ hdr = gf_hdr_new (rsp, 0);
+ rsp = gf_param (hdr);
+
+ hdr->rsp.op_ret = hton32 (op_ret);
+ gf_errno = gf_errno_to_error (op_errno);
+ hdr->rsp.op_errno = hton32 (gf_errno);
+
+ if (op_ret >= 0) {
+ gf_stat_from_stat (&rsp->stat, stbuf);
+ inode_link (inode, state->loc.parent, state->loc.name, stbuf);
+ inode_lookup (inode);
+ } else {
+ gf_log (this->name, GF_LOG_DEBUG,
+ "%"PRId64": MKNOD %s ==> %"PRId32" (%s)",
+ frame->root->unique, state->loc.path,
+ op_ret, strerror (op_errno));
+ }
+
+ server_loc_wipe (&(state->loc));
+
+ protocol_server_reply (frame, GF_OP_TYPE_FOP_REPLY, GF_FOP_MKNOD,
+ hdr, hdrlen, NULL, 0, NULL);
+
+ return 0;
+}
+
+/*
+ * server_fsyncdir_cbk - fsyncdir callback for server protocol
+ * @frame: call frame
+ * @cookie:
+ * @this:
+ * @op_ret:
+ * @op_errno:
+ *
+ * not for external reference
+ */
+int32_t
+server_fsyncdir_cbk (call_frame_t *frame,
+ void *cookie,
+ xlator_t *this,
+ int32_t op_ret,
+ int32_t op_errno)
+{
+ gf_hdr_common_t *hdr = NULL;
+ gf_fop_fsyncdir_rsp_t *rsp = NULL;
+ size_t hdrlen = 0;
+ int32_t gf_errno = 0;
+ server_state_t *state = NULL;
+
+ hdrlen = gf_hdr_len (rsp, 0);
+ hdr = gf_hdr_new (rsp, 0);
+ rsp = gf_param (hdr);
+
+ if (op_ret < 0) {
+ state = CALL_STATE(frame);
+
+ gf_log (this->name, GF_LOG_DEBUG,
+ "%"PRId64": FSYNCDIR %"PRId64" (%"PRId64") ==> %"PRId32" (%s)",
+ frame->root->unique, state->fd_no,
+ state->fd ? state->fd->inode->ino : 0, op_ret,
+ strerror (op_errno));
+ }
+
+ hdr->rsp.op_ret = hton32 (op_ret);
+ gf_errno = gf_errno_to_error (op_errno);
+ hdr->rsp.op_errno = hton32 (gf_errno);
+
+ protocol_server_reply (frame, GF_OP_TYPE_FOP_REPLY, GF_FOP_FSYNCDIR,
+ hdr, hdrlen, NULL, 0, NULL);
+
+ return 0;
+}
+
+
+/*
+ * server_getdents_cbk - readdir callback for server protocol
+ * @frame: call frame
+ * @cookie:
+ * @this:
+ * @op_ret: return value
+ * @op_errno: errno
+ * @entries:
+ * @count:
+ *
+ * not for external reference
+ */
+int32_t
+server_getdents_cbk (call_frame_t *frame,
+ void *cookie,
+ xlator_t *this,
+ int32_t op_ret,
+ int32_t op_errno,
+ dir_entry_t *entries,
+ int32_t count)
+{
+ gf_hdr_common_t *hdr = NULL;
+ gf_fop_getdents_rsp_t *rsp = NULL;
+ size_t hdrlen = 0;
+ int32_t vec_count = 0;
+ int32_t gf_errno = 0;
+ int32_t ret = -1;
+ dict_t *reply_dict = NULL;
+ char *buffer = NULL;
+ size_t buflen = 0;
+ struct iovec vector[1];
+ server_state_t *state = NULL;
+
+ state = CALL_STATE(frame);
+
+ if (op_ret >= 0) {
+ buflen = gf_direntry_to_bin (entries, &buffer);
+ if (buflen < 0) {
+ gf_log (this->name, GF_LOG_ERROR,
+ "fd - %"PRId64" (%"PRId64"): failed to convert "
+ "entries list to string buffer",
+ state->fd_no, state->fd->inode->ino);
+ op_ret = -1;
+ op_errno = EINVAL;
+ goto out;
+ }
+
+ reply_dict = dict_new ();
+ if (reply_dict == NULL) {
+ gf_log (this->name, GF_LOG_ERROR,
+ "fd - %"PRId64" (%"PRId64"): failed to get new dict",
+ state->fd_no, state->fd->inode->ino);
+ op_ret = -1;
+ op_errno = ENOMEM;
+ goto out;
+ }
+
+ ret = dict_set_dynptr (reply_dict, NULL,
+ buffer, buflen);
+ if (ret < 0) {
+ gf_log (this->name, GF_LOG_ERROR,
+ "fd - %"PRId64" (%"PRId64"): failed to set read buffer "
+ "to reply dictionary",
+ state->fd_no, state->fd->inode->ino);
+ op_ret = -1;
+ op_errno = -ret;
+ goto out;
+ }
+ frame->root->rsp_refs = reply_dict;
+ vector[0].iov_base = buffer;
+ vector[0].iov_len = buflen;
+ vec_count = 1;
+ } else {
+ gf_log (this->name, GF_LOG_DEBUG,
+ "%"PRId64": GETDENTS %"PRId64" (%"PRId64"): %"PRId32" (%s)",
+ frame->root->unique,
+ state->fd_no,
+ state->fd ? state->fd->inode->ino : 0,
+ op_ret, strerror (op_errno));
+ vector[0].iov_base = NULL;
+ vector[0].iov_len = 0;
+ }
+
+out:
+ hdrlen = gf_hdr_len (rsp, 0);
+ hdr = gf_hdr_new (rsp, 0);
+ rsp = gf_param (hdr);
+
+ rsp->count = hton32 (count);
+
+ hdr->rsp.op_ret = hton32 (op_ret);
+ gf_errno = gf_errno_to_error (op_errno);
+ hdr->rsp.op_errno = hton32 (gf_errno);
+
+ protocol_server_reply (frame, GF_OP_TYPE_FOP_REPLY, GF_FOP_GETDENTS,
+ hdr, hdrlen, vector, vec_count,
+ frame->root->rsp_refs);
+
+ if (reply_dict)
+ dict_unref (reply_dict);
+
+ return 0;
+}
+
+
+/*
+ * server_readdir_cbk - getdents callback for server protocol
+ * @frame: call frame
+ * @cookie:
+ * @this:
+ * @op_ret:
+ * @op_errno:
+ *
+ * not for external reference
+ */
+int32_t
+server_readdir_cbk (call_frame_t *frame,
+ void *cookie,
+ xlator_t *this,
+ int32_t op_ret,
+ int32_t op_errno,
+ gf_dirent_t *entries)
+{
+ gf_hdr_common_t *hdr = NULL;
+ gf_fop_readdir_rsp_t *rsp = NULL;
+ size_t hdrlen = 0;
+ size_t buf_size = 0;
+ int32_t gf_errno = 0;
+ server_state_t *state = NULL;
+
+ if (op_ret > 0)
+ buf_size = gf_dirent_serialize (entries, NULL, 0);
+
+ hdrlen = gf_hdr_len (rsp, buf_size);
+ hdr = gf_hdr_new (rsp, buf_size);
+ rsp = gf_param (hdr);
+
+ hdr->rsp.op_ret = hton32 (op_ret);
+ gf_errno = gf_errno_to_error (op_errno);
+ hdr->rsp.op_errno = hton32 (gf_errno);
+
+ if (op_ret > 0) {
+ rsp->size = hton32 (buf_size);
+ gf_dirent_serialize (entries, rsp->buf, buf_size);
+ } else {
+ state = CALL_STATE(frame);
+
+ gf_log (this->name, GF_LOG_DEBUG,
+ "%"PRId64": READDIR %"PRId64" (%"PRId64") ==> %"PRId32" (%s)",
+ frame->root->unique, state->fd_no,
+ state->fd ? state->fd->inode->ino : 0, op_ret,
+ strerror (op_errno));
+ }
+
+ protocol_server_reply (frame, GF_OP_TYPE_FOP_REPLY, GF_FOP_READDIR,
+ hdr, hdrlen, NULL, 0, NULL);
+
+ return 0;
+}
+
+
+/*
+ * server_releasedir_cbk - releasedir callback for server protocol
+ * @frame: call frame
+ * @cookie:
+ * @this:
+ * @op_ret: return value
+ * @op_errno: errno
+ *
+ * not for external reference
+ */
+int32_t
+server_releasedir_cbk (call_frame_t *frame,
+ void *cookie,
+ xlator_t *this,
+ int32_t op_ret,
+ int32_t op_errno)
+{
+ gf_hdr_common_t *hdr = NULL;
+ gf_cbk_releasedir_rsp_t *rsp = NULL;
+ size_t hdrlen = 0;
+ int32_t gf_errno = 0;
+
+ hdrlen = gf_hdr_len (rsp, 0);
+ hdr = gf_hdr_new (rsp, 0);
+ rsp = gf_param (hdr);
+
+ hdr->rsp.op_ret = hton32 (op_ret);
+ gf_errno = gf_errno_to_error (op_errno);
+ hdr->rsp.op_errno = hton32 (gf_errno);
+
+ protocol_server_reply (frame, GF_OP_TYPE_CBK_REPLY, GF_CBK_RELEASEDIR,
+ hdr, hdrlen, NULL, 0, NULL);
+
+ return 0;
+}
+
+
+/*
+ * server_opendir_cbk - opendir callback for server protocol
+ * @frame: call frame
+ * @cookie:
+ * @this:
+ * @op_ret: return value
+ * @op_errno: errno
+ * @fd: file descriptor structure of opened directory
+ *
+ * not for external reference
+ */
+int32_t
+server_opendir_cbk (call_frame_t *frame,
+ void *cookie,
+ xlator_t *this,
+ int32_t op_ret,
+ int32_t op_errno,
+ fd_t *fd)
+{
+ server_connection_t *conn = NULL;
+ gf_hdr_common_t *hdr = NULL;
+ gf_fop_opendir_rsp_t *rsp = NULL;
+ server_state_t *state = NULL;
+ size_t hdrlen = 0;
+ int32_t gf_errno = 0;
+
+ conn = SERVER_CONNECTION(frame);
+
+ state = CALL_STATE(frame);
+
+ if (op_ret >= 0) {
+ fd_bind (fd);
+
+ state->fd_no = gf_fd_unused_get (conn->fdtable, fd);
+ } else {
+ gf_log (this->name, GF_LOG_DEBUG,
+ "%"PRId64": OPENDIR %s (%"PRId64") ==> %"PRId32" (%s)",
+ frame->root->unique, state->loc.path,
+ state->loc.inode ? state->loc.inode->ino : 0,
+ op_ret, strerror (op_errno));
+
+ /* NOTE: corresponding to fd_create()'s ref */
+ if (state->fd)
+ fd_unref (state->fd);
+ }
+
+ hdrlen = gf_hdr_len (rsp, 0);
+ hdr = gf_hdr_new (rsp, 0);
+ rsp = gf_param (hdr);
+
+ hdr->rsp.op_ret = hton32 (op_ret);
+ gf_errno = gf_errno_to_error (op_errno);
+ hdr->rsp.op_errno = hton32 (gf_errno);
+ rsp->fd = hton64 (state->fd_no);
+
+ server_loc_wipe (&(state->loc));
+
+ protocol_server_reply (frame, GF_OP_TYPE_FOP_REPLY, GF_FOP_OPENDIR,
+ hdr, hdrlen, NULL, 0, NULL);
+
+ return 0;
+}
+
+/*
+ * server_statfs_cbk - statfs callback for server protocol
+ * @frame: call frame
+ * @cookie:
+ * @this:
+ * @op_ret: return value
+ * @op_errno: errno
+ * @buf:
+ *
+ * not for external reference
+ */
+int32_t
+server_statfs_cbk (call_frame_t *frame,
+ void *cookie,
+ xlator_t *this,
+ int32_t op_ret,
+ int32_t op_errno,
+ struct statvfs *buf)
+{
+ gf_hdr_common_t *hdr = NULL;
+ gf_fop_statfs_rsp_t *rsp = NULL;
+ server_state_t *state = NULL;
+ size_t hdrlen = 0;
+ int32_t gf_errno = 0;
+
+ state = CALL_STATE(frame);
+
+ hdrlen = gf_hdr_len (rsp, 0);
+ hdr = gf_hdr_new (rsp, 0);
+ rsp = gf_param (hdr);
+
+ hdr->rsp.op_ret = hton32 (op_ret);
+ gf_errno = gf_errno_to_error (op_errno);
+ hdr->rsp.op_errno = hton32 (gf_errno);
+
+ if (op_ret >= 0) {
+ gf_statfs_from_statfs (&rsp->statfs, buf);
+ }
+
+ server_loc_wipe (&(state->loc));
+
+ protocol_server_reply (frame, GF_OP_TYPE_FOP_REPLY, GF_FOP_STATFS,
+ hdr, hdrlen, NULL, 0, NULL);
+
+ return 0;
+}
+
+/*
+ * server_removexattr_cbk - removexattr callback for server protocol
+ * @frame: call frame
+ * @cookie:
+ * @this:
+ * @op_ret: return value
+ * @op_errno: errno
+ *
+ * not for external reference
+ */
+int32_t
+server_removexattr_cbk (call_frame_t *frame,
+ void *cookie,
+ xlator_t *this,
+ int32_t op_ret,
+ int32_t op_errno)
+{
+ gf_hdr_common_t *hdr = NULL;
+ gf_fop_removexattr_rsp_t *rsp = NULL;
+ server_state_t *state = NULL;
+ size_t hdrlen = 0;
+ int32_t gf_errno = 0;
+
+ state = CALL_STATE(frame);
+
+ hdrlen = gf_hdr_len (rsp, 0);
+ hdr = gf_hdr_new (rsp, 0);
+ rsp = gf_param (hdr);
+
+ hdr->rsp.op_ret = hton32 (op_ret);
+ gf_errno = gf_errno_to_error (op_errno);
+ hdr->rsp.op_errno = hton32 (gf_errno);
+
+ server_loc_wipe (&(state->loc));
+
+ protocol_server_reply (frame, GF_OP_TYPE_FOP_REPLY, GF_FOP_REMOVEXATTR,
+ hdr, hdrlen, NULL, 0, NULL);
+
+ return 0;
+}
+
+/*
+ * server_getxattr_cbk - getxattr callback for server protocol
+ * @frame: call frame
+ * @cookie:
+ * @this:
+ * @op_ret: return value
+ * @op_errno: errno
+ * @value:
+ *
+ * not for external reference
+ */
+int32_t
+server_getxattr_cbk (call_frame_t *frame,
+ void *cookie,
+ xlator_t *this,
+ int32_t op_ret,
+ int32_t op_errno,
+ dict_t *dict)
+{
+ gf_hdr_common_t *hdr = NULL;
+ gf_fop_getxattr_rsp_t *rsp = NULL;
+ server_state_t *state = NULL;
+ size_t hdrlen = 0;
+ int32_t len = 0;
+ int32_t gf_errno = 0;
+ int32_t ret = -1;
+
+ state = CALL_STATE(frame);
+
+ if (op_ret >= 0) {
+ len = dict_serialized_length (dict);
+ if (len < 0) {
+ gf_log (this->name, GF_LOG_ERROR,
+ "%s (%"PRId64"): failed to get serialized length of "
+ "reply dict",
+ state->loc.path, state->ino);
+ op_ret = -1;
+ op_errno = EINVAL;
+ len = 0;
+ }
+ }
+
+ hdrlen = gf_hdr_len (rsp, len + 1);
+ hdr = gf_hdr_new (rsp, len + 1);
+ rsp = gf_param (hdr);
+
+ if (op_ret >= 0) {
+ ret = dict_serialize (dict, rsp->dict);
+ if (len < 0) {
+ gf_log (this->name, GF_LOG_ERROR,
+ "%s (%"PRId64"): failed to serialize reply dict",
+ state->loc.path, state->ino);
+ op_ret = -1;
+ op_errno = -ret;
+ }
+ }
+ rsp->dict_len = hton32 (len);
+
+ hdr->rsp.op_ret = hton32 (op_ret);
+ gf_errno = gf_errno_to_error (op_errno);
+ hdr->rsp.op_errno = hton32 (gf_errno);
+
+
+ server_loc_wipe (&(state->loc));
+
+ protocol_server_reply (frame, GF_OP_TYPE_FOP_REPLY, GF_FOP_GETXATTR,
+ hdr, hdrlen, NULL, 0, NULL);
+
+ return 0;
+}
+
+/*
+ * server_setxattr_cbk - setxattr callback for server protocol
+ * @frame: call frame
+ * @cookie:
+ * @this:
+ * @op_ret: return value
+ * @op_errno: errno
+ *
+ * not for external reference
+ */
+int32_t
+server_setxattr_cbk (call_frame_t *frame,
+ void *cookie,
+ xlator_t *this,
+ int32_t op_ret,
+ int32_t op_errno)
+{
+ gf_hdr_common_t *hdr = NULL;
+ gf_fop_setxattr_rsp_t *rsp = NULL;
+ server_state_t *state = NULL;
+ size_t hdrlen = 0;
+ int32_t gf_errno = 0;
+ state = CALL_STATE(frame);
+
+ hdrlen = gf_hdr_len (rsp, 0);
+ hdr = gf_hdr_new (rsp, 0);
+ rsp = gf_param (hdr);
+
+ hdr->rsp.op_ret = hton32 (op_ret);
+ gf_errno = gf_errno_to_error (op_errno);
+ hdr->rsp.op_errno = hton32 (gf_errno);
+
+ server_loc_wipe (&(state->loc));
+
+ protocol_server_reply (frame, GF_OP_TYPE_FOP_REPLY, GF_FOP_SETXATTR,
+ hdr, hdrlen, NULL, 0, NULL);
+
+ return 0;
+}
+
+
+/*
+ * server_rename_cbk - rename callback for server protocol
+ * @frame: call frame
+ * @cookie:
+ * @this:
+ * @op_ret: return value
+ * @op_errno: errno
+ *
+ * not for external reference
+ */
+int32_t
+server_rename_cbk (call_frame_t *frame,
+ void *cookie,
+ xlator_t *this,
+ int32_t op_ret,
+ int32_t op_errno,
+ struct stat *stbuf)
+{
+ gf_hdr_common_t *hdr = NULL;
+ gf_fop_rename_rsp_t *rsp = NULL;
+ server_state_t *state = NULL;
+ size_t hdrlen = 0;
+ int32_t gf_errno = 0;
+
+ state = CALL_STATE(frame);
+
+ hdrlen = gf_hdr_len (rsp, 0);
+ hdr = gf_hdr_new (rsp, 0);
+ rsp = gf_param (hdr);
+
+ hdr->rsp.op_ret = hton32 (op_ret);
+ gf_errno = gf_errno_to_error (op_errno);
+ hdr->rsp.op_errno = hton32 (gf_errno);
+
+ if (op_ret == 0) {
+ stbuf->st_ino = state->loc.inode->ino;
+ stbuf->st_mode = state->loc.inode->st_mode;
+
+ gf_log (state->bound_xl->name, GF_LOG_DEBUG,
+ "%"PRId64": RENAME_CBK (%"PRId64") %"PRId64"/%s "
+ "==> %"PRId64"/%s",
+ frame->root->unique, state->loc.inode->ino,
+ state->loc.parent->ino, state->loc.name,
+ state->loc2.parent->ino, state->loc2.name);
+
+ inode_rename (state->itable,
+ state->loc.parent, state->loc.name,
+ state->loc2.parent, state->loc2.name,
+ state->loc.inode, stbuf);
+ gf_stat_from_stat (&rsp->stat, stbuf);
+ }
+
+ server_loc_wipe (&(state->loc));
+ server_loc_wipe (&(state->loc2));
+
+ protocol_server_reply (frame, GF_OP_TYPE_FOP_REPLY, GF_FOP_RENAME,
+ hdr, hdrlen, NULL, 0, NULL);
+
+ return 0;
+}
+
+
+/*
+ * server_unlink_cbk - unlink callback for server protocol
+ * @frame: call frame
+ * @cookie:
+ * @this:
+ * @op_ret: return value
+ * @op_errno: errno
+ *
+ * not for external reference
+ */
+int32_t
+server_unlink_cbk (call_frame_t *frame,
+ void *cookie,
+ xlator_t *this,
+ int32_t op_ret,
+ int32_t op_errno)
+{
+ gf_hdr_common_t *hdr = NULL;
+ gf_fop_unlink_rsp_t *rsp = NULL;
+ server_state_t *state = NULL;
+ size_t hdrlen = 0;
+ int32_t gf_errno = 0;
+
+ state = CALL_STATE(frame);
+
+ if (op_ret == 0) {
+ gf_log (state->bound_xl->name, GF_LOG_DEBUG,
+ "%"PRId64": UNLINK_CBK %"PRId64"/%s (%"PRId64")",
+ frame->root->unique, state->loc.parent->ino,
+ state->loc.name, state->loc.inode->ino);
+
+ inode_unlink (state->loc.inode, state->loc.parent,
+ state->loc.name);
+ } else {
+ gf_log (this->name, GF_LOG_DEBUG,
+ "%"PRId64": UNLINK %s (%"PRId64") ==> %"PRId32" (%s)",
+ frame->root->unique, state->loc.path,
+ state->loc.inode ? state->loc.inode->ino : 0,
+ op_ret, strerror (op_errno));
+ }
+
+ hdrlen = gf_hdr_len (rsp, 0);
+ hdr = gf_hdr_new (rsp, 0);
+ rsp = gf_param (hdr);
+
+ hdr->rsp.op_ret = hton32 (op_ret);
+ gf_errno = gf_errno_to_error (op_errno);
+ hdr->rsp.op_errno = hton32 (gf_errno);
+
+ server_loc_wipe (&(state->loc));
+
+ protocol_server_reply (frame, GF_OP_TYPE_FOP_REPLY, GF_FOP_UNLINK,
+ hdr, hdrlen, NULL, 0, NULL);
+
+ return 0;
+}
+
+/*
+ * server_symlink_cbk - symlink callback for server protocol
+ * @frame: call frame
+ * @cookie:
+ * @this:
+ * @op_ret: return value
+ * @op_errno: errno
+ *
+ * not for external reference
+ */
+int32_t
+server_symlink_cbk (call_frame_t *frame,
+ void *cookie,
+ xlator_t *this,
+ int32_t op_ret,
+ int32_t op_errno,
+ inode_t *inode,
+ struct stat *stbuf)
+{
+ gf_hdr_common_t *hdr = NULL;
+ gf_fop_symlink_rsp_t *rsp = NULL;
+ server_state_t *state = NULL;
+ size_t hdrlen = 0;
+ int32_t gf_errno = 0;
+
+ state = CALL_STATE(frame);
+
+ hdrlen = gf_hdr_len (rsp, 0);
+ hdr = gf_hdr_new (rsp, 0);
+ rsp = gf_param (hdr);
+
+ hdr->rsp.op_ret = hton32 (op_ret);
+ gf_errno = gf_errno_to_error (op_errno);
+ hdr->rsp.op_errno = hton32 (gf_errno_to_error (op_errno));
+
+ if (op_ret >= 0) {
+ gf_stat_from_stat (&rsp->stat, stbuf);
+ inode_link (inode, state->loc.parent, state->loc.name, stbuf);
+ inode_lookup (inode);
+ } else {
+ gf_log (this->name, GF_LOG_DEBUG,
+ "%"PRId64": SYMLINK %s (%"PRId64") ==> %"PRId32" (%s)",
+ frame->root->unique, state->loc.path,
+ state->loc.inode ? state->loc.inode->ino : 0,
+ op_ret, strerror (op_errno));
+ }
+
+ server_loc_wipe (&(state->loc));
+
+ protocol_server_reply (frame, GF_OP_TYPE_FOP_REPLY, GF_FOP_SYMLINK,
+ hdr, hdrlen, NULL, 0, NULL);
+
+ return 0;
+}
+
+
+/*
+ * server_link_cbk - link callback for server protocol
+ * @frame: call frame
+ * @this:
+ * @op_ret:
+ * @op_errno:
+ * @stbuf:
+ *
+ * not for external reference
+ */
+int32_t
+server_link_cbk (call_frame_t *frame,
+ void *cookie,
+ xlator_t *this,
+ int32_t op_ret,
+ int32_t op_errno,
+ inode_t *inode,
+ struct stat *stbuf)
+{
+ gf_hdr_common_t *hdr = NULL;
+ gf_fop_link_rsp_t *rsp = NULL;
+ server_state_t *state = NULL;
+ int32_t gf_errno = 0;
+ size_t hdrlen = 0;
+
+ state = CALL_STATE(frame);
+
+ hdrlen = gf_hdr_len (rsp, 0);
+ hdr = gf_hdr_new (rsp, 0);
+ rsp = gf_param (hdr);
+
+ hdr->rsp.op_ret = hton32 (op_ret);
+ gf_errno = gf_errno_to_error (op_errno);
+ hdr->rsp.op_errno = hton32 (gf_errno);
+
+ if (op_ret == 0) {
+ stbuf->st_ino = state->loc.inode->ino;
+ gf_stat_from_stat (&rsp->stat, stbuf);
+ gf_log (state->bound_xl->name, GF_LOG_DEBUG,
+ "%"PRId64": LINK (%"PRId64") %"PRId64"/%s ==> %"PRId64"/%s",
+ frame->root->unique, inode->ino, state->loc2.parent->ino,
+ state->loc2.name, state->loc.parent->ino, state->loc.name);
+
+ inode_link (inode, state->loc2.parent,
+ state->loc2.name, stbuf);
+ } else {
+ gf_log (state->bound_xl->name, GF_LOG_DEBUG,
+ "%"PRId64": LINK (%"PRId64") %"PRId64"/%s ==> %"PRId64"/%s "
+ " ==> %"PRId32" (%s)",
+ frame->root->unique, inode->ino, state->loc2.parent->ino,
+ state->loc2.name, state->loc.parent->ino, state->loc.name,
+ op_ret, strerror (op_errno));
+ }
+
+ server_loc_wipe (&(state->loc));
+ server_loc_wipe (&(state->loc2));
+
+ protocol_server_reply (frame, GF_OP_TYPE_FOP_REPLY, GF_FOP_LINK,
+ hdr, hdrlen, NULL, 0, NULL);
+
+ return 0;
+}
+
+
+/*
+ * server_truncate_cbk - truncate callback for server protocol
+ * @frame: call frame
+ * @cookie:
+ * @this:
+ * @op_ret:
+ * @op_errno:
+ * @stbuf:
+ *
+ * not for external reference
+ */
+int32_t
+server_truncate_cbk (call_frame_t *frame,
+ void *cookie,
+ xlator_t *this,
+ int32_t op_ret,
+ int32_t op_errno,
+ struct stat *stbuf)
+{
+ gf_hdr_common_t *hdr = NULL;
+ gf_fop_truncate_rsp_t *rsp = NULL;
+ server_state_t *state = NULL;
+ size_t hdrlen = 0;
+ int32_t gf_errno = 0;
+
+ state = CALL_STATE(frame);
+
+ hdrlen = gf_hdr_len (rsp, 0);
+ hdr = gf_hdr_new (rsp, 0);
+ rsp = gf_param (hdr);
+
+ hdr->rsp.op_ret = hton32 (op_ret);
+ gf_errno = gf_errno_to_error (op_errno);
+ hdr->rsp.op_errno = hton32 (gf_errno);
+
+ if (op_ret == 0) {
+ gf_stat_from_stat (&rsp->stat, stbuf);
+ } else {
+ gf_log (this->name, GF_LOG_DEBUG,
+ "%"PRId64": TRUNCATE %s (%"PRId64") ==> %"PRId32" (%s)",
+ frame->root->unique, state->loc.path,
+ state->loc.inode ? state->loc.inode->ino : 0,
+ op_ret, strerror (op_errno));
+ }
+
+ server_loc_wipe (&(state->loc));
+
+ protocol_server_reply (frame, GF_OP_TYPE_FOP_REPLY, GF_FOP_TRUNCATE,
+ hdr, hdrlen, NULL, 0, NULL);
+
+ return 0;
+}
+
+/*
+ * server_fstat_cbk - fstat callback for server protocol
+ * @frame: call frame
+ * @cookie:
+ * @this:
+ * @op_ret:
+ * @op_errno:
+ * @stbuf:
+ *
+ * not for external reference
+ */
+int32_t
+server_fstat_cbk (call_frame_t *frame,
+ void *cookie,
+ xlator_t *this,
+ int32_t op_ret,
+ int32_t op_errno,
+ struct stat *stbuf)
+{
+ gf_hdr_common_t *hdr = NULL;
+ gf_fop_fstat_rsp_t *rsp = NULL;
+ size_t hdrlen = 0;
+ int32_t gf_errno = 0;
+ server_state_t *state = NULL;
+
+ hdrlen = gf_hdr_len (rsp, 0);
+ hdr = gf_hdr_new (rsp, 0);
+ rsp = gf_param (hdr);
+
+ hdr->rsp.op_ret = hton32 (op_ret);
+ gf_errno = gf_errno_to_error (op_errno);
+ hdr->rsp.op_errno = hton32 (gf_errno);
+
+ if (op_ret == 0) {
+ gf_stat_from_stat (&rsp->stat, stbuf);
+ } else {
+ state = CALL_STATE(frame);
+
+ gf_log (this->name, GF_LOG_DEBUG,
+ "%"PRId64": FSTAT %"PRId64" (%"PRId64") ==> %"PRId32" (%s)",
+ frame->root->unique, state->fd_no,
+ state->fd ? state->fd->inode->ino : 0, op_ret,
+ strerror (op_errno));
+ }
+
+ protocol_server_reply (frame, GF_OP_TYPE_FOP_REPLY, GF_FOP_FSTAT,
+ hdr, hdrlen, NULL, 0, NULL);
+
+ return 0;
+}
+
+/*
+ * server_ftruncate_cbk - ftruncate callback for server protocol
+ * @frame: call frame
+ * @cookie:
+ * @this:
+ * @op_ret:
+ * @op_errno:
+ * @stbuf:
+ *
+ * not for external reference
+ */
+int32_t
+server_ftruncate_cbk (call_frame_t *frame,
+ void *cookie,
+ xlator_t *this,
+ int32_t op_ret,
+ int32_t op_errno,
+ struct stat *stbuf)
+{
+ gf_hdr_common_t *hdr = NULL;
+ gf_fop_ftruncate_rsp_t *rsp = NULL;
+ size_t hdrlen = 0;
+ int32_t gf_errno = 0;
+ server_state_t *state = NULL;
+
+ hdrlen = gf_hdr_len (rsp, 0);
+ hdr = gf_hdr_new (rsp, 0);
+ rsp = gf_param (hdr);
+
+ hdr->rsp.op_ret = hton32 (op_ret);
+ gf_errno = gf_errno_to_error (op_errno);
+ hdr->rsp.op_errno = hton32 (gf_errno);
+
+ if (op_ret == 0) {
+ gf_stat_from_stat (&rsp->stat, stbuf);
+ } else {
+ state = CALL_STATE(frame);
+
+ gf_log (this->name, GF_LOG_DEBUG,
+ "%"PRId64": FTRUNCATE %"PRId64" (%"PRId64") ==> %"PRId32" (%s)",
+ frame->root->unique, state->fd_no,
+ state->fd ? state->fd->inode->ino : 0, op_ret,
+ strerror (op_errno));
+ }
+
+ protocol_server_reply (frame, GF_OP_TYPE_FOP_REPLY, GF_FOP_FTRUNCATE,
+ hdr, hdrlen, NULL, 0, NULL);
+
+ return 0;
+}
+
+
+/*
+ * server_flush_cbk - flush callback for server protocol
+ * @frame: call frame
+ * @cookie:
+ * @this:
+ * @op_ret:
+ * @op_errno:
+ *
+ * not for external reference
+ */
+int32_t
+server_flush_cbk (call_frame_t *frame,
+ void *cookie,
+ xlator_t *this,
+ int32_t op_ret,
+ int32_t op_errno)
+{
+ gf_hdr_common_t *hdr = NULL;
+ gf_fop_flush_rsp_t *rsp = NULL;
+ size_t hdrlen = 0;
+ int32_t gf_errno = 0;
+ server_state_t *state = NULL;
+
+ if (op_ret < 0) {
+ state = CALL_STATE(frame);
+
+ gf_log (this->name, GF_LOG_DEBUG,
+ "%"PRId64": FLUSH %"PRId64" (%"PRId64") ==> %"PRId32" (%s)",
+ frame->root->unique, state->fd_no,
+ state->fd ? state->fd->inode->ino : 0, op_ret,
+ strerror (op_errno));
+ }
+
+ hdrlen = gf_hdr_len (rsp, 0);
+ hdr = gf_hdr_new (rsp, 0);
+
+ hdr->rsp.op_ret = hton32 (op_ret);
+ gf_errno = gf_errno_to_error (op_errno);
+ hdr->rsp.op_errno = hton32 (gf_errno);
+
+ protocol_server_reply (frame, GF_OP_TYPE_FOP_REPLY, GF_FOP_FLUSH,
+ hdr, hdrlen, NULL, 0, NULL);
+
+ return 0;
+}
+
+/*
+ * server_fsync_cbk - fsync callback for server protocol
+ * @frame: call frame
+ * @cookie:
+ * @this:
+ * @op_ret:
+ * @op_errno:
+ *
+ * not for external reference
+ */
+int32_t
+server_fsync_cbk (call_frame_t *frame,
+ void *cookie,
+ xlator_t *this,
+ int32_t op_ret,
+ int32_t op_errno)
+{
+ gf_hdr_common_t *hdr = NULL;
+ gf_fop_fsync_rsp_t *rsp = NULL;
+ size_t hdrlen = 0;
+ int32_t gf_errno = 0;
+ server_state_t *state = NULL;
+
+ if (op_ret < 0) {
+ state = CALL_STATE(frame);
+
+ gf_log (this->name, GF_LOG_DEBUG,
+ "%"PRId64": FSYNC %"PRId64" (%"PRId64") ==> %"PRId32" (%s)",
+ frame->root->unique, state->fd_no,
+ state->fd ? state->fd->inode->ino : 0, op_ret,
+ strerror (op_errno));
+ }
+
+ hdrlen = gf_hdr_len (rsp, 0);
+ hdr = gf_hdr_new (rsp, 0);
+
+ hdr->rsp.op_ret = hton32 (op_ret);
+ gf_errno = gf_errno_to_error (op_errno);
+ hdr->rsp.op_errno = hton32 (gf_errno);
+
+ protocol_server_reply (frame, GF_OP_TYPE_FOP_REPLY, GF_FOP_FSYNC,
+ hdr, hdrlen, NULL, 0, NULL);
+
+ return 0;
+}
+
+/*
+ * server_release_cbk - rleease callback for server protocol
+ * @frame: call frame
+ * @cookie:
+ * @this:
+ * @op_ret:
+ * @op_errno:
+ *
+ * not for external reference
+ */
+int32_t
+server_release_cbk (call_frame_t *frame,
+ void *cookie,
+ xlator_t *this,
+ int32_t op_ret,
+ int32_t op_errno)
+{
+ gf_hdr_common_t *hdr = NULL;
+ gf_cbk_release_rsp_t *rsp = NULL;
+ size_t hdrlen = 0;
+ int32_t gf_errno = 0;
+
+ hdrlen = gf_hdr_len (rsp, 0);
+ hdr = gf_hdr_new (rsp, 0);
+
+ hdr->rsp.op_ret = hton32 (op_ret);
+ gf_errno = gf_errno_to_error (op_errno);
+ hdr->rsp.op_errno = hton32 (gf_errno);
+
+ protocol_server_reply (frame, GF_OP_TYPE_CBK_REPLY, GF_CBK_RELEASE,
+ hdr, hdrlen, NULL, 0, NULL);
+
+ return 0;
+}
+
+
+/*
+ * server_writev_cbk - writev callback for server protocol
+ * @frame: call frame
+ * @cookie:
+ * @this:
+ * @op_ret:
+ * @op_errno:
+ *
+ * not for external reference
+ */
+
+int32_t
+server_writev_cbk (call_frame_t *frame,
+ void *cookie,
+ xlator_t *this,
+ int32_t op_ret,
+ int32_t op_errno,
+ struct stat *stbuf)
+{
+ gf_hdr_common_t *hdr = NULL;
+ gf_fop_write_rsp_t *rsp = NULL;
+ size_t hdrlen = 0;
+ int32_t gf_errno = 0;
+ server_state_t *state = NULL;
+
+ hdrlen = gf_hdr_len (rsp, 0);
+ hdr = gf_hdr_new (rsp, 0);
+ rsp = gf_param (hdr);
+
+ hdr->rsp.op_ret = hton32 (op_ret);
+ gf_errno = gf_errno_to_error (op_errno);
+ hdr->rsp.op_errno = hton32 (gf_errno_to_error (op_errno));
+
+ if (op_ret >= 0) {
+ gf_stat_from_stat (&rsp->stat, stbuf);
+ } else {
+ state = CALL_STATE(frame);
+
+ gf_log (this->name, GF_LOG_DEBUG,
+ "%"PRId64": WRITEV %"PRId64" (%"PRId64") ==> %"PRId32" (%s)",
+ frame->root->unique, state->fd_no,
+ state->fd ? state->fd->inode->ino : 0, op_ret,
+ strerror (op_errno));
+ }
+
+ protocol_server_reply (frame,
+ GF_OP_TYPE_FOP_REPLY, GF_FOP_WRITE,
+ hdr, hdrlen, NULL, 0, NULL);
+
+ return 0;
+}
+
+
+/*
+ * server_readv_cbk - readv callback for server protocol
+ * @frame: call frame
+ * @cookie:
+ * @this:
+ * @op_ret:
+ * @op_errno:
+ * @vector:
+ * @count:
+ *
+ * not for external reference
+ */
+int32_t
+server_readv_cbk (call_frame_t *frame,
+ void *cookie,
+ xlator_t *this,
+ int32_t op_ret,
+ int32_t op_errno,
+ struct iovec *vector,
+ int32_t count,
+ struct stat *stbuf)
+{
+ gf_hdr_common_t *hdr = NULL;
+ gf_fop_read_rsp_t *rsp = NULL;
+ size_t hdrlen = 0;
+ int32_t gf_errno = 0;
+ server_state_t *state = NULL;
+
+ hdrlen = gf_hdr_len (rsp, 0);
+ hdr = gf_hdr_new (rsp, 0);
+ rsp = gf_param (hdr);
+
+ hdr->rsp.op_ret = hton32 (op_ret);
+ gf_errno = gf_errno_to_error (op_errno);
+ hdr->rsp.op_errno = hton32 (gf_errno);
+
+ if (op_ret >= 0) {
+ gf_stat_from_stat (&rsp->stat, stbuf);
+ } else {
+ state = CALL_STATE(frame);
+
+ gf_log (this->name, GF_LOG_DEBUG,
+ "%"PRId64": READV %"PRId64" (%"PRId64") ==> %"PRId32" (%s)",
+ frame->root->unique, state->fd_no,
+ state->fd ? state->fd->inode->ino : 0, op_ret,
+ strerror (op_errno));
+ }
+
+ protocol_server_reply (frame, GF_OP_TYPE_FOP_REPLY, GF_FOP_READ,
+ hdr, hdrlen, vector, count,
+ frame->root->rsp_refs);
+
+ return 0;
+}
+
+
+/*
+ * server_open_cbk - open callback for server protocol
+ * @frame: call frame
+ * @cookie:
+ * @this:
+ * @op_ret:
+ * @op_errno:
+ * @fd:
+ *
+ * not for external reference
+ */
+int32_t
+server_open_cbk (call_frame_t *frame,
+ void *cookie,
+ xlator_t *this,
+ int32_t op_ret,
+ int32_t op_errno,
+ fd_t *fd)
+{
+ server_connection_t *conn = NULL;
+ gf_hdr_common_t *hdr = NULL;
+ gf_fop_open_rsp_t *rsp = NULL;
+ server_state_t *state = NULL;
+ size_t hdrlen = 0;
+ int32_t gf_errno = 0;
+
+ conn = SERVER_CONNECTION(frame);
+
+ state = CALL_STATE(frame);
+
+ if (op_ret >= 0) {
+ fd_bind (fd);
+
+ state->fd_no = gf_fd_unused_get (conn->fdtable, fd);
+ } else {
+ gf_log (this->name, GF_LOG_DEBUG,
+ "%"PRId64": OPEN %s (%"PRId64") ==> %"PRId32" (%s)",
+ frame->root->unique, state->loc.path,
+ state->loc.inode ? state->loc.inode->ino : 0,
+ op_ret, strerror (op_errno));
+
+ /* NOTE: corresponding to fd_create()'s ref */
+ if (state->fd)
+ fd_unref (state->fd);
+ }
+
+ hdrlen = gf_hdr_len (rsp, 0);
+ hdr = gf_hdr_new (rsp, 0);
+ rsp = gf_param (hdr);
+
+ hdr->rsp.op_ret = hton32 (op_ret);
+ gf_errno = gf_errno_to_error (op_errno);
+ hdr->rsp.op_errno = hton32 (gf_errno);
+ rsp->fd = hton64 (state->fd_no);
+
+ server_loc_wipe (&(state->loc));
+
+ protocol_server_reply (frame, GF_OP_TYPE_FOP_REPLY, GF_FOP_OPEN,
+ hdr, hdrlen, NULL, 0, NULL);
+
+ return 0;
+}
+
+
+/*
+ * server_create_cbk - create callback for server
+ * @frame: call frame
+ * @cookie:
+ * @this: translator structure
+ * @op_ret:
+ * @op_errno:
+ * @fd: file descriptor
+ * @inode: inode structure
+ * @stbuf: struct stat of created file
+ *
+ * not for external reference
+ */
+int32_t
+server_create_cbk (call_frame_t *frame,
+ void *cookie,
+ xlator_t *this,
+ int32_t op_ret,
+ int32_t op_errno,
+ fd_t *fd,
+ inode_t *inode,
+ struct stat *stbuf)
+{
+ server_connection_t *conn = NULL;
+ gf_hdr_common_t *hdr = NULL;
+ gf_fop_create_rsp_t *rsp = NULL;
+ server_state_t *state = NULL;
+ size_t hdrlen = 0;
+ int32_t gf_errno = 0;
+
+ conn = SERVER_CONNECTION(frame);
+
+ state = CALL_STATE(frame);
+
+ if (op_ret >= 0) {
+ gf_log (state->bound_xl->name, GF_LOG_DEBUG,
+ "%"PRId64": CREATE %"PRId64"/%s (%"PRId64")",
+ frame->root->unique, state->loc.parent->ino,
+ state->loc.name, stbuf->st_ino);
+
+ inode_link (inode, state->loc.parent, state->loc.name, stbuf);
+ inode_lookup (inode);
+
+ fd_bind (fd);
+
+ state->fd_no = gf_fd_unused_get (conn->fdtable, fd);
+
+ if ((state->fd_no < 0) || (fd == 0)) {
+ op_ret = state->fd_no;
+ op_errno = errno;
+ }
+ } else {
+ gf_log (this->name, GF_LOG_DEBUG,
+ "%"PRId64": CREATE %s (%"PRId64") ==> %"PRId32" (%s)",
+ frame->root->unique, state->loc.path,
+ state->loc.inode ? state->loc.inode->ino : 0,
+ op_ret, strerror (op_errno));
+
+ /* NOTE: corresponding to fd_create()'s ref */
+ if (state->fd)
+ fd_unref (state->fd);
+
+ }
+
+ hdrlen = gf_hdr_len (rsp, 0);
+ hdr = gf_hdr_new (rsp, 0);
+ rsp = gf_param (hdr);
+
+ hdr->rsp.op_ret = hton32 (op_ret);
+ gf_errno = gf_errno_to_error (op_errno);
+ hdr->rsp.op_errno = hton32 (gf_errno);
+ rsp->fd = hton64 (state->fd_no);
+
+ if (op_ret >= 0)
+ gf_stat_from_stat (&rsp->stat, stbuf);
+
+ server_loc_wipe (&(state->loc));
+
+ protocol_server_reply (frame, GF_OP_TYPE_FOP_REPLY, GF_FOP_CREATE,
+ hdr, hdrlen, NULL, 0, NULL);
+
+ return 0;
+}
+
+/*
+ * server_readlink_cbk - readlink callback for server protocol
+ * @frame: call frame
+ * @cookie:
+ * @this:
+ * @op_ret:
+ * @op_errno:
+ * @buf:
+ *
+ * not for external reference
+ */
+int32_t
+server_readlink_cbk (call_frame_t *frame,
+ void *cookie,
+ xlator_t *this,
+ int32_t op_ret,
+ int32_t op_errno,
+ const char *buf)
+{
+ gf_hdr_common_t *hdr = NULL;
+ gf_fop_readlink_rsp_t *rsp = NULL;
+ server_state_t *state = NULL;
+ size_t hdrlen = 0;
+ size_t linklen = 0;
+ int32_t gf_errno = 0;
+
+ state = CALL_STATE(frame);
+
+ if (op_ret >= 0) {
+ linklen = strlen (buf) + 1;
+ } else {
+ gf_log (this->name, GF_LOG_DEBUG,
+ "%"PRId64": READLINK %s (%"PRId64") ==> %"PRId32" (%s)",
+ frame->root->unique, state->loc.path,
+ state->loc.inode ? state->loc.inode->ino : 0,
+ op_ret, strerror (op_errno));
+ }
+
+ hdrlen = gf_hdr_len (rsp, linklen);
+ hdr = gf_hdr_new (rsp, linklen);
+ rsp = gf_param (hdr);
+
+ hdr->rsp.op_ret = hton32 (op_ret);
+ gf_errno = gf_errno_to_error (op_errno);
+ hdr->rsp.op_errno = hton32 (gf_errno_to_error (op_errno));
+
+ if (op_ret >= 0)
+ strcpy (rsp->path, buf);
+
+ server_loc_wipe (&(state->loc));
+
+ protocol_server_reply (frame, GF_OP_TYPE_FOP_REPLY, GF_FOP_READLINK,
+ hdr, hdrlen, NULL, 0, NULL);
+
+ return 0;
+}
+
+/*
+ * server_stat_cbk - stat callback for server protocol
+ * @frame: call frame
+ * @cookie:
+ * @this:
+ * @op_ret:
+ * @op_errno:
+ * @stbuf:
+ *
+ * not for external reference
+ */
+int32_t
+server_stat_cbk (call_frame_t *frame,
+ void *cookie,
+ xlator_t *this,
+ int32_t op_ret,
+ int32_t op_errno,
+ struct stat *stbuf)
+{
+ gf_hdr_common_t *hdr = NULL;
+ gf_fop_stat_rsp_t *rsp = NULL;
+ server_state_t *state = NULL;
+ size_t hdrlen = 0;
+ int32_t gf_errno = 0;
+
+ state = CALL_STATE(frame);
+
+ hdrlen = gf_hdr_len (rsp, 0);
+ hdr = gf_hdr_new (rsp, 0);
+ rsp = gf_param (hdr);
+
+ hdr->rsp.op_ret = hton32 (op_ret);
+ gf_errno = gf_errno_to_error (op_errno);
+ hdr->rsp.op_errno = hton32 (gf_errno_to_error (op_errno));
+
+ if (op_ret == 0) {
+ gf_stat_from_stat (&rsp->stat, stbuf);
+ } else {
+ gf_log (this->name, GF_LOG_DEBUG,
+ "%"PRId64": STAT %s (%"PRId64") ==> %"PRId32" (%s)",
+ frame->root->unique, state->loc.path,
+ state->loc.inode ? state->loc.inode->ino : 0,
+ op_ret, strerror (op_errno));
+ }
+
+ server_loc_wipe (&(state->loc));
+
+ protocol_server_reply (frame, GF_OP_TYPE_FOP_REPLY, GF_FOP_STAT,
+ hdr, hdrlen, NULL, 0, NULL);
+
+ return 0;
+}
+
+/*
+ * server_forget_cbk - forget callback for server protocol
+ * @frame: call frame
+ * @cookie:
+ * @this:
+ * @op_ret:
+ * @op_errno:
+ *
+ * not for external reference
+ */
+int32_t
+server_forget_cbk (call_frame_t *frame,
+ void *cookie,
+ xlator_t *this,
+ int32_t op_ret,
+ int32_t op_errno)
+{
+ gf_hdr_common_t *hdr = NULL;
+ gf_cbk_forget_rsp_t *rsp = NULL;
+ size_t hdrlen = 0;
+ int32_t gf_errno = 0;
+
+ hdrlen = gf_hdr_len (rsp, 0);
+ hdr = gf_hdr_new (rsp, 0);
+ rsp = gf_param (hdr);
+
+ hdr->rsp.op_ret = hton32 (op_ret);
+ gf_errno = gf_errno_to_error (op_errno);
+ hdr->rsp.op_errno = hton32 (gf_errno);
+
+ protocol_server_reply (frame, GF_OP_TYPE_CBK_REPLY, GF_CBK_FORGET,
+ hdr, hdrlen, NULL, 0, NULL);
+
+ return 0;
+}
+
+
+/*
+ * server_lookup_cbk - lookup callback for server protocol
+ * @frame: call frame
+ * @cookie:
+ * @this:
+ * @op_ret:
+ * @op_errno:
+ * @inode:
+ * @stbuf:
+ *
+ * not for external reference
+ */
+int32_t
+server_lookup_cbk (call_frame_t *frame,
+ void *cookie,
+ xlator_t *this,
+ int32_t op_ret,
+ int32_t op_errno,
+ inode_t *inode,
+ struct stat *stbuf,
+ dict_t *dict)
+{
+ gf_hdr_common_t *hdr = NULL;
+ gf_fop_lookup_rsp_t *rsp = NULL;
+ server_state_t *state = NULL;
+ inode_t *root_inode = NULL;
+ int32_t dict_len = 0;
+ size_t hdrlen = 0;
+ int32_t gf_errno = 0;
+ int32_t ret = -1;
+
+ state = CALL_STATE(frame);
+ if ((op_errno == ESTALE) && (op_ret == -1)) {
+ /* Send lookup again with new ctx dictionary */
+ loc_t loc = {0,};
+
+ root_inode = BOUND_XL(frame)->itable->root;
+ if (state->loc.inode != root_inode) {
+ if (state->loc.inode)
+ inode_unref (state->loc.inode);
+ state->loc.inode = inode_new (BOUND_XL(frame)->itable);
+ }
+ loc.inode = state->loc.inode;
+ loc.path = state->path;
+ state->is_revalidate = 2;
+ STACK_WIND (frame, server_lookup_cbk,
+ BOUND_XL(frame),
+ BOUND_XL(frame)->fops->lookup,
+ &loc,
+ state->xattr_req);
+ return 0;
+ }
+
+ if (dict) {
+ dict_len = dict_serialized_length (dict);
+ if (dict_len < 0) {
+ gf_log (this->name, GF_LOG_ERROR,
+ "%s (%"PRId64"): failed to get serialized "
+ "length of reply dict",
+ state->loc.path, state->loc.inode->ino);
+ op_ret = -1;
+ op_errno = EINVAL;
+ dict_len = 0;
+ }
+ }
+
+ hdrlen = gf_hdr_len (rsp, dict_len);
+ hdr = gf_hdr_new (rsp, dict_len);
+ rsp = gf_param (hdr);
+
+ if ((op_ret >= 0) && dict) {
+ ret = dict_serialize (dict, rsp->dict);
+ if (ret < 0) {
+ gf_log (this->name, GF_LOG_ERROR,
+ "%s (%"PRId64"): failed to serialize reply dict",
+ state->loc.path, state->loc.inode->ino);
+ op_ret = -1;
+ op_errno = -ret;
+ dict_len = 0;
+ }
+ }
+ rsp->dict_len = hton32 (dict_len);
+
+ hdr->rsp.op_ret = hton32 (op_ret);
+ gf_errno = gf_errno_to_error (op_errno);
+ hdr->rsp.op_errno = hton32 (gf_errno);
+
+ if (op_ret == 0) {
+ root_inode = BOUND_XL(frame)->itable->root;
+ if (inode == root_inode) {
+ /* we just looked up root ("/") */
+ stbuf->st_ino = 1;
+ if (inode->st_mode == 0)
+ inode->st_mode = stbuf->st_mode;
+ }
+
+ gf_stat_from_stat (&rsp->stat, stbuf);
+
+ if (inode->ino == 0) {
+ inode_link (inode, state->loc.parent,
+ state->loc.name, stbuf);
+ inode_lookup (inode);
+ }
+ } else {
+ gf_log (this->name, GF_LOG_DEBUG,
+ "%"PRId64": LOOKUP %s (%"PRId64") ==> %"PRId32" (%s)",
+ frame->root->unique, state->loc.path,
+ state->loc.inode ? state->loc.inode->ino : 0,
+ op_ret, strerror (op_errno));
+ }
+
+ server_loc_wipe (&state->loc);
+ protocol_server_reply (frame, GF_OP_TYPE_FOP_REPLY, GF_FOP_LOOKUP,
+ hdr, hdrlen, NULL, 0, NULL);
+
+ return 0;
+}
+
+int32_t
+server_xattrop_cbk (call_frame_t *frame,
+ void *cookie,
+ xlator_t *this,
+ int32_t op_ret,
+ int32_t op_errno,
+ dict_t *dict)
+{
+ gf_hdr_common_t *hdr = NULL;
+ gf_fop_xattrop_rsp_t *rsp = NULL;
+ server_state_t *state = NULL;
+ size_t hdrlen = 0;
+ int32_t len = 0;
+ int32_t gf_errno = 0;
+ int32_t ret = -1;
+
+ state = CALL_STATE(frame);
+
+ if (op_ret < 0) {
+ gf_log (this->name, GF_LOG_DEBUG,
+ "%"PRId64": XATTROP %s (%"PRId64") ==> %"PRId32" (%s)",
+ frame->root->unique, state->loc.path,
+ state->loc.inode ? state->loc.inode->ino : 0,
+ op_ret, strerror (op_errno));
+ }
+
+ if ((op_ret >= 0) && dict) {
+ len = dict_serialized_length (dict);
+ if (len < 0) {
+ gf_log (this->name, GF_LOG_ERROR,
+ "%s (%"PRId64"): failed to get serialized length"
+ " for reply dict",
+ state->loc.path, state->loc.inode->ino);
+ op_ret = -1;
+ op_errno = EINVAL;
+ len = 0;
+ }
+ }
+
+ hdrlen = gf_hdr_len (rsp, len + 1);
+ hdr = gf_hdr_new (rsp, len + 1);
+ rsp = gf_param (hdr);
+
+ if ((op_ret >= 0) && dict) {
+ ret = dict_serialize (dict, rsp->dict);
+ if (ret < 0) {
+ gf_log (this->name, GF_LOG_ERROR,
+ "%s (%"PRId64"): failed to serialize reply dict",
+ state->loc.path, state->loc.inode->ino);
+ op_ret = -1;
+ op_errno = -ret;
+ len = 0;
+ }
+ }
+ rsp->dict_len = hton32 (len);
+
+ hdr->rsp.op_ret = hton32 (op_ret);
+ gf_errno = gf_errno_to_error (op_errno);
+ hdr->rsp.op_errno = hton32 (gf_errno);
+
+ server_loc_wipe (&(state->loc));
+
+ protocol_server_reply (frame, GF_OP_TYPE_FOP_REPLY, GF_FOP_XATTROP,
+ hdr, hdrlen, NULL, 0, NULL);
+
+ return 0;
+}
+
+int32_t
+server_fxattrop_cbk (call_frame_t *frame,
+ void *cookie,
+ xlator_t *this,
+ int32_t op_ret,
+ int32_t op_errno,
+ dict_t *dict)
+{
+ gf_hdr_common_t *hdr = NULL;
+ gf_fop_xattrop_rsp_t *rsp = NULL;
+ size_t hdrlen = 0;
+ int32_t len = 0;
+ int32_t gf_errno = 0;
+ int32_t ret = -1;
+ server_state_t *state = NULL;
+
+ state = CALL_STATE(frame);
+
+ if (op_ret < 0) {
+ gf_log (this->name, GF_LOG_DEBUG,
+ "%"PRId64": FXATTROP %"PRId64" (%"PRId64") ==> %"PRId32" (%s)",
+ frame->root->unique, state->fd_no,
+ state->fd ? state->fd->inode->ino : 0, op_ret,
+ strerror (op_errno));
+ }
+
+ if ((op_ret >= 0) && dict) {
+ len = dict_serialized_length (dict);
+ if (len < 0) {
+ gf_log (this->name, GF_LOG_ERROR,
+ "fd - %"PRId64" (%"PRId64"): failed to get "
+ "serialized length for reply dict",
+ state->fd_no, state->fd->inode->ino);
+ op_ret = -1;
+ op_errno = EINVAL;
+ len = 0;
+ }
+ }
+
+ hdrlen = gf_hdr_len (rsp, len + 1);
+ hdr = gf_hdr_new (rsp, len + 1);
+ rsp = gf_param (hdr);
+
+ if ((op_ret >= 0) && dict) {
+ ret = dict_serialize (dict, rsp->dict);
+ if (ret < 0) {
+ gf_log (this->name, GF_LOG_ERROR,
+ "fd - %"PRId64" (%"PRId64"): failed to "
+ "serialize reply dict",
+ state->fd_no, state->fd->inode->ino);
+ op_ret = -1;
+ op_errno = -ret;
+ len = 0;
+ }
+ }
+ rsp->dict_len = hton32 (len);
+
+ hdr->rsp.op_ret = hton32 (op_ret);
+ gf_errno = gf_errno_to_error (op_errno);
+ hdr->rsp.op_errno = hton32 (gf_errno);
+
+
+ protocol_server_reply (frame, GF_OP_TYPE_FOP_REPLY, GF_FOP_FXATTROP,
+ hdr, hdrlen, NULL, 0, NULL);
+
+ return 0;
+}
+
+/*
+ * server_stub_resume - this is callback function used whenever an fop does
+ * STACK_WIND to fops->lookup in order to lookup the inode
+ * for a pathname. this case of doing fops->lookup arises
+ * when fop searches in inode table for pathname and search
+ * fails.
+ *
+ * @stub: call stub
+ * @op_ret:
+ * @op_errno:
+ * @inode:
+ * @parent:
+ *
+ * not for external reference
+ */
+int32_t
+server_stub_resume (call_stub_t *stub,
+ int32_t op_ret,
+ int32_t op_errno,
+ inode_t *inode,
+ inode_t *parent)
+{
+ inode_t *server_inode = inode;
+
+ if (!stub) {
+ return 0;
+ }
+ switch (stub->fop)
+ {
+ case GF_FOP_RENAME:
+ if (stub->args.rename.old.inode == NULL) {
+ loc_t *newloc = NULL;
+ /* now we are called by lookup of oldpath. */
+ if (op_ret < 0) {
+ gf_log (stub->frame->this->name, GF_LOG_ERROR,
+ "%"PRId64": RENAME (%s -> %s) on %s "
+ "returning error: "
+ "%"PRId32" (%"PRId32")",
+ stub->frame->root->unique,
+ stub->args.rename.old.path,
+ stub->args.rename.new.path,
+ BOUND_XL(stub->frame)->name,
+ op_ret, op_errno);
+
+ /* lookup of oldpath failed, UNWIND to
+ * server_rename_cbk with ret=-1 and
+ * errno=ENOENT
+ */
+ server_rename_cbk (stub->frame,
+ NULL,
+ stub->frame->this,
+ -1,
+ ENOENT,
+ NULL);
+ server_loc_wipe (&stub->args.rename.old);
+ server_loc_wipe (&stub->args.rename.new);
+ FREE (stub);
+ return 0;
+ }
+
+ if (stub->args.rename.old.parent == NULL)
+ stub->args.rename.old.parent =
+ inode_ref (parent);
+
+ /* store inode information of oldpath in our stub
+ * and search for newpath in inode table.
+ */
+ if (server_inode) {
+ stub->args.rename.old.inode =
+ inode_ref (server_inode);
+
+ stub->args.rename.old.ino =
+ server_inode->ino;
+ }
+
+ /* now lookup for newpath */
+ newloc = &stub->args.rename.new;
+
+ if (newloc->parent == NULL) {
+ /* lookup for newpath */
+ do_path_lookup (stub, newloc);
+ break;
+ } else {
+ /* found newpath in inode cache */
+ call_resume (stub);
+ break;
+ }
+ } else {
+ /* we are called by the lookup of newpath */
+ if (stub->args.rename.new.parent == NULL)
+ stub->args.rename.new.parent =
+ inode_ref (parent);
+ }
+
+ /* after looking up for oldpath as well as newpath,
+ * we are ready to resume */
+ {
+ call_resume (stub);
+ }
+ break;
+
+ case GF_FOP_OPEN:
+ {
+ if (op_ret < 0) {
+ gf_log (stub->frame->this->name, GF_LOG_ERROR,
+ "%"PRId64": OPEN (%s) on %s returning error: "
+ "%"PRId32" (%"PRId32")",
+ stub->frame->root->unique,
+ stub->args.open.loc.path,
+ BOUND_XL(stub->frame)->name,
+ op_ret, op_errno);
+
+ server_open_cbk (stub->frame,
+ NULL,
+ stub->frame->this,
+ -1,
+ ENOENT,
+ NULL);
+ FREE (stub->args.open.loc.path);
+ FREE (stub);
+ return 0;
+ }
+ if (stub->args.open.loc.parent == NULL)
+ stub->args.open.loc.parent = inode_ref (parent);
+
+ if (server_inode && (stub->args.open.loc.inode == NULL)) {
+ stub->args.open.loc.inode = inode_ref (server_inode);
+ stub->args.open.loc.ino = server_inode->ino;
+ }
+ call_resume (stub);
+ break;
+ }
+
+ case GF_FOP_LOOKUP:
+ {
+ if (op_ret < 0) {
+ gf_log (stub->frame->this->name,
+ GF_LOG_DEBUG,
+ "%"PRId64": LOOKUP (%s) on %s returning error: "
+ "%"PRId32" (%"PRId32")",
+ stub->frame->root->unique,
+ stub->args.lookup.loc.path,
+ BOUND_XL(stub->frame)->name,
+ op_ret, op_errno);
+
+ server_lookup_cbk (stub->frame,
+ NULL,
+ stub->frame->this,
+ -1, ENOENT,
+ NULL, NULL,
+ NULL);
+ server_loc_wipe (&stub->args.lookup.loc);
+ FREE (stub);
+ return 0;
+ }
+
+ if (stub->args.lookup.loc.parent == NULL)
+ stub->args.lookup.loc.parent = inode_ref (parent);
+
+ if (server_inode && (stub->args.lookup.loc.inode == NULL)) {
+ stub->args.lookup.loc.inode = inode_ref (server_inode);
+ stub->args.lookup.loc.ino = server_inode->ino;
+ }
+
+ call_resume (stub);
+
+ break;
+ }
+
+ case GF_FOP_STAT:
+ {
+ if (op_ret < 0) {
+ gf_log (stub->frame->this->name, GF_LOG_ERROR,
+ "%"PRId64": STAT (%s) on %s returning error: "
+ "%"PRId32" (%"PRId32")",
+ stub->frame->root->unique,
+ stub->args.stat.loc.path,
+ BOUND_XL(stub->frame)->name,
+ op_ret, op_errno);
+ server_stat_cbk (stub->frame,
+ NULL,
+ stub->frame->this,
+ -1, ENOENT,
+ NULL);
+ server_loc_wipe (&stub->args.stat.loc);
+ FREE (stub);
+ return 0;
+ }
+
+ /* TODO:reply from here only, we already have stat structure */
+ if (stub->args.stat.loc.parent == NULL)
+ stub->args.stat.loc.parent = inode_ref (parent);
+
+ if (server_inode && (stub->args.stat.loc.inode == NULL)) {
+ stub->args.stat.loc.inode = inode_ref (server_inode);
+ stub->args.stat.loc.ino = server_inode->ino;
+ }
+ call_resume (stub);
+ break;
+ }
+
+ case GF_FOP_XATTROP:
+ {
+ if (op_ret < 0) {
+ gf_log (stub->frame->this->name, GF_LOG_ERROR,
+ "%"PRId64": XATTROP (%s) on %s returning error: "
+ "%"PRId32" (%"PRId32")",
+ stub->frame->root->unique,
+ stub->args.xattrop.loc.path,
+ BOUND_XL(stub->frame)->name,
+ op_ret, op_errno);
+ server_xattrop_cbk (stub->frame,
+ NULL,
+ stub->frame->this,
+ -1, ENOENT,
+ NULL);
+ server_loc_wipe (&stub->args.xattrop.loc);
+ FREE (stub);
+ return 0;
+ }
+
+ if (stub->args.xattrop.loc.parent == NULL)
+ stub->args.xattrop.loc.parent = inode_ref (parent);
+
+ if (server_inode && (stub->args.xattrop.loc.inode == NULL)) {
+ stub->args.xattrop.loc.inode =
+ inode_ref (server_inode);
+
+ stub->args.xattrop.loc.ino = server_inode->ino;
+ }
+ call_resume (stub);
+ break;
+ }
+
+ case GF_FOP_UNLINK:
+ {
+ if (op_ret < 0) {
+ gf_log (stub->frame->this->name, GF_LOG_ERROR,
+ "%"PRId64": UNLINK (%s) on %s returning error: "
+ "%"PRId32" (%"PRId32")",
+ stub->frame->root->unique,
+ stub->args.unlink.loc.path,
+ BOUND_XL(stub->frame)->name,
+ op_ret, op_errno);
+ server_unlink_cbk (stub->frame, NULL,
+ stub->frame->this,
+ -1, ENOENT);
+ server_loc_wipe (&stub->args.unlink.loc);
+ FREE (stub);
+ return 0;
+ }
+
+ if (stub->args.unlink.loc.parent == NULL)
+ stub->args.unlink.loc.parent = inode_ref (parent);
+
+ if (server_inode && (stub->args.unlink.loc.inode == NULL)) {
+ stub->args.unlink.loc.inode = inode_ref (server_inode);
+ stub->args.unlink.loc.ino = server_inode->ino;
+ }
+ call_resume (stub);
+ break;
+ }
+
+ case GF_FOP_SYMLINK:
+ {
+ if ((op_ret < 0) && (parent == NULL)) {
+ gf_log (stub->frame->this->name, GF_LOG_ERROR,
+ "%"PRId64": SYMLINK (%s -> %s) on %s returning error: "
+ "%"PRId32" (%"PRId32")",
+ stub->frame->root->unique,
+ stub->args.symlink.loc.path,
+ stub->args.symlink.linkname,
+ BOUND_XL(stub->frame)->name,
+ op_ret, op_errno);
+ server_symlink_cbk (stub->frame, NULL,
+ stub->frame->this,
+ -1, ENOENT,
+ NULL, NULL);
+ server_loc_wipe (&stub->args.symlink.loc);
+ FREE (stub);
+ return 0;
+ }
+
+ if (stub->args.symlink.loc.parent == NULL)
+ stub->args.symlink.loc.parent = inode_ref (parent);
+
+ if (server_inode && (stub->args.symlink.loc.inode == NULL)) {
+ stub->args.symlink.loc.inode =
+ inode_ref (server_inode);
+ stub->args.symlink.loc.ino = server_inode->ino;
+ }
+ call_resume (stub);
+ break;
+ }
+
+ case GF_FOP_RMDIR:
+ {
+ if (op_ret < 0) {
+ gf_log (stub->frame->this->name, GF_LOG_ERROR,
+ "%"PRId64": RMDIR (%s) on %s returning error: "
+ "%"PRId32" (%"PRId32")",
+ stub->frame->root->unique,
+ stub->args.rmdir.loc.path,
+ BOUND_XL(stub->frame)->name,
+ op_ret, op_errno);
+ server_rmdir_cbk (stub->frame,
+ NULL,
+ stub->frame->this,
+ -1,
+ ENOENT);
+ server_loc_wipe (&stub->args.rmdir.loc);
+ FREE (stub);
+ return 0;
+ }
+
+ if (stub->args.rmdir.loc.parent == NULL)
+ stub->args.rmdir.loc.parent = inode_ref (parent);
+
+ if (server_inode && (stub->args.rmdir.loc.inode == NULL)) {
+ stub->args.rmdir.loc.inode = inode_ref (server_inode);
+ stub->args.rmdir.loc.ino = server_inode->ino;
+ }
+ call_resume (stub);
+ break;
+ }
+
+ case GF_FOP_CHMOD:
+ {
+ if (op_ret < 0) {
+ gf_log (stub->frame->this->name, GF_LOG_ERROR,
+ "%"PRId64": CHMOD (%s) on %s returning error: "
+ "%"PRId32" (%"PRId32")",
+ stub->frame->root->unique,
+ stub->args.chmod.loc.path,
+ BOUND_XL(stub->frame)->name,
+ op_ret, op_errno);
+ server_chmod_cbk (stub->frame,
+ NULL,
+ stub->frame->this,
+ -1,
+ ENOENT,
+ NULL);
+ server_loc_wipe (&stub->args.chmod.loc);
+ FREE (stub);
+ return 0;
+ }
+
+ if (stub->args.chmod.loc.parent == NULL)
+ stub->args.chmod.loc.parent = inode_ref (parent);
+
+ if (server_inode && (stub->args.chmod.loc.inode == NULL)) {
+ stub->args.chmod.loc.inode = inode_ref (server_inode);
+ stub->args.chmod.loc.ino = server_inode->ino;
+ }
+ call_resume (stub);
+ break;
+ }
+
+ case GF_FOP_CHOWN:
+ {
+ if (op_ret < 0) {
+ gf_log (stub->frame->this->name, GF_LOG_ERROR,
+ "%"PRId64": CHOWN (%s) on %s returning ENOENT: "
+ "%"PRId32" (%"PRId32")",
+ stub->frame->root->unique,
+ stub->args.chown.loc.path,
+ BOUND_XL(stub->frame)->name,
+ op_ret, op_errno);
+ server_chown_cbk (stub->frame,
+ NULL,
+ stub->frame->this,
+ -1,
+ ENOENT,
+ NULL);
+ server_loc_wipe (&stub->args.chown.loc);
+ FREE (stub);
+ return 0;
+ }
+
+ if (stub->args.chown.loc.parent == NULL)
+ stub->args.chown.loc.parent = inode_ref (parent);
+
+ if (server_inode && (stub->args.chown.loc.inode == NULL)) {
+ stub->args.chown.loc.inode = inode_ref (server_inode);
+ stub->args.chown.loc.ino = server_inode->ino;
+ }
+ call_resume (stub);
+ break;
+ }
+
+ case GF_FOP_LINK:
+ {
+ if (stub->args.link.oldloc.inode == NULL) {
+ if (op_ret < 0) {
+ gf_log (stub->frame->this->name, GF_LOG_ERROR,
+ "%"PRId64": LINK (%s -> %s) on %s returning "
+ "error for oldloc: "
+ "%"PRId32" (%"PRId32")",
+ stub->frame->root->unique,
+ stub->args.link.oldloc.path,
+ stub->args.link.newloc.path,
+ BOUND_XL(stub->frame)->name,
+ op_ret, op_errno);
+
+ server_link_cbk (stub->frame,
+ NULL,
+ stub->frame->this,
+ -1, ENOENT,
+ NULL, NULL);
+ server_loc_wipe (&stub->args.link.oldloc);
+ server_loc_wipe (&stub->args.link.newloc);
+ FREE (stub);
+ return 0;
+ }
+
+ if (stub->args.link.oldloc.parent == NULL)
+ stub->args.link.oldloc.parent =
+ inode_ref (parent);
+
+ if (server_inode &&
+ (stub->args.link.oldloc.inode == NULL)) {
+ stub->args.link.oldloc.inode =
+ inode_ref (server_inode);
+ stub->args.link.oldloc.ino = server_inode->ino;
+ }
+
+ if (stub->args.link.newloc.parent == NULL) {
+ do_path_lookup (stub,
+ &(stub->args.link.newloc));
+ break;
+ }
+ } else {
+ /* we are called by the lookup of newpath */
+ if ((op_ret < 0) && (parent == NULL)) {
+ gf_log (stub->frame->this->name, GF_LOG_ERROR,
+ "%"PRId64": LINK (%s -> %s) on %s returning "
+ "error for newloc: "
+ "%"PRId32" (%"PRId32")",
+ stub->frame->root->unique,
+ stub->args.link.oldloc.path,
+ stub->args.link.newloc.path,
+ BOUND_XL(stub->frame)->name,
+ op_ret, op_errno);
+
+ server_link_cbk (stub->frame, NULL,
+ stub->frame->this,
+ -1, ENOENT,
+ NULL, NULL);
+
+ server_loc_wipe (&stub->args.link.oldloc);
+ server_loc_wipe (&stub->args.link.newloc);
+ FREE (stub);
+ break;
+ }
+
+ if (stub->args.link.newloc.parent == NULL) {
+ stub->args.link.newloc.parent =
+ inode_ref (parent);
+ }
+
+ if (server_inode &&
+ (stub->args.link.newloc.inode == NULL)) {
+ /* as new.inode doesn't get forget, it
+ * needs to be unref'd here */
+ stub->args.link.newloc.inode =
+ inode_ref (server_inode);
+ stub->args.link.newloc.ino = server_inode->ino;
+ }
+ }
+ call_resume (stub);
+ break;
+ }
+
+ case GF_FOP_TRUNCATE:
+ {
+ if (op_ret < 0) {
+ gf_log (stub->frame->this->name, GF_LOG_ERROR,
+ "%"PRId64": TRUNCATE (%s) on %s returning error: "
+ "%"PRId32" (%"PRId32")",
+ stub->frame->root->unique,
+ stub->args.truncate.loc.path,
+ BOUND_XL(stub->frame)->name,
+ op_ret, op_errno);
+
+ server_truncate_cbk (stub->frame,
+ NULL,
+ stub->frame->this,
+ -1, ENOENT,
+ NULL);
+ server_loc_wipe (&stub->args.truncate.loc);
+ FREE (stub);
+ return 0;
+ }
+
+ if (stub->args.truncate.loc.parent == NULL)
+ stub->args.truncate.loc.parent = inode_ref (parent);
+
+ if (server_inode && (stub->args.truncate.loc.inode == NULL)) {
+ stub->args.truncate.loc.inode =
+ inode_ref (server_inode);
+ stub->args.truncate.loc.ino = server_inode->ino;
+ }
+ call_resume (stub);
+ break;
+ }
+
+ case GF_FOP_STATFS:
+ {
+ if (op_ret < 0) {
+ gf_log (stub->frame->this->name, GF_LOG_ERROR,
+ "%"PRId64": STATFS (%s) on %s returning ENOENT: "
+ "%"PRId32" (%"PRId32")",
+ stub->frame->root->unique,
+ stub->args.statfs.loc.path,
+ BOUND_XL(stub->frame)->name,
+ op_ret, op_errno);
+
+ server_statfs_cbk (stub->frame,
+ NULL,
+ stub->frame->this,
+ -1, ENOENT,
+ NULL);
+ server_loc_wipe (&stub->args.statfs.loc);
+ FREE (stub);
+ return 0;
+ }
+
+ if (stub->args.statfs.loc.parent == NULL)
+ stub->args.statfs.loc.parent = inode_ref (parent);
+
+ if (server_inode && (stub->args.statfs.loc.inode == NULL)) {
+ stub->args.statfs.loc.inode = inode_ref (server_inode);
+ stub->args.statfs.loc.ino = server_inode->ino;
+ }
+ call_resume (stub);
+ break;
+ }
+
+ case GF_FOP_SETXATTR:
+ {
+ dict_t *dict = stub->args.setxattr.dict;
+ if (op_ret < 0) {
+ gf_log (stub->frame->this->name, GF_LOG_ERROR,
+ "%"PRId64": SETXATTR (%s) on %s returning error: "
+ "%"PRId32" (%"PRId32")",
+ stub->frame->root->unique,
+ stub->args.setxattr.loc.path,
+ BOUND_XL(stub->frame)->name,
+ op_ret, op_errno);
+
+ server_setxattr_cbk (stub->frame,
+ NULL,
+ stub->frame->this,
+ -1, ENOENT);
+
+ server_loc_wipe (&stub->args.setxattr.loc);
+ dict_unref (dict);
+ FREE (stub);
+ return 0;
+ }
+
+ if (stub->args.setxattr.loc.parent == NULL)
+ stub->args.setxattr.loc.parent = inode_ref (parent);
+
+ if (server_inode && (stub->args.setxattr.loc.inode == NULL)) {
+ stub->args.setxattr.loc.inode =
+ inode_ref (server_inode);
+ stub->args.setxattr.loc.ino = server_inode->ino;
+ }
+ call_resume (stub);
+ break;
+ }
+
+ case GF_FOP_GETXATTR:
+ {
+ if (op_ret < 0) {
+ gf_log (stub->frame->this->name, GF_LOG_ERROR,
+ "%"PRId64": GETXATTR (%s) on %s for key %s "
+ "returning error: %"PRId32" (%"PRId32")",
+ stub->frame->root->unique,
+ stub->args.getxattr.loc.path,
+ BOUND_XL(stub->frame)->name,
+ stub->args.getxattr.name ?
+ stub->args.getxattr.name : "<nul>",
+ op_ret, op_errno);
+
+ server_getxattr_cbk (stub->frame,
+ NULL,
+ stub->frame->this,
+ -1, ENOENT,
+ NULL);
+ server_loc_wipe (&stub->args.getxattr.loc);
+ FREE (stub);
+ return 0;
+ }
+
+ if (stub->args.getxattr.loc.parent == NULL)
+ stub->args.getxattr.loc.parent = inode_ref (parent);
+
+ if (server_inode && (stub->args.getxattr.loc.inode == NULL)) {
+ stub->args.getxattr.loc.inode =
+ inode_ref (server_inode);
+ stub->args.getxattr.loc.ino = server_inode->ino;
+ }
+ call_resume (stub);
+ break;
+ }
+
+ case GF_FOP_REMOVEXATTR:
+ {
+ if (op_ret < 0) {
+ gf_log (stub->frame->this->name, GF_LOG_ERROR,
+ "%"PRId64": REMOVEXATTR (%s) on %s for key %s "
+ "returning error: %"PRId32" (%"PRId32")",
+ stub->frame->root->unique,
+ stub->args.removexattr.loc.path,
+ BOUND_XL(stub->frame)->name,
+ stub->args.removexattr.name,
+ op_ret, op_errno);
+
+ server_removexattr_cbk (stub->frame,
+ NULL,
+ stub->frame->this,
+ -1,
+ ENOENT);
+ server_loc_wipe (&stub->args.removexattr.loc);
+ FREE (stub);
+ return 0;
+ }
+
+ if (stub->args.removexattr.loc.parent == NULL)
+ stub->args.removexattr.loc.parent = inode_ref (parent);
+
+ if (server_inode &&
+ (stub->args.removexattr.loc.inode == NULL)) {
+ stub->args.removexattr.loc.inode =
+ inode_ref (server_inode);
+ stub->args.removexattr.loc.ino = server_inode->ino;
+ }
+ call_resume (stub);
+ break;
+ }
+
+ case GF_FOP_OPENDIR:
+ {
+ if (op_ret < 0) {
+ gf_log (stub->frame->this->name, GF_LOG_ERROR,
+ "%"PRId64": OPENDIR (%s) on %s returning error: "
+ "%"PRId32" (%"PRId32")",
+ stub->frame->root->unique,
+ stub->args.opendir.loc.path,
+ BOUND_XL(stub->frame)->name,
+ op_ret, op_errno);
+
+ server_opendir_cbk (stub->frame,
+ NULL,
+ stub->frame->this,
+ -1, ENOENT,
+ NULL);
+ server_loc_wipe (&stub->args.opendir.loc);
+ FREE (stub);
+ return 0;
+ }
+
+ if (stub->args.opendir.loc.parent == NULL)
+ stub->args.opendir.loc.parent = inode_ref (parent);
+
+ if (server_inode && (stub->args.opendir.loc.inode == NULL)) {
+ stub->args.opendir.loc.inode =
+ inode_ref (server_inode);
+ stub->args.opendir.loc.ino = server_inode->ino;
+ }
+ call_resume (stub);
+ break;
+ }
+
+ case GF_FOP_ACCESS:
+ {
+ if (op_ret < 0) {
+ gf_log (stub->frame->this->name, GF_LOG_ERROR,
+ "%"PRId64": ACCESS (%s) on %s returning error: "
+ "%"PRId32" (%"PRId32")",
+ stub->frame->root->unique,
+ stub->args.access.loc.path,
+ BOUND_XL(stub->frame)->name,
+ op_ret, op_errno);
+
+ server_access_cbk (stub->frame,
+ NULL,
+ stub->frame->this,
+ -1, ENOENT);
+ server_loc_wipe (&stub->args.access.loc);
+ FREE (stub);
+ return 0;
+ }
+
+ if (stub->args.access.loc.parent == NULL)
+ stub->args.access.loc.parent = inode_ref (parent);
+
+ if (server_inode && (stub->args.access.loc.inode == NULL)) {
+ stub->args.access.loc.inode = inode_ref (server_inode);
+ stub->args.access.loc.ino = server_inode->ino;
+ }
+ call_resume (stub);
+ break;
+ }
+
+
+ case GF_FOP_UTIMENS:
+ {
+ if (op_ret < 0) {
+ gf_log (stub->frame->this->name, GF_LOG_ERROR,
+ "%"PRId64": UTIMENS (%s) on %s returning error: "
+ "%"PRId32" (%"PRId32")",
+ stub->frame->root->unique,
+ stub->args.utimens.loc.path,
+ BOUND_XL(stub->frame)->name,
+ op_ret, op_errno);
+
+ server_utimens_cbk (stub->frame,
+ NULL,
+ stub->frame->this,
+ -1, ENOENT,
+ NULL);
+ server_loc_wipe (&stub->args.utimens.loc);
+ FREE (stub);
+ return 0;
+ }
+
+ if (stub->args.utimens.loc.parent == NULL)
+ stub->args.utimens.loc.parent = inode_ref (parent);
+
+ if (server_inode && (stub->args.utimens.loc.inode == NULL)) {
+ stub->args.utimens.loc.inode =
+ inode_ref (server_inode);
+ stub->args.utimens.loc.ino = server_inode->ino;
+ }
+ call_resume (stub);
+ break;
+ }
+
+ case GF_FOP_READLINK:
+ {
+ if (op_ret < 0) {
+ gf_log (stub->frame->this->name, GF_LOG_ERROR,
+ "%"PRId64": READLINK (%s) on %s returning error: "
+ "%"PRId32" (%"PRId32")",
+ stub->frame->root->unique,
+ stub->args.readlink.loc.path,
+ BOUND_XL(stub->frame)->name,
+ op_ret, op_errno);
+
+ server_readlink_cbk (stub->frame,
+ NULL,
+ stub->frame->this,
+ -1, ENOENT,
+ NULL);
+ server_loc_wipe (&stub->args.readlink.loc);
+ FREE (stub);
+ return 0;
+ }
+
+ if (stub->args.readlink.loc.parent == NULL)
+ stub->args.readlink.loc.parent = inode_ref (parent);
+
+ if (server_inode && (stub->args.readlink.loc.inode == NULL)) {
+ stub->args.readlink.loc.inode =
+ inode_ref (server_inode);
+ stub->args.readlink.loc.ino = server_inode->ino;
+ }
+ call_resume (stub);
+ break;
+ }
+ case GF_FOP_MKDIR:
+ {
+ if ((op_ret < 0) && (parent == NULL)) {
+ gf_log (stub->frame->this->name, GF_LOG_ERROR,
+ "%"PRId64": MKDIR (%s) on %s returning error: "
+ "%"PRId32" (%"PRId32")",
+ stub->frame->root->unique,
+ stub->args.mkdir.loc.path,
+ BOUND_XL(stub->frame)->name,
+ op_ret, op_errno);
+
+ server_mkdir_cbk (stub->frame,
+ NULL,
+ stub->frame->this,
+ -1, ENOENT,
+ NULL, NULL);
+ server_loc_wipe (&stub->args.mkdir.loc);
+ FREE (stub);
+ break;
+ }
+
+ if (stub->args.mkdir.loc.parent == NULL)
+ stub->args.mkdir.loc.parent = inode_ref (parent);
+
+ if (server_inode && (stub->args.mkdir.loc.inode == NULL)) {
+ stub->args.mkdir.loc.inode = inode_ref (server_inode);
+ stub->args.mkdir.loc.ino = server_inode->ino;
+ }
+
+ call_resume (stub);
+ break;
+ }
+
+ case GF_FOP_CREATE:
+ {
+ if ((op_ret < 0) && (parent == NULL)) {
+ gf_log (stub->frame->this->name, GF_LOG_ERROR,
+ "%"PRId64": CREATE (%s) on %s returning error: "
+ "%"PRId32" (%"PRId32")",
+ stub->frame->root->unique,
+ stub->args.create.loc.path,
+ BOUND_XL(stub->frame)->name,
+ op_ret, op_errno);
+
+ server_create_cbk (stub->frame,
+ NULL,
+ stub->frame->this,
+ -1, ENOENT,
+ NULL, NULL,
+ NULL);
+ if (stub->args.create.fd)
+ fd_unref (stub->args.create.fd);
+ server_loc_wipe (&stub->args.create.loc);
+ FREE (stub);
+ break;
+ }
+
+ if (stub->args.create.loc.parent == NULL)
+ stub->args.create.loc.parent = inode_ref (parent);
+
+ if (server_inode && (stub->args.create.loc.inode == NULL)) {
+ stub->args.create.loc.inode = inode_ref (server_inode);
+ stub->args.create.loc.ino = server_inode->ino;
+ }
+
+ call_resume (stub);
+ break;
+ }
+
+ case GF_FOP_MKNOD:
+ {
+ if ((op_ret < 0) && (parent == NULL)) {
+ gf_log (stub->frame->this->name, GF_LOG_ERROR,
+ "%"PRId64": MKNOD (%s) on %s returning error: "
+ "%"PRId32" (%"PRId32")",
+ stub->frame->root->unique,
+ stub->args.mknod.loc.path,
+ BOUND_XL(stub->frame)->name,
+ op_ret, op_errno);
+
+ server_mknod_cbk (stub->frame,
+ NULL,
+ stub->frame->this,
+ -1, ENOENT,
+ NULL, NULL);
+ server_loc_wipe (&stub->args.mknod.loc);
+ FREE (stub);
+ break;
+ }
+
+ if (stub->args.mknod.loc.parent == NULL)
+ stub->args.mknod.loc.parent = inode_ref (parent);
+
+ if (server_inode && (stub->args.mknod.loc.inode == NULL)) {
+ stub->args.mknod.loc.inode = inode_ref (server_inode);
+ stub->args.mknod.loc.ino = server_inode->ino;
+ }
+ call_resume (stub);
+ break;
+ }
+ case GF_FOP_ENTRYLK:
+ {
+ if (op_ret < 0) {
+ gf_log (stub->frame->this->name, GF_LOG_ERROR,
+ "%"PRId64": ENTRYLK (%s) on %s for key %s returning "
+ "error: %"PRId32" (%"PRId32")",
+ stub->frame->root->unique,
+ stub->args.entrylk.loc.path,
+ BOUND_XL(stub->frame)->name,
+ stub->args.entrylk.name ?
+ stub->args.entrylk.name : "<nul>",
+ op_ret, op_errno);
+
+ server_entrylk_cbk (stub->frame,
+ NULL,
+ stub->frame->this,
+ -1, ENOENT);
+ server_loc_wipe (&stub->args.entrylk.loc);
+ FREE (stub);
+ break;
+ }
+
+ if (stub->args.entrylk.loc.parent == NULL)
+ stub->args.entrylk.loc.parent = inode_ref (parent);
+
+ if (server_inode && (stub->args.entrylk.loc.inode == NULL)) {
+ stub->args.entrylk.loc.inode = inode_ref (server_inode);
+ stub->args.entrylk.loc.ino = server_inode->ino;
+ }
+ call_resume (stub);
+ break;
+ }
+ case GF_FOP_INODELK:
+ {
+ if (op_ret < 0) {
+ gf_log (stub->frame->this->name, GF_LOG_ERROR,
+ "%"PRId64": INODELK (%s) on %s returning error: "
+ "%"PRId32" (%"PRId32")",
+ stub->frame->root->unique,
+ stub->args.inodelk.loc.path,
+ BOUND_XL(stub->frame)->name,
+ op_ret, op_errno);
+
+ server_inodelk_cbk (stub->frame,
+ NULL,
+ stub->frame->this,
+ -1, ENOENT);
+ server_loc_wipe (&stub->args.inodelk.loc);
+ FREE (stub);
+ break;
+ }
+
+ if (stub->args.inodelk.loc.parent == NULL)
+ stub->args.inodelk.loc.parent = inode_ref (parent);
+
+ if (server_inode && (stub->args.inodelk.loc.inode == NULL)) {
+ stub->args.inodelk.loc.inode =
+ inode_ref (server_inode);
+ stub->args.inodelk.loc.ino = server_inode->ino;
+ }
+ call_resume (stub);
+ break;
+ }
+ default:
+ call_resume (stub);
+ }
+
+ return 0;
+}
+
+static int
+server_lookup_resume (call_frame_t *frame,
+ xlator_t *this,
+ loc_t *loc,
+ dict_t *xattr_req)
+{
+ server_state_t *state = NULL;
+
+ state = CALL_STATE(frame);
+
+ if ((state->loc.parent == NULL) &&
+ (loc->parent))
+ state->loc.parent = inode_ref (loc->parent);
+
+ if (state->loc.inode == NULL) {
+ if (loc->inode == NULL)
+ state->loc.inode = inode_new (state->itable);
+ else
+ /* FIXME: why another lookup? */
+ state->loc.inode = inode_ref (loc->inode);
+ } else {
+ if (loc->inode && (state->loc.inode != loc->inode)) {
+ if (state->loc.inode)
+ inode_unref (state->loc.inode);
+ state->loc.inode = inode_ref (loc->inode);
+ }
+ }
+
+ gf_log (BOUND_XL(frame)->name, GF_LOG_DEBUG,
+ "%"PRId64": LOOKUP \'%"PRId64"/%s\'",
+ frame->root->unique, state->par, state->bname);
+
+ STACK_WIND (frame,
+ server_lookup_cbk,
+ BOUND_XL(frame),
+ BOUND_XL(frame)->fops->lookup,
+ &(state->loc),
+ xattr_req);
+ return 0;
+}
+
+/*
+ * server_lookup - lookup function for server protocol
+ * @frame: call frame
+ * @bound_xl:
+ * @params: parameter dictionary
+ *
+ * not for external reference
+ */
+int
+server_lookup (call_frame_t *frame,
+ xlator_t *bound_xl,
+ gf_hdr_common_t *hdr, size_t hdrlen,
+ char *buf, size_t buflen)
+{
+ gf_fop_lookup_req_t *req = NULL;
+ server_state_t *state = NULL;
+ call_stub_t *lookup_stub = NULL;
+ int32_t ret = -1;
+ size_t pathlen = 0, baselen = 0;
+ size_t dictlen = 0;
+ dict_t *xattr_req = NULL;
+ char *req_dictbuf = NULL;
+
+ req = gf_param (hdr);
+
+ state = CALL_STATE(frame);
+ {
+
+ pathlen = STRLEN_0 (req->path);
+ dictlen = ntoh32 (req->dictlen);
+
+ /* NOTE: lookup() uses req->ino only to identify if a lookup()
+ * is requested for 'root' or not
+ */
+ state->ino = ntoh64 (req->ino);
+ if (state->ino != 1)
+ state->ino = 0;
+
+ state->par = ntoh64 (req->par);
+ state->path = req->path;
+ if (IS_NOT_ROOT(pathlen)) {
+ state->bname = req->bname + pathlen;
+ baselen = STRLEN_0 (state->bname);
+ }
+
+ if (dictlen) {
+ /* Unserialize the dictionary */
+ req_dictbuf = memdup (req->dict + pathlen + baselen, dictlen);
+ GF_VALIDATE_OR_GOTO(bound_xl->name, req_dictbuf, fail);
+
+ xattr_req = dict_new ();
+ GF_VALIDATE_OR_GOTO(bound_xl->name, xattr_req, fail);
+
+ ret = dict_unserialize (req_dictbuf, dictlen, &xattr_req);
+ if (ret < 0) {
+ gf_log (bound_xl->name, GF_LOG_ERROR,
+ "%"PRId64": %s (%"PRId64"): failed to "
+ "unserialize request buffer to dictionary",
+ frame->root->unique, state->loc.path,
+ state->ino);
+ free (req_dictbuf);
+ goto fail;
+ } else{
+ xattr_req->extra_free = req_dictbuf;
+ state->xattr_req = xattr_req;
+ xattr_req = NULL;
+ }
+ }
+ }
+
+ ret = server_loc_fill (&state->loc, state,
+ state->ino, state->par, state->bname,
+ state->path);
+
+ if (state->loc.inode) {
+ /* revalidate */
+ state->is_revalidate = 1;
+ } else {
+ /* fresh lookup or inode was previously pruned out */
+ state->is_revalidate = -1;
+ }
+
+ lookup_stub = fop_lookup_stub (frame, server_lookup_resume,
+ &(state->loc), state->xattr_req);
+ GF_VALIDATE_OR_GOTO(bound_xl->name, lookup_stub, fail);
+
+ if ((state->loc.parent == NULL) &&
+ IS_NOT_ROOT(pathlen))
+ do_path_lookup (lookup_stub, &(state->loc));
+ else
+ call_resume (lookup_stub);
+
+ return 0;
+fail:
+ server_lookup_cbk (frame, NULL, frame->this,
+ -1,EINVAL,
+ NULL, NULL, NULL);
+ if (xattr_req)
+ dict_unref (xattr_req);
+
+ return 0;
+}
+
+
+/*
+ * server_forget - forget function for server protocol
+ * @frame: call frame
+ * @bound_xl:
+ * @params: parameter dictionary
+ *
+ * not for external reference
+ */
+int32_t
+server_forget (call_frame_t *frame, xlator_t *bound_xl,
+ gf_hdr_common_t *hdr, size_t hdrlen,
+ char *buf, size_t buflen)
+{
+ int index = 0;
+ ino_t ino = 0;
+ int32_t count = 0;
+ inode_t *inode = NULL;
+ gf_cbk_forget_req_t *req = NULL;
+
+ req = gf_param (hdr);
+ count = ntoh32 (req->count);
+
+ for (index = 0; index < count; index++) {
+
+ ino = ntoh64 (req->ino_array[index]);
+
+ if (!ino)
+ continue;
+
+ inode = inode_search (bound_xl->itable, ino, NULL);
+
+ if (inode) {
+ inode_forget (inode, 0);
+ inode_unref (inode);
+ } else {
+ gf_log (bound_xl->name, GF_LOG_DEBUG,
+ "%"PRId64": FORGET %"PRId64" not found "
+ "in inode table",
+ frame->root->unique, ino);
+ }
+
+ gf_log (bound_xl->name, GF_LOG_DEBUG,
+ "%"PRId64": FORGET \'%"PRId64"\'",
+ frame->root->unique, ino);
+ }
+
+ server_forget_cbk (frame, NULL, bound_xl, 0, 0);
+
+ return 0;
+}
+
+
+
+int32_t
+server_stat_resume (call_frame_t *frame,
+ xlator_t *this,
+ loc_t *loc)
+{
+ server_state_t *state = NULL;
+
+ state = CALL_STATE(frame);
+
+ gf_log (BOUND_XL(frame)->name, GF_LOG_DEBUG,
+ "%"PRId64": STAT \'%s (%"PRId64")\'",
+ frame->root->unique, state->loc.path, state->loc.ino);
+
+ STACK_WIND (frame,
+ server_stat_cbk,
+ BOUND_XL(frame),
+ BOUND_XL(frame)->fops->stat,
+ loc);
+ return 0;
+}
+
+/*
+ * server_stat - stat function for server
+ * @frame: call frame
+ * @bound_xl: translator this server is bound to
+ * @params: parameters dictionary
+ *
+ * not for external reference
+ */
+int32_t
+server_stat (call_frame_t *frame,
+ xlator_t *bound_xl,
+ gf_hdr_common_t *hdr, size_t hdrlen,
+ char *buf, size_t buflen)
+{
+ call_stub_t *stat_stub = NULL;
+ gf_fop_stat_req_t *req = NULL;
+ server_state_t *state = NULL;
+ int32_t ret = -1;
+ size_t pathlen = 0;
+
+ req = gf_param (hdr);
+ state = CALL_STATE(frame);
+
+ state->ino = ntoh64 (req->ino);
+ state->path = req->path;
+ pathlen = STRLEN_0(state->path);
+
+ ret = server_loc_fill (&(state->loc), state,
+ state->ino, state->par, state->bname,
+ state->path);
+
+ stat_stub = fop_stat_stub (frame,
+ server_stat_resume,
+ &(state->loc));
+ GF_VALIDATE_OR_GOTO(bound_xl->name, stat_stub, fail);
+
+ if (((state->loc.parent == NULL) && IS_NOT_ROOT(pathlen)) ||
+ (state->loc.inode == NULL)) {
+ do_path_lookup (stat_stub, &(state->loc));
+ } else {
+ call_resume (stat_stub);
+ }
+ return 0;
+fail:
+ server_stat_cbk (frame, NULL, frame->this,
+ -1, EINVAL,
+ NULL);
+ return 0;
+}
+
+
+int32_t
+server_readlink_resume (call_frame_t *frame,
+ xlator_t *this,
+ loc_t *loc,
+ size_t size)
+{
+ server_state_t *state = NULL;
+
+ state = CALL_STATE(frame);
+
+ gf_log (BOUND_XL(frame)->name, GF_LOG_DEBUG,
+ "%"PRId64": READLINK \'%s (%"PRId64")\'",
+ frame->root->unique, state->loc.path, state->loc.ino);
+
+ STACK_WIND (frame,
+ server_readlink_cbk,
+ BOUND_XL(frame),
+ BOUND_XL(frame)->fops->readlink,
+ loc,
+ size);
+ return 0;
+}
+
+/*
+ * server_readlink - readlink function for server
+ * @frame: call frame
+ * @bound_xl: translator this server is bound to
+ * @params: parameters dictionary
+ *
+ * not for external reference
+ */
+int32_t
+server_readlink (call_frame_t *frame,
+ xlator_t *bound_xl,
+ gf_hdr_common_t *hdr, size_t hdrlen,
+ char *buf, size_t buflen)
+{
+ call_stub_t *readlink_stub = NULL;
+ gf_fop_readlink_req_t *req = NULL;
+ server_state_t *state = NULL;
+ int32_t ret = -1;
+
+ req = gf_param (hdr);
+ state = CALL_STATE(frame);
+
+ state->size = ntoh32 (req->size);
+
+ state->ino = ntoh64 (req->ino);
+ state->path = req->path;
+
+ ret = server_loc_fill (&(state->loc), state,
+ state->ino, 0, NULL, state->path);
+
+ readlink_stub = fop_readlink_stub (frame,
+ server_readlink_resume,
+ &(state->loc),
+ state->size);
+ GF_VALIDATE_OR_GOTO(bound_xl->name, readlink_stub, fail);
+
+ if ((state->loc.parent == NULL) ||
+ (state->loc.inode == NULL)) {
+ do_path_lookup (readlink_stub, &(state->loc));
+ } else {
+ call_resume (readlink_stub);
+ }
+ return 0;
+fail:
+ server_readlink_cbk (frame, NULL,frame->this,
+ -1, EINVAL,
+ NULL);
+ return 0;
+}
+
+int32_t
+server_create_resume (call_frame_t *frame,
+ xlator_t *this,
+ loc_t *loc,
+ int32_t flags,
+ mode_t mode,
+ fd_t *fd)
+{
+ server_state_t *state = CALL_STATE(frame);
+
+ if (state->loc.parent == NULL)
+ state->loc.parent = inode_ref (loc->parent);
+
+ state->loc.inode = inode_new (state->itable);
+ GF_VALIDATE_OR_GOTO(BOUND_XL(frame)->name, state->loc.inode, fail);
+
+ state->fd = fd_create (state->loc.inode, frame->root->pid);
+ GF_VALIDATE_OR_GOTO(BOUND_XL(frame)->name, state->fd, fail);
+
+ state->fd->flags = flags;
+ state->fd = fd_ref (state->fd);
+
+ gf_log (BOUND_XL(frame)->name, GF_LOG_DEBUG,
+ "%"PRId64": CREATE \'%"PRId64"/%s\'",
+ frame->root->unique, state->par, state->bname);
+
+ STACK_WIND (frame,
+ server_create_cbk,
+ BOUND_XL(frame),
+ BOUND_XL(frame)->fops->create,
+ &(state->loc),
+ flags,
+ mode,
+ state->fd);
+
+ return 0;
+fail:
+ server_create_cbk (frame, NULL, frame->this,
+ -1, EINVAL,
+ NULL, NULL, NULL);
+ return 0;
+}
+
+
+/*
+ * server_create - create function for server
+ * @frame: call frame
+ * @bound_xl: translator this server is bound to
+ * @params: parameters dictionary
+ *
+ * not for external reference
+ */
+int32_t
+server_create (call_frame_t *frame, xlator_t *bound_xl,
+ gf_hdr_common_t *hdr, size_t hdrlen,
+ char *buf, size_t buflen)
+{
+ gf_fop_create_req_t *req = NULL;
+ server_state_t *state = NULL;
+ call_stub_t *create_stub = NULL;
+ int32_t ret = -1;
+ size_t pathlen = 0;
+
+ req = gf_param (hdr);
+ state = CALL_STATE(frame);
+ {
+ pathlen = STRLEN_0(req->path);
+
+ state->par = ntoh64 (req->par);
+ state->path = req->path;
+ if (IS_NOT_ROOT(pathlen))
+ state->bname = req->bname + pathlen;
+
+ state->mode = ntoh32 (req->mode);
+ state->flags = ntoh32 (req->flags);
+ }
+
+ ret = server_loc_fill (&(state->loc), state,
+ 0, state->par, state->bname,
+ state->path);
+
+ create_stub = fop_create_stub (frame, server_create_resume,
+ &(state->loc), state->flags,
+ state->mode, state->fd);
+ GF_VALIDATE_OR_GOTO(bound_xl->name, create_stub, fail);
+
+ if (state->loc.parent == NULL) {
+ do_path_lookup (create_stub, &state->loc);
+ } else {
+ call_resume (create_stub);
+ }
+ return 0;
+fail:
+ server_create_cbk (frame, NULL, frame->this,
+ -1, EINVAL,
+ NULL, NULL, NULL);
+ return 0;
+}
+
+
+int32_t
+server_open_resume (call_frame_t *frame,
+ xlator_t *this,
+ loc_t *loc,
+ int32_t flags,
+ fd_t *fd)
+{
+ server_state_t *state = CALL_STATE(frame);
+ fd_t *new_fd = NULL;
+
+ new_fd = fd_create (loc->inode, frame->root->pid);
+ GF_VALIDATE_OR_GOTO(BOUND_XL(frame)->name, new_fd, fail);
+
+ new_fd->flags = flags;
+
+ state->fd = fd_ref (new_fd);
+
+ gf_log (BOUND_XL(frame)->name, GF_LOG_DEBUG,
+ "%"PRId64": OPEN \'%s (%"PRId64")\'",
+ frame->root->unique, state->path, state->ino);
+
+ STACK_WIND (frame,
+ server_open_cbk,
+ BOUND_XL(frame),
+ BOUND_XL(frame)->fops->open,
+ loc,
+ flags,
+ state->fd);
+
+ return 0;
+fail:
+ server_open_cbk (frame, NULL, frame->this,
+ -1, EINVAL,
+ NULL);
+ return 0;
+}
+
+/*
+ * server_open - open function for server protocol
+ * @frame: call frame
+ * @bound_xl: translator this server protocol is bound to
+ * @params: parameters dictionary
+ *
+ * not for external reference
+ */
+int32_t
+server_open (call_frame_t *frame, xlator_t *bound_xl,
+ gf_hdr_common_t *hdr, size_t hdrlen,
+ char *buf, size_t buflen)
+{
+ call_stub_t *open_stub = NULL;
+ gf_fop_open_req_t *req = NULL;
+ server_state_t *state = NULL;
+ int32_t ret = -1;
+ size_t pathlen = 0;
+
+ req = gf_param (hdr);
+ state = CALL_STATE(frame);
+ {
+ state->ino = ntoh64 (req->ino);
+ state->path = req->path;
+ pathlen = STRLEN_0(state->path);
+ state->flags = ntoh32 (req->flags);
+ }
+ ret = server_loc_fill (&(state->loc), state,
+ state->ino, 0, NULL, state->path);
+
+ open_stub = fop_open_stub (frame,
+ server_open_resume,
+ &(state->loc), state->flags, NULL);
+ GF_VALIDATE_OR_GOTO(bound_xl->name, open_stub, fail);
+
+ if (((state->loc.parent == NULL) && IS_NOT_ROOT(pathlen)) ||
+ (state->loc.inode == NULL)) {
+ do_path_lookup (open_stub, &state->loc);
+ } else {
+ call_resume (open_stub);
+ }
+ return 0;
+fail:
+ server_open_cbk (frame, NULL, frame->this,
+ -1, EINVAL,
+ NULL);
+ return 0;
+}
+
+
+/*
+ * server_readv - readv function for server protocol
+ * @frame: call frame
+ * @bound_xl:
+ * @params: parameter dictionary
+ *
+ * not for external reference
+ */
+int32_t
+server_readv (call_frame_t *frame, xlator_t *bound_xl,
+ gf_hdr_common_t *hdr, size_t hdrlen,
+ char *buf, size_t buflen)
+{
+ gf_fop_read_req_t *req = NULL;
+ server_state_t *state = NULL;
+ server_connection_t *conn = NULL;
+
+ conn = SERVER_CONNECTION(frame);
+
+ req = gf_param (hdr);
+
+ state = CALL_STATE(frame);
+ {
+ state->fd_no = ntoh64 (req->fd);
+ if (state->fd_no >= 0)
+ state->fd = gf_fd_fdptr_get (conn->fdtable,
+ state->fd_no);
+
+ state->size = ntoh32 (req->size);
+ state->offset = ntoh64 (req->offset);
+ }
+
+ GF_VALIDATE_OR_GOTO(bound_xl->name, state->fd, fail);
+
+ gf_log (bound_xl->name, GF_LOG_DEBUG,
+ "%"PRId64": READV \'fd=%"PRId64" (%"PRId64"); "
+ "offset=%"PRId64"; size=%"PRId64,
+ frame->root->unique, state->fd_no, state->fd->inode->ino,
+ state->offset, (int64_t)state->size);
+
+ STACK_WIND (frame,
+ server_readv_cbk,
+ BOUND_XL(frame),
+ BOUND_XL(frame)->fops->readv,
+ state->fd, state->size, state->offset);
+ return 0;
+fail:
+ server_readv_cbk (frame, NULL, frame->this,
+ -1, EINVAL, NULL, 0, NULL);
+ return 0;
+}
+
+
+/*
+ * server_writev - writev function for server
+ * @frame: call frame
+ * @bound_xl:
+ * @params: parameter dictionary
+ *
+ * not for external reference
+ */
+int32_t
+server_writev (call_frame_t *frame, xlator_t *bound_xl,
+ gf_hdr_common_t *hdr, size_t hdrlen,
+ char *buf, size_t buflen)
+{
+ server_connection_t *conn = NULL;
+ gf_fop_write_req_t *req = NULL;
+ struct iovec iov = {0, };
+ dict_t *refs = NULL;
+ server_state_t *state = NULL;
+ int32_t ret = -1;
+
+ conn = SERVER_CONNECTION(frame);
+
+ req = gf_param (hdr);
+ state = CALL_STATE(frame);
+ {
+ state->fd_no = ntoh64 (req->fd);
+ if (state->fd_no >= 0)
+ state->fd = gf_fd_fdptr_get (conn->fdtable,
+ state->fd_no);
+
+ state->offset = ntoh64 (req->offset);
+ }
+
+ GF_VALIDATE_OR_GOTO(bound_xl->name, state->fd, fail);
+
+ iov.iov_base = buf;
+ iov.iov_len = buflen;
+
+ refs = dict_new ();
+ GF_VALIDATE_OR_GOTO(bound_xl->name, refs, fail);
+
+ ret = dict_set_dynptr (refs, NULL, buf, buflen);
+ if (ret < 0) {
+ gf_log (frame->this->name, GF_LOG_ERROR,
+ "fd - %"PRId64" (%"PRId64"): failed to set buffer entry "
+ "to req_refs",
+ state->fd_no, state->fd->inode->ino);
+ goto fail;
+ } else {
+ buf = NULL;
+ }
+
+ frame->root->req_refs = refs;
+
+ gf_log (bound_xl->name, GF_LOG_DEBUG,
+ "%"PRId64": WRITEV \'fd=%"PRId64" (%"PRId64"); "
+ "offset=%"PRId64"; size=%"PRId64,
+ frame->root->unique, state->fd_no, state->fd->inode->ino,
+ state->offset, (int64_t)buflen);
+
+ STACK_WIND (frame,
+ server_writev_cbk,
+ BOUND_XL(frame),
+ BOUND_XL(frame)->fops->writev,
+ state->fd, &iov, 1, state->offset);
+
+ if (refs)
+ dict_unref (refs);
+ return 0;
+fail:
+ server_writev_cbk (frame, NULL, frame->this,
+ -1, EINVAL, NULL);
+
+ if (buf)
+ free (buf);
+
+ if (refs)
+ dict_unref (refs);
+
+ return 0;
+}
+
+
+
+/*
+ * server_release - release function for server protocol
+ * @frame: call frame
+ * @bound_xl:
+ * @params: parameter dictionary
+ *
+ * not for external reference
+ */
+int32_t
+server_release (call_frame_t *frame, xlator_t *bound_xl,
+ gf_hdr_common_t *hdr, size_t hdrlen,
+ char *buf, size_t buflen)
+{
+ gf_cbk_release_req_t *req = NULL;
+ server_state_t *state = NULL;
+ server_connection_t *conn = NULL;
+
+ conn = SERVER_CONNECTION(frame);
+
+ req = gf_param (hdr);
+ state = CALL_STATE(frame);
+
+ state->fd_no = ntoh64 (req->fd);
+ state->fd = gf_fd_fdptr_get (conn->fdtable,
+ state->fd_no);
+
+ GF_VALIDATE_OR_GOTO(bound_xl->name, state->fd, fail);
+
+ gf_fd_put (conn->fdtable,
+ state->fd_no);
+
+ gf_log (bound_xl->name, GF_LOG_DEBUG,
+ "%"PRId64": RELEASE \'fd=%"PRId64" (%"PRId64")\'",
+ frame->root->unique, state->fd_no, state->fd->inode->ino);
+
+ STACK_WIND (frame,
+ server_release_cbk,
+ BOUND_XL(frame),
+ BOUND_XL(frame)->fops->flush,
+ state->fd);
+ return 0;
+fail:
+ server_release_cbk (frame, NULL, frame->this,
+ -1, EINVAL);
+ return 0;
+}
+
+
+/*
+ * server_fsync - fsync function for server protocol
+ * @frame: call frame
+ * @bound_xl:
+ * @params: parameters dictionary
+ *
+ * not for external reference
+ */
+int32_t
+server_fsync (call_frame_t *frame,
+ xlator_t *bound_xl,
+ gf_hdr_common_t *hdr, size_t hdrlen,
+ char *buf, size_t buflen)
+{
+ gf_fop_fsync_req_t *req = NULL;
+ server_state_t *state = NULL;
+ server_connection_t *conn = NULL;
+
+ conn = SERVER_CONNECTION(frame);
+
+ req = gf_param (hdr);
+ state = CALL_STATE(frame);
+ {
+ state->fd_no = ntoh64 (req->fd);
+ if (state->fd_no >= 0)
+ state->fd = gf_fd_fdptr_get (conn->fdtable,
+ state->fd_no);
+
+ state->flags = ntoh32 (req->data);
+ }
+
+ GF_VALIDATE_OR_GOTO(bound_xl->name, state->fd, fail);
+
+ gf_log (bound_xl->name, GF_LOG_DEBUG,
+ "%"PRId64": FSYNC \'fd=%"PRId64" (%"PRId64")\'",
+ frame->root->unique, state->fd_no, state->fd->inode->ino);
+
+ STACK_WIND (frame,
+ server_fsync_cbk,
+ BOUND_XL(frame),
+ BOUND_XL(frame)->fops->fsync,
+ state->fd, state->flags);
+ return 0;
+fail:
+ server_fsync_cbk (frame, NULL, frame->this,
+ -1, EINVAL);
+
+ return 0;
+}
+
+
+/*
+ * server_flush - flush function for server protocol
+ * @frame: call frame
+ * @bound_xl:
+ * @params: parameter dictionary
+ *
+ * not for external reference
+ */
+int32_t
+server_flush (call_frame_t *frame, xlator_t *bound_xl,
+ gf_hdr_common_t *hdr, size_t hdrlen,
+ char *buf, size_t buflen)
+{
+ gf_fop_flush_req_t *req = NULL;
+ server_state_t *state = NULL;
+ server_connection_t *conn = NULL;
+
+ conn = SERVER_CONNECTION(frame);
+
+ req = gf_param (hdr);
+ state = CALL_STATE(frame);
+ {
+ state->fd_no = ntoh64 (req->fd);
+ if (state->fd_no >= 0)
+ state->fd = gf_fd_fdptr_get (conn->fdtable,
+ state->fd_no);
+ }
+
+ GF_VALIDATE_OR_GOTO(bound_xl->name, state->fd, fail);
+
+ gf_log (bound_xl->name, GF_LOG_DEBUG,
+ "%"PRId64": FLUSH \'fd=%"PRId64" (%"PRId64")\'",
+ frame->root->unique, state->fd_no, state->fd->inode->ino);
+
+ STACK_WIND (frame,
+ server_flush_cbk,
+ BOUND_XL(frame),
+ BOUND_XL(frame)->fops->flush,
+ state->fd);
+ return 0;
+
+fail:
+ server_flush_cbk (frame, NULL, frame->this,
+ -1, EINVAL);
+
+ return 0;
+}
+
+
+/*
+ * server_ftruncate - ftruncate function for server protocol
+ * @frame: call frame
+ * @bound_xl:
+ * @params: parameters dictionary
+ *
+ * not for external reference
+ */
+int32_t
+server_ftruncate (call_frame_t *frame,
+ xlator_t *bound_xl,
+ gf_hdr_common_t *hdr, size_t hdrlen,
+ char *buf, size_t buflen)
+{
+ gf_fop_ftruncate_req_t *req = NULL;
+ server_state_t *state = NULL;
+ server_connection_t *conn = NULL;
+
+ conn = SERVER_CONNECTION(frame);
+
+ req = gf_param (hdr);
+
+ state = CALL_STATE(frame);
+ {
+ state->fd_no = ntoh64 (req->fd);
+ if (state->fd_no >= 0)
+ state->fd = gf_fd_fdptr_get (conn->fdtable,
+ state->fd_no);
+
+ state->offset = ntoh64 (req->offset);
+ }
+
+ GF_VALIDATE_OR_GOTO(bound_xl->name, state->fd, fail);
+
+ gf_log (bound_xl->name, GF_LOG_DEBUG,
+ "%"PRId64": FTRUNCATE \'fd=%"PRId64" (%"PRId64"); "
+ "offset=%"PRId64"\'",
+ frame->root->unique, state->fd_no, state->fd->inode->ino,
+ state->offset);
+
+ STACK_WIND (frame,
+ server_ftruncate_cbk,
+ bound_xl,
+ bound_xl->fops->ftruncate,
+ state->fd,
+ state->offset);
+ return 0;
+fail:
+ server_ftruncate_cbk (frame, NULL, frame->this,
+ -1, EINVAL, NULL);
+
+ return 0;
+}
+
+
+/*
+ * server_fstat - fstat function for server protocol
+ * @frame: call frame
+ * @bound_xl:
+ * @params: parameter dictionary
+ *
+ * not for external reference
+ */
+int32_t
+server_fstat (call_frame_t *frame,
+ xlator_t *bound_xl,
+ gf_hdr_common_t *hdr, size_t hdrlen,
+ char *buf, size_t buflen)
+{
+ gf_fop_fstat_req_t *req = NULL;
+ server_state_t *state = NULL;
+ server_connection_t *conn = NULL;
+
+ conn = SERVER_CONNECTION(frame);
+
+ req = gf_param (hdr);
+ state = CALL_STATE(frame);
+ {
+ state->fd_no = ntoh64 (req->fd);
+ if (state->fd_no >= 0)
+ state->fd = gf_fd_fdptr_get (conn->fdtable,
+ state->fd_no);
+ }
+
+
+ if (state->fd == NULL) {
+ gf_log (frame->this->name, GF_LOG_ERROR,
+ "fd - %"PRId64": unresolved fd",
+ state->fd_no);
+
+ server_fstat_cbk (frame, NULL, frame->this,
+ -1, EINVAL, NULL);
+
+ goto out;
+ }
+
+ gf_log (bound_xl->name, GF_LOG_DEBUG,
+ "%"PRId64": FSTAT \'fd=%"PRId64" (%"PRId64")\'",
+ frame->root->unique, state->fd_no, state->fd->inode->ino);
+
+ STACK_WIND (frame,
+ server_fstat_cbk,
+ bound_xl,
+ bound_xl->fops->fstat,
+ state->fd);
+out:
+ return 0;
+}
+
+
+int32_t
+server_truncate_resume (call_frame_t *frame,
+ xlator_t *this,
+ loc_t *loc,
+ off_t offset)
+{
+ server_state_t *state = NULL;
+
+ state = CALL_STATE(frame);
+
+ gf_log (BOUND_XL(frame)->name, GF_LOG_DEBUG,
+ "%"PRId64": TRUNCATE \'%s (%"PRId64")\'",
+ frame->root->unique, state->path, state->ino);
+
+ STACK_WIND (frame,
+ server_truncate_cbk,
+ BOUND_XL(frame),
+ BOUND_XL(frame)->fops->truncate,
+ loc,
+ offset);
+ return 0;
+}
+
+
+/*
+ * server_truncate - truncate function for server protocol
+ * @frame: call frame
+ * @bound_xl:
+ * @params:
+ *
+ * not for external reference
+ */
+int32_t
+server_truncate (call_frame_t *frame,
+ xlator_t *bound_xl,
+ gf_hdr_common_t *hdr, size_t hdrlen,
+ char *buf, size_t buflen)
+{
+ call_stub_t *truncate_stub = NULL;
+ gf_fop_truncate_req_t *req = NULL;
+ server_state_t *state = NULL;
+ int32_t ret = -1;
+ size_t pathlen = 0;
+
+ req = gf_param (hdr);
+ state = CALL_STATE(frame);
+ {
+ pathlen = STRLEN_0(req->path);
+ state->offset = ntoh64 (req->offset);
+
+ state->path = req->path;
+ state->ino = ntoh64 (req->ino);
+ }
+
+
+ ret = server_loc_fill (&(state->loc), state,
+ state->ino, 0, NULL, state->path);
+
+ truncate_stub = fop_truncate_stub (frame,
+ server_truncate_resume,
+ &(state->loc),
+ state->offset);
+ if ((state->loc.parent == NULL) ||
+ (state->loc.inode == NULL)) {
+ do_path_lookup (truncate_stub, &(state->loc));
+ } else {
+ call_resume (truncate_stub);
+ }
+
+ return 0;
+}
+
+
+
+
+
+int32_t
+server_unlink_resume (call_frame_t *frame,
+ xlator_t *this,
+ loc_t *loc)
+{
+ server_state_t *state = NULL;
+
+ state = CALL_STATE(frame);
+
+ if (state->loc.parent == NULL)
+ state->loc.parent = inode_ref (loc->parent);
+
+ if (state->loc.inode == NULL)
+ state->loc.inode = inode_ref (loc->inode);
+
+ gf_log (BOUND_XL(frame)->name, GF_LOG_DEBUG,
+ "%"PRId64": UNLINK \'%"PRId64"/%s (%"PRId64")\'",
+ frame->root->unique, state->par, state->path,
+ state->loc.inode->ino);
+
+ STACK_WIND (frame,
+ server_unlink_cbk,
+ BOUND_XL(frame),
+ BOUND_XL(frame)->fops->unlink,
+ loc);
+ return 0;
+}
+
+/*
+ * server_unlink - unlink function for server protocol
+ * @frame: call frame
+ * @bound_xl:
+ * @params: parameter dictionary
+ *
+ * not for external reference
+ */
+int32_t
+server_unlink (call_frame_t *frame,
+ xlator_t *bound_xl,
+ gf_hdr_common_t *hdr, size_t hdrlen,
+ char *buf, size_t buflen)
+{
+ call_stub_t *unlink_stub = NULL;
+ gf_fop_unlink_req_t *req = NULL;
+ server_state_t *state = NULL;
+ int32_t ret = -1;
+ size_t pathlen = 0;
+
+ req = gf_param (hdr);
+ state = CALL_STATE(frame);
+
+ pathlen = STRLEN_0(req->path);
+
+ state->par = ntoh64 (req->par);
+ state->path = req->path;
+ if (IS_NOT_ROOT(pathlen))
+ state->bname = req->bname + pathlen;
+
+ ret = server_loc_fill (&(state->loc), state,
+ 0, state->par, state->bname,
+ state->path);
+
+ unlink_stub = fop_unlink_stub (frame,
+ server_unlink_resume,
+ &(state->loc));
+
+ if ((state->loc.parent == NULL) ||
+ (state->loc.inode == NULL)) {
+ do_path_lookup (unlink_stub, &state->loc);
+ } else {
+ call_resume (unlink_stub);
+ }
+
+ return 0;
+}
+
+
+
+
+
+int32_t
+server_setxattr_resume (call_frame_t *frame,
+ xlator_t *this,
+ loc_t *loc,
+ dict_t *dict,
+ int32_t flags)
+{
+ server_state_t *state = NULL;
+
+ state = CALL_STATE(frame);
+
+ gf_log (BOUND_XL(frame)->name, GF_LOG_DEBUG,
+ "%"PRId64": SETXATTR \'%s (%"PRId64")\'",
+ frame->root->unique, state->path, state->ino);
+
+ STACK_WIND (frame,
+ server_setxattr_cbk,
+ BOUND_XL(frame),
+ BOUND_XL(frame)->fops->setxattr,
+ loc,
+ dict,
+ flags);
+ return 0;
+}
+
+/*
+ * server_setxattr - setxattr function for server protocol
+ * @frame: call frame
+ * @bound_xl:
+ * @params: parameter dictionary
+ *
+ * not for external reference
+ */
+
+int32_t
+server_setxattr (call_frame_t *frame,
+ xlator_t *bound_xl,
+ gf_hdr_common_t *hdr, size_t hdrlen,
+ char *buf, size_t buflen)
+{
+ call_stub_t *setxattr_stub = NULL;
+ gf_fop_setxattr_req_t *req = NULL;
+ dict_t *dict = NULL;
+ server_state_t *state = NULL;
+ int32_t ret = -1;
+ size_t pathlen = 0;
+ size_t dict_len = 0;
+ char *req_dictbuf = NULL;
+
+ req = gf_param (hdr);
+ state = CALL_STATE(frame);
+ {
+ dict_len = ntoh32 (req->dict_len);
+
+ state->path = req->path + dict_len;
+
+ pathlen = STRLEN_0(state->path);
+ state->ino = ntoh64 (req->ino);
+
+ state->flags = ntoh32 (req->flags);
+ }
+ ret = server_loc_fill (&(state->loc), state,
+ state->ino, 0, NULL, state->path);
+
+ {
+ /* Unserialize the dictionary */
+ req_dictbuf = memdup (req->dict, dict_len);
+ GF_VALIDATE_OR_GOTO(bound_xl->name, req_dictbuf, fail);
+
+ dict = dict_new ();
+ GF_VALIDATE_OR_GOTO(bound_xl->name, dict, fail);
+
+ ret = dict_unserialize (req_dictbuf, dict_len, &dict);
+ if (ret < 0) {
+ gf_log (bound_xl->name, GF_LOG_ERROR,
+ "%"PRId64": %s (%"PRId64"): failed to "
+ "unserialize request buffer to dictionary",
+ frame->root->unique, state->loc.path,
+ state->ino);
+ free (req_dictbuf);
+ goto fail;
+ } else{
+ dict->extra_free = req_dictbuf;
+ }
+ }
+
+ setxattr_stub = fop_setxattr_stub (frame,
+ server_setxattr_resume,
+ &(state->loc),
+ dict,
+ state->flags);
+ GF_VALIDATE_OR_GOTO(bound_xl->name, setxattr_stub, fail);
+
+ if (((state->loc.parent == NULL) && IS_NOT_ROOT(pathlen)) ||
+ (state->loc.inode == NULL)) {
+ do_path_lookup (setxattr_stub, &(state->loc));
+ } else {
+ call_resume (setxattr_stub);
+ }
+
+ if (dict)
+ dict_unref (dict);
+
+ return 0;
+fail:
+ if (dict)
+ dict_unref (dict);
+
+ server_setxattr_cbk (frame, NULL, frame->this,
+ -1, ENOENT);
+ return 0;
+
+}
+
+
+
+int32_t
+server_fxattrop (call_frame_t *frame,
+ xlator_t *bound_xl,
+ gf_hdr_common_t *hdr, size_t hdrlen,
+ char *buf, size_t buflen)
+{
+ server_connection_t *conn = NULL;
+ gf_fop_fxattrop_req_t *req = NULL;
+ dict_t *dict = NULL;
+ server_state_t *state = NULL;
+ size_t dict_len = 0;
+ char *req_dictbuf = NULL;
+ int32_t ret = -1;
+
+ conn = SERVER_CONNECTION(frame);
+
+ req = gf_param (hdr);
+ state = CALL_STATE(frame);
+ {
+ state->fd_no = ntoh64 (req->fd);
+ if (state->fd_no >= 0)
+ state->fd = gf_fd_fdptr_get (conn->fdtable,
+ state->fd_no);
+
+ dict_len = ntoh32 (req->dict_len);
+ state->ino = ntoh64 (req->ino);
+ state->flags = ntoh32 (req->flags);
+ }
+
+ if (dict_len) {
+ /* Unserialize the dictionary */
+ req_dictbuf = memdup (req->dict, dict_len);
+ GF_VALIDATE_OR_GOTO(bound_xl->name, req_dictbuf, fail);
+
+ dict = dict_new ();
+ GF_VALIDATE_OR_GOTO(bound_xl->name, dict, fail);
+
+ ret = dict_unserialize (req_dictbuf, dict_len, &dict);
+ if (ret < 0) {
+ gf_log (bound_xl->name, GF_LOG_ERROR,
+ "fd - %"PRId64" (%"PRId64"): failed to unserialize "
+ "request buffer to dictionary",
+ state->fd_no, state->fd->inode->ino);
+ free (req_dictbuf);
+ goto fail;
+ } else {
+ dict->extra_free = req_dictbuf;
+ }
+ }
+
+ gf_log (bound_xl->name, GF_LOG_DEBUG,
+ "%"PRId64": FXATTROP \'fd=%"PRId64" (%"PRId64")\'",
+ frame->root->unique, state->fd_no, state->fd->inode->ino);
+
+ STACK_WIND (frame,
+ server_fxattrop_cbk,
+ bound_xl,
+ bound_xl->fops->fxattrop,
+ state->fd,
+ state->flags,
+ dict);
+ if (dict)
+ dict_unref (dict);
+ return 0;
+fail:
+ if (dict)
+ dict_unref (dict);
+
+ server_fxattrop_cbk (frame, NULL, frame->this,
+ -1, EINVAL, NULL);
+ return 0;
+}
+
+int32_t
+server_xattrop_resume (call_frame_t *frame,
+ xlator_t *this,
+ loc_t *loc,
+ gf_xattrop_flags_t flags,
+ dict_t *dict)
+{
+ server_state_t *state = NULL;
+
+ state = CALL_STATE(frame);
+
+ gf_log (BOUND_XL(frame)->name, GF_LOG_DEBUG,
+ "%"PRId64": XATTROP \'%s (%"PRId64")\'",
+ frame->root->unique, state->path, state->ino);
+
+ STACK_WIND (frame,
+ server_xattrop_cbk,
+ BOUND_XL(frame),
+ BOUND_XL(frame)->fops->xattrop,
+ loc,
+ flags,
+ dict);
+ return 0;
+}
+
+int32_t
+server_xattrop (call_frame_t *frame,
+ xlator_t *bound_xl,
+ gf_hdr_common_t *hdr, size_t hdrlen,
+ char *buf, size_t buflen)
+{
+ gf_fop_xattrop_req_t *req = NULL;
+ dict_t *dict = NULL;
+ server_state_t *state = NULL;
+ call_stub_t *xattrop_stub = NULL;
+ int32_t ret = -1;
+ size_t pathlen = 0;
+ size_t dict_len = 0;
+ char *req_dictbuf = NULL;
+
+ req = gf_param (hdr);
+ state = CALL_STATE(frame);
+ {
+ dict_len = ntoh32 (req->dict_len);
+ state->ino = ntoh64 (req->ino);
+ state->path = req->path + dict_len;
+ pathlen = STRLEN_0(state->path);
+ state->flags = ntoh32 (req->flags);
+ }
+
+ ret = server_loc_fill (&(state->loc), state,
+ state->ino, 0, NULL, state->path);
+
+ if (dict_len) {
+ /* Unserialize the dictionary */
+ req_dictbuf = memdup (req->dict, dict_len);
+ GF_VALIDATE_OR_GOTO(bound_xl->name, req_dictbuf, fail);
+
+ dict = dict_new ();
+ GF_VALIDATE_OR_GOTO(bound_xl->name, dict, fail);
+
+ ret = dict_unserialize (req_dictbuf, dict_len, &dict);
+ if (ret < 0) {
+ gf_log (bound_xl->name, GF_LOG_ERROR,
+ "%s (%"PRId64"): failed to unserialize "
+ "request buffer to dictionary",
+ state->loc.path, state->ino);
+ goto fail;
+ } else {
+ dict->extra_free = req_dictbuf;
+ }
+ }
+ xattrop_stub = fop_xattrop_stub (frame,
+ server_xattrop_resume,
+ &(state->loc),
+ state->flags,
+ dict);
+ GF_VALIDATE_OR_GOTO(bound_xl->name, xattrop_stub, fail);
+
+ if (((state->loc.parent == NULL) && IS_NOT_ROOT(pathlen)) ||
+ (state->loc.inode == NULL)) {
+ do_path_lookup (xattrop_stub, &(state->loc));
+ } else {
+ call_resume (xattrop_stub);
+ }
+
+ if (dict)
+ dict_unref (dict);
+ return 0;
+fail:
+ if (dict)
+ dict_unref (dict);
+
+ server_xattrop_cbk (frame, NULL, frame->this,
+ -1, EINVAL,
+ NULL);
+ return 0;
+}
+
+
+int32_t
+server_getxattr_resume (call_frame_t *frame,
+ xlator_t *this,
+ loc_t *loc,
+ const char *name)
+{
+ server_state_t *state = NULL;
+
+ state = CALL_STATE(frame);
+
+ gf_log (BOUND_XL(frame)->name, GF_LOG_DEBUG,
+ "%"PRId64": GETXATTR \'%s (%"PRId64")\'",
+ frame->root->unique, state->path, state->ino);
+
+ STACK_WIND (frame,
+ server_getxattr_cbk,
+ BOUND_XL(frame),
+ BOUND_XL(frame)->fops->getxattr,
+ loc,
+ name);
+ return 0;
+}
+
+/*
+ * server_getxattr - getxattr function for server protocol
+ * @frame: call frame
+ * @bound_xl:
+ * @params: parameter dictionary
+ *
+ * not for external reference
+ */
+int32_t
+server_getxattr (call_frame_t *frame,
+ xlator_t *bound_xl,
+ gf_hdr_common_t *hdr, size_t hdrlen,
+ char *buf, size_t buflen)
+{
+ gf_fop_getxattr_req_t *req = NULL;
+ call_stub_t *getxattr_stub = NULL;
+ server_state_t *state = NULL;
+ int32_t ret = -1;
+ size_t namelen = 0;
+ size_t pathlen = 0;
+
+ req = gf_param (hdr);
+ state = CALL_STATE(frame);
+ {
+ pathlen = STRLEN_0(req->path);
+
+ state->path = req->path;
+ state->ino = ntoh64 (req->ino);
+
+ namelen = ntoh32 (req->namelen);
+ if (namelen)
+ state->name = (req->name + pathlen);
+ }
+
+ ret = server_loc_fill (&(state->loc), state,
+ state->ino, 0, NULL, state->path);
+
+ getxattr_stub = fop_getxattr_stub (frame,
+ server_getxattr_resume,
+ &(state->loc),
+ state->name);
+
+ if (((state->loc.parent == NULL) && IS_NOT_ROOT(pathlen)) ||
+ (state->loc.inode == NULL)) {
+ do_path_lookup (getxattr_stub, &(state->loc));
+ } else {
+ call_resume (getxattr_stub);
+ }
+
+ return 0;
+}
+
+
+
+int32_t
+server_removexattr_resume (call_frame_t *frame,
+ xlator_t *this,
+ loc_t *loc,
+ const char *name)
+{
+ server_state_t *state = NULL;
+
+ state = CALL_STATE(frame);
+
+ gf_log (BOUND_XL(frame)->name, GF_LOG_DEBUG,
+ "%"PRId64": REMOVEXATTR \'%s (%"PRId64")\'",
+ frame->root->unique, state->path, state->ino);
+
+ STACK_WIND (frame,
+ server_removexattr_cbk,
+ BOUND_XL(frame),
+ BOUND_XL(frame)->fops->removexattr,
+ loc,
+ name);
+ return 0;
+}
+
+/*
+ * server_removexattr - removexattr function for server protocol
+ * @frame: call frame
+ * @bound_xl:
+ * @params: parameter dictionary
+ *
+ * not for external reference
+ */
+int32_t
+server_removexattr (call_frame_t *frame,
+ xlator_t *bound_xl,
+ gf_hdr_common_t *hdr, size_t hdrlen,
+ char *buf, size_t buflen)
+{
+ gf_fop_removexattr_req_t *req = NULL;
+ call_stub_t *removexattr_stub = NULL;
+ server_state_t *state = NULL;
+ int32_t ret = -1;
+ size_t pathlen = 0;
+
+ req = gf_param (hdr);
+ state = CALL_STATE(frame);
+ {
+ pathlen = STRLEN_0(req->path);
+
+ state->path = req->path;
+ state->ino = ntoh64 (req->ino);
+
+ state->name = (req->name + pathlen);
+ }
+
+ ret = server_loc_fill (&(state->loc), state,
+ state->ino, 0, NULL, state->path);
+
+ removexattr_stub = fop_removexattr_stub (frame,
+ server_removexattr_resume,
+ &(state->loc),
+ state->name);
+
+ if (((state->loc.parent == NULL) && IS_NOT_ROOT(pathlen)) ||
+ (state->loc.inode == NULL)) {
+ do_path_lookup (removexattr_stub, &(state->loc));
+ } else {
+ call_resume (removexattr_stub);
+ }
+
+ return 0;
+}
+
+
+/*
+ * server_statfs - statfs function for server protocol
+ * @frame: call frame
+ * @bound_xl:
+ * @params: parameter dictionary
+ *
+ * not for external reference
+ */
+int32_t
+server_statfs (call_frame_t *frame,
+ xlator_t *bound_xl,
+ gf_hdr_common_t *hdr, size_t hdrlen,
+ char *buf, size_t buflen)
+{
+ gf_fop_statfs_req_t *req = NULL;
+ server_state_t *state = NULL;
+ int32_t ret = -1;
+
+ req = gf_param (hdr);
+
+ state = CALL_STATE(frame);
+ state->ino = ntoh64 (req->ino);
+ state->path = req->path;
+
+ ret = server_loc_fill (&state->loc, state,
+ state->ino, 0, NULL, state->path);
+
+ gf_log (BOUND_XL(frame)->name, GF_LOG_DEBUG,
+ "%"PRId64": STATFS \'%s (%"PRId64")\'",
+ frame->root->unique, state->path, state->ino);
+
+ STACK_WIND (frame,
+ server_statfs_cbk,
+ BOUND_XL(frame),
+ BOUND_XL(frame)->fops->statfs,
+ &(state->loc));
+
+ return 0;
+}
+
+
+
+int32_t
+server_opendir_resume (call_frame_t *frame,
+ xlator_t *this,
+ loc_t *loc,
+ fd_t *fd)
+{
+ server_state_t *state = CALL_STATE(frame);
+ fd_t *new_fd = NULL;
+
+ new_fd = fd_create (loc->inode, frame->root->pid);
+ state->fd = fd_ref (new_fd);
+
+ gf_log (BOUND_XL(frame)->name, GF_LOG_DEBUG,
+ "%"PRId64": OPENDIR \'%s (%"PRId64")\'",
+ frame->root->unique, state->path, state->ino);
+
+ STACK_WIND (frame,
+ server_opendir_cbk,
+ BOUND_XL(frame),
+ BOUND_XL(frame)->fops->opendir,
+ loc,
+ state->fd);
+ return 0;
+}
+
+
+/*
+ * server_opendir - opendir function for server protocol
+ * @frame: call frame
+ * @bound_xl:
+ * @params: parameter dictionary
+ *
+ * not for external reference
+ */
+int32_t
+server_opendir (call_frame_t *frame, xlator_t *bound_xl,
+ gf_hdr_common_t *hdr, size_t hdrlen,
+ char *buf, size_t buflen)
+{
+ call_stub_t *opendir_stub = NULL;
+ gf_fop_opendir_req_t *req = NULL;
+ server_state_t *state = NULL;
+ int32_t ret = -1;
+ size_t pathlen = 0;
+
+ req = gf_param (hdr);
+ state = CALL_STATE(frame);
+ {
+ state->path = req->path;
+ pathlen = STRLEN_0(state->path);
+ state->ino = ntoh64 (req->ino);
+ }
+
+ ret = server_loc_fill (&state->loc, state,
+ state->ino, 0, NULL, state->path);
+
+ opendir_stub = fop_opendir_stub (frame,
+ server_opendir_resume,
+ &(state->loc),
+ NULL);
+
+ if (((state->loc.parent == NULL) && IS_NOT_ROOT(pathlen)) ||
+ (state->loc.inode == NULL)) {
+ do_path_lookup (opendir_stub, &(state->loc));
+ } else {
+ call_resume (opendir_stub);
+ }
+
+ return 0;
+}
+
+
+/*
+ * server_releasedir - releasedir function for server protocol
+ * @frame: call frame
+ * @bound_xl:
+ * @params: parameter dictionary
+ *
+ * not for external reference
+ */
+int32_t
+server_releasedir (call_frame_t *frame, xlator_t *bound_xl,
+ gf_hdr_common_t *hdr, size_t hdrlen,
+ char *buf, size_t buflen)
+{
+ gf_cbk_releasedir_req_t *req = NULL;
+ server_state_t *state = NULL;
+ server_connection_t *conn = NULL;
+
+ conn = SERVER_CONNECTION(frame);
+
+ req = gf_param (hdr);
+ state = CALL_STATE(frame);
+
+ state->fd_no = ntoh64 (req->fd);
+ state->fd = gf_fd_fdptr_get (conn->fdtable,
+ state->fd_no);
+
+ if (state->fd == NULL) {
+ gf_log (frame->this->name, GF_LOG_ERROR,
+ "fd - %"PRId64": unresolved fd",
+ state->fd_no);
+
+ server_releasedir_cbk (frame, NULL, frame->this,
+ -1, EINVAL);
+ goto out;
+ }
+
+ gf_log (bound_xl->name, GF_LOG_DEBUG,
+ "%"PRId64": RELEASEDIR \'fd=%"PRId64" (%"PRId64")\'",
+ frame->root->unique, state->fd_no, state->fd->inode->ino);
+
+ gf_fd_put (conn->fdtable, state->fd_no);
+
+ server_releasedir_cbk (frame, NULL, frame->this,
+ 0, 0);
+out:
+ return 0;
+}
+
+
+/*
+ * server_readdir - readdir function for server protocol
+ * @frame: call frame
+ * @bound_xl:
+ * @params: parameter dictionary
+ *
+ * not for external reference
+ */
+int32_t
+server_getdents (call_frame_t *frame,
+ xlator_t *bound_xl,
+ gf_hdr_common_t *hdr, size_t hdrlen,
+ char *buf, size_t buflen)
+{
+ gf_fop_getdents_req_t *req = NULL;
+ server_state_t *state = NULL;
+ server_connection_t *conn = NULL;
+
+ conn = SERVER_CONNECTION(frame);
+
+ req = gf_param (hdr);
+ state = CALL_STATE(frame);
+ {
+ state->fd_no = ntoh64 (req->fd);
+ if (state->fd_no >= 0)
+ state->fd = gf_fd_fdptr_get (conn->fdtable,
+ state->fd_no);
+
+ state->size = ntoh32 (req->size);
+ state->offset = ntoh64 (req->offset);
+ state->flags = ntoh32 (req->flags);
+ }
+
+
+ if (state->fd == NULL) {
+ gf_log (frame->this->name, GF_LOG_ERROR,
+ "fd - %"PRId64": unresolved fd",
+ state->fd_no);
+
+ server_getdents_cbk (frame, NULL, frame->this,
+ -1, EINVAL, NULL, 0);
+
+ goto out;
+ }
+
+ gf_log (bound_xl->name, GF_LOG_DEBUG,
+ "%"PRId64": GETDENTS \'fd=%"PRId64" (%"PRId64"); "
+ "offset=%"PRId64"; size=%"PRId64,
+ frame->root->unique, state->fd_no, state->fd->inode->ino,
+ state->offset, (int64_t)state->size);
+
+ STACK_WIND (frame,
+ server_getdents_cbk,
+ bound_xl,
+ bound_xl->fops->getdents,
+ state->fd,
+ state->size,
+ state->offset,
+ state->flags);
+out:
+ return 0;
+}
+
+
+/*
+ * server_readdir - readdir function for server protocol
+ * @frame: call frame
+ * @bound_xl:
+ * @params: parameter dictionary
+ *
+ * not for external reference
+ */
+int32_t
+server_readdir (call_frame_t *frame, xlator_t *bound_xl,
+ gf_hdr_common_t *hdr, size_t hdrlen,
+ char *buf, size_t buflen)
+{
+ gf_fop_readdir_req_t *req = NULL;
+ server_state_t *state = NULL;
+ server_connection_t *conn = NULL;
+
+ conn = SERVER_CONNECTION(frame);
+
+ req = gf_param (hdr);
+ state = CALL_STATE(frame);
+ {
+ state->fd_no = ntoh64 (req->fd);
+ if (state->fd_no >= 0)
+ state->fd = gf_fd_fdptr_get (conn->fdtable,
+ state->fd_no);
+
+ state->size = ntoh32 (req->size);
+ state->offset = ntoh64 (req->offset);
+ }
+
+
+ if (state->fd == NULL) {
+ gf_log (frame->this->name, GF_LOG_ERROR,
+ "fd - %"PRId64": unresolved fd",
+ state->fd_no);
+
+ server_readdir_cbk (frame, NULL, frame->this,
+ -1, EINVAL, NULL);
+
+ goto out;
+ }
+
+ gf_log (bound_xl->name, GF_LOG_DEBUG,
+ "%"PRId64": READDIR \'fd=%"PRId64" (%"PRId64"); "
+ "offset=%"PRId64"; size=%"PRId64,
+ frame->root->unique, state->fd_no, state->fd->inode->ino,
+ state->offset, (int64_t)state->size);
+
+ STACK_WIND (frame,
+ server_readdir_cbk,
+ bound_xl,
+ bound_xl->fops->readdir,
+ state->fd, state->size, state->offset);
+out:
+ return 0;
+}
+
+
+
+/*
+ * server_fsyncdir - fsyncdir function for server protocol
+ * @frame: call frame
+ * @bound_xl:
+ * @params: parameter dictionary
+ *
+ * not for external reference
+ */
+int32_t
+server_fsyncdir (call_frame_t *frame,
+ xlator_t *bound_xl,
+ gf_hdr_common_t *hdr, size_t hdrlen,
+ char *buf, size_t buflen)
+{
+ gf_fop_fsyncdir_req_t *req = NULL;
+ server_state_t *state = NULL;
+ server_connection_t *conn = NULL;
+
+ conn = SERVER_CONNECTION(frame);
+
+ req = gf_param (hdr);
+ state = CALL_STATE(frame);
+ {
+ state->fd_no = ntoh64 (req->fd);
+ if (state->fd_no >= 0)
+ state->fd = gf_fd_fdptr_get (conn->fdtable,
+ state->fd_no);
+
+ state->flags = ntoh32 (req->data);
+ }
+
+ if (state->fd == NULL) {
+ gf_log (frame->this->name, GF_LOG_ERROR,
+ "fd - %"PRId64": unresolved fd",
+ state->fd_no);
+
+ server_fsyncdir_cbk (frame, NULL, frame->this,
+ -1, EINVAL);
+ goto out;
+ }
+
+ gf_log (bound_xl->name, GF_LOG_DEBUG,
+ "%"PRId64": FSYNCDIR \'fd=%"PRId64" (%"PRId64")\'",
+ frame->root->unique, state->fd_no, state->fd->inode->ino);
+
+ STACK_WIND (frame,
+ server_fsyncdir_cbk,
+ bound_xl,
+ bound_xl->fops->fsyncdir,
+ state->fd, state->flags);
+out:
+ return 0;
+}
+
+
+int32_t
+server_mknod_resume (call_frame_t *frame,
+ xlator_t *this,
+ loc_t *loc,
+ mode_t mode,
+ dev_t dev)
+{
+ server_state_t *state = NULL;
+
+ state = CALL_STATE(frame);
+
+ if (state->loc.parent == NULL)
+ state->loc.parent = inode_ref (loc->parent);
+
+ state->loc.inode = inode_new (state->itable);
+
+ gf_log (BOUND_XL(frame)->name, GF_LOG_DEBUG,
+ "%"PRId64": MKNOD \'%"PRId64"/%s\'",
+ frame->root->unique, state->par, state->bname);
+
+ STACK_WIND (frame,
+ server_mknod_cbk,
+ BOUND_XL(frame),
+ BOUND_XL(frame)->fops->mknod,
+ &(state->loc), mode, dev);
+
+ return 0;
+}
+/*
+ * server_mknod - mknod function for server protocol
+ * @frame: call frame
+ * @bound_xl:
+ * @params: parameter dictionary
+ *
+ * not for external reference
+ */
+int32_t
+server_mknod (call_frame_t *frame,
+ xlator_t *bound_xl,
+ gf_hdr_common_t *hdr, size_t hdrlen,
+ char *buf, size_t buflen)
+{
+ gf_fop_mknod_req_t *req = NULL;
+ server_state_t *state = NULL;
+ call_stub_t *mknod_stub = NULL;
+ int32_t ret = -1;
+ size_t pathlen = 0;
+
+ req = gf_param (hdr);
+ state = CALL_STATE(frame);
+ {
+ pathlen = STRLEN_0(req->path);
+
+ state->par = ntoh64 (req->par);
+ state->path = req->path;
+ if (IS_NOT_ROOT(pathlen))
+ state->bname = req->bname + pathlen;
+
+ state->mode = ntoh32 (req->mode);
+ state->dev = ntoh64 (req->dev);
+ }
+ ret = server_loc_fill (&(state->loc), state,
+ 0, state->par, state->bname,
+ state->path);
+
+ mknod_stub = fop_mknod_stub (frame, server_mknod_resume,
+ &(state->loc), state->mode, state->dev);
+
+ if (state->loc.parent == NULL) {
+ do_path_lookup (mknod_stub, &(state->loc));
+ } else {
+ call_resume (mknod_stub);
+ }
+
+ return 0;
+}
+
+int32_t
+server_mkdir_resume (call_frame_t *frame,
+ xlator_t *this,
+ loc_t *loc,
+ mode_t mode)
+
+{
+ server_state_t *state = NULL;
+
+ state = CALL_STATE(frame);
+
+ if (state->loc.parent == NULL)
+ state->loc.parent = inode_ref (loc->parent);
+
+ state->loc.inode = inode_new (state->itable);
+
+ gf_log (BOUND_XL(frame)->name, GF_LOG_DEBUG,
+ "%"PRId64": MKDIR \'%"PRId64"/%s\'",
+ frame->root->unique, state->par, state->bname);
+
+ STACK_WIND (frame,
+ server_mkdir_cbk,
+ BOUND_XL(frame),
+ BOUND_XL(frame)->fops->mkdir,
+ &(state->loc),
+ state->mode);
+
+ return 0;
+}
+
+/*
+ * server_mkdir - mkdir function for server protocol
+ * @frame: call frame
+ * @bound_xl:
+ * @params:
+ *
+ * not for external reference
+ */
+int32_t
+server_mkdir (call_frame_t *frame,
+ xlator_t *bound_xl,
+ gf_hdr_common_t *hdr, size_t hdrlen,
+ char *buf, size_t buflen)
+{
+ gf_fop_mkdir_req_t *req = NULL;
+ server_state_t *state = NULL;
+ call_stub_t *mkdir_stub = NULL;
+ int32_t ret = -1;
+ size_t pathlen = 0;
+
+ req = gf_param (hdr);
+ state = CALL_STATE(frame);
+ {
+ pathlen = STRLEN_0(req->path);
+ state->mode = ntoh32 (req->mode);
+
+ state->path = req->path;
+ state->bname = req->bname + pathlen;
+ state->par = ntoh64 (req->par);
+ }
+
+
+ ret = server_loc_fill (&(state->loc), state,
+ 0, state->par, state->bname,
+ state->path);
+
+ mkdir_stub = fop_mkdir_stub (frame, server_mkdir_resume,
+ &(state->loc), state->mode);
+
+ if (state->loc.parent == NULL) {
+ do_path_lookup (mkdir_stub, &(state->loc));
+ } else {
+ call_resume (mkdir_stub);
+ }
+
+ return 0;
+}
+
+
+int32_t
+server_rmdir_resume (call_frame_t *frame,
+ xlator_t *this,
+ loc_t *loc)
+{
+ server_state_t *state = NULL;
+
+ state = CALL_STATE(frame);
+
+ if (state->loc.parent == NULL)
+ state->loc.parent = inode_ref (loc->parent);
+
+ if (state->loc.inode == NULL)
+ state->loc.inode = inode_ref (loc->inode);
+
+ gf_log (BOUND_XL(frame)->name, GF_LOG_DEBUG,
+ "%"PRId64": RMDIR \'%"PRId64"/%s\'",
+ frame->root->unique, state->par, state->bname);
+
+ STACK_WIND (frame,
+ server_rmdir_cbk,
+ BOUND_XL(frame),
+ BOUND_XL(frame)->fops->rmdir,
+ loc);
+ return 0;
+}
+
+/*
+ * server_rmdir - rmdir function for server protocol
+ * @frame: call frame
+ * @bound_xl:
+ * @params:
+ *
+ * not for external reference
+ */
+int32_t
+server_rmdir (call_frame_t *frame,
+ xlator_t *bound_xl,
+ gf_hdr_common_t *hdr, size_t hdrlen,
+ char *buf, size_t buflen)
+{
+ call_stub_t *rmdir_stub = NULL;
+ gf_fop_rmdir_req_t *req = NULL;
+ server_state_t *state = NULL;
+ int32_t ret = -1;
+ size_t pathlen = 0;
+
+ req = gf_param (hdr);
+ state = CALL_STATE(frame);
+ {
+ pathlen = STRLEN_0(req->path);
+ state->path = req->path;
+ state->par = ntoh64 (req->par);
+ state->bname = req->bname + pathlen;
+ }
+
+
+ ret = server_loc_fill (&(state->loc), state,
+ state->ino, state->par, state->bname,
+ state->path);
+
+ rmdir_stub = fop_rmdir_stub (frame,
+ server_rmdir_resume,
+ &(state->loc));
+
+ if ((state->loc.parent == NULL) ||
+ (state->loc.inode == NULL)) {
+ do_path_lookup (rmdir_stub, &(state->loc));
+ } else {
+ call_resume (rmdir_stub);
+ }
+
+ return 0;
+}
+
+
+
+int32_t
+server_chown_resume (call_frame_t *frame,
+ xlator_t *this,
+ loc_t *loc,
+ uid_t uid,
+ gid_t gid)
+{
+ server_state_t *state = NULL;
+
+ state = CALL_STATE(frame);
+
+ gf_log (BOUND_XL(frame)->name, GF_LOG_DEBUG,
+ "%"PRId64": CHOWN \'%s (%"PRId64")\'",
+ frame->root->unique, state->path, state->ino);
+
+ STACK_WIND (frame, server_chown_cbk,
+ BOUND_XL(frame),
+ BOUND_XL(frame)->fops->chown,
+ loc, uid, gid);
+ return 0;
+}
+
+
+/*
+ * server_chown - chown function for server protocol
+ * @frame: call frame
+ * @bound_xl:
+ * @params: parameter dictionary
+ *
+ * not for external reference
+ */
+int32_t
+server_chown (call_frame_t *frame,
+ xlator_t *bound_xl,
+ gf_hdr_common_t *hdr, size_t hdrlen,
+ char *buf, size_t buflen)
+{
+ call_stub_t *chown_stub = NULL;
+ gf_fop_chown_req_t *req = NULL;
+ server_state_t *state = NULL;
+ int32_t ret = -1;
+ size_t pathlen = 0;
+
+ req = gf_param (hdr);
+ state = CALL_STATE(frame);
+ {
+ state->ino = ntoh64 (req->ino);
+ state->path = req->path;
+ pathlen = STRLEN_0(state->path);
+ state->uid = ntoh32 (req->uid);
+ state->gid = ntoh32 (req->gid);
+ }
+
+
+ ret = server_loc_fill (&(state->loc), state,
+ state->ino, 0, NULL, state->path);
+
+ chown_stub = fop_chown_stub (frame,
+ server_chown_resume,
+ &(state->loc),
+ state->uid,
+ state->gid);
+
+ if (((state->loc.parent == NULL) && IS_NOT_ROOT(pathlen)) ||
+ (state->loc.inode == NULL)) {
+ do_path_lookup (chown_stub, &(state->loc));
+ } else {
+ call_resume (chown_stub);
+ }
+
+ return 0;
+}
+
+
+int32_t
+server_chmod_resume (call_frame_t *frame,
+ xlator_t *this,
+ loc_t *loc,
+ mode_t mode)
+{
+ server_state_t *state = NULL;
+
+ state = CALL_STATE(frame);
+
+ gf_log (BOUND_XL(frame)->name, GF_LOG_DEBUG,
+ "%"PRId64": CHMOD \'%s (%"PRId64")\'",
+ frame->root->unique, state->path, state->ino);
+
+ STACK_WIND (frame,
+ server_chmod_cbk,
+ BOUND_XL(frame),
+ BOUND_XL(frame)->fops->chmod,
+ loc,
+ mode);
+ return 0;
+
+}
+
+/*
+ * server_chmod - chmod function for server protocol
+ * @frame: call frame
+ * @bound_xl:
+ * @params: parameter dictionary
+ *
+ * not for external reference
+ */
+int32_t
+server_chmod (call_frame_t *frame,
+ xlator_t *bound_xl,
+ gf_hdr_common_t *hdr, size_t hdrlen,
+ char *buf, size_t buflen)
+{
+ call_stub_t *chmod_stub = NULL;
+ gf_fop_chmod_req_t *req = NULL;
+ server_state_t *state = NULL;
+ int32_t ret = -1;
+ size_t pathlen = 0;
+
+ req = gf_param (hdr);
+
+ state = CALL_STATE(frame);
+ {
+ state->ino = ntoh64 (req->ino);
+ state->path = req->path;
+ pathlen = STRLEN_0(state->path);
+
+ state->mode = ntoh32 (req->mode);
+ }
+
+ ret = server_loc_fill (&(state->loc), state,
+ state->ino, 0, NULL, state->path);
+
+ chmod_stub = fop_chmod_stub (frame,
+ server_chmod_resume,
+ &(state->loc),
+ state->mode);
+
+ if (((state->loc.parent == NULL) && IS_NOT_ROOT(pathlen)) ||
+ (state->loc.inode == NULL)) {
+ do_path_lookup (chmod_stub, &(state->loc));
+ } else {
+ call_resume (chmod_stub);
+ }
+
+ return 0;
+}
+
+
+int32_t
+server_utimens_resume (call_frame_t *frame,
+ xlator_t *this,
+ loc_t *loc,
+ struct timespec *tv)
+{
+ server_state_t *state = NULL;
+
+ state = CALL_STATE(frame);
+
+ gf_log (BOUND_XL(frame)->name, GF_LOG_DEBUG,
+ "%"PRId64": UTIMENS \'%s (%"PRId64")\'",
+ frame->root->unique, state->path, state->ino);
+
+ STACK_WIND (frame,
+ server_utimens_cbk,
+ BOUND_XL(frame),
+ BOUND_XL(frame)->fops->utimens,
+ loc,
+ tv);
+ return 0;
+}
+
+/*
+ * server_utimens - utimens function for server protocol
+ * @frame: call frame
+ * @bound_xl:
+ * @params: parameter dictionary
+ *
+ * not for external reference
+ */
+int32_t
+server_utimens (call_frame_t *frame,
+ xlator_t *bound_xl,
+ gf_hdr_common_t *hdr, size_t hdrlen,
+ char *buf, size_t buflen)
+{
+ call_stub_t *utimens_stub = NULL;
+ gf_fop_utimens_req_t *req = NULL;
+ server_state_t *state = NULL;
+ int32_t ret = -1;
+ size_t pathlen = 0;
+
+ req = gf_param (hdr);
+ state = CALL_STATE(frame);
+ {
+ state->ino = ntoh64 (req->ino);
+ state->path = req->path;
+ pathlen = STRLEN_0(state->path);
+
+ gf_timespec_to_timespec (req->tv, state->tv);
+ }
+
+
+ ret = server_loc_fill (&(state->loc), state,
+ state->ino, 0, NULL, state->path);
+
+ utimens_stub = fop_utimens_stub (frame,
+ server_utimens_resume,
+ &(state->loc),
+ state->tv);
+
+ if (((state->loc.parent == NULL) && IS_NOT_ROOT(pathlen)) ||
+ (state->loc.inode == NULL)) {
+ do_path_lookup (utimens_stub, &(state->loc));
+ } else {
+ call_resume (utimens_stub);
+ }
+
+ return 0;
+}
+
+
+
+int32_t
+server_inodelk_resume (call_frame_t *frame,
+ xlator_t *this,
+ loc_t *loc, int32_t cmd,
+ struct flock *flock)
+{
+ server_state_t *state = NULL;
+
+ state = CALL_STATE(frame);
+ if (state->loc.inode == NULL) {
+ state->loc.inode = inode_ref (loc->inode);
+ }
+
+ if (state->loc.parent == NULL) {
+ state->loc.parent = inode_ref (loc->parent);
+ }
+
+ gf_log (BOUND_XL(frame)->name, GF_LOG_DEBUG,
+ "%"PRId64": INODELK \'%s (%"PRId64")\'",
+ frame->root->unique, state->path, state->ino);
+
+ STACK_WIND (frame,
+ server_inodelk_cbk,
+ BOUND_XL(frame),
+ BOUND_XL(frame)->fops->inodelk,
+ loc, cmd, flock);
+ return 0;
+
+}
+
+
+int32_t
+server_inodelk (call_frame_t *frame,
+ xlator_t *bound_xl,
+ gf_hdr_common_t *hdr, size_t hdrlen,
+ char *buf, size_t buflen)
+{
+ call_stub_t *inodelk_stub = NULL;
+ gf_fop_inodelk_req_t *req = NULL;
+ server_state_t *state = NULL;
+ size_t pathlen = 0;
+
+ req = gf_param (hdr);
+ state = CALL_STATE(frame);
+ {
+ state->cmd = ntoh32 (req->cmd);
+ switch (state->cmd) {
+ case GF_LK_GETLK:
+ state->cmd = F_GETLK;
+ break;
+ case GF_LK_SETLK:
+ state->cmd = F_SETLK;
+ break;
+ case GF_LK_SETLKW:
+ state->cmd = F_SETLKW;
+ break;
+ }
+
+ state->type = ntoh32 (req->type);
+
+ pathlen = STRLEN_0(req->path);
+
+ state->path = req->path;
+ state->ino = ntoh64 (req->ino);
+
+ gf_flock_to_flock (&req->flock, &state->flock);
+
+ switch (state->type) {
+ case GF_LK_F_RDLCK:
+ state->flock.l_type = F_RDLCK;
+ break;
+ case GF_LK_F_WRLCK:
+ state->flock.l_type = F_WRLCK;
+ break;
+ case GF_LK_F_UNLCK:
+ state->flock.l_type = F_UNLCK;
+ break;
+ }
+
+ }
+
+ server_loc_fill (&(state->loc), state,
+ state->ino, 0, NULL, state->path);
+
+ inodelk_stub = fop_inodelk_stub (frame,
+ server_inodelk_resume,
+ &state->loc, state->cmd, &state->flock);
+
+ if ((state->loc.parent == NULL) ||
+ (state->loc.inode == NULL)) {
+ do_path_lookup (inodelk_stub, &(state->loc));
+ } else {
+ call_resume (inodelk_stub);
+ }
+
+ return 0;
+}
+
+
+int32_t
+server_finodelk (call_frame_t *frame,
+ xlator_t *bound_xl,
+ gf_hdr_common_t *hdr, size_t hdrlen,
+ char *buf, size_t buflen)
+{
+ gf_fop_finodelk_req_t *req = NULL;
+ server_state_t *state = NULL;
+ server_connection_t *conn = NULL;
+
+ conn = SERVER_CONNECTION(frame);
+
+ req = gf_param (hdr);
+ state = CALL_STATE(frame);
+ {
+ state->fd_no = ntoh64 (req->fd);
+ if (state->fd_no >= 0)
+ state->fd = gf_fd_fdptr_get (conn->fdtable,
+ state->fd_no);
+
+ state->cmd = ntoh32 (req->cmd);
+ switch (state->cmd) {
+ case GF_LK_GETLK:
+ state->cmd = F_GETLK;
+ break;
+ case GF_LK_SETLK:
+ state->cmd = F_SETLK;
+ break;
+ case GF_LK_SETLKW:
+ state->cmd = F_SETLKW;
+ break;
+ }
+
+ state->type = ntoh32 (req->type);
+
+ gf_flock_to_flock (&req->flock, &state->flock);
+
+ switch (state->type) {
+ case GF_LK_F_RDLCK:
+ state->flock.l_type = F_RDLCK;
+ break;
+ case GF_LK_F_WRLCK:
+ state->flock.l_type = F_WRLCK;
+ break;
+ case GF_LK_F_UNLCK:
+ state->flock.l_type = F_UNLCK;
+ break;
+ }
+
+ }
+
+ if (state->fd == NULL) {
+ gf_log (frame->this->name, GF_LOG_ERROR,
+ "fd - %"PRId64": unresolved fd",
+ state->fd_no);
+
+ server_finodelk_cbk (frame, NULL, frame->this,
+ -1, EINVAL);
+ return -1;
+ }
+
+ gf_log (BOUND_XL(frame)->name, GF_LOG_DEBUG,
+ "%"PRId64": FINODELK \'fd=%"PRId64" (%"PRId64")\'",
+ frame->root->unique, state->fd_no, state->fd->inode->ino);
+
+ STACK_WIND (frame, server_finodelk_cbk,
+ BOUND_XL(frame),
+ BOUND_XL(frame)->fops->finodelk,
+ state->fd, state->cmd, &state->flock);
+ return 0;
+}
+
+
+int32_t
+server_entrylk_resume (call_frame_t *frame,
+ xlator_t *this,
+ loc_t *loc, const char *name,
+ entrylk_cmd cmd, entrylk_type type)
+{
+ server_state_t *state = NULL;
+
+ state = CALL_STATE(frame);
+
+ if (state->loc.inode == NULL)
+ state->loc.inode = inode_ref (loc->inode);
+
+ if ((state->loc.parent == NULL) &&
+ (loc->parent))
+ state->loc.parent = inode_ref (loc->parent);
+
+ gf_log (BOUND_XL(frame)->name, GF_LOG_DEBUG,
+ "%"PRId64": ENTRYLK \'%s (%"PRId64") \'",
+ frame->root->unique, state->path, state->ino);
+
+ STACK_WIND (frame,
+ server_entrylk_cbk,
+ BOUND_XL(frame),
+ BOUND_XL(frame)->fops->entrylk,
+ loc, name, cmd, type);
+ return 0;
+
+}
+
+/*
+ * server_entrylk - entrylk function for server protocol
+ * @frame: call frame
+ * @bound_xl:
+ * @params: parameter dictionary
+ *
+ * not for external reference
+ */
+int32_t
+server_entrylk (call_frame_t *frame,
+ xlator_t *bound_xl,
+ gf_hdr_common_t *hdr, size_t hdrlen,
+ char *buf, size_t buflen)
+{
+ gf_fop_entrylk_req_t *req = NULL;
+ server_state_t *state = NULL;
+ call_stub_t *entrylk_stub = NULL;
+ size_t pathlen = 0;
+ size_t namelen = 0;
+
+ req = gf_param (hdr);
+ state = CALL_STATE(frame);
+ {
+ pathlen = STRLEN_0(req->path);
+
+ state->path = req->path;
+ state->ino = ntoh64 (req->ino);
+ namelen = ntoh64 (req->namelen);
+ if (namelen)
+ state->name = req->name + pathlen;
+
+ state->cmd = ntoh32 (req->cmd);
+ state->type = ntoh32 (req->type);
+ }
+
+
+ server_loc_fill (&(state->loc), state,
+ state->ino, 0, NULL, state->path);
+
+ entrylk_stub = fop_entrylk_stub (frame,
+ server_entrylk_resume,
+ &state->loc, state->name, state->cmd,
+ state->type);
+
+ if (((state->loc.parent == NULL) && IS_NOT_ROOT(pathlen)) ||
+ (state->loc.inode == NULL)) {
+ do_path_lookup (entrylk_stub, &(state->loc));
+ } else {
+ call_resume (entrylk_stub);
+ }
+
+ return 0;
+}
+
+
+int32_t
+server_fentrylk (call_frame_t *frame,
+ xlator_t *bound_xl,
+ gf_hdr_common_t *hdr, size_t hdrlen,
+ char *buf, size_t buflen)
+{
+ gf_fop_fentrylk_req_t *req = NULL;
+ server_state_t *state = NULL;
+ size_t namelen = 0;
+ server_connection_t *conn = NULL;
+
+ conn = SERVER_CONNECTION(frame);
+
+ req = gf_param (hdr);
+ state = CALL_STATE(frame);
+ {
+ state->fd_no = ntoh64 (req->fd);
+ if (state->fd_no >= 0)
+ state->fd = gf_fd_fdptr_get (conn->fdtable,
+ state->fd_no);
+
+ state->cmd = ntoh32 (req->cmd);
+ state->type = ntoh32 (req->type);
+ namelen = ntoh64 (req->namelen);
+
+ if (namelen)
+ state->name = req->name;
+ }
+
+ if (state->fd == NULL) {
+ gf_log (frame->this->name, GF_LOG_ERROR,
+ "fd - %"PRId64": unresolved fd",
+ state->fd_no);
+
+ server_fentrylk_cbk (frame, NULL, frame->this,
+ -1, EINVAL);
+ return -1;
+ }
+
+ gf_log (BOUND_XL(frame)->name, GF_LOG_DEBUG,
+ "%"PRId64": FENTRYLK \'fd=%"PRId64" (%"PRId64")\'",
+ frame->root->unique, state->fd_no, state->fd->inode->ino);
+
+ STACK_WIND (frame, server_fentrylk_cbk,
+ BOUND_XL(frame),
+ BOUND_XL(frame)->fops->fentrylk,
+ state->fd, state->name, state->cmd, state->type);
+ return 0;
+}
+
+
+int32_t
+server_access_resume (call_frame_t *frame,
+ xlator_t *this,
+ loc_t *loc,
+ int32_t mask)
+{
+ server_state_t *state = NULL;
+
+ state = CALL_STATE(frame);
+
+ gf_log (BOUND_XL(frame)->name, GF_LOG_DEBUG,
+ "%"PRId64": ACCESS \'%s (%"PRId64")\'",
+ frame->root->unique, state->path, state->ino);
+
+ STACK_WIND (frame,
+ server_access_cbk,
+ BOUND_XL(frame),
+ BOUND_XL(frame)->fops->access,
+ loc,
+ mask);
+ return 0;
+}
+
+/*
+ * server_access - access function for server protocol
+ * @frame: call frame
+ * @bound_xl:
+ * @params: parameter dictionary
+ *
+ * not for external reference
+ */
+int32_t
+server_access (call_frame_t *frame,
+ xlator_t *bound_xl,
+ gf_hdr_common_t *hdr, size_t hdrlen,
+ char *buf, size_t buflen)
+{
+ call_stub_t *access_stub = NULL;
+ gf_fop_access_req_t *req = NULL;
+ server_state_t *state = NULL;
+ int32_t ret = -1;
+ size_t pathlen = 0;
+
+ req = gf_param (hdr);
+ state = CALL_STATE(frame);
+
+ state->mask = ntoh32 (req->mask);
+
+ state->ino = ntoh64 (req->ino);
+ state->path = req->path;
+ pathlen = STRLEN_0(state->path);
+
+ ret = server_loc_fill (&(state->loc), state,
+ state->ino, 0, NULL, state->path);
+
+ access_stub = fop_access_stub (frame,
+ server_access_resume,
+ &(state->loc),
+ state->mask);
+
+ if (((state->loc.parent == NULL) && IS_NOT_ROOT(pathlen)) ||
+ (state->loc.inode == NULL)) {
+ do_path_lookup (access_stub, &(state->loc));
+ } else {
+ call_resume (access_stub);
+ }
+
+ return 0;
+}
+
+
+int32_t
+server_symlink_resume (call_frame_t *frame,
+ xlator_t *this,
+ const char *linkname,
+ loc_t *loc)
+{
+ server_state_t *state = NULL;
+
+ state = CALL_STATE(frame);
+ if (state->loc.parent == NULL)
+ state->loc.parent = inode_ref (loc->parent);
+
+ state->loc.inode = inode_new (BOUND_XL(frame)->itable);
+
+ gf_log (BOUND_XL(frame)->name, GF_LOG_DEBUG,
+ "%"PRId64": SYMLINK \'%"PRId64"/%s \'",
+ frame->root->unique, state->par, state->bname);
+
+ STACK_WIND (frame,
+ server_symlink_cbk,
+ BOUND_XL(frame),
+ BOUND_XL(frame)->fops->symlink,
+ linkname,
+ &(state->loc));
+
+ return 0;
+}
+
+/*
+ * server_symlink- symlink function for server protocol
+ * @frame: call frame
+ * @bound_xl:
+ * @params: parameter dictionary
+ *
+ * not for external reference
+ */
+
+int32_t
+server_symlink (call_frame_t *frame,
+ xlator_t *bound_xl,
+ gf_hdr_common_t *hdr, size_t hdrlen,
+ char *buf, size_t buflen)
+{
+ server_state_t *state = NULL;
+ gf_fop_symlink_req_t *req = NULL;
+ call_stub_t *symlink_stub = NULL;
+ int32_t ret = -1;
+ size_t pathlen = 0;
+ size_t baselen = 0;
+
+ req = gf_param (hdr);
+ state = CALL_STATE(frame);
+ {
+ pathlen = STRLEN_0(req->path);
+ baselen = STRLEN_0(req->bname + pathlen);
+
+ state->par = ntoh64 (req->par);
+ state->path = req->path;
+ state->bname = req->bname + pathlen;
+
+ state->name = (req->linkname + pathlen + baselen);
+ }
+
+ ret = server_loc_fill (&(state->loc), state,
+ 0, state->par, state->bname,
+ state->path);
+
+ symlink_stub = fop_symlink_stub (frame, server_symlink_resume,
+ state->name, &(state->loc));
+
+ if (state->loc.parent == NULL) {
+ do_path_lookup (symlink_stub, &(state->loc));
+ } else {
+ call_resume (symlink_stub);
+ }
+
+ return 0;
+}
+
+int32_t
+server_link_resume (call_frame_t *frame,
+ xlator_t *this,
+ loc_t *oldloc,
+ loc_t *newloc)
+{
+ server_state_t *state = NULL;
+
+ state = CALL_STATE(frame);
+
+ if (state->loc.parent == NULL)
+ state->loc.parent = inode_ref (oldloc->parent);
+
+ if (state->loc.inode == NULL) {
+ state->loc.inode = inode_ref (oldloc->inode);
+ } else if (state->loc.inode != oldloc->inode) {
+ if (state->loc.inode)
+ inode_unref (state->loc.inode);
+ state->loc.inode = inode_ref (oldloc->inode);
+ }
+
+ if (state->loc2.parent == NULL)
+ state->loc2.parent = inode_ref (newloc->parent);
+
+ state->loc2.inode = inode_ref (state->loc.inode);
+
+ gf_log (BOUND_XL(frame)->name, GF_LOG_DEBUG,
+ "%"PRId64": LINK \'%"PRId64"/%s ==> %s (%"PRId64")\'",
+ frame->root->unique, state->par2, state->bname2,
+ state->path, state->ino);
+
+ STACK_WIND (frame,
+ server_link_cbk,
+ BOUND_XL(frame),
+ BOUND_XL(frame)->fops->link,
+ &(state->loc),
+ &(state->loc2));
+ return 0;
+}
+
+/*
+ * server_link - link function for server protocol
+ * @frame: call frame
+ * @bound_xl:
+ * @params:
+ *
+ * not for external reference
+ */
+int32_t
+server_link (call_frame_t *frame,
+ xlator_t *this,
+ gf_hdr_common_t *hdr, size_t hdrlen,
+ char *buf, size_t buflen)
+{
+ gf_fop_link_req_t *req = NULL;
+ server_state_t *state = NULL;
+ call_stub_t *link_stub = NULL;
+ int32_t ret = -1;
+ size_t oldpathlen = 0;
+ size_t newpathlen = 0;
+ size_t newbaselen = 0;
+
+ req = gf_param (hdr);
+
+ state = CALL_STATE(frame);
+ {
+ oldpathlen = STRLEN_0(req->oldpath);
+ newpathlen = STRLEN_0(req->newpath + oldpathlen);
+ newbaselen = STRLEN_0(req->newbname + oldpathlen + newpathlen);
+
+ state->path = req->oldpath;
+ state->path2 = req->newpath + oldpathlen;
+ state->bname2 = req->newbname + oldpathlen + newpathlen;
+ state->ino = ntoh64 (req->oldino);
+ state->par2 = ntoh64 (req->newpar);
+ }
+
+ ret = server_loc_fill (&(state->loc), state,
+ state->ino, 0, NULL,
+ state->path);
+ ret = server_loc_fill (&(state->loc2), state,
+ 0, state->par2, state->bname2,
+ state->path2);
+
+ link_stub = fop_link_stub (frame, server_link_resume,
+ &(state->loc), &(state->loc2));
+
+ if ((state->loc.parent == NULL) ||
+ (state->loc.inode == NULL)) {
+ do_path_lookup (link_stub, &(state->loc));
+ } else if (state->loc2.parent == NULL) {
+ do_path_lookup (link_stub, &(state->loc2));
+ } else {
+ call_resume (link_stub);
+ }
+
+ return 0;
+}
+
+
+int32_t
+server_rename_resume (call_frame_t *frame,
+ xlator_t *this,
+ loc_t *oldloc,
+ loc_t *newloc)
+{
+ server_state_t *state = NULL;
+
+ state = CALL_STATE(frame);
+
+ if (state->loc.parent == NULL)
+ state->loc.parent = inode_ref (oldloc->parent);
+
+ if (state->loc.inode == NULL) {
+ state->loc.inode = inode_ref (oldloc->inode);
+ }
+
+ if (state->loc2.parent == NULL)
+ state->loc2.parent = inode_ref (newloc->parent);
+
+
+ gf_log (BOUND_XL(frame)->name, GF_LOG_DEBUG,
+ "%"PRId64": RENAME %s (%"PRId64"/%s) ==> %s (%"PRId64"/%s)",
+ frame->root->unique, state->path, state->par, state->bname,
+ state->path2, state->par2, state->bname2);
+
+ STACK_WIND (frame,
+ server_rename_cbk,
+ BOUND_XL(frame),
+ BOUND_XL(frame)->fops->rename,
+ &(state->loc),
+ &(state->loc2));
+ return 0;
+}
+
+/*
+ * server_rename - rename function for server protocol
+ * @frame: call frame
+ * @bound_xl:
+ * @params: parameter dictionary
+ *
+ * not for external reference
+ */
+int32_t
+server_rename (call_frame_t *frame,
+ xlator_t *bound_xl,
+ gf_hdr_common_t *hdr, size_t hdrlen,
+ char *buf, size_t buflen)
+{
+ gf_fop_rename_req_t *req = NULL;
+ server_state_t *state = NULL;
+ call_stub_t *rename_stub = NULL;
+ int32_t ret = -1;
+ size_t oldpathlen = 0;
+ size_t oldbaselen = 0;
+ size_t newpathlen = 0;
+ size_t newbaselen = 0;
+
+ req = gf_param (hdr);
+
+ state = CALL_STATE(frame);
+ {
+ oldpathlen = STRLEN_0(req->oldpath);
+ oldbaselen = STRLEN_0(req->oldbname + oldpathlen);
+ newpathlen = STRLEN_0(req->newpath + oldpathlen + oldbaselen);
+ newbaselen = STRLEN_0(req->newbname + oldpathlen +
+ oldbaselen + newpathlen);
+
+ state->path = req->oldpath;
+ state->bname = req->oldbname + oldpathlen;
+ state->path2 = req->newpath + oldpathlen + oldbaselen;
+ state->bname2 = (req->newbname + oldpathlen + oldbaselen +
+ newpathlen);
+
+ state->par = ntoh64 (req->oldpar);
+ state->par2 = ntoh64 (req->newpar);
+ }
+
+ ret = server_loc_fill (&(state->loc), state,
+ 0, state->par, state->bname,
+ state->path);
+ ret = server_loc_fill (&(state->loc2), state,
+ 0, state->par2, state->bname2,
+ state->path2);
+
+ rename_stub = fop_rename_stub (frame,
+ server_rename_resume,
+ &(state->loc),
+ &(state->loc2));
+
+ if ((state->loc.parent == NULL) ||
+ (state->loc.inode == NULL)){
+ do_path_lookup (rename_stub, &(state->loc));
+ } else if ((state->loc2.parent == NULL)){
+ do_path_lookup (rename_stub, &(state->loc2));
+ } else {
+ /* we have found inode for both oldpath and newpath in
+ * inode cache. lets continue with fops->rename() */
+ call_resume (rename_stub);
+ }
+
+ return 0;
+}
+
+
+/*
+ * server_lk - lk function for server protocol
+ * @frame: call frame
+ * @bound_xl:
+ * @params: parameter dictionary
+ *
+ * not for external reference
+ */
+
+int32_t
+server_lk (call_frame_t *frame,
+ xlator_t *bound_xl,
+ gf_hdr_common_t *hdr, size_t hdrlen,
+ char *buf, size_t buflen)
+{
+ struct flock lock = {0, };
+ gf_fop_lk_req_t *req = NULL;
+ server_state_t *state = NULL;
+ server_connection_t *conn = NULL;
+
+ conn = SERVER_CONNECTION(frame);
+
+ req = gf_param (hdr);
+ state = CALL_STATE(frame);
+ {
+ state->fd_no = ntoh64 (req->fd);
+ if (state->fd_no >= 0)
+ state->fd = gf_fd_fdptr_get (conn->fdtable,
+ state->fd_no);
+
+ state->cmd = ntoh32 (req->cmd);
+ state->type = ntoh32 (req->type);
+ }
+
+
+ if (state->fd == NULL) {
+ gf_log (frame->this->name, GF_LOG_ERROR,
+ "fd - %"PRId64": unresolved fd",
+ state->fd_no);
+
+ server_lk_cbk (frame, NULL, frame->this,
+ -1, EINVAL, NULL);
+
+ goto out;
+ }
+
+ switch (state->cmd) {
+ case GF_LK_GETLK:
+ state->cmd = F_GETLK;
+ break;
+ case GF_LK_SETLK:
+ state->cmd = F_SETLK;
+ break;
+ case GF_LK_SETLKW:
+ state->cmd = F_SETLKW;
+ break;
+ }
+
+ switch (state->type) {
+ case GF_LK_F_RDLCK:
+ lock.l_type = F_RDLCK;
+ break;
+ case GF_LK_F_WRLCK:
+ lock.l_type = F_WRLCK;
+ break;
+ case GF_LK_F_UNLCK:
+ lock.l_type = F_UNLCK;
+ break;
+ default:
+ gf_log (bound_xl->name, GF_LOG_ERROR,
+ "fd - %"PRId64" (%"PRId64"): Unknown lock type: %"PRId32"!",
+ state->fd_no, state->fd->inode->ino, state->type);
+ break;
+ }
+
+ gf_flock_to_flock (&req->flock, &lock);
+
+ gf_log (BOUND_XL(frame)->name, GF_LOG_DEBUG,
+ "%"PRId64": LK \'fd=%"PRId64" (%"PRId64")\'",
+ frame->root->unique, state->fd_no, state->fd->inode->ino);
+
+ STACK_WIND (frame, server_lk_cbk,
+ BOUND_XL(frame),
+ BOUND_XL(frame)->fops->lk,
+ state->fd, state->cmd, &lock);
+
+out:
+ return 0;
+}
+
+
+/*
+ * server_writedir -
+ *
+ * @frame:
+ * @bound_xl:
+ * @params:
+ *
+ */
+int32_t
+server_setdents (call_frame_t *frame,
+ xlator_t *bound_xl,
+ gf_hdr_common_t *hdr, size_t hdrlen,
+ char *buf, size_t buflen)
+{
+ server_connection_t *conn = NULL;
+ gf_fop_setdents_req_t *req = NULL;
+ server_state_t *state = NULL;
+ dir_entry_t *entry = NULL;
+ dir_entry_t *trav = NULL;
+ dir_entry_t *prev = NULL;
+ int32_t count = 0;
+ int32_t i = 0;
+ int32_t bread = 0;
+ char *ender = NULL;
+ char *buffer_ptr = NULL;
+ char tmp_buf[512] = {0,};
+
+ conn = SERVER_CONNECTION(frame);
+
+ req = gf_param (hdr);
+ state = CALL_STATE(frame);
+
+ state->fd_no = ntoh64 (req->fd);
+ if (state->fd_no >= 0)
+ state->fd = gf_fd_fdptr_get (conn->fdtable,
+ state->fd_no);
+
+ state->nr_count = ntoh32 (req->count);
+
+ if (state->fd == NULL) {
+ gf_log (frame->this->name, GF_LOG_ERROR,
+ "fd - %"PRId64": unresolved fd",
+ state->fd_no);
+
+ server_setdents_cbk (frame, NULL, frame->this,
+ -1, EINVAL);
+
+ goto out;
+ }
+
+ if (buf == NULL) {
+ gf_log (frame->this->name, GF_LOG_ERROR,
+ "fd - %"PRId64" (%"PRId64"): received a null buffer, "
+ "returning EINVAL",
+ state->fd_no, state->fd->inode->ino);
+
+ server_setdents_cbk (frame, NULL, frame->this,
+ -1, EINVAL);
+
+ goto out;
+ }
+
+ entry = CALLOC (1, sizeof (dir_entry_t));
+ ERR_ABORT (entry);
+ prev = entry;
+ buffer_ptr = buf;
+
+ for (i = 0; i < state->nr_count ; i++) {
+ bread = 0;
+ trav = CALLOC (1, sizeof (dir_entry_t));
+ ERR_ABORT (trav);
+
+ ender = strchr (buffer_ptr, '/');
+ if (!ender)
+ break;
+ count = ender - buffer_ptr;
+ trav->name = CALLOC (1, count + 2);
+ ERR_ABORT (trav->name);
+
+ strncpy (trav->name, buffer_ptr, count);
+ bread = count + 1;
+ buffer_ptr += bread;
+
+ ender = strchr (buffer_ptr, '\n');
+ if (!ender)
+ break;
+ count = ender - buffer_ptr;
+ strncpy (tmp_buf, buffer_ptr, count);
+ bread = count + 1;
+ buffer_ptr += bread;
+
+ /* TODO: use str_to_stat instead */
+ {
+ uint64_t dev;
+ uint64_t ino;
+ uint32_t mode;
+ uint32_t nlink;
+ uint32_t uid;
+ uint32_t gid;
+ uint64_t rdev;
+ uint64_t size;
+ uint32_t blksize;
+ uint64_t blocks;
+ uint32_t atime;
+ uint32_t atime_nsec;
+ uint32_t mtime;
+ uint32_t mtime_nsec;
+ uint32_t ctime;
+ uint32_t ctime_nsec;
+
+ sscanf (tmp_buf, GF_STAT_PRINT_FMT_STR,
+ &dev,
+ &ino,
+ &mode,
+ &nlink,
+ &uid,
+ &gid,
+ &rdev,
+ &size,
+ &blksize,
+ &blocks,
+ &atime,
+ &atime_nsec,
+ &mtime,
+ &mtime_nsec,
+ &ctime,
+ &ctime_nsec);
+
+ trav->buf.st_dev = dev;
+ trav->buf.st_ino = ino;
+ trav->buf.st_mode = mode;
+ trav->buf.st_nlink = nlink;
+ trav->buf.st_uid = uid;
+ trav->buf.st_gid = gid;
+ trav->buf.st_rdev = rdev;
+ trav->buf.st_size = size;
+ trav->buf.st_blksize = blksize;
+ trav->buf.st_blocks = blocks;
+
+ trav->buf.st_atime = atime;
+ trav->buf.st_mtime = mtime;
+ trav->buf.st_ctime = ctime;
+
+ ST_ATIM_NSEC_SET(&trav->buf, atime_nsec);
+ ST_MTIM_NSEC_SET(&trav->buf, mtime_nsec);
+ ST_CTIM_NSEC_SET(&trav->buf, ctime_nsec);
+
+ }
+
+ ender = strchr (buffer_ptr, '\n');
+ if (!ender)
+ break;
+ count = ender - buffer_ptr;
+ *ender = '\0';
+ if (S_ISLNK (trav->buf.st_mode)) {
+ trav->link = strdup (buffer_ptr);
+ } else
+ trav->link = "";
+ bread = count + 1;
+ buffer_ptr += bread;
+
+ prev->next = trav;
+ prev = trav;
+ }
+
+
+ gf_log (bound_xl->name, GF_LOG_DEBUG,
+ "%"PRId64": SETDENTS \'fd=%"PRId64" (%"PRId64"); count=%"PRId64,
+ frame->root->unique, state->fd_no, state->fd->inode->ino,
+ (int64_t)state->nr_count);
+
+ STACK_WIND (frame,
+ server_setdents_cbk,
+ BOUND_XL(frame),
+ BOUND_XL(frame)->fops->setdents,
+ state->fd,
+ state->flags,
+ entry,
+ state->nr_count);
+
+
+ /* Free the variables allocated in this fop here */
+ trav = entry->next;
+ prev = entry;
+ while (trav) {
+ prev->next = trav->next;
+ FREE (trav->name);
+ if (S_ISLNK (trav->buf.st_mode))
+ FREE (trav->link);
+ FREE (trav);
+ trav = prev->next;
+ }
+ FREE (entry);
+
+out:
+ return 0;
+}
+
+
+
+/* xxx_MOPS */
+
+/* Management Calls */
+/*
+ * mop_getspec - getspec function for server protocol
+ * @frame: call frame
+ * @bound_xl:
+ * @params:
+ *
+ */
+int32_t
+mop_getspec (call_frame_t *frame,
+ xlator_t *bound_xl,
+ gf_hdr_common_t *hdr, size_t hdrlen,
+ char *buf, size_t buflen)
+{
+ gf_hdr_common_t *_hdr = NULL;
+ gf_mop_getspec_rsp_t *rsp = NULL;
+ int32_t ret = -1;
+ int32_t op_errno = ENOENT;
+ int32_t gf_errno = 0;
+ int32_t spec_fd = -1;
+ size_t file_len = 0;
+ size_t _hdrlen = 0;
+ char tmp_filename[ZR_FILENAME_MAX] = {0,};
+ char data_key[256] = {0,};
+ char *filename = NULL;
+ struct stat stbuf = {0,};
+ peer_info_t *peerinfo = NULL;
+ transport_t *trans = NULL;
+
+ gf_mop_getspec_req_t *req = NULL;
+ uint32_t flags = 0;
+ uint32_t keylen = 0;
+ char *key = NULL;
+
+ req = gf_param (hdr);
+ flags = ntoh32 (req->flags);
+ keylen = ntoh32 (req->keylen);
+ if (keylen) {
+ key = req->key;
+ }
+
+ trans = TRANSPORT_FROM_FRAME(frame);
+
+ peerinfo = &(trans->peerinfo);
+ /* Inform users that this option is changed now */
+ ret = dict_get_str (frame->this->options, "client-volume-filename",
+ &filename);
+ if (ret == 0) {
+ gf_log (trans->xl->name, GF_LOG_WARNING,
+ "option 'client-volume-specfile' is changed to "
+ "'volume-filename.<key>' which now takes 'key' as an "
+ "option to choose/fetch different files from server. "
+ "Refer documentation or contact developers for more "
+ "info. Currently defaulting to given file '%s'",
+ filename);
+ }
+
+ if (key && !filename) {
+ sprintf (data_key, "volume-filename.%s", key);
+ ret = dict_get_str (frame->this->options, data_key, &filename);
+ if (ret < 0) {
+ gf_log (trans->xl->name, GF_LOG_ERROR,
+ "failed to get corresponding volume file "
+ "for the key '%s'. using default file %s",
+ key, GLUSTERFSD_SPEC_PATH);
+ }
+ }
+ if (!filename) {
+ filename = GLUSTERFSD_SPEC_PATH;
+ if (!key)
+ gf_log (trans->xl->name, GF_LOG_WARNING,
+ "using default volume file %s",
+ GLUSTERFSD_SPEC_PATH);
+ }
+
+ {
+ sprintf (tmp_filename, "%s.%s",
+ filename, peerinfo->identifier);
+
+ /* Try for ip specific client volfile.
+ * If not found, then go for, regular client file.
+ */
+ ret = open (tmp_filename, O_RDONLY);
+ spec_fd = ret;
+ if (spec_fd < 0) {
+ gf_log (trans->xl->name, GF_LOG_DEBUG,
+ "Unable to open %s (%s)",
+ tmp_filename, strerror (errno));
+ /* fall back */
+ ret = open (filename, O_RDONLY);
+ spec_fd = ret;
+ if (spec_fd < 0) {
+ gf_log (trans->xl->name, GF_LOG_ERROR,
+ "Unable to open %s (%s)",
+ filename, strerror (errno));
+ goto fail;
+ }
+ } else {
+ /* Successful */
+ filename = tmp_filename;
+ }
+ }
+
+ /* to allocate the proper buffer to hold the file data */
+ {
+ ret = stat (filename, &stbuf);
+ if (ret < 0){
+ gf_log (trans->xl->name, GF_LOG_ERROR,
+ "Unable to stat %s (%s)",
+ filename, strerror (errno));
+ goto fail;
+ }
+
+ file_len = stbuf.st_size;
+ }
+
+fail:
+ op_errno = errno;
+
+ _hdrlen = gf_hdr_len (rsp, file_len + 1);
+ _hdr = gf_hdr_new (rsp, file_len + 1);
+ rsp = gf_param (_hdr);
+
+ _hdr->rsp.op_ret = hton32 (ret);
+ gf_errno = gf_errno_to_error (op_errno);
+ _hdr->rsp.op_errno = hton32 (gf_errno);
+
+ if (file_len) {
+ read (spec_fd, rsp->spec, file_len);
+ close (spec_fd);
+ }
+ protocol_server_reply (frame, GF_OP_TYPE_MOP_REPLY, GF_MOP_GETSPEC,
+ _hdr, _hdrlen, NULL, 0, NULL);
+
+ return 0;
+}
+
+int32_t
+server_checksum_cbk (call_frame_t *frame,
+ void *cookie,
+ xlator_t *this,
+ int32_t op_ret,
+ int32_t op_errno,
+ uint8_t *fchecksum,
+ uint8_t *dchecksum)
+{
+ gf_hdr_common_t *hdr = NULL;
+ gf_fop_checksum_rsp_t *rsp = NULL;
+ size_t hdrlen = 0;
+ int32_t gf_errno = 0;
+
+ hdrlen = gf_hdr_len (rsp, ZR_FILENAME_MAX + 1 + ZR_FILENAME_MAX + 1);
+ hdr = gf_hdr_new (rsp, ZR_FILENAME_MAX + 1 + ZR_FILENAME_MAX + 1);
+ rsp = gf_param (hdr);
+
+ hdr->rsp.op_ret = hton32 (op_ret);
+ gf_errno = gf_errno_to_error (op_errno);
+ hdr->rsp.op_errno = hton32 (gf_errno);
+
+ if (op_ret >= 0) {
+ memcpy (rsp->fchecksum, fchecksum, ZR_FILENAME_MAX);
+ rsp->fchecksum[ZR_FILENAME_MAX] = '\0';
+ memcpy (rsp->dchecksum + ZR_FILENAME_MAX,
+ dchecksum, ZR_FILENAME_MAX);
+ rsp->dchecksum[ZR_FILENAME_MAX + ZR_FILENAME_MAX] = '\0';
+ }
+
+ protocol_server_reply (frame, GF_OP_TYPE_FOP_REPLY, GF_FOP_CHECKSUM,
+ hdr, hdrlen, NULL, 0, NULL);
+
+ return 0;
+}
+
+int32_t
+server_checksum (call_frame_t *frame,
+ xlator_t *bound_xl,
+ gf_hdr_common_t *hdr, size_t hdrlen,
+ char *buf, size_t buflen)
+{
+ loc_t loc = {0,};
+ int32_t flag = 0;
+ gf_fop_checksum_req_t *req = NULL;
+
+ req = gf_param (hdr);
+
+ loc.path = req->path;
+ loc.ino = ntoh64 (req->ino);
+ loc.inode = NULL;
+ flag = ntoh32 (req->flag);
+
+ gf_log (bound_xl->name, GF_LOG_DEBUG,
+ "%"PRId64": CHECKSUM \'%s (%"PRId64")\'",
+ frame->root->unique, loc.path, loc.ino);
+
+ STACK_WIND (frame,
+ server_checksum_cbk,
+ BOUND_XL(frame),
+ BOUND_XL(frame)->fops->checksum,
+ &loc,
+ flag);
+
+ return 0;
+}
+
+
+/*
+ * mop_unlock - unlock management function for server protocol
+ * @frame: call frame
+ * @bound_xl:
+ * @params: parameter dictionary
+ *
+ */
+int32_t
+mop_getvolume (call_frame_t *frame,
+ xlator_t *bound_xl,
+ gf_hdr_common_t *hdr, size_t hdrlen,
+ char *buf, size_t buflen)
+{
+ return 0;
+}
+
+struct __get_xl_struct {
+ const char *name;
+ xlator_t *reply;
+};
+
+void __check_and_set (xlator_t *each,
+ void *data)
+{
+ if (!strcmp (each->name,
+ ((struct __get_xl_struct *) data)->name))
+ ((struct __get_xl_struct *) data)->reply = each;
+}
+
+static xlator_t *
+get_xlator_by_name (xlator_t *some_xl,
+ const char *name)
+{
+ struct __get_xl_struct get = {
+ .name = name,
+ .reply = NULL
+ };
+
+ xlator_foreach (some_xl, __check_and_set, &get);
+
+ return get.reply;
+}
+
+
+/*
+ * mop_setvolume - setvolume management function for server protocol
+ * @frame: call frame
+ * @bound_xl:
+ * @params: parameter dictionary
+ *
+ */
+int
+mop_setvolume (call_frame_t *frame, xlator_t *bound_xl,
+ gf_hdr_common_t *req_hdr, size_t req_hdrlen,
+ char *req_buf, size_t req_buflen)
+{
+ server_connection_t *conn = NULL;
+ server_conf_t *conf = NULL;
+ gf_hdr_common_t *rsp_hdr = NULL;
+ gf_mop_setvolume_req_t *req = NULL;
+ gf_mop_setvolume_rsp_t *rsp = NULL;
+ peer_info_t *peerinfo = NULL;
+ int32_t ret = -1;
+ int32_t op_ret = -1;
+ int32_t op_errno = EINVAL;
+ int32_t gf_errno = 0;
+ dict_t *reply = NULL;
+ dict_t *config_params = NULL;
+ dict_t *params = NULL;
+ char *name = NULL;
+ char *version = NULL;
+ char *process_uuid = NULL;
+ xlator_t *xl = NULL;
+ transport_t *trans = NULL;
+ size_t rsp_hdrlen = -1;
+ size_t dict_len = -1;
+ size_t req_dictlen = -1;
+
+ params = dict_new ();
+ reply = dict_new ();
+
+ req = gf_param (req_hdr);
+ req_dictlen = ntoh32 (req->dict_len);
+ ret = dict_unserialize (req->buf, req_dictlen, &params);
+
+ config_params = dict_copy_with_ref (frame->this->options, NULL);
+ trans = TRANSPORT_FROM_FRAME(frame);
+ conf = SERVER_CONF(frame);
+
+ if (ret < 0) {
+ ret = dict_set_str (reply, "ERROR",
+ "Internal error: failed to unserialize "
+ "request dictionary");
+ if (ret < 0)
+ gf_log (bound_xl->name, GF_LOG_ERROR,
+ "failed to set error msg \"%s\"",
+ "Internal error: failed to unserialize "
+ "request dictionary");
+
+ op_ret = -1;
+ op_errno = EINVAL;
+ goto fail;
+ }
+
+ ret = dict_get_str (params, "process-uuid", &process_uuid);
+ if (ret < 0) {
+ ret = dict_set_str (reply, "ERROR",
+ "UUID not specified");
+ if (ret < 0)
+ gf_log (bound_xl->name, GF_LOG_ERROR,
+ "failed to set error msg");
+
+ op_ret = -1;
+ op_errno = EINVAL;
+ goto fail;
+ }
+
+
+ conn = server_connection_get (frame->this, process_uuid);
+ if (trans->xl_private != conn)
+ trans->xl_private = conn;
+
+ ret = dict_get_str (params, "version", &version);
+ if (ret < 0) {
+ ret = dict_set_str (reply, "ERROR",
+ "No version number specified");
+ if (ret < 0)
+ gf_log (trans->xl->name, GF_LOG_ERROR,
+ "failed to set error msg");
+
+ op_ret = -1;
+ op_errno = EINVAL;
+ goto fail;
+ }
+
+ ret = strcmp (version, PACKAGE_VERSION);
+ if (ret != 0) {
+ char *msg = NULL;
+ asprintf (&msg,
+ "Version mismatch: client(%s) Vs server (%s)",
+ version, PACKAGE_VERSION);
+ ret = dict_set_dynstr (reply, "ERROR", msg);
+ if (ret < 0)
+ gf_log (trans->xl->name, GF_LOG_ERROR,
+ "failed to set error msg");
+
+ op_ret = -1;
+ op_errno = EINVAL;
+ goto fail;
+ }
+
+
+ ret = dict_get_str (params,
+ "remote-subvolume", &name);
+ if (ret < 0) {
+ ret = dict_set_str (reply, "ERROR",
+ "No remote-subvolume option specified");
+ if (ret < 0)
+ gf_log (trans->xl->name, GF_LOG_ERROR,
+ "failed to set error msg");
+
+ op_ret = -1;
+ op_errno = EINVAL;
+ goto fail;
+ }
+
+ xl = get_xlator_by_name (frame->this, name);
+ if (xl == NULL) {
+ char *msg = NULL;
+ asprintf (&msg, "remote-subvolume \"%s\" is not found", name);
+ ret = dict_set_dynstr (reply, "ERROR", msg);
+ if (ret < 0)
+ gf_log (trans->xl->name, GF_LOG_ERROR,
+ "failed to set error msg");
+
+ op_ret = -1;
+ op_errno = ENOENT;
+ goto fail;
+ }
+
+ peerinfo = &trans->peerinfo;
+ ret = dict_set_static_ptr (params, "peer-info", peerinfo);
+ if (ret < 0)
+ gf_log (trans->xl->name, GF_LOG_ERROR,
+ "failed to set peer-info");
+
+ if (conf->auth_modules == NULL) {
+ gf_log (trans->xl->name, GF_LOG_ERROR,
+ "Authentication module not initialized");
+ }
+
+ ret = gf_authenticate (params, config_params,
+ conf->auth_modules);
+ if (ret == AUTH_ACCEPT) {
+ gf_log (trans->xl->name, GF_LOG_INFO,
+ "accepted client from %s",
+ peerinfo->identifier);
+ op_ret = 0;
+ conn->bound_xl = xl;
+ ret = dict_set_str (reply, "ERROR", "Success");
+ if (ret < 0)
+ gf_log (trans->xl->name, GF_LOG_ERROR,
+ "failed to set error msg");
+ } else {
+ gf_log (trans->xl->name, GF_LOG_ERROR,
+ "Cannot authenticate client from %s",
+ peerinfo->identifier);
+ op_ret = -1;
+ op_errno = EACCES;
+ ret = dict_set_str (reply, "ERROR", "Authentication failed");
+ if (ret < 0)
+ gf_log (bound_xl->name, GF_LOG_ERROR,
+ "failed to set error msg");
+
+ goto fail;
+ }
+
+ if (conn->bound_xl == NULL) {
+ ret = dict_set_str (reply, "ERROR",
+ "Check volfile and handshake "
+ "options in protocol/client");
+ if (ret < 0)
+ gf_log (trans->xl->name, GF_LOG_ERROR,
+ "failed to set error msg");
+
+ op_ret = -1;
+ op_errno = EACCES;
+ goto fail;
+ }
+
+ if ((conn->bound_xl != NULL) &&
+ (ret >= 0) &&
+ (conn->bound_xl->itable == NULL)) {
+ /* create inode table for this bound_xl, if one doesn't
+ already exist */
+ int32_t lru_limit = 1024;
+
+ lru_limit = INODE_LRU_LIMIT (frame->this);
+
+ gf_log (trans->xl->name, GF_LOG_DEBUG,
+ "creating inode table with lru_limit=%"PRId32", "
+ "xlator=%s", lru_limit, conn->bound_xl->name);
+
+ conn->bound_xl->itable =
+ inode_table_new (lru_limit,
+ conn->bound_xl);
+ }
+
+ ret = dict_set_str (reply, "process-uuid",
+ xl->ctx->process_uuid);
+
+fail:
+ dict_len = dict_serialized_length (reply);
+ if (dict_len < 0) {
+ gf_log (xl->name, GF_LOG_ERROR,
+ "failed to get serialized length of reply dict");
+ op_ret = -1;
+ op_errno = EINVAL;
+ dict_len = 0;
+ }
+
+ rsp_hdr = gf_hdr_new (rsp, dict_len);
+ rsp_hdrlen = gf_hdr_len (rsp, dict_len);
+ rsp = gf_param (rsp_hdr);
+
+ if (dict_len) {
+ ret = dict_serialize (reply, rsp->buf);
+ if (ret < 0) {
+ gf_log (xl->name, GF_LOG_ERROR,
+ "failed to serialize reply dict");
+ op_ret = -1;
+ op_errno = -ret;
+ }
+ }
+ rsp->dict_len = hton32 (dict_len);
+
+ rsp_hdr->rsp.op_ret = hton32 (op_ret);
+ gf_errno = gf_errno_to_error (op_errno);
+ rsp_hdr->rsp.op_errno = hton32 (gf_errno);
+
+ protocol_server_reply (frame, GF_OP_TYPE_MOP_REPLY, GF_MOP_SETVOLUME,
+ rsp_hdr, rsp_hdrlen, NULL, 0, NULL);
+
+ dict_unref (params);
+ dict_unref (reply);
+ dict_unref (config_params);
+
+ return 0;
+}
+
+/*
+ * server_mop_stats_cbk - stats callback for server management operation
+ * @frame: call frame
+ * @cookie:
+ * @this:
+ * @op_ret: return value
+ * @op_errno: errno
+ * @stats:err
+ *
+ * not for external reference
+ */
+
+int32_t
+server_mop_stats_cbk (call_frame_t *frame,
+ void *cookie,
+ xlator_t *xl,
+ int32_t ret,
+ int32_t op_errno,
+ struct xlator_stats *stats)
+{
+ /* TODO: get this information from somewhere else, not extern */
+ gf_hdr_common_t *hdr = NULL;
+ gf_mop_stats_rsp_t *rsp = NULL;
+ char buffer[256] = {0,};
+ int64_t glusterfsd_stats_nr_clients = 0;
+ size_t hdrlen = 0;
+ size_t buf_len = 0;
+ int32_t gf_errno = 0;
+
+ if (ret >= 0) {
+ sprintf (buffer,
+ "%"PRIx64",%"PRIx64",%"PRIx64
+ ",%"PRIx64",%"PRIx64",%"PRIx64
+ ",%"PRIx64",%"PRIx64"\n",
+ stats->nr_files,
+ stats->disk_usage,
+ stats->free_disk,
+ stats->total_disk_size,
+ stats->read_usage,
+ stats->write_usage,
+ stats->disk_speed,
+ glusterfsd_stats_nr_clients);
+
+ buf_len = strlen (buffer);
+ }
+
+ hdrlen = gf_hdr_len (rsp, buf_len + 1);
+ hdr = gf_hdr_new (rsp, buf_len + 1);
+ rsp = gf_param (hdr);
+
+ hdr->rsp.op_ret = hton32 (ret);
+ gf_errno = gf_errno_to_error (op_errno);
+ hdr->rsp.op_errno = hton32 (gf_errno);
+
+ strcpy (rsp->buf, buffer);
+
+ protocol_server_reply (frame, GF_OP_TYPE_MOP_REPLY, GF_MOP_STATS,
+ hdr, hdrlen, NULL, 0, NULL);
+
+ return 0;
+}
+
+
+/*
+ * mop_unlock - unlock management function for server protocol
+ * @frame: call frame
+ * @bound_xl:
+ * @params: parameter dictionary
+ *
+ */
+static int32_t
+mop_stats (call_frame_t *frame,
+ xlator_t *bound_xl,
+ gf_hdr_common_t *hdr, size_t hdrlen,
+ char *buf, size_t buflen)
+{
+ int32_t flag = 0;
+ gf_mop_stats_req_t *req = NULL;
+
+ req = gf_param (hdr);
+
+ flag = ntoh32 (req->flags);
+
+ STACK_WIND (frame,
+ server_mop_stats_cbk,
+ bound_xl,
+ bound_xl->mops->stats,
+ flag);
+
+ return 0;
+}
+
+int32_t
+mop_ping (call_frame_t *frame,
+ xlator_t *bound_xl,
+ gf_hdr_common_t *hdr, size_t hdrlen,
+ char *buf, size_t buflen)
+{
+ gf_hdr_common_t *rsp_hdr = NULL;
+ gf_mop_ping_rsp_t *rsp = NULL;
+ size_t rsp_hdrlen = 0;
+
+ rsp_hdrlen = gf_hdr_len (rsp, 0);
+ rsp_hdr = gf_hdr_new (rsp, 0);
+
+ hdr->rsp.op_ret = 0;
+
+ protocol_server_reply (frame, GF_OP_TYPE_MOP_REPLY, GF_MOP_PING,
+ rsp_hdr, rsp_hdrlen, NULL, 0, NULL);
+
+ return 0;
+}
+/*
+ * unknown_op_cbk - This function is called when a opcode for unknown
+ * type is called. Helps to keep the backward/forward
+ * compatiblity
+ * @frame: call frame
+ * @type:
+ * @opcode:
+ *
+ */
+
+int32_t
+unknown_op_cbk (call_frame_t *frame,
+ int32_t type,
+ int32_t opcode)
+{
+ gf_hdr_common_t *hdr = NULL;
+ gf_fop_flush_rsp_t *rsp = NULL;
+ size_t hdrlen = 0;
+ int32_t gf_errno = 0;
+ hdrlen = gf_hdr_len (rsp, 0);
+ hdr = gf_hdr_new (rsp, 0);
+ rsp = gf_param (hdr);
+
+ hdr->rsp.op_ret = hton32 (-1);
+ gf_errno = gf_errno_to_error (ENOSYS);
+ hdr->rsp.op_errno = hton32 (gf_errno);
+
+ protocol_server_reply (frame, type, opcode,
+ hdr, hdrlen, NULL, 0, NULL);
+
+ return 0;
+}
+
+/*
+ * get_frame_for_transport - get call frame for specified transport object
+ *
+ * @trans: transport object
+ *
+ */
+static call_frame_t *
+get_frame_for_transport (transport_t *trans)
+{
+ call_frame_t *frame = NULL;
+ call_pool_t *pool = NULL;
+ server_connection_t *conn = NULL;
+ server_state_t *state = NULL;;
+
+ GF_VALIDATE_OR_GOTO("server", trans, out);
+
+ if (trans->xl && trans->xl->ctx)
+ pool = trans->xl->ctx->pool;
+ GF_VALIDATE_OR_GOTO("server", pool, out);
+
+ frame = create_frame (trans->xl, pool);
+ GF_VALIDATE_OR_GOTO("server", frame, out);
+
+ state = CALLOC (1, sizeof (*state));
+ GF_VALIDATE_OR_GOTO("server", state, out);
+
+ conn = trans->xl_private;
+ if (conn) {
+ if (conn->bound_xl)
+ state->itable = conn->bound_xl->itable;
+ state->bound_xl = conn->bound_xl;
+ }
+
+ state->trans = transport_ref (trans);
+
+ frame->root->trans = conn;
+ frame->root->state = state; /* which socket */
+ frame->root->unique = 0; /* which call */
+
+out:
+ return frame;
+}
+
+/*
+ * get_frame_for_call - create a frame into the capable of
+ * generating and replying the reply packet by itself.
+ * By making a call with this frame, the last UNWIND
+ * function will have all needed state from its
+ * frame_t->root to send reply.
+ * @trans:
+ * @blk:
+ * @params:
+ *
+ * not for external reference
+ */
+static call_frame_t *
+get_frame_for_call (transport_t *trans, gf_hdr_common_t *hdr)
+{
+ call_frame_t *frame = NULL;
+
+ frame = get_frame_for_transport (trans);
+
+ frame->root->op = ntoh32 (hdr->op);
+ frame->root->type = ntoh32 (hdr->type);
+
+ frame->root->uid = ntoh32 (hdr->req.uid);
+ frame->root->unique = ntoh64 (hdr->callid); /* which call */
+ frame->root->gid = ntoh32 (hdr->req.gid);
+ frame->root->pid = ntoh32 (hdr->req.pid);
+
+ return frame;
+}
+
+/*
+ * prototype of operations function for each of mop and
+ * fop at server protocol level
+ *
+ * @frame: call frame pointer
+ * @bound_xl: the xlator that this frame is bound to
+ * @params: parameters dictionary
+ *
+ * to be used by protocol interpret, _not_ for exterenal reference
+ */
+typedef int32_t (*gf_op_t) (call_frame_t *frame, xlator_t *bould_xl,
+ gf_hdr_common_t *hdr, size_t hdrlen,
+ char *buf, size_t buflen);
+
+
+static gf_op_t gf_fops[] = {
+ [GF_FOP_STAT] = server_stat,
+ [GF_FOP_READLINK] = server_readlink,
+ [GF_FOP_MKNOD] = server_mknod,
+ [GF_FOP_MKDIR] = server_mkdir,
+ [GF_FOP_UNLINK] = server_unlink,
+ [GF_FOP_RMDIR] = server_rmdir,
+ [GF_FOP_SYMLINK] = server_symlink,
+ [GF_FOP_RENAME] = server_rename,
+ [GF_FOP_LINK] = server_link,
+ [GF_FOP_CHMOD] = server_chmod,
+ [GF_FOP_CHOWN] = server_chown,
+ [GF_FOP_TRUNCATE] = server_truncate,
+ [GF_FOP_OPEN] = server_open,
+ [GF_FOP_READ] = server_readv,
+ [GF_FOP_WRITE] = server_writev,
+ [GF_FOP_STATFS] = server_statfs,
+ [GF_FOP_FLUSH] = server_flush,
+ [GF_FOP_FSYNC] = server_fsync,
+ [GF_FOP_SETXATTR] = server_setxattr,
+ [GF_FOP_GETXATTR] = server_getxattr,
+ [GF_FOP_REMOVEXATTR] = server_removexattr,
+ [GF_FOP_OPENDIR] = server_opendir,
+ [GF_FOP_GETDENTS] = server_getdents,
+ [GF_FOP_FSYNCDIR] = server_fsyncdir,
+ [GF_FOP_ACCESS] = server_access,
+ [GF_FOP_CREATE] = server_create,
+ [GF_FOP_FTRUNCATE] = server_ftruncate,
+ [GF_FOP_FSTAT] = server_fstat,
+ [GF_FOP_LK] = server_lk,
+ [GF_FOP_UTIMENS] = server_utimens,
+ [GF_FOP_FCHMOD] = server_fchmod,
+ [GF_FOP_FCHOWN] = server_fchown,
+ [GF_FOP_LOOKUP] = server_lookup,
+ [GF_FOP_SETDENTS] = server_setdents,
+ [GF_FOP_READDIR] = server_readdir,
+ [GF_FOP_INODELK] = server_inodelk,
+ [GF_FOP_FINODELK] = server_finodelk,
+ [GF_FOP_ENTRYLK] = server_entrylk,
+ [GF_FOP_FENTRYLK] = server_fentrylk,
+ [GF_FOP_CHECKSUM] = server_checksum,
+ [GF_FOP_XATTROP] = server_xattrop,
+ [GF_FOP_FXATTROP] = server_fxattrop,
+};
+
+
+
+static gf_op_t gf_mops[] = {
+ [GF_MOP_SETVOLUME] = mop_setvolume,
+ [GF_MOP_GETVOLUME] = mop_getvolume,
+ [GF_MOP_STATS] = mop_stats,
+ [GF_MOP_GETSPEC] = mop_getspec,
+ [GF_MOP_PING] = mop_ping,
+};
+
+static gf_op_t gf_cbks[] = {
+ [GF_CBK_FORGET] = server_forget,
+ [GF_CBK_RELEASE] = server_release,
+ [GF_CBK_RELEASEDIR] = server_releasedir
+};
+
+int
+protocol_server_interpret (xlator_t *this, transport_t *trans,
+ char *hdr_p, size_t hdrlen, char *buf,
+ size_t buflen)
+{
+ server_connection_t *conn = NULL;
+ gf_hdr_common_t *hdr = NULL;
+ xlator_t *bound_xl = NULL;
+ call_frame_t *frame = NULL;
+ peer_info_t *peerinfo = NULL;
+ int32_t type = -1;
+ int32_t op = -1;
+ int32_t ret = -1;
+
+ hdr = (gf_hdr_common_t *)hdr_p;
+ type = ntoh32 (hdr->type);
+ op = ntoh32 (hdr->op);
+
+ conn = trans->xl_private;
+ if (conn)
+ bound_xl = conn->bound_xl;
+
+ peerinfo = &trans->peerinfo;
+ switch (type) {
+ case GF_OP_TYPE_FOP_REQUEST:
+ if ((op < 0) ||
+ (op > GF_FOP_MAXVALUE)) {
+ gf_log (this->name, GF_LOG_ERROR,
+ "invalid fop %"PRId32" from client %s",
+ op, peerinfo->identifier);
+ break;
+ }
+ if (bound_xl == NULL) {
+ gf_log (this->name, GF_LOG_ERROR,
+ "Received fop %"PRId32" before "
+ "authentication.", op);
+ break;
+ }
+ frame = get_frame_for_call (trans, hdr);
+ ret = gf_fops[op] (frame, bound_xl, hdr, hdrlen, buf, buflen);
+ break;
+
+ case GF_OP_TYPE_MOP_REQUEST:
+ if (op < 0 || op > GF_MOP_MAXVALUE) {
+ gf_log (this->name, GF_LOG_ERROR,
+ "invalid mop %"PRId32" from client %s",
+ op, peerinfo->identifier);
+ break;
+ }
+ frame = get_frame_for_call (trans, hdr);
+ ret = gf_mops[op] (frame, bound_xl, hdr, hdrlen, buf, buflen);
+ break;
+
+ case GF_OP_TYPE_CBK_REQUEST:
+ if (op < 0 || op > GF_CBK_MAXVALUE) {
+ gf_log (this->name, GF_LOG_ERROR,
+ "invalid cbk %"PRId32" from client %s",
+ op, peerinfo->identifier);
+ break;
+ }
+ if (bound_xl == NULL) {
+ gf_log (this->name, GF_LOG_ERROR,
+ "Received cbk %d before authentication.", op);
+ break;
+ }
+
+ frame = get_frame_for_call (trans, hdr);
+ ret = gf_cbks[op] (frame, bound_xl, hdr, hdrlen, buf, buflen);
+ break;
+
+ default:
+ break;
+ }
+
+ return ret;
+}
+
+
+/*
+ * server_nop_cbk - nop callback for server protocol
+ * @frame: call frame
+ * @cookie:
+ * @this:
+ * @op_ret: return value
+ * @op_errno: errno
+ *
+ * not for external reference
+ */
+int
+server_nop_cbk (call_frame_t *frame, void *cookie,
+ xlator_t *this, int32_t op_ret, int32_t op_errno)
+{
+ server_state_t *state = NULL;
+
+ state = CALL_STATE(frame);
+
+ if (state)
+ free_state (state);
+ STACK_DESTROY (frame->root);
+ return 0;
+}
+
+
+static void
+get_auth_types (dict_t *this,
+ char *key,
+ data_t *value,
+ void *data)
+{
+ dict_t *auth_dict = data;
+ char *saveptr = NULL, *tmp = NULL;
+ char *key_cpy = NULL;
+ int32_t ret = -1;
+
+ key_cpy = strdup (key);
+ GF_VALIDATE_OR_GOTO("server", key_cpy, out);
+
+ tmp = strtok_r (key_cpy, ".", &saveptr);
+ ret = strcmp (tmp, "auth");
+ if (ret == 0) {
+ tmp = strtok_r (NULL, ".", &saveptr);
+ if (strcmp (tmp, "ip") == 0) {
+ /* TODO: backward compatibility, remove when
+ newer versions are available */
+ tmp = "addr";
+ gf_log ("server", GF_LOG_WARNING,
+ "assuming 'auth.ip' to be 'auth.addr'");
+ }
+ ret = dict_set_dynptr (auth_dict, tmp, NULL, 0);
+ if (ret < 0) {
+ gf_log ("server", GF_LOG_ERROR,
+ "failed to dict_set_dynptr");
+ }
+ }
+
+ FREE (key_cpy);
+out:
+ return;
+}
+
+
+static int
+validate_auth_options (xlator_t *this, dict_t *dict)
+{
+ int ret = -1;
+ int error = 0;
+ xlator_list_t *trav = NULL;
+ data_pair_t *pair = NULL;
+ char *saveptr = NULL, *tmp = NULL;
+ char *key_cpy = NULL;
+
+ trav = this->children;
+ while (trav) {
+ error = -1;
+ for (pair = dict->members_list; pair; pair = pair->next) {
+ key_cpy = strdup (pair->key);
+ tmp = strtok_r (key_cpy, ".", &saveptr);
+ ret = strcmp (tmp, "auth");
+ if (ret == 0) {
+ /* for module type */
+ tmp = strtok_r (NULL, ".", &saveptr);
+ /* for volume name */
+ tmp = strtok_r (NULL, ".", &saveptr);
+ }
+
+ if (strcmp (tmp, trav->xlator->name) == 0) {
+ error = 0;
+ free (key_cpy);
+ break;
+ }
+ free (key_cpy);
+ }
+ if (-1 == error) {
+ gf_log (this->name, GF_LOG_ERROR,
+ "volume '%s' defined as subvolume, but no "
+ "authentication defined for the same",
+ trav->xlator->name);
+ break;
+ }
+ trav = trav->next;
+ }
+
+ return error;
+}
+
+
+/*
+ * init - called during server protocol initialization
+ *
+ * @this:
+ *
+ */
+int
+init (xlator_t *this)
+{
+ int32_t ret = -1;
+ transport_t *trans = NULL;
+ server_conf_t *conf = NULL;
+
+ if (this->children == NULL) {
+ gf_log (this->name, GF_LOG_ERROR,
+ "protocol/server should have subvolume");
+ goto out;
+ }
+
+ trans = transport_load (this->options, this);
+ if (trans == NULL) {
+ gf_log (this->name, GF_LOG_ERROR,
+ "failed to load transport");
+ goto out;
+ }
+
+ ret = transport_listen (trans);
+ if (ret == -1) {
+ gf_log (this->name, GF_LOG_ERROR,
+ "failed to bind/listen on socket");
+ goto out;
+ }
+
+ conf = CALLOC (1, sizeof (server_conf_t));
+ GF_VALIDATE_OR_GOTO(this->name, conf, out);
+
+ INIT_LIST_HEAD (&conf->conns);
+ pthread_mutex_init (&conf->mutex, NULL);
+
+ conf->trans = trans;
+
+ conf->auth_modules = dict_new ();
+ GF_VALIDATE_OR_GOTO(this->name, conf->auth_modules, out);
+
+ dict_foreach (this->options, get_auth_types,
+ conf->auth_modules);
+ ret = validate_auth_options (this, this->options);
+ if (ret == -1) {
+ /* logging already done in validate_auth_options function. */
+ goto out;
+ }
+
+ ret = gf_auth_init (this, conf->auth_modules);
+ if (ret) {
+ dict_unref (conf->auth_modules);
+ goto out;
+ }
+
+ this->private = conf;
+
+ ret = dict_get_int32 (this->options, "inode-lru-limit",
+ &conf->inode_lru_limit);
+ if (ret < 0) {
+ conf->inode_lru_limit = 1024;
+ }
+
+ ret = dict_get_int32 (this->options, "limits.transaction-size",
+ &conf->max_block_size);
+ if (ret < 0) {
+ gf_log (this->name, GF_LOG_DEBUG,
+ "defaulting limits.transaction-size to %d",
+ DEFAULT_BLOCK_SIZE);
+ conf->max_block_size = DEFAULT_BLOCK_SIZE;
+ }
+
+#ifndef GF_DARWIN_HOST_OS
+ {
+ struct rlimit lim;
+
+ lim.rlim_cur = 1048576;
+ lim.rlim_max = 1048576;
+
+ if (setrlimit (RLIMIT_NOFILE, &lim) == -1) {
+ gf_log (this->name, GF_LOG_WARNING,
+ "WARNING: Failed to set 'ulimit -n 1M': %s",
+ strerror(errno));
+ lim.rlim_cur = 65536;
+ lim.rlim_max = 65536;
+
+ if (setrlimit (RLIMIT_NOFILE, &lim) == -1) {
+ gf_log (this->name, GF_LOG_ERROR,
+ "Failed to set max open fd to 64k: %s",
+ strerror(errno));
+ } else {
+ gf_log (this->name, GF_LOG_ERROR,
+ "max open fd set to 64k");
+ }
+ }
+ }
+#endif
+ this->ctx->top = this;
+
+ ret = 0;
+out:
+ return ret;
+}
+
+
+
+int
+protocol_server_pollin (xlator_t *this, transport_t *trans)
+{
+ char *hdr = NULL;
+ size_t hdrlen = 0;
+ char *buf = NULL;
+ size_t buflen = 0;
+ int ret = -1;
+
+
+ ret = transport_receive (trans, &hdr, &hdrlen, &buf, &buflen);
+
+ if (ret == 0)
+ ret = protocol_server_interpret (this, trans, hdr,
+ hdrlen, buf, buflen);
+
+ /* TODO: use mem-pool */
+ FREE (hdr);
+
+ return ret;
+}
+
+
+/*
+ * fini - finish function for server protocol, called before
+ * unloading server protocol.
+ *
+ * @this:
+ *
+ */
+void
+fini (xlator_t *this)
+{
+ server_conf_t *conf = this->private;
+
+ GF_VALIDATE_OR_GOTO(this->name, conf, out);
+
+ if (conf->auth_modules) {
+ dict_unref (conf->auth_modules);
+ }
+
+ FREE (conf);
+ this->private = NULL;
+out:
+ return;
+}
+
+/*
+ * server_protocol_notify - notify function for server protocol
+ * @this:
+ * @trans:
+ * @event:
+ *
+ */
+int
+notify (xlator_t *this, int32_t event, void *data, ...)
+{
+ int ret = 0;
+ transport_t *trans = data;
+
+ switch (event) {
+ case GF_EVENT_POLLIN:
+ ret = protocol_server_pollin (this, trans);
+ break;
+ case GF_EVENT_POLLERR:
+ {
+ peer_info_t *peerinfo = NULL;
+
+ peerinfo = &(trans->peerinfo);
+ gf_log (trans->xl->name, GF_LOG_INFO, "%s disconnected",
+ peerinfo->identifier);
+
+ ret = -1;
+ transport_disconnect (trans);
+ }
+ break;
+
+ case GF_EVENT_TRANSPORT_CLEANUP:
+ {
+ if (trans->xl_private)
+ server_connection_put (this, trans->xl_private);
+ }
+ break;
+
+ default:
+ default_notify (this, event, data);
+ break;
+ }
+
+ return ret;
+}
+
+
+struct xlator_mops mops = {
+};
+
+struct xlator_fops fops = {
+};
+
+struct xlator_cbks cbks = {
+};
+
+struct volume_options options[] = {
+ { .key = {"transport-type"},
+ .value = {"tcp", "socket", "ib-verbs", "unix", "ib-sdp",
+ "tcp/server", "ib-verbs/server"},
+ .type = GF_OPTION_TYPE_STR
+ },
+ { .key = {"volume-filename.*"},
+ .type = GF_OPTION_TYPE_PATH,
+ },
+ { .key = {"inode-lru-limit"},
+ .type = GF_OPTION_TYPE_INT,
+ .min = 0,
+ .max = (1 * GF_UNIT_MB)
+ },
+ { .key = {"client-volume-filename"},
+ .type = GF_OPTION_TYPE_PATH
+ },
+ { .key = {NULL} },
+};
diff --git a/xlators/protocol/server/src/server-protocol.h b/xlators/protocol/server/src/server-protocol.h
new file mode 100644
index 00000000000..cc5f6f9512c
--- /dev/null
+++ b/xlators/protocol/server/src/server-protocol.h
@@ -0,0 +1,143 @@
+/*
+ Copyright (c) 2006, 2007, 2008 Z RESEARCH, Inc. <http://www.zresearch.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 _SERVER_PROTOCOL_H_
+#define _SERVER_PROTOCOL_H_
+
+#ifndef _CONFIG_H
+#define _CONFIG_H
+#include "config.h"
+#endif
+
+#include <pthread.h>
+
+#include "glusterfs.h"
+#include "xlator.h"
+#include "logging.h"
+#include "call-stub.h"
+#include "authenticate.h"
+#include "fd.h"
+#include "byte-order.h"
+
+#define DEFAULT_BLOCK_SIZE 4194304 /* 4MB */
+#define GLUSTERFSD_SPEC_PATH CONFDIR "/glusterfs-client.vol"
+
+typedef struct _server_state server_state_t;
+
+struct _locker {
+ struct list_head lockers;
+ loc_t loc;
+ fd_t *fd;
+ pid_t pid;
+};
+
+struct _lock_table {
+ struct list_head file_lockers;
+ struct list_head dir_lockers;
+ gf_lock_t lock;
+ size_t count;
+};
+
+
+/* private structure per connection (transport object)
+ * used as transport_t->xl_private
+ */
+struct _server_connection {
+ struct list_head list;
+ char *id;
+ int ref;
+ pthread_mutex_t lock;
+ char disconnected;
+ fdtable_t *fdtable;
+ struct _lock_table *ltable;
+ xlator_t *bound_xl;
+};
+
+typedef struct _server_connection server_connection_t;
+
+
+server_connection_t *
+server_connection_get (xlator_t *this, const char *id);
+
+void
+server_connection_put (xlator_t *this, server_connection_t *conn);
+
+int
+server_connection_destroy (xlator_t *this, server_connection_t *conn);
+
+int
+server_nop_cbk (call_frame_t *frame, void *cookie,
+ xlator_t *this, int32_t op_ret, int32_t op_errno);
+
+
+typedef struct {
+ dict_t *auth_modules;
+ transport_t *trans;
+ int32_t max_block_size;
+ int32_t inode_lru_limit;
+ pthread_mutex_t mutex;
+ struct list_head conns;
+} server_conf_t;
+
+
+struct _server_state {
+ transport_t *trans;
+ xlator_t *bound_xl;
+ loc_t loc;
+ loc_t loc2;
+ int flags;
+ fd_t *fd;
+ size_t size;
+ off_t offset;
+ mode_t mode;
+ dev_t dev;
+ uid_t uid;
+ gid_t gid;
+ size_t nr_count;
+ int cmd;
+ int type;
+ char *name;
+ int name_len;
+ inode_table_t *itable;
+ int64_t fd_no;
+ ino_t ino;
+ ino_t par;
+ ino_t ino2;
+ ino_t par2;
+ char *path;
+ char *path2;
+ char *bname;
+ char *bname2;
+ int mask;
+ char is_revalidate;
+ dict_t *xattr_req;
+ struct flock flock;
+ struct timespec tv[2];
+ char *resolved;
+};
+
+
+int
+server_stub_resume (call_stub_t *stub, int32_t op_ret, int32_t op_errno,
+ inode_t *inode, inode_t *parent);
+
+int
+do_path_lookup (call_stub_t *stub, const loc_t *loc);
+
+#endif