summaryrefslogtreecommitdiffstats
path: root/xlators/protocol/server/src/server-handshake.c
diff options
context:
space:
mode:
Diffstat (limited to 'xlators/protocol/server/src/server-handshake.c')
-rw-r--r--xlators/protocol/server/src/server-handshake.c258
1 files changed, 190 insertions, 68 deletions
diff --git a/xlators/protocol/server/src/server-handshake.c b/xlators/protocol/server/src/server-handshake.c
index 98ec18cc2..d4941011d 100644
--- a/xlators/protocol/server/src/server-handshake.c
+++ b/xlators/protocol/server/src/server-handshake.c
@@ -1,20 +1,11 @@
/*
- Copyright (c) 2010 Gluster, Inc. <http://www.gluster.com>
+ Copyright (c) 2010-2013 Red Hat, Inc. <http://www.redhat.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/>.
+ This file is licensed to you under your choice of the GNU Lesser
+ General Public License, version 3 or any later version (LGPLv3 or
+ later), or the GNU General Public License, version 2 (GPLv2), in all
+ cases as published by the Free Software Foundation.
*/
@@ -40,7 +31,7 @@ gf_compare_client_version (rpcsvc_request_t *req, int fop_prognum,
{
int ret = -1;
/* TODO: think.. */
- if (glusterfs3_1_fop_prog.prognum == fop_prognum)
+ if (glusterfs3_3_fop_prog.prognum == fop_prognum)
ret = 0;
return ret;
@@ -102,26 +93,26 @@ _volfile_update_checksum (xlator_t *this, char *key, uint32_t checksum)
}
if (temp_volfile->checksum != checksum) {
- gf_log (this->name, GF_LOG_CRITICAL,
- "the volume file got modified between earlier access "
- "and now, this may lead to inconsistency between "
- "clients, advised to remount client");
+ gf_log (this->name, GF_LOG_INFO,
+ "the volume file was modified between a prior access "
+ "and now. This may lead to inconsistency between "
+ "clients, you are advised to remount client");
temp_volfile->checksum = checksum;
}
- out:
+out:
return 0;
}
static size_t
getspec_build_volfile_path (xlator_t *this, const char *key, char *path,
- size_t path_len)
+ size_t path_len)
{
- int ret = -1;
+ char *filename = NULL;
+ server_conf_t *conf = NULL;
+ int ret = -1;
int free_filename = 0;
- char *filename = NULL;
- server_conf_t *conf = NULL;
char data_key[256] = {0,};
conf = this->private;
@@ -190,7 +181,7 @@ int
_validate_volfile_checksum (xlator_t *this, char *key,
uint32_t checksum)
{
- char filename[ZR_PATH_MAX] = {0,};
+ char filename[PATH_MAX] = {0,};
server_conf_t *conf = NULL;
struct _volfile_ctx *temp_volfile = NULL;
int ret = 0;
@@ -205,13 +196,13 @@ _validate_volfile_checksum (xlator_t *this, char *key,
if (!temp_volfile) {
ret = getspec_build_volfile_path (this, key, filename,
- sizeof (filename));
+ sizeof (filename));
if (ret <= 0)
goto out;
fd = open (filename, O_RDONLY);
if (-1 == fd) {
ret = 0;
- gf_log (this->name, GF_LOG_DEBUG,
+ gf_log (this->name, GF_LOG_INFO,
"failed to open volume file (%s) : %s",
filename, strerror (errno));
goto out;
@@ -253,7 +244,7 @@ server_getspec (rpcsvc_request_t *req)
int32_t op_errno = ENOENT;
int32_t spec_fd = -1;
size_t file_len = 0;
- char filename[ZR_PATH_MAX] = {0,};
+ char filename[PATH_MAX] = {0,};
struct stat stbuf = {0,};
uint32_t checksum = 0;
char *key = NULL;
@@ -261,12 +252,12 @@ server_getspec (rpcsvc_request_t *req)
xlator_t *this = NULL;
gf_getspec_req args = {0,};
gf_getspec_rsp rsp = {0,};
- server_connection_t *conn = NULL;
- conn = req->trans->private;
this = req->svc->mydata;
conf = this->private;
- if (xdr_to_glusterfs_req (req, &args, xdr_to_getspec_req)) {
+ ret = xdr_to_generic (req->msg[0], &args,
+ (xdrproc_t)xdr_gf_getspec_req);
+ if (ret < 0) {
//failed to decode msg;
req->rpc_err = GARBAGE_ARGS;
op_errno = EINVAL;
@@ -313,8 +304,6 @@ server_getspec (rpcsvc_request_t *req)
goto fail;
}
ret = read (spec_fd, rsp.spec, file_len);
-
- close (spec_fd);
}
/* convert to XDR */
@@ -325,8 +314,11 @@ fail:
rsp.op_errno = gf_errno_to_error (op_errno);
rsp.op_ret = ret;
+ if (spec_fd != -1)
+ close (spec_fd);
+
server_submit_reply (NULL, req, &rsp, NULL, 0, NULL,
- (gfs_serialize_t)xdr_serialize_getspec_rsp);
+ (xdrproc_t)xdr_gf_getspec_rsp);
return 0;
}
@@ -335,16 +327,18 @@ fail:
int
server_setvolume (rpcsvc_request_t *req)
{
- gf_setvolume_req args = {0,};
+ gf_setvolume_req args = {{0,},};
gf_setvolume_rsp rsp = {0,};
- server_connection_t *conn = NULL;
+ client_t *client = NULL;
+ server_ctx_t *serv_ctx = NULL;
server_conf_t *conf = NULL;
peer_info_t *peerinfo = NULL;
dict_t *reply = NULL;
dict_t *config_params = NULL;
dict_t *params = NULL;
char *name = NULL;
- char *process_uuid = NULL;
+ char *client_uid = NULL;
+ char *clnt_version = NULL;
xlator_t *xl = NULL;
char *msg = NULL;
char *volfile_key = NULL;
@@ -355,10 +349,15 @@ server_setvolume (rpcsvc_request_t *req)
int32_t op_errno = EINVAL;
int32_t fop_version = 0;
int32_t mgmt_version = 0;
+ uint32_t lk_version = 0;
+ char *buf = NULL;
+ gf_boolean_t cancelled = _gf_false;
params = dict_new ();
reply = dict_new ();
- if (xdr_to_glusterfs_req (req, &args, xdr_to_setvolume_req)) {
+ ret = xdr_to_generic (req->msg[0], &args,
+ (xdrproc_t)xdr_gf_setvolume_req);
+ if (ret < 0) {
//failed to decode msg;
req->rpc_err = GARBAGE_ARGS;
goto fail;
@@ -369,7 +368,14 @@ server_setvolume (rpcsvc_request_t *req)
config_params = dict_copy_with_ref (this->options, NULL);
conf = this->private;
- ret = dict_unserialize (args.dict.dict_val, args.dict.dict_len, &params);
+ buf = memdup (args.dict.dict_val, args.dict.dict_len);
+ if (buf == NULL) {
+ op_ret = -1;
+ op_errno = ENOMEM;
+ goto fail;
+ }
+
+ ret = dict_unserialize (buf, args.dict.dict_len, &params);
if (ret < 0) {
ret = dict_set_str (reply, "ERROR",
"Internal error: failed to unserialize "
@@ -385,7 +391,10 @@ server_setvolume (rpcsvc_request_t *req)
goto fail;
}
- ret = dict_get_str (params, "process-uuid", &process_uuid);
+ params->extra_free = buf;
+ buf = NULL;
+
+ ret = dict_get_str (params, "process-uuid", &client_uid);
if (ret < 0) {
ret = dict_set_str (reply, "ERROR",
"UUID not specified");
@@ -398,10 +407,46 @@ server_setvolume (rpcsvc_request_t *req)
goto fail;
}
+ /*lk_verion :: [1..2^31-1]*/
+ ret = dict_get_uint32 (params, "clnt-lk-version", &lk_version);
+ if (ret < 0) {
+ ret = dict_set_str (reply, "ERROR",
+ "lock state version not supplied");
+ if (ret < 0)
+ gf_log (this->name, GF_LOG_DEBUG,
+ "failed to set error msg");
- conn = server_connection_get (this, process_uuid);
- if (req->trans->xl_private != conn)
- req->trans->xl_private = conn;
+ op_ret = -1;
+ op_errno = EINVAL;
+ goto fail;
+ }
+
+ client = gf_client_get (this, &req->cred, client_uid);
+ if (client == NULL) {
+ op_ret = -1;
+ op_errno = ENOMEM;
+ goto fail;
+ }
+
+ gf_log (this->name, GF_LOG_DEBUG, "Connected to %s", client->client_uid);
+ cancelled = server_cancel_grace_timer (this, client);
+ if (cancelled)//Do gf_client_put on behalf of grace-timer-handler.
+ gf_client_put (client, NULL);
+
+ serv_ctx = server_ctx_get (client, client->this);
+ if (serv_ctx == NULL) {
+ gf_log (this->name, GF_LOG_INFO, "server_ctx_get() failed");
+ goto fail;
+ }
+
+ if (serv_ctx->lk_version != 0 &&
+ serv_ctx->lk_version != lk_version) {
+ (void) server_connection_cleanup (this, client,
+ INTERNAL_LOCKS | POSIX_LOCKS);
+ }
+
+ if (req->trans->xl_private != client)
+ req->trans->xl_private = client;
ret = dict_get_int32 (params, "fops-version", &fop_version);
if (ret < 0) {
@@ -426,7 +471,7 @@ server_setvolume (rpcsvc_request_t *req)
ret = gf_asprintf (&msg, "version mismatch: client(%d)"
" - client-mgmt(%d)",
fop_version, mgmt_version);
- /* get_supported_version (req)); */
+ /* get_supported_version (req)); */
if (-1 == ret) {
gf_log (this->name, GF_LOG_ERROR,
"asprintf failed while setting up error msg");
@@ -458,7 +503,7 @@ server_setvolume (rpcsvc_request_t *req)
xl = get_xlator_by_name (this, name);
if (xl == NULL) {
ret = gf_asprintf (&msg, "remote-subvolume \"%s\" is not found",
- name);
+ name);
if (-1 == ret) {
gf_log (this->name, GF_LOG_ERROR,
"asprintf failed while setting error msg");
@@ -514,34 +559,42 @@ server_setvolume (rpcsvc_request_t *req)
"Authentication module not initialized");
}
+ ret = dict_get_str (params, "client-version", &clnt_version);
+ if (ret)
+ gf_log (this->name, GF_LOG_INFO, "client-version not set, "
+ "may be of older version");
+
ret = gf_authenticate (params, config_params,
conf->auth_modules);
if (ret == AUTH_ACCEPT) {
+
gf_log (this->name, GF_LOG_INFO,
- "accepted client from %s",
- (peerinfo)?peerinfo->identifier:"");
+ "accepted client from %s (version: %s)",
+ client->client_uid,
+ (clnt_version) ? clnt_version : "old");
op_ret = 0;
- conn->bound_xl = xl;
+ client->bound_xl = xl;
ret = dict_set_str (reply, "ERROR", "Success");
if (ret < 0)
gf_log (this->name, GF_LOG_DEBUG,
"failed to set error msg");
} else {
gf_log (this->name, GF_LOG_ERROR,
- "Cannot authenticate client from %s",
- (peerinfo)? peerinfo->identifier:"<>");
+ "Cannot authenticate client from %s %s",
+ client->client_uid,
+ (clnt_version) ? clnt_version : "old");
+
op_ret = -1;
op_errno = EACCES;
ret = dict_set_str (reply, "ERROR", "Authentication failed");
if (ret < 0)
gf_log (this->name, GF_LOG_DEBUG,
"failed to set error msg");
-
goto fail;
}
- if (conn->bound_xl == NULL) {
+ if (client->bound_xl == NULL) {
ret = dict_set_str (reply, "ERROR",
"Check volfile and handshake "
"options in protocol/client");
@@ -554,20 +607,21 @@ server_setvolume (rpcsvc_request_t *req)
goto fail;
}
- if ((conn->bound_xl != NULL) &&
+ if ((client->bound_xl != NULL) &&
(ret >= 0) &&
- (conn->bound_xl->itable == NULL)) {
+ (client->bound_xl->itable == NULL)) {
/* create inode table for this bound_xl, if one doesn't
already exist */
gf_log (this->name, GF_LOG_TRACE,
"creating inode table with lru_limit=%"PRId32", "
"xlator=%s", conf->inode_lru_limit,
- conn->bound_xl->name);
+ client->bound_xl->name);
/* TODO: what is this ? */
- conn->bound_xl->itable = inode_table_new (conf->inode_lru_limit,
- conn->bound_xl);
+ client->bound_xl->itable =
+ inode_table_new (conf->inode_lru_limit,
+ client->bound_xl);
}
ret = dict_set_str (reply, "process-uuid",
@@ -576,6 +630,11 @@ server_setvolume (rpcsvc_request_t *req)
gf_log (this->name, GF_LOG_DEBUG,
"failed to set 'process-uuid'");
+ ret = dict_set_uint32 (reply, "clnt-lk-version", serv_ctx->lk_version);
+ if (ret)
+ gf_log (this->name, GF_LOG_WARNING,
+ "failed to set 'clnt-lk-version'");
+
ret = dict_set_uint64 (reply, "transport-ptr",
((uint64_t) (long) req->trans));
if (ret)
@@ -608,20 +667,35 @@ fail:
rsp.op_ret = op_ret;
rsp.op_errno = gf_errno_to_error (op_errno);
+ /* if bound_xl is NULL or something fails, then put the connection
+ * back. Otherwise the connection would have been added to the
+ * list of connections the server is maintaining and might segfault
+ * during statedump when bound_xl of the connection is accessed.
+ */
+ if (op_ret && !xl) {
+ /* We would have set the xl_private of the transport to the
+ * @conn. But if we have put the connection i.e shutting down
+ * the connection, then we should set xl_private to NULL as it
+ * would be pointing to a freed memory and would segfault when
+ * accessed upon getting DISCONNECT.
+ */
+ gf_client_put (client, NULL);
+ req->trans->xl_private = NULL;
+ }
server_submit_reply (NULL, req, &rsp, NULL, 0, NULL,
- (gfs_serialize_t)xdr_serialize_setvolume_rsp);
+ (xdrproc_t)xdr_gf_setvolume_rsp);
- if (args.dict.dict_val)
- free (args.dict.dict_val);
+ free (args.dict.dict_val);
- if (rsp.dict.dict_val)
- GF_FREE (rsp.dict.dict_val);
+ GF_FREE (rsp.dict.dict_val);
dict_unref (params);
dict_unref (reply);
dict_unref (config_params);
+ GF_FREE (buf);
+
return 0;
}
@@ -631,22 +705,70 @@ server_ping (rpcsvc_request_t *req)
{
gf_common_rsp rsp = {0,};
- rsp.gfs_id = req->gfs_id;
/* Accepted */
rsp.op_ret = 0;
server_submit_reply (NULL, req, &rsp, NULL, 0, NULL,
- xdr_serialize_common_rsp);
+ (xdrproc_t)xdr_gf_common_rsp);
return 0;
}
+int
+server_set_lk_version (rpcsvc_request_t *req)
+{
+ int op_ret = -1;
+ int op_errno = EINVAL;
+ gf_set_lk_ver_req args = {0,};
+ gf_set_lk_ver_rsp rsp = {0,};
+ client_t *client = NULL;
+ server_ctx_t *serv_ctx = NULL;
+ xlator_t *this = NULL;
+
+ this = req->svc->mydata;
+ //TODO: Decide on an appropriate errno for the error-path
+ //below
+ if (!this)
+ goto fail;
+
+ op_ret = xdr_to_generic (req->msg[0], &args,
+ (xdrproc_t)xdr_gf_set_lk_ver_req);
+ if (op_ret < 0) {
+ //failed to decode msg;
+ req->rpc_err = GARBAGE_ARGS;
+ goto fail;
+ }
+
+ client = gf_client_get (this, &req->cred, args.uid);
+ serv_ctx = server_ctx_get (client, client->this);
+ if (serv_ctx == NULL) {
+ gf_log (this->name, GF_LOG_INFO, "server_ctx_get() failed");
+ goto fail;
+ }
+
+ serv_ctx->lk_version = args.lk_ver;
+ gf_client_put (client, NULL);
+
+ rsp.lk_ver = args.lk_ver;
+
+ op_ret = 0;
+fail:
+ rsp.op_ret = op_ret;
+ rsp.op_errno = op_errno;
+ server_submit_reply (NULL, req, &rsp, NULL, 0, NULL,
+ (xdrproc_t)xdr_gf_set_lk_ver_rsp);
+
+ free (args.uid);
+
+ return 0;
+}
rpcsvc_actor_t gluster_handshake_actors[] = {
- [GF_HNDSK_NULL] = {"NULL", GF_HNDSK_NULL, server_null, NULL, NULL },
- [GF_HNDSK_SETVOLUME] = {"SETVOLUME", GF_HNDSK_SETVOLUME, server_setvolume, NULL, NULL },
- [GF_HNDSK_GETSPEC] = {"GETSPEC", GF_HNDSK_GETSPEC, server_getspec, NULL, NULL },
- [GF_HNDSK_PING] = {"PING", GF_HNDSK_PING, server_ping, NULL, NULL },
+ [GF_HNDSK_NULL] = {"NULL", GF_HNDSK_NULL, server_null, NULL, 0, DRC_NA},
+ [GF_HNDSK_SETVOLUME] = {"SETVOLUME", GF_HNDSK_SETVOLUME, server_setvolume, NULL, 0, DRC_NA},
+ [GF_HNDSK_GETSPEC] = {"GETSPEC", GF_HNDSK_GETSPEC, server_getspec, NULL, 0, DRC_NA},
+ [GF_HNDSK_PING] = {"PING", GF_HNDSK_PING, server_ping, NULL, 0, DRC_NA},
+ [GF_HNDSK_SET_LK_VER] = {"SET_LK_VER", GF_HNDSK_SET_LK_VER, server_set_lk_version, NULL, 0, DRC_NA},
};