From fdd20492638fe98a62b5e6d5e82f18cf4799fd1a Mon Sep 17 00:00:00 2001 From: Amar Tumballi Date: Mon, 21 Jun 2010 07:00:04 +0000 Subject: rpc protocol Signed-off-by: Amar Tumballi Signed-off-by: Raghavendra G Signed-off-by: Anand V. Avati BUG: 875 (Implement a new protocol to provide proper backward/forward compatibility) URL: http://bugs.gluster.com/cgi-bin/bugzilla3/show_bug.cgi?id=875 --- xlators/protocol/client/src/client.c | 1791 ++++++++++++++++++++++++++++++++++ 1 file changed, 1791 insertions(+) create mode 100644 xlators/protocol/client/src/client.c (limited to 'xlators/protocol/client/src/client.c') diff --git a/xlators/protocol/client/src/client.c b/xlators/protocol/client/src/client.c new file mode 100644 index 000000000..49e88bfde --- /dev/null +++ b/xlators/protocol/client/src/client.c @@ -0,0 +1,1791 @@ +/* + Copyright (c) 2010 Gluster, Inc. + 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 + . +*/ + + +#ifndef _CONFIG_H +#define _CONFIG_H +#include "config.h" +#endif + +#include "client.h" +#include "xlator.h" +#include "defaults.h" +#include "glusterfs.h" +#include "msg-xdr.h" +#include "statedump.h" +#include "compat-errno.h" + +extern rpc_clnt_prog_t clnt_handshake_prog; +int +client_handshake (xlator_t *this, struct rpc_clnt *rpc); + +void +client_start_ping (void *data); + +int +client_submit_request (xlator_t *this, void *req, + call_frame_t *frame, rpc_clnt_prog_t *prog, int procnum, + struct iobref *iobref, gfs_serialize_t sfunc) +{ + int ret = -1; + clnt_conf_t *conf = NULL; + struct iovec iov = {0, }; + struct iobuf *iobuf = NULL; + int count = 0; + char new_iobref = 0, start_ping = 0; + + conf = this->private; + + iobuf = iobuf_get (this->ctx->iobuf_pool); + if (!iobuf) { + goto out; + }; + + if (!iobref) { + iobref = iobref_new (); + if (!iobref) { + goto out; + } + + new_iobref = 1; + } + + iobref_add (iobref, iobuf); + + iov.iov_base = iobuf->ptr; + iov.iov_len = 128 * GF_UNIT_KB; + + /* Create the xdr payload */ + if (req && sfunc) { + ret = sfunc (iov, req); + if (ret == -1) { + goto out; + } + iov.iov_len = ret; + count = 1; + } + /* Send the msg */ + ret = rpc_clnt_submit (conf->rpc, prog, procnum, &iov, count, NULL, 0, + iobref, frame); + + if (ret == 0) { + pthread_mutex_lock (&conf->rpc->conn.lock); + { + if (!conf->rpc->conn.ping_started) { + start_ping = 1; + } + } + pthread_mutex_unlock (&conf->rpc->conn.lock); + } + + if (start_ping) + client_start_ping ((void *) this); + + ret = 0; +out: + if (new_iobref) { + iobref_unref (iobref); + } + + iobuf_unref (iobuf); + + return ret; +} + + +int32_t +client_forget (xlator_t *this, inode_t *inode) +{ + /* Nothing here */ + return 0; +} + +int32_t +client_releasedir (xlator_t *this, fd_t *fd) +{ + int ret = -1; + clnt_conf_t *conf = NULL; + rpc_clnt_procedure_t *proc = NULL; + clnt_args_t args = {0,}; + call_frame_t *frame = NULL; + + conf = this->private; + if (!conf->fops) + goto out; + + args.fd = fd; + + proc = &conf->fops->actor[GF_FOP_RELEASEDIR]; + if (proc->fn) { + frame = create_frame (this, this->ctx->pool); + if (!frame) { + goto out; + } + ret = proc->fn (frame, this, conf->fops, &args); + } +out: + return 0; +} + +int32_t +client_release (xlator_t *this, fd_t *fd) +{ + int ret = -1; + clnt_conf_t *conf = NULL; + rpc_clnt_procedure_t *proc = NULL; + clnt_args_t args = {0,}; + call_frame_t *frame = NULL; + + conf = this->private; + if (!conf->fops) + goto out; + + args.fd = fd; + proc = &conf->fops->actor[GF_FOP_RELEASE]; + if (proc->fn) { + frame = create_frame (this, this->ctx->pool); + if (!frame) { + goto out; + } + ret = proc->fn (frame, this, conf->fops, &args); + } +out: + return 0; +} + + +int32_t +client_lookup (call_frame_t *frame, xlator_t *this, loc_t *loc, + dict_t *xattr_req) +{ + int ret = -1; + clnt_conf_t *conf = NULL; + rpc_clnt_procedure_t *proc = NULL; + clnt_args_t args = {0,}; + + conf = this->private; + if (!conf->fops) + goto out; + + args.loc = loc; + args.dict = xattr_req; + + proc = &conf->fops->actor[GF_FOP_LOOKUP]; + if (proc->fn) + ret = proc->fn (frame, this, conf->fops, &args); +out: + /* think of avoiding a missing frame */ + if (ret) + STACK_UNWIND_STRICT (lookup, frame, -1, ENOTCONN, + NULL, NULL, NULL, NULL); + + return 0; +} + + +int32_t +client_stat (call_frame_t *frame, xlator_t *this, loc_t *loc) +{ + int ret = -1; + clnt_conf_t *conf = NULL; + rpc_clnt_procedure_t *proc = NULL; + clnt_args_t args = {0,}; + + conf = this->private; + if (!conf->fops) + goto out; + + args.loc = loc; + + proc = &conf->fops->actor[GF_FOP_STAT]; + if (proc->fn) + ret = proc->fn (frame, this, conf->fops, &args); +out: + if (ret) + STACK_UNWIND_STRICT (stat, frame, -1, ENOTCONN, NULL); + + + return 0; +} + + +int32_t +client_truncate (call_frame_t *frame, xlator_t *this, loc_t *loc, off_t offset) +{ + int ret = -1; + clnt_conf_t *conf = NULL; + rpc_clnt_procedure_t *proc = NULL; + clnt_args_t args = {0,}; + + conf = this->private; + if (!conf->fops) + goto out; + + args.loc = loc; + args.offset = offset; + + proc = &conf->fops->actor[GF_FOP_TRUNCATE]; + if (proc->fn) + ret = proc->fn (frame, this, conf->fops, &args); +out: + if (ret) + STACK_UNWIND_STRICT (truncate, frame, -1, ENOTCONN, NULL, NULL); + + + return 0; +} + + +int32_t +client_ftruncate (call_frame_t *frame, xlator_t *this, fd_t *fd, off_t offset) +{ + int ret = -1; + clnt_conf_t *conf = NULL; + rpc_clnt_procedure_t *proc = NULL; + clnt_args_t args = {0,}; + + conf = this->private; + if (!conf->fops) + goto out; + + args.fd = fd; + args.offset = offset; + + proc = &conf->fops->actor[GF_FOP_FTRUNCATE]; + if (proc->fn) + ret = proc->fn (frame, this, conf->fops, &args); +out: + if (ret) + STACK_UNWIND_STRICT (ftruncate, frame, -1, ENOTCONN, NULL, NULL); + + return 0; +} + + + +int32_t +client_access (call_frame_t *frame, xlator_t *this, loc_t *loc, int32_t mask) +{ + int ret = -1; + clnt_conf_t *conf = NULL; + rpc_clnt_procedure_t *proc = NULL; + clnt_args_t args = {0,}; + + conf = this->private; + if (!conf->fops) + goto out; + + args.loc = loc; + args.mask = mask; + + proc = &conf->fops->actor[GF_FOP_ACCESS]; + if (proc->fn) + ret = proc->fn (frame, this, conf->fops, &args); +out: + if (ret) + STACK_UNWIND_STRICT (access, frame, -1, ENOTCONN); + + return 0; +} + + + + +int32_t +client_readlink (call_frame_t *frame, xlator_t *this, loc_t *loc, size_t size) +{ + int ret = -1; + clnt_conf_t *conf = NULL; + rpc_clnt_procedure_t *proc = NULL; + clnt_args_t args = {0,}; + + conf = this->private; + if (!conf->fops) + goto out; + + args.loc = loc; + args.size = size; + + proc = &conf->fops->actor[GF_FOP_READLINK]; + if (proc->fn) + ret = proc->fn (frame, this, conf->fops, &args); +out: + if (ret) + STACK_UNWIND_STRICT (readlink, frame, -1, ENOTCONN, NULL, NULL); + + return 0; +} + + + +int32_t +client_mknod (call_frame_t *frame, xlator_t *this, loc_t *loc, mode_t mode, + dev_t rdev) +{ + int ret = -1; + clnt_conf_t *conf = NULL; + rpc_clnt_procedure_t *proc = NULL; + clnt_args_t args = {0,}; + + conf = this->private; + if (!conf->fops) + goto out; + + args.loc = loc; + args.mode = mode; + args.rdev = rdev; + + proc = &conf->fops->actor[GF_FOP_MKNOD]; + if (proc->fn) + ret = proc->fn (frame, this, conf->fops, &args); +out: + if (ret) + STACK_UNWIND_STRICT (mknod, frame, -1, ENOTCONN, + NULL, NULL, NULL, NULL); + + return 0; +} + + + +int32_t +client_mkdir (call_frame_t *frame, xlator_t *this, loc_t *loc, + mode_t mode) +{ + int ret = -1; + clnt_conf_t *conf = NULL; + rpc_clnt_procedure_t *proc = NULL; + clnt_args_t args = {0,}; + + conf = this->private; + if (!conf->fops) + goto out; + + args.loc = loc; + args.mode = mode; + + proc = &conf->fops->actor[GF_FOP_MKDIR]; + if (proc->fn) + ret = proc->fn (frame, this, conf->fops, &args); +out: + if (ret) + STACK_UNWIND_STRICT (mkdir, frame, -1, ENOTCONN, + NULL, NULL, NULL, NULL); + + return 0; +} + + + +int32_t +client_unlink (call_frame_t *frame, xlator_t *this, loc_t *loc) +{ + int ret = -1; + clnt_conf_t *conf = NULL; + rpc_clnt_procedure_t *proc = NULL; + clnt_args_t args = {0,}; + + conf = this->private; + if (!conf->fops) + goto out; + + args.loc = loc; + + proc = &conf->fops->actor[GF_FOP_UNLINK]; + if (proc->fn) + ret = proc->fn (frame, this, conf->fops, &args); +out: + if (ret) + STACK_UNWIND_STRICT (unlink, frame, -1, ENOTCONN, + NULL, NULL); + + return 0; +} + +int32_t +client_rmdir (call_frame_t *frame, xlator_t *this, loc_t *loc) +{ + int ret = -1; + clnt_conf_t *conf = NULL; + rpc_clnt_procedure_t *proc = NULL; + clnt_args_t args = {0,}; + + conf = this->private; + if (!conf->fops) + goto out; + + args.loc = loc; + + proc = &conf->fops->actor[GF_FOP_RMDIR]; + if (proc->fn) + ret = proc->fn (frame, this, conf->fops, &args); +out: + /* think of avoiding a missing frame */ + if (ret) + STACK_UNWIND_STRICT (rmdir, frame, -1, ENOTCONN, + NULL, NULL); + + return 0; +} + + + +int32_t +client_symlink (call_frame_t *frame, xlator_t *this, const char *linkpath, + loc_t *loc) +{ + int ret = -1; + clnt_conf_t *conf = NULL; + rpc_clnt_procedure_t *proc = NULL; + clnt_args_t args = {0,}; + + conf = this->private; + if (!conf->fops) + goto out; + + args.linkname = linkpath; + args.loc = loc; + + proc = &conf->fops->actor[GF_FOP_SYMLINK]; + if (proc->fn) + ret = proc->fn (frame, this, conf->fops, &args); +out: + if (ret) + STACK_UNWIND_STRICT (symlink, frame, -1, ENOTCONN, + NULL, NULL, NULL, NULL); + + return 0; +} + + + +int32_t +client_rename (call_frame_t *frame, xlator_t *this, loc_t *oldloc, + loc_t *newloc) +{ + int ret = -1; + clnt_conf_t *conf = NULL; + rpc_clnt_procedure_t *proc = NULL; + clnt_args_t args = {0,}; + + conf = this->private; + if (!conf->fops) + goto out; + + args.oldloc = oldloc; + args.newloc = newloc; + proc = &conf->fops->actor[GF_FOP_RENAME]; + if (proc->fn) + ret = proc->fn (frame, this, conf->fops, &args); +out: + if (ret) + STACK_UNWIND_STRICT (rename, frame, -1, ENOTCONN, + NULL, NULL, NULL, NULL, NULL); + + return 0; +} + + + +int32_t +client_link (call_frame_t *frame, xlator_t *this, loc_t *oldloc, + loc_t *newloc) +{ + int ret = -1; + clnt_conf_t *conf = NULL; + rpc_clnt_procedure_t *proc = NULL; + clnt_args_t args = {0,}; + + conf = this->private; + if (!conf->fops) + goto out; + + args.oldloc = oldloc; + args.newloc = newloc; + + proc = &conf->fops->actor[GF_FOP_LINK]; + if (proc->fn) + ret = proc->fn (frame, this, conf->fops, &args); +out: + if (ret) + STACK_UNWIND_STRICT (link, frame, -1, ENOTCONN, + NULL, NULL, NULL, NULL); + + return 0; +} + + + +int32_t +client_create (call_frame_t *frame, xlator_t *this, loc_t *loc, + int32_t flags, mode_t mode, fd_t *fd) +{ + int ret = -1; + clnt_conf_t *conf = NULL; + rpc_clnt_procedure_t *proc = NULL; + clnt_args_t args = {0,}; + + conf = this->private; + if (!conf->fops) + goto out; + + args.loc = loc; + args.flags = flags; + args.mode = mode; + args.fd = fd; + + proc = &conf->fops->actor[GF_FOP_CREATE]; + if (proc->fn) + ret = proc->fn (frame, this, conf->fops, &args); +out: + if (ret) + STACK_UNWIND_STRICT (create, frame, -1, ENOTCONN, + NULL, NULL, NULL, NULL, NULL); + + return 0; +} + + + +int32_t +client_open (call_frame_t *frame, xlator_t *this, loc_t *loc, + int32_t flags, fd_t *fd, int32_t wbflags) +{ + int ret = -1; + clnt_conf_t *conf = NULL; + rpc_clnt_procedure_t *proc = NULL; + clnt_args_t args = {0,}; + + conf = this->private; + if (!conf->fops) + goto out; + + args.loc = loc; + args.flags = flags; + args.fd = fd; + args.wbflags = wbflags; + + proc = &conf->fops->actor[GF_FOP_OPEN]; + if (proc->fn) + ret = proc->fn (frame, this, conf->fops, &args); + +out: + if (ret) + STACK_UNWIND_STRICT (open, frame, -1, ENOTCONN, NULL); + + return 0; +} + + + +int32_t +client_readv (call_frame_t *frame, xlator_t *this, fd_t *fd, size_t size, + off_t offset) +{ + int ret = -1; + clnt_conf_t *conf = NULL; + rpc_clnt_procedure_t *proc = NULL; + clnt_args_t args = {0,}; + + conf = this->private; + if (!conf->fops) + goto out; + + args.fd = fd; + args.size = size; + args.offset = offset; + + proc = &conf->fops->actor[GF_FOP_READ]; + if (proc->fn) + ret = proc->fn (frame, this, conf->fops, &args); + +out: + if (ret) + STACK_UNWIND_STRICT (readv, frame, -1, ENOTCONN, + NULL, 0, NULL, NULL); + + return 0; +} + + + + +int32_t +client_writev (call_frame_t *frame, xlator_t *this, fd_t *fd, + struct iovec *vector, int32_t count, off_t off, + struct iobref *iobref) +{ + int ret = -1; + clnt_conf_t *conf = NULL; + rpc_clnt_procedure_t *proc = NULL; + clnt_args_t args = {0,}; + + conf = this->private; + if (!conf->fops) + goto out; + + args.fd = fd; + args.vector = vector; + args.count = count; + args.offset = off; + args.iobref = iobref; + + proc = &conf->fops->actor[GF_FOP_WRITE]; + if (proc->fn) + ret = proc->fn (frame, this, conf->fops, &args); +out: + if (ret) + STACK_UNWIND_STRICT (writev, frame, -1, ENOTCONN, NULL, NULL); + + return 0; +} + + + +int32_t +client_flush (call_frame_t *frame, xlator_t *this, fd_t *fd) +{ + int ret = -1; + clnt_conf_t *conf = NULL; + rpc_clnt_procedure_t *proc = NULL; + clnt_args_t args = {0,}; + + conf = this->private; + if (!conf->fops) + goto out; + + args.fd = fd; + + proc = &conf->fops->actor[GF_FOP_FLUSH]; + if (proc->fn) + ret = proc->fn (frame, this, conf->fops, &args); +out: + if (ret) + STACK_UNWIND_STRICT (flush, frame, -1, ENOTCONN); + + return 0; +} + + + +int32_t +client_fsync (call_frame_t *frame, xlator_t *this, fd_t *fd, + int32_t flags) +{ + int ret = -1; + clnt_conf_t *conf = NULL; + rpc_clnt_procedure_t *proc = NULL; + clnt_args_t args = {0,}; + + conf = this->private; + if (!conf->fops) + goto out; + + args.fd = fd; + args.flags = flags; + + proc = &conf->fops->actor[GF_FOP_FSYNC]; + if (proc->fn) + ret = proc->fn (frame, this, conf->fops, &args); +out: + if (ret) + STACK_UNWIND_STRICT (fsync, frame, -1, ENOTCONN, NULL, NULL); + + return 0; +} + + + +int32_t +client_fstat (call_frame_t *frame, xlator_t *this, fd_t *fd) +{ + int ret = -1; + clnt_conf_t *conf = NULL; + rpc_clnt_procedure_t *proc = NULL; + clnt_args_t args = {0,}; + + conf = this->private; + if (!conf->fops) + goto out; + + args.fd = fd; + + proc = &conf->fops->actor[GF_FOP_FSTAT]; + if (proc->fn) + ret = proc->fn (frame, this, conf->fops, &args); +out: + if (ret) + STACK_UNWIND_STRICT (fstat, frame, -1, ENOTCONN, NULL); + + return 0; +} + + + +int32_t +client_opendir (call_frame_t *frame, xlator_t *this, loc_t *loc, fd_t *fd) +{ + int ret = -1; + clnt_conf_t *conf = NULL; + rpc_clnt_procedure_t *proc = NULL; + clnt_args_t args = {0,}; + + conf = this->private; + if (!conf->fops) + goto out; + + args.loc = loc; + args.fd = fd; + + proc = &conf->fops->actor[GF_FOP_OPENDIR]; + if (proc->fn) + ret = proc->fn (frame, this, conf->fops, &args); +out: + if (ret) + STACK_UNWIND_STRICT (opendir, frame, -1, ENOTCONN, NULL); + + return 0; +} + + + +int32_t +client_fsyncdir (call_frame_t *frame, xlator_t *this, fd_t *fd, int32_t flags) +{ + int ret = -1; + clnt_conf_t *conf = NULL; + rpc_clnt_procedure_t *proc = NULL; + clnt_args_t args = {0,}; + + conf = this->private; + if (!conf->fops) + goto out; + + args.fd = fd; + args.flags = flags; + + proc = &conf->fops->actor[GF_FOP_FSYNCDIR]; + if (proc->fn) + ret = proc->fn (frame, this, conf->fops, &args); +out: + if (ret) + STACK_UNWIND_STRICT (fsyncdir, frame, -1, ENOTCONN); + + return 0; +} + + + +int32_t +client_statfs (call_frame_t *frame, xlator_t *this, loc_t *loc) +{ + int ret = -1; + clnt_conf_t *conf = NULL; + rpc_clnt_procedure_t *proc = NULL; + clnt_args_t args = {0,}; + + conf = this->private; + if (!conf->fops) + goto out; + + args.loc = loc; + + proc = &conf->fops->actor[GF_FOP_STATFS]; + if (proc->fn) + ret = proc->fn (frame, this, conf->fops, &args); +out: + if (ret) + STACK_UNWIND_STRICT (statfs, frame, -1, ENOTCONN, NULL); + + return 0; +} + + + +int32_t +client_setxattr (call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *dict, + int32_t flags) +{ + int ret = -1; + clnt_conf_t *conf = NULL; + rpc_clnt_procedure_t *proc = NULL; + clnt_args_t args = {0,}; + + conf = this->private; + if (!conf->fops) + goto out; + + args.loc = loc; + args.dict = dict; + args.flags = flags; + + proc = &conf->fops->actor[GF_FOP_SETXATTR]; + if (proc->fn) + ret = proc->fn (frame, this, conf->fops, &args); +out: + if (ret) + STACK_UNWIND_STRICT (setxattr, frame, -1, ENOTCONN); + + return 0; +} + + + +int32_t +client_fsetxattr (call_frame_t *frame, xlator_t *this, fd_t *fd, + dict_t *dict, int32_t flags) +{ + int ret = -1; + clnt_conf_t *conf = NULL; + rpc_clnt_procedure_t *proc = NULL; + clnt_args_t args = {0,}; + + conf = this->private; + if (!conf->fops) + goto out; + + args.fd = fd; + args.dict = dict; + args.flags = flags; + + proc = &conf->fops->actor[GF_FOP_FSETXATTR]; + if (proc->fn) + ret = proc->fn (frame, this, conf->fops, &args); +out: + if (ret) + STACK_UNWIND_STRICT (fsetxattr, frame, -1, ENOTCONN); + + return 0; +} + + + + +int32_t +client_fgetxattr (call_frame_t *frame, xlator_t *this, fd_t *fd, + const char *name) +{ + int ret = -1; + clnt_conf_t *conf = NULL; + rpc_clnt_procedure_t *proc = NULL; + clnt_args_t args = {0,}; + + conf = this->private; + if (!conf->fops) + goto out; + + args.fd = fd; + args.name = name; + + proc = &conf->fops->actor[GF_FOP_FGETXATTR]; + if (proc->fn) + ret = proc->fn (frame, this, conf->fops, &args); +out: + if (ret) + STACK_UNWIND_STRICT (fgetxattr, frame, -1, ENOTCONN, NULL); + + return 0; +} + + + +int32_t +client_getxattr (call_frame_t *frame, xlator_t *this, loc_t *loc, + const char *name) +{ + int ret = -1; + clnt_conf_t *conf = NULL; + rpc_clnt_procedure_t *proc = NULL; + clnt_args_t args = {0,}; + + conf = this->private; + if (!conf->fops) + goto out; + + args.name = name; + args.loc = loc; + + proc = &conf->fops->actor[GF_FOP_GETXATTR]; + if (proc->fn) + ret = proc->fn (frame, this, conf->fops, &args); +out: + if (ret) + STACK_UNWIND_STRICT (getxattr, frame, -1, ENOTCONN, NULL); + + return 0; +} + + + +int32_t +client_xattrop (call_frame_t *frame, xlator_t *this, loc_t *loc, + gf_xattrop_flags_t flags, dict_t *dict) +{ + int ret = -1; + clnt_conf_t *conf = NULL; + rpc_clnt_procedure_t *proc = NULL; + clnt_args_t args = {0,}; + + conf = this->private; + if (!conf->fops) + goto out; + + args.loc = loc; + args.flags = flags; + args.dict = dict; + + proc = &conf->fops->actor[GF_FOP_XATTROP]; + if (proc->fn) + ret = proc->fn (frame, this, conf->fops, &args); +out: + if (ret) + STACK_UNWIND_STRICT (xattrop, frame, -1, ENOTCONN, NULL); + + return 0; +} + + + +int32_t +client_fxattrop (call_frame_t *frame, xlator_t *this, fd_t *fd, + gf_xattrop_flags_t flags, dict_t *dict) +{ + int ret = -1; + clnt_conf_t *conf = NULL; + rpc_clnt_procedure_t *proc = NULL; + clnt_args_t args = {0,}; + + conf = this->private; + if (!conf->fops) + goto out; + + args.fd = fd; + args.flags = flags; + args.dict = dict; + + proc = &conf->fops->actor[GF_FOP_FXATTROP]; + if (proc->fn) + ret = proc->fn (frame, this, conf->fops, &args); +out: + if (ret) + STACK_UNWIND_STRICT (fxattrop, frame, -1, ENOTCONN, NULL); + + return 0; +} + + + +int32_t +client_removexattr (call_frame_t *frame, xlator_t *this, loc_t *loc, + const char *name) +{ + int ret = -1; + clnt_conf_t *conf = NULL; + rpc_clnt_procedure_t *proc = NULL; + clnt_args_t args = {0,}; + + conf = this->private; + if (!conf->fops) + goto out; + + args.name = name; + args.loc = loc; + + proc = &conf->fops->actor[GF_FOP_REMOVEXATTR]; + if (proc->fn) + ret = proc->fn (frame, this, conf->fops, &args); +out: + if (ret) + STACK_UNWIND_STRICT (removexattr, frame, -1, ENOTCONN); + + return 0; +} + + +int32_t +client_lk (call_frame_t *frame, xlator_t *this, fd_t *fd, int32_t cmd, + struct flock *lock) +{ + int ret = -1; + clnt_conf_t *conf = NULL; + rpc_clnt_procedure_t *proc = NULL; + clnt_args_t args = {0,}; + + conf = this->private; + if (!conf->fops) + goto out; + + args.fd = fd; + args.cmd = cmd; + args.flock = lock; + + proc = &conf->fops->actor[GF_FOP_LK]; + if (proc->fn) + ret = proc->fn (frame, this, conf->fops, &args); +out: + if (ret) + STACK_UNWIND_STRICT (lk, frame, -1, ENOTCONN, NULL); + + return 0; +} + + +int32_t +client_inodelk (call_frame_t *frame, xlator_t *this, const char *volume, + loc_t *loc, int32_t cmd, struct flock *lock) +{ + int ret = -1; + clnt_conf_t *conf = NULL; + rpc_clnt_procedure_t *proc = NULL; + clnt_args_t args = {0,}; + + conf = this->private; + if (!conf->fops) + goto out; + + args.loc = loc; + args.cmd = cmd; + args.flock = lock; + args.volume = volume; + + proc = &conf->fops->actor[GF_FOP_INODELK]; + if (proc->fn) + ret = proc->fn (frame, this, conf->fops, &args); +out: + if (ret) + STACK_UNWIND_STRICT (inodelk, frame, -1, ENOTCONN); + + return 0; +} + + + +int32_t +client_finodelk (call_frame_t *frame, xlator_t *this, const char *volume, + fd_t *fd, int32_t cmd, struct flock *lock) +{ + int ret = -1; + clnt_conf_t *conf = NULL; + rpc_clnt_procedure_t *proc = NULL; + clnt_args_t args = {0,}; + + conf = this->private; + if (!conf->fops) + goto out; + + args.fd = fd; + args.cmd = cmd; + args.flock = lock; + args.volume = volume; + + proc = &conf->fops->actor[GF_FOP_FINODELK]; + if (proc->fn) + ret = proc->fn (frame, this, conf->fops, &args); +out: + if (ret) + STACK_UNWIND_STRICT (finodelk, frame, -1, ENOTCONN); + + return 0; +} + + +int32_t +client_entrylk (call_frame_t *frame, xlator_t *this, const char *volume, + loc_t *loc, const char *basename, entrylk_cmd cmd, + entrylk_type type) +{ + int ret = -1; + clnt_conf_t *conf = NULL; + rpc_clnt_procedure_t *proc = NULL; + clnt_args_t args = {0,}; + + conf = this->private; + if (!conf->fops) + goto out; + + args.loc = loc; + args.basename = basename; + args.type = type; + args.volume = volume; + args.cmd_entrylk = cmd; + + proc = &conf->fops->actor[GF_FOP_ENTRYLK]; + if (proc->fn) + ret = proc->fn (frame, this, conf->fops, &args); +out: + if (ret) + STACK_UNWIND_STRICT (entrylk, frame, -1, ENOTCONN); + + return 0; +} + + + +int32_t +client_fentrylk (call_frame_t *frame, xlator_t *this, const char *volume, + fd_t *fd, const char *basename, entrylk_cmd cmd, + entrylk_type type) +{ + int ret = -1; + clnt_conf_t *conf = NULL; + rpc_clnt_procedure_t *proc = NULL; + clnt_args_t args = {0,}; + + conf = this->private; + if (!conf->fops) + goto out; + + args.fd = fd; + args.basename = basename; + args.type = type; + args.volume = volume; + args.cmd_entrylk = cmd; + + proc = &conf->fops->actor[GF_FOP_FENTRYLK]; + if (proc->fn) + ret = proc->fn (frame, this, conf->fops, &args); +out: + if (ret) + STACK_UNWIND_STRICT (fentrylk, frame, -1, ENOTCONN); + + return 0; +} + + +int32_t +client_checksum (call_frame_t *frame, xlator_t *this, loc_t *loc, + int32_t flag) +{ + int ret = -1; + clnt_conf_t *conf = NULL; + rpc_clnt_procedure_t *proc = NULL; + clnt_args_t args = {0,}; + + conf = this->private; + if (!conf->fops) + goto out; + + args.loc = loc; + args.flags = flag; + + proc = &conf->fops->actor[GF_FOP_CHECKSUM]; + if (proc->fn) + ret = proc->fn (frame, this, conf->fops, &args); +out: + if (ret) + STACK_UNWIND_STRICT (checksum, frame, -1, ENOTCONN, NULL, NULL); + + return 0; +} + + + +int32_t +client_rchecksum (call_frame_t *frame, xlator_t *this, fd_t *fd, off_t offset, + int32_t len) +{ + int ret = -1; + clnt_conf_t *conf = NULL; + rpc_clnt_procedure_t *proc = NULL; + clnt_args_t args = {0,}; + + conf = this->private; + if (!conf->fops) + goto out; + + args.fd = fd; + args.offset = offset; + args.len = len; + + proc = &conf->fops->actor[GF_FOP_RCHECKSUM]; + if (proc->fn) + ret = proc->fn (frame, this, conf->fops, &args); +out: + if (ret) + STACK_UNWIND_STRICT (rchecksum, frame, -1, ENOTCONN, 0, NULL); + + return 0; +} + +int32_t +client_readdir (call_frame_t *frame, xlator_t *this, fd_t *fd, + size_t size, off_t off) +{ + int ret = -1; + clnt_conf_t *conf = NULL; + rpc_clnt_procedure_t *proc = NULL; + clnt_args_t args = {0,}; + + conf = this->private; + if (!conf->fops) + goto out; + + args.fd = fd; + args.size = size; + args.offset = off; + + proc = &conf->fops->actor[GF_FOP_READDIR]; + if (proc->fn) + ret = proc->fn (frame, this, conf->fops, &args); +out: + if (ret) + STACK_UNWIND_STRICT (readdir, frame, -1, ENOTCONN, NULL); + + return 0; +} + + +int32_t +client_readdirp (call_frame_t *frame, xlator_t *this, fd_t *fd, + size_t size, off_t off) +{ + int ret = -1; + clnt_conf_t *conf = NULL; + rpc_clnt_procedure_t *proc = NULL; + clnt_args_t args = {0,}; + + conf = this->private; + if (!conf->fops) + goto out; + + args.fd = fd; + args.size = size; + args.offset = off; + + proc = &conf->fops->actor[GF_FOP_READDIRP]; + if (proc->fn) + ret = proc->fn (frame, this, conf->fops, &args); +out: + if (ret) + STACK_UNWIND_STRICT (readdirp, frame, -1, ENOTCONN, NULL); + + return 0; +} + + +int32_t +client_setattr (call_frame_t *frame, xlator_t *this, loc_t *loc, + struct iatt *stbuf, int32_t valid) +{ + int ret = -1; + clnt_conf_t *conf = NULL; + rpc_clnt_procedure_t *proc = NULL; + clnt_args_t args = {0,}; + + conf = this->private; + if (!conf->fops) + goto out; + + args.loc = loc; + args.stbuf = stbuf; + args.valid = valid; + + proc = &conf->fops->actor[GF_FOP_SETATTR]; + if (proc->fn) + ret = proc->fn (frame, this, conf->fops, &args); +out: + if (ret) + STACK_UNWIND_STRICT (setattr, frame, -1, ENOTCONN, NULL, NULL); + + return 0; +} + +int32_t +client_fsetattr (call_frame_t *frame, xlator_t *this, fd_t *fd, + struct iatt *stbuf, int32_t valid) +{ + int ret = -1; + clnt_conf_t *conf = NULL; + rpc_clnt_procedure_t *proc = NULL; + clnt_args_t args = {0,}; + + conf = this->private; + if (!conf->fops) + goto out; + + args.fd = fd; + args.stbuf = stbuf; + args.valid = valid; + + proc = &conf->fops->actor[GF_FOP_FSETATTR]; + if (proc->fn) + ret = proc->fn (frame, this, conf->fops, &args); +out: + if (ret) + STACK_UNWIND_STRICT (fsetattr, frame, -1, ENOTCONN, NULL, NULL); + + return 0; +} + +///////////////// +int32_t +client_getspec (call_frame_t *frame, xlator_t *this, const char *key, + int32_t flags) +{ + int ret = -1; + clnt_conf_t *conf = NULL; + gf_getspec_req req = {0,}; + + conf = this->private; + if (!conf->handshake) + goto out; + + req.key = (char *)key; + req.flags = flags; + + client_submit_request (this, &req, frame, conf->handshake, + GF_HNDSK_GETSPEC, NULL, xdr_from_getspec_req); + ret = 0; +out: + if (ret) + STACK_UNWIND_STRICT (getspec, frame, -1, EINVAL, NULL); + + return 0; +} + + + int +client_mark_fd_bad (xlator_t *this) +{ + clnt_conf_t *conf = NULL; + clnt_fd_ctx_t *tmp = NULL, *fdctx = NULL; + + conf = this->private; + + pthread_mutex_lock (&conf->lock); + { + list_for_each_entry_safe (fdctx, tmp, &conf->saved_fds, + sfd_pos) { + fdctx->remote_fd = -1; + } + } + pthread_mutex_unlock (&conf->lock); + + return 0; +} + + +int +client_rpc_notify (struct rpc_clnt *rpc, void *mydata, rpc_clnt_event_t event, + void *data) +{ + xlator_t *this = NULL; + char *handshake = NULL; + clnt_conf_t *conf = NULL; + int ret = 0; + + this = mydata; + conf = this->private; + + switch (event) { + case RPC_CLNT_CONNECT: + { + // connect happened, send 'get_supported_versions' mop + ret = dict_get_str (this->options, "disable-handshake", + &handshake); + + gf_log (this->name, GF_LOG_TRACE, "got RPC_CLNT_CONNECT"); + + if ((ret < 0) || (strcasecmp (handshake, "on"))) { + ret = client_handshake (this, conf->rpc); + + } else { + //conf->rpc->connected = 1; + ret = default_notify (this, GF_EVENT_CHILD_UP, NULL); + } + break; + } + case RPC_CLNT_DISCONNECT: + + client_mark_fd_bad (this); + + gf_log (this->name, GF_LOG_TRACE, "got RPC_CLNT_DISCONNECT"); + + default_notify (this, GF_EVENT_CHILD_DOWN, NULL); + break; + + default: + gf_log (this->name, GF_LOG_TRACE, + "got some other RPC event %d", event); + + break; + } + + return 0; +} + + +int +notify (xlator_t *this, int32_t event, void *data, ...) +{ + clnt_conf_t *conf = NULL; + void *trans = NULL; + + conf = this->private; + + switch (event) { + case GF_EVENT_PARENT_UP: + { + if (conf->rpc) + trans = conf->rpc->conn.trans; + + if (!trans) { + gf_log (this->name, GF_LOG_DEBUG, + "transport init failed"); + return 0; + } + + gf_log (this->name, GF_LOG_DEBUG, + "got GF_EVENT_PARENT_UP, attempting connect " + "on transport"); + + rpc_clnt_reconnect (trans); + } + break; + + default: + gf_log (this->name, GF_LOG_DEBUG, + "got %d, calling default_notify ()", event); + + default_notify (this, event, data); + break; + } + + return 0; +} + +int +build_client_config (xlator_t *this, clnt_conf_t *conf) +{ + int ret = 0; + + ret = dict_get_str (this->options, "remote-subvolume", + &conf->opt.remote_subvolume); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, + "option 'remote-subvolume' not given"); + goto out; + } + + ret = dict_get_int32 (this->options, "frame-timeout", + &conf->rpc_conf.rpc_timeout); + if (ret >= 0) { + gf_log (this->name, GF_LOG_DEBUG, + "setting frame-timeout to %d", + conf->rpc_conf.rpc_timeout); + } else { + gf_log (this->name, GF_LOG_DEBUG, + "defaulting frame-timeout to 30mins"); + conf->rpc_conf.rpc_timeout = 1800; + } + + ret = dict_get_int32 (this->options, "remote-port", + &conf->rpc_conf.remote_port); + if (ret >= 0) { + gf_log (this->name, GF_LOG_DEBUG, + "remote-port is %d", conf->rpc_conf.remote_port); + } else { + gf_log (this->name, GF_LOG_DEBUG, + "defaulting remote-port to %d", + GF_PROTOCOL_DEFAULT_PORT); + conf->rpc_conf.remote_port = GF_PROTOCOL_DEFAULT_PORT; + } + + ret = dict_get_int32 (this->options, "ping-timeout", + &conf->opt.ping_timeout); + if (ret >= 0) { + gf_log (this->name, GF_LOG_DEBUG, + "setting ping-timeout to %d", conf->opt.ping_timeout); + } else { + gf_log (this->name, GF_LOG_DEBUG, + "defaulting ping-timeout to 42"); + conf->opt.ping_timeout = GF_UNIVERSAL_ANSWER; + } + + ret = 0; +out: + return ret;} + + +static int32_t +mem_acct_init (xlator_t *this) +{ + int ret = -1; + + if (!this) + return ret; + + ret = xlator_mem_acct_init (this, gf_client_mt_end + 1); + + if (ret != 0) { + gf_log (this->name, GF_LOG_ERROR, "Memory accounting init" + "failed"); + return ret; + } + + return ret; +} + + +int +init (xlator_t *this) +{ + int ret = -1; + clnt_conf_t *conf = NULL; + + /* */ + if (this->children) { + gf_log (this->name, GF_LOG_ERROR, + "FATAL: client protocol translator cannot have any " + "subvolumes"); + goto out; + } + + if (!this->parents) { + gf_log (this->name, GF_LOG_WARNING, + "Volume is dangling. "); + } + + ret = mem_acct_init (this); + if (ret) + goto out; + + conf = GF_CALLOC (1, sizeof (*conf), gf_client_mt_clnt_conf_t); + if (!conf) + goto out; + + pthread_mutex_init (&conf->lock, NULL); + INIT_LIST_HEAD (&conf->saved_fds); + + ret = build_client_config (this, conf); + if (ret) + goto out; + + conf->rpc = rpc_clnt_init (&conf->rpc_conf, this->options, this->ctx, + this->name); + if (!conf->rpc) + goto out; + conf->rpc->xid = 42; /* It should be enough random everytime :O */ + ret = rpc_clnt_register_notify (conf->rpc, client_rpc_notify, this); + if (ret) + goto out; + + conf->handshake = &clnt_handshake_prog; + this->private = conf; + + ret = 0; +out: + if (ret) + this->fini (this); + + return ret; +} + +void +fini (xlator_t *this) +{ + clnt_conf_t *conf = NULL; + + conf = this->private; + this->private = NULL; + + if (conf) { + if (conf->rpc) + rpc_clnt_destroy (conf->rpc); + + /* Saved Fds */ + /* TODO: */ + + pthread_mutex_destroy (&conf->lock); + + GF_FREE (conf); + } + return; +} + +int +client_priv_dump (xlator_t *this) +{ + clnt_conf_t *conf = NULL; + int ret = -1; + clnt_fd_ctx_t *tmp = NULL; + int i = 0; + char key[GF_DUMP_MAX_BUF_LEN]; + char key_prefix[GF_DUMP_MAX_BUF_LEN]; + + if (!this) + return -1; + + conf = this->private; + if (!conf) { + gf_log (this->name, GF_LOG_WARNING, + "conf null in xlator"); + return -1; + } + + ret = pthread_mutex_trylock(&conf->lock); + if (ret) { + gf_log("", GF_LOG_WARNING, "Unable to lock client %s" + " errno: %d", this->name, errno); + return -1; + } + + gf_proc_dump_build_key(key_prefix, "xlator.protocol.client", + "%s.priv", this->name); + + gf_proc_dump_add_section(key_prefix); + + list_for_each_entry(tmp, &conf->saved_fds, sfd_pos) { + gf_proc_dump_build_key(key, key_prefix, + "fd.%d.remote_fd", ++i); + gf_proc_dump_write(key, "%d", tmp->remote_fd); + } + + gf_proc_dump_build_key(key, key_prefix, "connecting"); + gf_proc_dump_write(key, "%d", conf->connecting); + gf_proc_dump_build_key(key, key_prefix, "last_sent"); + gf_proc_dump_write(key, "%s", ctime(&conf->last_sent.tv_sec)); + gf_proc_dump_build_key(key, key_prefix, "last_received"); + gf_proc_dump_write(key, "%s", ctime(&conf->last_received.tv_sec)); + + pthread_mutex_unlock(&conf->lock); + + return 0; + +} + +int32_t +client_inodectx_dump (xlator_t *this, inode_t *inode) +{ + ino_t par = 0; + uint64_t gen = 0; + int ret = -1; + char key[GF_DUMP_MAX_BUF_LEN]; + + if (!inode) + return -1; + + if (!this) + return -1; + + ret = inode_ctx_get2 (inode, this, &par, &gen); + + if (ret != 0) + return ret; + + gf_proc_dump_build_key(key, "xlator.protocol.client", + "%s.inode.%ld.par", + this->name,inode->ino); + gf_proc_dump_write(key, "%ld, %ld", par, gen); + + return 0; +} + + + + +struct xlator_cbks cbks = { + .forget = client_forget, + .release = client_release, + .releasedir = client_releasedir +}; + +struct xlator_fops fops = { + .stat = client_stat, + .readlink = client_readlink, + .mknod = client_mknod, + .mkdir = client_mkdir, + .unlink = client_unlink, + .rmdir = client_rmdir, + .symlink = client_symlink, + .rename = client_rename, + .link = client_link, + .truncate = client_truncate, + .open = client_open, + .readv = client_readv, + .writev = client_writev, + .statfs = client_statfs, + .flush = client_flush, + .fsync = client_fsync, + .setxattr = client_setxattr, + .getxattr = client_getxattr, + .fsetxattr = client_fsetxattr, + .fgetxattr = client_fgetxattr, + .removexattr = client_removexattr, + .opendir = client_opendir, + .readdir = client_readdir, + .readdirp = client_readdirp, + .fsyncdir = client_fsyncdir, + .access = client_access, + .ftruncate = client_ftruncate, + .fstat = client_fstat, + .create = client_create, + .lk = client_lk, + .inodelk = client_inodelk, + .finodelk = client_finodelk, + .entrylk = client_entrylk, + .fentrylk = client_fentrylk, + .lookup = client_lookup, + .checksum = client_checksum, + .rchecksum = client_rchecksum, + .xattrop = client_xattrop, + .fxattrop = client_fxattrop, + .setattr = client_setattr, + .fsetattr = client_fsetattr, + .getspec = client_getspec, +}; + + +struct xlator_dumpops dumpops = { + .priv = client_priv_dump, + .inodectx = client_inodectx_dump, +}; + + +struct volume_options options[] = { + { .key = {"username"}, + .type = GF_OPTION_TYPE_ANY + }, + { .key = {"password"}, + .type = GF_OPTION_TYPE_ANY + }, + { .key = {"transport-type"}, + .value = {"tcp", "socket", "ib-verbs", "unix", "ib-sdp", + "tcp/client", "ib-verbs/client"}, + .type = GF_OPTION_TYPE_STR + }, + { .key = {"remote-host"}, + .type = GF_OPTION_TYPE_INTERNET_ADDRESS + }, + { .key = {"remote-subvolume"}, + .type = GF_OPTION_TYPE_ANY + }, + { .key = {"frame-timeout", + "rpc-timeout" }, + .type = GF_OPTION_TYPE_TIME, + .min = 0, + .max = 86400, + }, + { .key = {"ping-timeout"}, + .type = GF_OPTION_TYPE_TIME, + .min = 1, + .max = 1013, + }, + { .key = {NULL} }, +}; -- cgit