From 02d653931c8967accf766014efce0c2dce340cdf Mon Sep 17 00:00:00 2001 From: Kaushal M Date: Wed, 28 Nov 2012 16:22:15 +0530 Subject: glusterd,glusterfsd,libgfapi: Client op-version This patch introduces op-version support for glusterfs clients. Now, a client sends its supported op-versions during the volfile fetch request and glusterd will return the volfile only if the client can support the current op-version of the cluster. Change-Id: Iab1f1f1706802962bcf27058657c44e8a344d2f6 BUG: 907311 Signed-off-by: Kaushal M Reviewed-on: http://review.gluster.org/4247 Tested-by: Gluster Build System Reviewed-by: Amar Tumballi Reviewed-by: Anand Avati --- api/src/glfs-mgmt.c | 41 ++++++++++++++- glusterfsd/src/glusterfsd-mgmt.c | 40 ++++++++++++++ libglusterfs/src/globals.h | 18 +++++++ xlators/mgmt/glusterd/src/glusterd-handshake.c | 72 ++++++++++++++++++++++++-- xlators/mgmt/glusterd/src/glusterd.h | 17 ------ 5 files changed, 167 insertions(+), 21 deletions(-) diff --git a/api/src/glfs-mgmt.c b/api/src/glfs-mgmt.c index 2ead93863bc..a76692bfd06 100644 --- a/api/src/glfs-mgmt.c +++ b/api/src/glfs-mgmt.c @@ -477,6 +477,13 @@ out: if (rsp.spec) free (rsp.spec); + // Stop if server is running at an unsupported op-version + if (ENOTSUP == ret) { + gf_log ("mgmt", GF_LOG_ERROR, "Server is operating at an " + "op-version which is not supported"); + glfs_init_done (fs, -1); + } + if (ret && ctx && !ctx->active) { /* Do it only for the first time */ /* Failed to get the volume file, something wrong, @@ -503,6 +510,7 @@ glfs_volfile_fetch (struct glfs *fs) int ret = 0; call_frame_t *frame = NULL; glusterfs_ctx_t *ctx = NULL; + dict_t *dict = NULL; ctx = fs->ctx; cmd_args = &ctx->cmd_args; @@ -512,10 +520,41 @@ glfs_volfile_fetch (struct glfs *fs) req.key = cmd_args->volfile_id; req.flags = 0; + dict = dict_new (); + if (!dict) { + ret = -1; + goto out; + } + + // Set the supported min and max op-versions, so glusterd can make a + // decision + ret = dict_set_int32 (dict, "min-op-version", GD_OP_VERSION_MIN); + if (ret) { + gf_log (THIS->name, GF_LOG_ERROR, "Failed to set min-op-version" + " in request dict"); + goto out; + } + + ret = dict_set_int32 (dict, "max-op-version", GD_OP_VERSION_MAX); + if (ret) { + gf_log (THIS->name, GF_LOG_ERROR, "Failed to set max-op-version" + " in request dict"); + goto out; + } + + ret = dict_allocate_and_serialize (dict, &req.xdata.xdata_val, + &req.xdata.xdata_len); + if (ret < 0) { + gf_log (THIS->name, GF_LOG_ERROR, + "Failed to serialize dictionary"); + goto out; + } + ret = mgmt_submit_request (&req, frame, ctx, &clnt_handshake_prog, GF_HNDSK_GETSPEC, mgmt_getspec_cbk, (xdrproc_t)xdr_gf_getspec_req); - return ret; +out: + return ret; } diff --git a/glusterfsd/src/glusterfsd-mgmt.c b/glusterfsd/src/glusterfsd-mgmt.c index 5bebdaf178c..8082ad3d1d4 100644 --- a/glusterfsd/src/glusterfsd-mgmt.c +++ b/glusterfsd/src/glusterfsd-mgmt.c @@ -1639,6 +1639,13 @@ out: emancipate (ctx, ret); + // Stop if server is running at an unsupported op-version + if (ENOTSUP == ret) { + gf_log ("mgmt", GF_LOG_ERROR, "Server is operating at an " + "op-version which is not supported"); + cleanup_and_exit (0); + } + if (ret && ctx && !ctx->active) { /* Do it only for the first time */ /* Failed to get the volume file, something wrong, @@ -1649,6 +1656,7 @@ out: cleanup_and_exit (0); } + if (tmpfp) fclose (tmpfp); @@ -1663,6 +1671,7 @@ glusterfs_volfile_fetch (glusterfs_ctx_t *ctx) gf_getspec_req req = {0, }; int ret = 0; call_frame_t *frame = NULL; + dict_t *dict = NULL; cmd_args = &ctx->cmd_args; @@ -1671,9 +1680,40 @@ glusterfs_volfile_fetch (glusterfs_ctx_t *ctx) req.key = cmd_args->volfile_id; req.flags = 0; + dict = dict_new (); + if (!dict) { + ret = -1; + goto out; + } + + // Set the supported min and max op-versions, so glusterd can make a + // decision + ret = dict_set_int32 (dict, "min-op-version", GD_OP_VERSION_MIN); + if (ret) { + gf_log (THIS->name, GF_LOG_ERROR, "Failed to set min-op-version" + " in request dict"); + goto out; + } + + ret = dict_set_int32 (dict, "max-op-version", GD_OP_VERSION_MAX); + if (ret) { + gf_log (THIS->name, GF_LOG_ERROR, "Failed to set max-op-version" + " in request dict"); + goto out; + } + + ret = dict_allocate_and_serialize (dict, &req.xdata.xdata_val, + &req.xdata.xdata_len); + if (ret < 0) { + gf_log (THIS->name, GF_LOG_ERROR, + "Failed to serialize dictionary"); + goto out; + } + ret = mgmt_submit_request (&req, frame, ctx, &clnt_handshake_prog, GF_HNDSK_GETSPEC, mgmt_getspec_cbk, (xdrproc_t)xdr_gf_getspec_req); +out: return ret; } diff --git a/libglusterfs/src/globals.h b/libglusterfs/src/globals.h index e13902b2992..64a1594f5f8 100644 --- a/libglusterfs/src/globals.h +++ b/libglusterfs/src/globals.h @@ -13,6 +13,24 @@ #define GF_DEFAULT_BASE_PORT 24007 +#define GD_OP_VERSION_KEY "operating-version" +#define GD_MIN_OP_VERSION_KEY "minimum-operating-version" +#define GD_MAX_OP_VERSION_KEY "maximum-operating-version" + +/* Gluster versions - OP-VERSION mapping + * + * 3.3.0 - 1 + * 3.3.Next/3.Next - 2 + * + * TODO: Change above comment once gluster version is finalised + * TODO: Finalize the op-version ranges + */ +#define GD_OP_VERSION_MIN 1 /* MIN is the fresh start op-version, mostly + should not change */ +#define GD_OP_VERSION_MAX 2 /* MAX VERSION is the maximum count in VME table, + should keep changing with introduction of newer + versions */ + #include "xlator.h" /* THIS */ diff --git a/xlators/mgmt/glusterd/src/glusterd-handshake.c b/xlators/mgmt/glusterd/src/glusterd-handshake.c index 6a273df54b6..5b3299d549a 100644 --- a/xlators/mgmt/glusterd/src/glusterd-handshake.c +++ b/xlators/mgmt/glusterd/src/glusterd-handshake.c @@ -124,7 +124,17 @@ server_getspec (rpcsvc_request_t *req) gf_getspec_req args = {0,}; gf_getspec_rsp rsp = {0,}; char addrstr[RPCSVC_PEER_STRLEN] = {0}; + dict_t *dict = NULL; + xlator_t *this = NULL; + glusterd_conf_t *conf = NULL; + int client_min_op_version = 0; + int client_max_op_version = 0; + this = THIS; + GF_ASSERT (this); + + conf = this->private; + GF_ASSERT (conf); ret = xdr_to_generic (req->msg[0], &args, (xdrproc_t)xdr_gf_getspec_req); @@ -134,6 +144,63 @@ server_getspec (rpcsvc_request_t *req) goto fail; } + if (!args.xdata.xdata_len) { + // For clients <= 3.3.0, only allow if op_version = 1 + if (1 != conf->op_version) { + ret = -1; + op_errno = ENOTSUP; + gf_log (this->name, GF_LOG_INFO, + "Client %s doesn't support required op-version. " + "Rejecting getspec request.", + req->trans->peerinfo.identifier); + goto fail; + } + } else { + // For clients > 3.3, only allow if they can support + // clusters' op_version + dict = dict_new (); + if (!dict) { + ret = -1; + goto fail; + } + + ret = dict_unserialize (args.xdata.xdata_val, + args.xdata.xdata_len, &dict); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, + "Failed to unserialize request dictionary"); + goto fail; + } + + ret = dict_get_int32 (dict, "min-op-version", + &client_min_op_version); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, + "Failed to get client-min-op-version"); + goto fail; + } + + ret = dict_get_int32 (dict, "max-op-version", + &client_max_op_version); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, + "Failed to get client-max-op-version"); + goto fail; + } + + if ((client_min_op_version > conf->op_version) || + (client_max_op_version < conf->op_version)) { + ret = -1; + op_errno = ENOTSUP; + //TODO: Add client identifier + gf_log (this->name, GF_LOG_INFO, + "Client %s doesn't support required op-version. " + "Rejecting getspec request.", + req->trans->peerinfo.identifier); + goto fail; + } + } + volume = args.key; trans = req->trans; @@ -387,7 +454,7 @@ glusterd_mgmt_hndsk_versions_ack (rpcsvc_request_t *req) glusterd_conf_t *conf = NULL; int ret = -1; int op_errno = EINVAL; - int32_t peer_op_version = 0; + int peer_op_version = 0; gf_mgmt_hndsk_req args = {{0,},}; gf_mgmt_hndsk_rsp rsp = {0,}; @@ -406,8 +473,7 @@ glusterd_mgmt_hndsk_versions_ack (rpcsvc_request_t *req) (args.hndsk.hndsk_len), ret, op_errno, out); - ret = dict_get_int32 (clnt_dict, GD_OP_VERSION_KEY, - &peer_op_version); + ret = dict_get_int32 (clnt_dict, GD_OP_VERSION_KEY, &peer_op_version); if (ret) { gf_log (this->name, GF_LOG_WARNING, "failed to get the op-version key peer=%s", diff --git a/xlators/mgmt/glusterd/src/glusterd.h b/xlators/mgmt/glusterd/src/glusterd.h index f7bfad697e8..95e23674c57 100644 --- a/xlators/mgmt/glusterd/src/glusterd.h +++ b/xlators/mgmt/glusterd/src/glusterd.h @@ -114,23 +114,6 @@ typedef struct { gf_boolean_t online; } nodesrv_t; -#define GD_OP_VERSION_KEY "operating-version" -#define GD_MIN_OP_VERSION_KEY "minimum-operating-version" -#define GD_MAX_OP_VERSION_KEY "maxium-operating-version" - -/* Gluster versions - OP-VERSION mapping - * - * 3.3.0 - 1 - * 3.3.Next/3.Next - 2 - * - * (TODO: Change above comment once gluster version is finalised) - */ -#define GD_OP_VERSION_MIN 1 /* MIN is the fresh start op-version, mostly - should not change */ -#define GD_OP_VERSION_MAX 2 /* MAX VERSION is the maximum count in VME table, - should keep changing with introduction of newer - versions */ - typedef struct { gf_boolean_t quorum; double quorum_ratio; -- cgit