/*
Copyright (c) 2010 Gluster, Inc. <http://www.gluster.com>
This file is part of GlusterFS.
GlusterFS is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published
by the Free Software Foundation; either version 3 of the License,
or (at your option) any later version.
GlusterFS is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see
<http://www.gnu.org/licenses/>.
*/
#ifndef _CONFIG_H
#define _CONFIG_H
#include "config.h"
#endif
#include "client.h"
#include "glusterfs3-xdr.h"
#include "glusterfs3.h"
#include "compat-errno.h"
int32_t client3_getspec (call_frame_t *frame, xlator_t *this, void *data);
void client_start_ping (void *data);
rpc_clnt_prog_t clnt3_1_fop_prog;
int
client_submit_vec_request (xlator_t *this, void *req, call_frame_t *frame,
rpc_clnt_prog_t *prog, int procnum, fop_cbk_fn_t cbk,
struct iovec *payload, int payloadcnt,
struct iobref *iobref, gfs_serialize_t sfunc)
{
int ret = 0;
clnt_conf_t *conf = NULL;
struct iovec iov = {0, };
struct iobuf *iobuf = NULL;
int count = 0;
char new_iobref = 0;
int start_ping = 0;
start_ping = 0;
conf = this->private;
iobuf = iobuf_get (this->ctx->iobuf_pool);
if (!iobuf) {
goto out;
};
if (!iobref) {
iobref = iobref_new ();
if (!iobref) {
goto out;
}
new_iobref = 1;
}
iobref_add (iobref, iobuf);
iov.iov_base = iobuf->ptr;
iov.iov_len = 128 * GF_UNIT_KB;
/* Create the xdr payload */
if (req && sfunc) {
ret = sfunc (iov, req);
if (ret == -1) {
goto out;
}
iov.iov_len = ret;
count = 1;
}
/* Send the msg */
ret = rpc_clnt_submit (conf->rpc, prog, procnum, cbk, &iov, count,
payload, payloadcnt, iobref, frame, NULL, 0,
NULL, 0, NULL);
if (ret == 0) {
pthread_mutex_lock (&conf->rpc->conn.lock);
{
if (!conf->rpc->conn.ping_started) {
start_ping = 1;
}
}
pthread_mutex_unlock (&conf->rpc->conn.lock);
}
if (start_ping)
client_start_ping ((void *) this);
out:
if (new_iobref) {
iobref_unref (iobref);
}
iobuf_unref (iobuf);
return 0;
}
/* CBK */
int
client3_1_symlink_cbk (struct rpc_req *req, struct iovec *iov, int count,
void *myframe)
{
call_frame_t *frame = NULL;
gfs3_symlink_rsp rsp = {0,};
struct iatt stbuf = {0,};
struct iatt preparent = {0,};
struct iatt postparent = {0,};
int ret = 0;
clnt_local_t *local = NULL;
inode_t *inode = NULL;
frame = myframe;
local = frame->local;
frame->local = NULL;
inode = local->loc.inode;
if (-1 == req->rpc_status) {
rsp.op_ret = -1;
rsp.op_errno = ENOTCONN;
goto out;
}
ret = xdr_to_symlink_rsp (*iov, &rsp);
if (ret < 0) {
gf_log ("", GF_LOG_ERROR, "error");
rsp.op_ret = -1;
rsp.op_errno = EINVAL;
goto out;
}
if (-1 != rsp.op_ret) {
gf_stat_to_iatt (&rsp.stat, &stbuf);
ret = inode_ctx_put2 (inode, frame->this,
stbuf.ia_ino, stbuf.ia_gen);
if (ret < 0) {
gf_log (frame->this->name, GF_LOG_DEBUG,
"SYMLINK %"PRId64"/%s (%s): failed to set "
"remote inode number to inode ctx",
local->loc.parent->ino, local->loc.name,
local->loc.path);
}
gf_stat_to_iatt (&rsp.preparent, &preparent);
gf_stat_to_iatt (&rsp.postparent, &postparent);
}
out:
frame->local = NULL;
STACK_UNWIND_STRICT (symlink, frame, rsp.op_ret,
gf_error_to_errno (rsp.op_errno), inode, &stbuf,
&preparent, &postparent);
if (local)
client_local_wipe (local);
return 0;
}
int
client3_1_mknod_cbk (struct rpc_req *req, struct iovec *iov, int count,
void *myframe)
{
call_frame_t *frame = NULL;
gfs3_mknod_rsp rsp = {0,};
struct iatt stbuf = {0,};
struct iatt preparent = {0,};
struct iatt postparent = {0,};
int ret = 0;
clnt_local_t *local = NULL;
inode_t *inode = NULL;
frame = myframe;
local = frame->local;
frame->local = NULL;
inode = local->loc.inode;
if (-1 == req->rpc_status) {
rsp.op_ret = -1;
rsp.op_errno = ENOTCONN;
goto out;
}
ret = xdr_to_mknod_rsp (*iov, &rsp);
if (ret < 0) {
gf_log ("", GF_LOG_ERROR, "error");
rsp.op_ret = -1;
rsp.op_errno = EINVAL;
goto out;
}
if (-1 != rsp.op_ret) {
gf_stat_to_iatt (&rsp.stat, &stbuf);
ret = inode_ctx_put2 (inode, frame->this,
stbuf.ia_ino, stbuf.ia_gen);
if (ret < 0) {
gf_log (frame->this->name, GF_LOG_DEBUG,
"MKNOD %"PRId64"/%s (%s): failed to set "
"remote inode number to inode ctx",
local->loc.parent->ino, local->loc.name,
local->loc.path);
}
gf_stat_to_iatt (&rsp.preparent, &preparent);
gf_stat_to_iatt (&rsp.postparent, &postparent);
}
out:
frame->local = NULL;
STACK_UNWIND_STRICT (mknod, frame, rsp.op_ret,
gf_error_to_errno (rsp.op_errno), inode,
&stbuf, &preparent, &postparent);
if (local)
client_local_wipe (local);
return 0;
}
int
client3_1_mkdir_cbk (struct rpc_req *req, struct iovec *iov, int count,
void *myframe)
{
call_frame_t *frame = NULL;
gfs3_mkdir_rsp rsp = {0,};
struct iatt stbuf = {0,};
struct iatt preparent = {0,};
struct iatt postparent = {0,};
int ret = 0;
clnt_local_t *local = NULL;
inode_t *inode = NULL;
frame = myframe;
local = frame->local;
frame->local = NULL;
inode = local->loc.inode;
if (-1 == req->rpc_status) {
rsp.op_ret = -1;
rsp.op_errno = ENOTCONN;
goto out;
}
ret = xdr_to_mkdir_rsp (*iov, &rsp);
if (ret < 0) {
gf_log ("", GF_LOG_ERROR, "error");
rsp.op_ret = -1;
rsp.op_errno = EINVAL;
goto out;
}
if (-1 != rsp.op_ret) {
gf_stat_to_iatt (&rsp.stat, &stbuf);
ret = inode_ctx_put2 (inode, frame->this,
stbuf.ia_ino, stbuf.ia_gen);
if (ret < 0) {
gf_log (frame->this->name, GF_LOG_DEBUG,
"MKDIR %"PRId64"/%s (%s): failed to set "
"remote inode number to inode ctx",
local->loc.parent->ino, local->loc.name,
local->loc.path);
}
gf_stat_to_iatt (&rsp.preparent, &preparent);
gf_stat_to_iatt (&rsp.postparent, &postparent);
}
out:
STACK_UNWIND_STRICT (mkdir, frame, rsp.op_ret,
gf_error_to_errno (rsp.op_errno), inode,
&stbuf, &preparent, &postparent);
if (local)
client_local_wipe (local);
return 0;
}
int
client3_1_open_cbk (struct rpc_req *req, struct iovec *iov, int count,
void *myframe)
{
clnt_local_t *local = NULL;
clnt_conf_t *conf = NULL;
clnt_fd_ctx_t *fdctx = NULL;
call_frame_t *frame = NULL;
fd_t *fd = NULL;
ino_t ino = 0;
uint64_t gen = 0;
int ret = 0;
gfs3_open_rsp rsp = {0,};
frame = myframe;
local = frame->local;
if (local->op) {
local->op (req, iov, 1, myframe);
return 0;
}
frame->local = NULL;
conf = frame->this->private;
fd = local->fd;
if (-1 == req->rpc_status) {
rsp.op_ret = -1;
rsp.op_errno = ENOTCONN;
goto out;
}
ret = xdr_to_open_rsp (*iov, &rsp);
if (ret < 0) {
gf_log ("", GF_LOG_ERROR, "error");
rsp.op_ret = -1;
rsp.op_errno = EINVAL;
goto out;
}
if (-1 != rsp.op_ret) {
fdctx = GF_CALLOC (1, sizeof (*fdctx),
gf_client_mt_clnt_fdctx_t);
if (!fdctx) {
rsp.op_ret = -1;
rsp.op_errno = ENOMEM;
goto out;
}
inode_ctx_get2 (fd->inode, frame->this, &ino, &gen);
fdctx->remote_fd = rsp.fd;
fdctx->inode = inode_ref (fd->inode);
fdctx->ino = ino;
fdctx->gen = gen;
fdctx->flags = local->flags;
fdctx->wbflags = local->wbflags;
INIT_LIST_HEAD (&fdctx->sfd_pos);
this_fd_set_ctx (fd, frame->this, &local->loc, fdctx);
pthread_mutex_lock (&conf->lock);
{
list_add_tail (&fdctx->sfd_pos, &conf->saved_fds);
}
pthread_mutex_unlock (&conf->lock);
}
out:
frame->local = NULL;
STACK_UNWIND_STRICT (open, frame, rsp.op_ret,
gf_error_to_errno (rsp.op_errno), fd);
client_local_wipe (local);
return 0;
}
int
client3_1_stat_cbk (struct rpc_req *req, struct iovec *iov, int count,
void *myframe)
{
gfs3_stat_rsp rsp = {0,};
call_frame_t *frame = NULL;
struct iatt iatt = {0,};
int ret = 0;
frame = myframe;
if (-1 == req->rpc_status) {
rsp.op_ret = -1;
rsp.op_errno = ENOTCONN;
goto out;
}
ret = xdr_to_stat_rsp (*iov, &rsp);
if (ret < 0) {
gf_log ("", GF_LOG_ERROR, "error");
rsp.op_ret = -1;
rsp.op_errno = EINVAL;
goto out;
}
if (-1 != rsp.op_ret) {
gf_stat_to_iatt (&rsp.stat, &iatt);
}
out:
STACK_UNWIND_STRICT (stat, frame, rsp.op_ret,
gf_error_to_errno (rsp.op_errno), &iatt);
return 0;
}
int
client3_1_readlink_cbk (struct rpc_req *req, struct iovec *iov, int count,
void *myframe)
{
gfs3_readlink_rsp rsp = {0,};
call_frame_t *frame = NULL;
struct iatt iatt = {0,};
int ret = 0;
frame = myframe;
if (-1 == req->rpc_status) {
rsp.op_ret = -1;
rsp.op_errno = ENOTCONN;
goto out;
}
ret = xdr_to_readlink_rsp (*iov, &rsp);
if (ret < 0) {
gf_log ("", GF_LOG_ERROR, "error");
rsp.op_ret = -1;
rsp.op_errno = EINVAL;
goto out;
}
if (-1 != rsp.op_ret) {
gf_stat_to_iatt (&rsp.buf, &iatt);
}
out:
STACK_UNWIND_STRICT (readlink, frame, rsp.op_ret,
gf_error_to_errno (rsp.op_errno), rsp.path, &iatt);
/* This is allocated by the libc while decoding RPC msg */
/* Hence no 'GF_FREE', but just 'free' */
if (rsp.path)
free (rsp.path);
return 0;
}
int
client3_1_unlink_cbk (struct rpc_req *req, struct iovec *iov, int count,
void *myframe)
{
call_frame_t *frame = NULL;
gfs3_unlink_rsp rsp = {0,};
struct iatt preparent = {0,};
struct iatt postparent = {0,};
int ret = 0;
frame = myframe;
if (-1 == req->rpc_status) {
rsp.op_ret = -1;
rsp.op_errno = ENOTCONN;
goto out;
}
ret = xdr_to_unlink_rsp (*iov, &rsp);
if (ret < 0) {
gf_log ("", GF_LOG_ERROR, "error");
rsp.op_ret = -1;
rsp.op_errno = EINVAL;
goto out;
}
if (-1 != rsp.op_ret) {
gf_stat_to_iatt (&rsp.preparent, &preparent);
gf_stat_to_iatt (&rsp.postparent, &postparent);
}
out:
STACK_UNWIND_STRICT (unlink, frame, rsp.op_ret,
gf_error_to_errno (rsp.op_errno), &preparent,
&postparent);
return 0;
}
int
client3_1_rmdir_cbk (struct rpc_req *req, struct iovec *iov, int count,
void *myframe)
{
gfs3_rmdir_rsp rsp = {0,};
call_frame_t *frame = NULL;
struct iatt preparent = {0,};
struct iatt postparent = {0,};
int ret = 0;
frame = myframe;
if (-1 == req->rpc_status) {
rsp.op_ret = -1;
rsp.op_errno = ENOTCONN;
goto out;
}
ret = xdr_to_rmdir_rsp (*iov, &rsp);
if (ret < 0) {
gf_log ("", GF_LOG_ERROR, "error");
rsp.op_ret = -1;
rsp.op_errno = EINVAL;
goto out;
}
if (-1 != rsp.op_ret) {
gf_stat_to_iatt (&rsp.preparent, &preparent);
gf_stat_to_iatt (&rsp.postparent, &postparent);
}
out:
STACK_UNWIND_STRICT (rmdir, frame, rsp.op_ret,
gf_error_to_errno (rsp.op_errno), &preparent,
&postparent);
return 0;
}
int
client3_1_truncate_cbk (struct rpc_req *req, struct iovec *iov, int count,
void *myframe)
{
gfs3_truncate_rsp rsp = {0,};
call_frame_t *frame = NULL;
struct iatt prestat = {0,};
struct iatt poststat = {0,};
int ret = 0;
frame = myframe;
if (-1 == req->rpc_status) {
rsp.op_ret = -1;
rsp.op_errno = ENOTCONN;
goto out;
}
ret = xdr_to_truncate_rsp (*iov, &rsp);
if (ret < 0) {
gf_log ("", GF_LOG_ERROR, "error");
rsp.op_ret = -1;
rsp.op_errno = EINVAL;
goto out;
}
if (-1 != rsp.op_ret) {
gf_stat_to_iatt (&rsp.prestat, &prestat);
gf_stat_to_iatt (&rsp.poststat, &poststat);
}
out:
STACK_UNWIND_STRICT (truncate, frame, rsp.op_ret,
gf_error_to_errno (rsp.op_errno), &prestat,
&poststat);
return 0;
}
int
client3_1_statfs_cbk (struct rpc_req *req, struct iovec *iov, int count,
void *myframe)
{
gfs3_statfs_rsp rsp = {0,};
call_frame_t *frame = NULL;
struct statvfs statfs = {0,};
int ret = 0;
frame = myframe;
if (-1 == req->rpc_status) {
rsp.op_ret = -1;
rsp.op_errno = ENOTCONN;
goto out;
}
ret = xdr_to_statfs_rsp (*iov, &rsp);
if (ret < 0) {
gf_log ("", GF_LOG_ERROR, "error");
rsp.op_ret = -1;
rsp.op_errno = EINVAL;
goto out;
}
if (-1 != rsp.op_ret) {
gf_statfs_to_statfs (&rsp.statfs, &statfs);
}
out:
STACK_UNWIND_STRICT (statfs, frame, rsp.op_ret,
gf_error_to_errno (rsp.op_errno), &statfs);
return 0;
}
int
client3_1_writev_cbk (struct rpc_req *req, struct iovec *iov, int count,
void *myframe)
{
gfs3_write_rsp rsp = {0,};
call_frame_t *frame = NULL;
struct iatt prestat = {0,};
struct iatt poststat = {0,};
int ret = 0;
frame = myframe;
if (-1 == req->rpc_status) {
rsp.op_ret = -1;
rsp.op_errno = ENOTCONN;
goto out;
}
ret = xdr_to_truncate_rsp (*iov, &rsp);
if (ret < 0) {
gf_log ("", GF_LOG_ERROR, "error");
rsp.op_ret = -1;
rsp.op_errno = EINVAL;
goto out;
}
if (-1 != rsp.op_ret) {
gf_stat_to_iatt (&rsp.prestat, &prestat);
gf_stat_to_iatt (&rsp.poststat, &poststat);
}
out:
STACK_UNWIND_STRICT (writev, frame, rsp.op_ret,
gf_error_to_errno (rsp.op_errno), &prestat,
&poststat);
return 0;
}
int
client3_1_flush_cbk (struct rpc_req *req, struct iovec *iov, int count,
void *myframe)
{
call_frame_t *frame = NULL;
gf_common_rsp rsp = {0,};
int ret = 0;
frame = myframe;
if (-1 == req->rpc_status) {
rsp.op_ret = -1;
rsp.op_errno = ENOTCONN;
goto out;
}
ret = xdr_to_common_rsp (*iov, &rsp);
if (ret < 0) {
gf_log ("", GF_LOG_ERROR, "error");
rsp.op_ret = -1;
rsp.op_errno = EINVAL;
goto out;
}
out:
STACK_UNWIND_STRICT (flush, frame, rsp.op_ret,
gf_error_to_errno (rsp.op_errno));
return 0;
}
int
client3_1_fsync_cbk (struct rpc_req *req, struct iovec *iov, int count,
void *myframe)
{
gfs3_fsync_rsp rsp = {0,};
call_frame_t *frame = NULL;
struct iatt prestat = {0,};
struct iatt poststat = {0,};
int ret = 0;
frame = myframe;
if (-1 == req->rpc_status) {
rsp.op_ret = -1;
rsp.op_errno = ENOTCONN;
goto out;
}
ret = xdr_to_truncate_rsp (*iov, &rsp);
if (ret < 0) {
gf_log ("", GF_LOG_ERROR, "error");
rsp.op_ret = -1;
rsp.op_errno = EINVAL;
goto out;
}
if (-1 != rsp.op_ret) {
gf_stat_to_iatt (&rsp.prestat, &prestat);
gf_stat_to_iatt (&rsp.poststat, &poststat);
}
out:
STACK_UNWIND_STRICT (fsync, frame, rsp.op_ret,
gf_error_to_errno (rsp.op_errno), &prestat,
&poststat);
return 0;
}
int
client3_1_setxattr_cbk (struct rpc_req *req, struct iovec *iov, int count,
void *myframe)
{
call_frame_t *frame = NULL;
gf_common_rsp rsp = {0,};
int ret = 0;
frame = myframe;
if (-1 == req->rpc_status) {
rsp.op_ret = -1;
rsp.op_errno = ENOTCONN;
goto out;
}
ret = xdr_to_common_rsp (*iov, &rsp);
if (ret < 0) {
gf_log ("", GF_LOG_ERROR, "error");
rsp.op_ret = -1;
rsp.op_errno = EINVAL;
goto out;
}
out:
STACK_UNWIND_STRICT (setxattr, frame, rsp.op_ret,
gf_error_to_errno (rsp.op_errno));
return 0;
}
int
client3_1_getxattr_cbk (struct rpc_req *req, struct iovec *iov, int count,
void *myframe)
{
call_frame_t *frame = NULL;
dict_t *dict = NULL;
char *buf = NULL;
int dict_len = 0;
int op_ret = 0;
int op_errno = 0;
gfs3_getxattr_rsp rsp = {0,};
int ret = 0;
frame = myframe;
if (-1 == req->rpc_status) {
op_ret = -1;
op_errno = ENOTCONN;
goto out;
}
ret = xdr_to_getxattr_rsp (*iov, &rsp);
if (ret < 0) {
gf_log ("", GF_LOG_ERROR, "error");
op_ret = -1;
op_errno = EINVAL;
goto out;
}
op_errno = gf_error_to_errno (rsp.op_errno);
op_ret = rsp.op_ret;
if (-1 != op_ret) {
op_ret = -1;
dict_len = rsp.dict.dict_len;
if (dict_len > 0) {
dict = dict_new();
buf = memdup (rsp.dict.dict_val, rsp.dict.dict_len);
GF_VALIDATE_OR_GOTO (frame->this->name, dict, out);
GF_VALIDATE_OR_GOTO (frame->this->name, buf, out);
ret = dict_unserialize (buf, dict_len, &dict);
if (ret < 0) {
gf_log (frame->this->name, GF_LOG_DEBUG,
"failed to unserialize xattr dict");
op_errno = EINVAL;
goto out;
}
dict->extra_free = buf;
buf = NULL;
|