/*
Copyright (c) 2006-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 Affero 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
Affero General Public License for more details.
You should have received a copy of the GNU Affero 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"
#include "statedump.h"
#include "md5.h"
static void
print_caller (char *str, int size, call_frame_t *frame)
{
int filled = 0;
server_state_t *state = NULL;
transport_t *trans = NULL;
state = CALL_STATE (frame);
trans = state->trans;
filled += snprintf (str + filled, size - filled,
" Callid=%"PRId64", Client=%s",
frame->root->unique,
trans->peerinfo.identifier);
return;
}
static void
server_print_resolve (char *str, int size, server_resolve_t *resolve)
{
int filled = 0;
if (!resolve) {
snprintf (str, size, "<nul>");
return;
}
filled += snprintf (str + filled, size - filled,
" Resolve={");
if (resolve->fd_no != -1)
filled += snprintf (str + filled, size - filled,
"fd=%"PRId64",", (uint64_t) resolve->fd_no);
if (resolve->ino)
filled += snprintf (str + filled, size - filled,
"ino=%"PRIu64",", (uint64_t) resolve->ino);
if (resolve->par)
filled += snprintf (str + filled, size - filled,
"par=%"PRIu64",", (uint64_t) resolve->par);
if (resolve->gen)
filled += snprintf (str + filled, size - filled,
"gen=%"PRIu64",", (uint64_t) resolve->gen);
if (resolve->bname)
filled += snprintf (str + filled, size - filled,
"bname=%s,", resolve->bname);
if (resolve->path)
filled += snprintf (str + filled, size - filled,
"path=%s", resolve->path);
filled += snprintf (str + filled, size - filled, "}");
}
static void
server_print_loc (char *str, int size, loc_t *loc)
{
int filled = 0;
if (!loc) {
snprintf (str, size, "<nul>");
return;
}
filled += snprintf (str + filled, size - filled,
" Loc={");
if (loc->path)
filled += snprintf (str + filled, size - filled,
"path=%s,", loc->path);
if (loc->inode)
filled += snprintf (str + filled, size - filled,
"inode=%p,", loc->inode);
if (loc->parent)
filled += snprintf (str + filled, size - filled,
"parent=%p", loc->parent);
filled += snprintf (str + filled, size - filled, "}");
}
static void
server_print_params (char *str, int size, server_state_t *state)
{
int filled = 0;
filled += snprintf (str + filled, size - filled,
" Params={");
if (state->fd)
filled += snprintf (str + filled, size - filled,
"fd=%p,", state->fd);
if (state->valid)
filled += snprintf (str + filled, size - filled,
"valid=%d,", state->valid);
if (state->flags)
filled += snprintf (str + filled, size - filled,
"flags=%d,", state->flags);
if (state->wbflags)
filled += snprintf (str + filled, size - filled,
"wbflags=%d,", state->wbflags);
if (state->size)
filled += snprintf (str + filled, size - filled,
"size=%zu,", state->size);
if (state->offset)
filled += snprintf (str + filled, size - filled,
"offset=%"PRId64",", state->offset);
if (state->cmd)
filled += snprintf (str + filled, size - filled,
"cmd=%d,", state->cmd);
if (state->type)
filled += snprintf (str + filled, size - filled,
"type=%d,", state->type);
if (state->name)
filled += snprintf (str + filled, size - filled,
"name=%s,", state->name);
if (state->mask)
filled += snprintf (str + filled, size - filled,
"mask=%d,", state->mask);
if (state->volume)
filled += snprintf (str + filled, size - filled,
"volume=%s,", state->volume);
filled += snprintf (str + filled, size - filled,
"bound_xl=%s}", state->bound_xl->name);
}
static int
server_resolve_is_empty (server_resolve_t *resolve)
{
if (resolve->fd_no != -1)
return 0;
if (resolve->ino != 0)
return 0;
if (resolve->gen != 0)
return 0;
if (resolve->par != 0)
return 0;
if (resolve->path != 0)
return 0;
if (resolve->bname != 0)
return 0;
return 1;
}
void
gf_server_print_request (call_frame_t *frame)
{
server_conf_t *conf = NULL;
xlator_t *this = NULL;
server_state_t *state = NULL;
char resolve_vars[256];
char resolve2_vars[256];
char loc_vars[256];
char loc2_vars[256];
char other_vars[512];
char caller[512];
char *op = "UNKNOWN";
this = frame->this;
conf = this->private;
state = CALL_STATE (frame);
if (!conf->trace)
return;
memset (resolve_vars, '\0', 256);
memset (resolve2_vars, '\0', 256);
memset (loc_vars, '\0', 256);
memset (loc2_vars, '\0', 256);
memset (other_vars, '\0', 256);
print_caller (caller, 256, frame);
if (!server_resolve_is_empty (&state->resolve)) {
server_print_resolve (resolve_vars, 256, &state->resolve);
server_print_loc (loc_vars, 256, &state->loc);
}
if (!server_resolve_is_empty (&state->resolve2)) {
server_print_resolve (resolve2_vars, 256, &state->resolve2);
server_print_loc (loc2_vars, 256, &state->loc2);
}
server_print_params (other_vars, 512, state);
switch (frame->root->type) {
case GF_OP_TYPE_FOP_REQUEST:
case GF_OP_TYPE_FOP_REPLY:
op = gf_fop_list[frame->root->op];
break;
case GF_OP_TYPE_MOP_REQUEST:
case GF_OP_TYPE_MOP_REPLY:
op = gf_mop_list[frame->root->op];
break;
case GF_OP_TYPE_CBK_REQUEST:
case GF_OP_TYPE_CBK_REPLY:
op = gf_cbk_list[frame->root->op];
break;
}
gf_log (this->name, GF_LOG_NORMAL,
"%s%s%s%s%s%s%s",
gf_fop_list[frame->root->op], caller,
resolve_vars, loc_vars, resolve2_vars, loc2_vars, other_vars);
}
static void
server_print_reply (call_frame_t *frame, int op_ret, int op_errno)
{
server_conf_t *conf = NULL;
server_state_t *state = NULL;
xlator_t *this = NULL;
char caller[512];
char fdstr[32];
char *op = "UNKNOWN";
this = frame->this;
conf = this->private;
if (!conf->trace)
return;
state = CALL_STATE (frame);
print_caller (caller, 256, frame);
switch (frame->root->type) {
case GF_OP_TYPE_FOP_REQUEST:
case GF_OP_TYPE_FOP_REPLY:
op = gf_fop_list[frame->root->op];
break;
case GF_OP_TYPE_MOP_REQUEST:
case GF_OP_TYPE_MOP_REPLY:
op = gf_mop_list[frame->root->op];
break;
case GF_OP_TYPE_CBK_REQUEST:
case GF_OP_TYPE_CBK_REPLY:
op = gf_cbk_list[frame->root->op];
break;
}
fdstr[0] = '\0';
if (state->fd)
snprintf (fdstr, 32, " fd=%p", state->fd);
gf_log (this->name, GF_LOG_NORMAL,
"%s%s => (%d, %d)%s",
op, caller, op_ret, op_errno, fdstr);
}
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,
struct iobref *iobref)
{
server_state_t *state = NULL;
xlator_t *bound_xl = NULL;
transport_t *trans = NULL;
int ret = 0;
xlator_t *this = NULL;
bound_xl = BOUND_XL (frame);
state = CALL_STATE (frame);
trans = state->trans;
this = frame->this;
hdr->callid = hton64 (frame->root->unique);
hdr->type = hton32 (type);
hdr->op = hton32 (op);
server_print_reply (frame, ntoh32 (hdr->rsp.op_ret),
gf_error_to_errno (ntoh32 (hdr->rsp.op_errno)));
ret = transport_submit (trans, (char *)hdr, hdrlen, vector,
count, iobref);
if (ret < 0) {
gf_log ("protocol/server", GF_LOG_ERROR,
"frame %"PRId64": failed to submit. op= %d, type= %d",
frame->root->unique, op, type);
}
STACK_DESTROY (frame->root);
if (state)
free_old_server_state (state);
}
static int
gf_add_locker (struct _lock_table *table, const char *volume,
loc_t *loc, fd_t *fd, pid_t pid)
{
int32_t ret = -1;
struct _locker *new = NULL;
uint8_t dir = 0;
new = GF_CALLOC (1, sizeof (struct _locker),
gf_server_mt_locker);
if (new == NULL) {
gf_log ("server", GF_LOG_ERROR,
"failed to allocate memory for \'struct _locker\'");
goto out;
}
INIT_LIST_HEAD (&new->lockers);
new->volume = gf_strdup (volume);
if (fd == NULL) {
loc_copy (&new->loc, lo
|