From c9854677fcd5a0a68e885cc18b6d9d6d92218f23 Mon Sep 17 00:00:00 2001 From: Amar Tumballi Date: Tue, 21 Jun 2011 04:56:41 +0000 Subject: gluster volume create: option for stripe + replicate volume So RAID01 like option is a possibility Signed-off-by: Amar Tumballi Signed-off-by: Anand Avati BUG: 3040 (need a way to create volumes with 'stripe+replicate' setup..) URL: http://bugs.gluster.com/cgi-bin/bugzilla3/show_bug.cgi?id=3040 --- cli/src/cli-cmd-parser.c | 118 ++++++++++++++++++++++------ rpc/xdr/src/cli1-xdr.h | 1 + xlators/mgmt/glusterd/src/glusterd-op-sm.c | 11 +++ xlators/mgmt/glusterd/src/glusterd-volgen.c | 41 +++++++++- xlators/mgmt/glusterd/src/glusterd.h | 2 + 5 files changed, 149 insertions(+), 24 deletions(-) diff --git a/cli/src/cli-cmd-parser.c b/cli/src/cli-cmd-parser.c index 3e331848d1b..2c1897550ec 100644 --- a/cli/src/cli-cmd-parser.c +++ b/cli/src/cli-cmd-parser.c @@ -158,6 +158,7 @@ cli_cmd_volume_create_parse (const char **words, int wordcount, dict_t **options int ret = -1; gf1_cluster_type type = GF_CLUSTER_TYPE_NONE; int count = 1; + int sub_count = 1; int brick_index = 0; int i = 0; char *trans_type = NULL; @@ -204,19 +205,23 @@ cli_cmd_volume_create_parse (const char **words, int wordcount, dict_t **options goto out; } - - ret = dict_set_str (dict, "volname", volname); - if (ret) - goto out; - if (wordcount < 4) { ret = -1; goto out; } + + if (wordcount < 6) { + /* seems no options are given, go directly to the parse_brick */ + brick_index = 3; + type = GF_CLUSTER_TYPE_NONE; + trans_type = gf_strdup ("tcp"); + goto parse_bricks; + } + w = str_getunamb (words[3], opwords_cl); if (!w) { type = GF_CLUSTER_TYPE_NONE; - brick_index = 3; + index = 3; } else if ((strcmp (w, "replica")) == 0) { type = GF_CLUSTER_TYPE_REPLICATE; if (wordcount < 5) { @@ -232,7 +237,7 @@ cli_cmd_volume_create_parse (const char **words, int wordcount, dict_t **options ret = dict_set_int32 (dict, "replica-count", count); if (ret) goto out; - brick_index = 5; + index = 5; } else if ((strcmp (w, "stripe")) == 0) { type = GF_CLUSTER_TYPE_STRIPE; if (wordcount < 5) { @@ -248,24 +253,78 @@ cli_cmd_volume_create_parse (const char **words, int wordcount, dict_t **options ret = dict_set_int32 (dict, "stripe-count", count); if (ret) goto out; - brick_index = 5; - } else + index = 5; + } else { GF_ASSERT (!"opword mismatch"); - - ret = dict_set_int32 (dict, "type", type); - if (ret) + ret = -1; goto out; + } - if (type) - index = 5; - else - index = 3; + /* Ie, how many bricks together forms a subvolume of distribute */ + sub_count = count; + /* reset the count value now */ + count = 1; + + /* It can be a 'stripe x replicate' (ie, RAID01) type of volume */ + w = str_getunamb (words[5], opwords_cl); + if (w && ((strcmp (w, "replica")) == 0)) { + if (type == GF_CLUSTER_TYPE_REPLICATE) { + cli_out ("'replica' option is already given"); + ret = -1; + goto out; + } + /* The previous one should have been 'stripe' option */ + type = GF_CLUSTER_TYPE_STRIPE_REPLICATE; - if (wordcount < (index + 1)) { + if (wordcount < 7) { + ret = -1; + goto out; + } + count = strtol (words[6], NULL, 0); + if (!count || (count < 2)) { + cli_out ("replica count should be greater than 1"); + ret = -1; + goto out; + } + + ret = dict_set_int32 (dict, "replica-count", count); + if (ret) + goto out; + index = 7; + } else if (w && ((strcmp (w, "stripe")) == 0)) { + if (type == GF_CLUSTER_TYPE_STRIPE) { + cli_out ("'stripe' option is already given"); + ret = -1; + goto out; + } + + /* The previous one should have been 'replica' option */ + type = GF_CLUSTER_TYPE_STRIPE_REPLICATE; + + if (wordcount < 7) { + ret = -1; + goto out; + } + count = strtol (words[6], NULL, 0); + if (!count || (count < 2)) { + cli_out ("stripe count should be greater than 1"); + ret = -1; + goto out; + } + ret = dict_set_int32 (dict, "stripe-count", count); + if (ret) + goto out; + index = 7; + } else if (w) { + GF_ASSERT (!"opword mismatch"); ret = -1; goto out; } + sub_count *= count; + + brick_index = index; + if (str_getunamb (words[index], opwords_tr)) { brick_index = index+2; if (wordcount < (index + 2)) { @@ -290,10 +349,7 @@ cli_cmd_volume_create_parse (const char **words, int wordcount, dict_t **options trans_type = gf_strdup ("tcp"); } - ret = dict_set_dynstr (dict, "transport", trans_type); - if (ret) - goto out; - +parse_bricks: ret = cli_cmd_bricks_parse (words, wordcount, brick_index, &bricks, &brick_count); if (ret) @@ -307,17 +363,35 @@ cli_cmd_volume_create_parse (const char **words, int wordcount, dict_t **options goto out; } - if (brick_count % count) { + if (brick_count % sub_count) { if (type == GF_CLUSTER_TYPE_STRIPE) cli_out ("number of bricks is not a multiple of " "stripe count"); else if (type == GF_CLUSTER_TYPE_REPLICATE) cli_out ("number of bricks is not a multiple of " "replica count"); + else + cli_out ("number of bricks given doesn't match " + "required count"); + ret = -1; goto out; } + /* Everything if parsed fine. start setting info in dict */ + ret = dict_set_str (dict, "volname", volname); + if (ret) + goto out; + + ret = dict_set_int32 (dict, "type", type); + if (ret) + goto out; + + ret = dict_set_dynstr (dict, "transport", trans_type); + if (ret) + goto out; + + ret = dict_set_dynstr (dict, "bricks", bricks); if (ret) goto out; diff --git a/rpc/xdr/src/cli1-xdr.h b/rpc/xdr/src/cli1-xdr.h index 80a2b4633ec..01b4e461ce0 100644 --- a/rpc/xdr/src/cli1-xdr.h +++ b/rpc/xdr/src/cli1-xdr.h @@ -37,6 +37,7 @@ enum gf1_cluster_type { GF_CLUSTER_TYPE_NONE = 0, GF_CLUSTER_TYPE_STRIPE = 0 + 1, GF_CLUSTER_TYPE_REPLICATE = 0 + 2, + GF_CLUSTER_TYPE_STRIPE_REPLICATE = 0 + 3, }; typedef enum gf1_cluster_type gf1_cluster_type; diff --git a/xlators/mgmt/glusterd/src/glusterd-op-sm.c b/xlators/mgmt/glusterd/src/glusterd-op-sm.c index 0cf94171c89..47f2c73c9eb 100644 --- a/xlators/mgmt/glusterd/src/glusterd-op-sm.c +++ b/xlators/mgmt/glusterd/src/glusterd-op-sm.c @@ -2707,6 +2707,17 @@ glusterd_op_create_volume (dict_t *dict, char **op_errstr) &sub_count); if (ret) goto out; + } else if (GF_CLUSTER_TYPE_STRIPE_REPLICATE == volinfo->type) { + ret = dict_get_int32 (dict, "stripe-count", + &volinfo->stripe_count); + if (ret) + goto out; + ret = dict_get_int32 (dict, "replica-count", + &volinfo->replica_count); + if (ret) + goto out; + + sub_count = volinfo->stripe_count * volinfo->replica_count; } ret = dict_get_str (dict, "transport", &trans_type); diff --git a/xlators/mgmt/glusterd/src/glusterd-volgen.c b/xlators/mgmt/glusterd/src/glusterd-volgen.c index a090f46debd..607fe1dafae 100644 --- a/xlators/mgmt/glusterd/src/glusterd-volgen.c +++ b/xlators/mgmt/glusterd/src/glusterd-volgen.c @@ -1506,6 +1506,7 @@ static int client_graph_builder (volgen_graph_t *graph, glusterd_volinfo_t *volinfo, dict_t *set_dict, void *param) { + int sub_count = 0; int dist_count = 0; char transt[16] = {0,}; char *volname = NULL; @@ -1576,7 +1577,8 @@ client_graph_builder (volgen_graph_t *graph, glusterd_volinfo_t *volinfo, return -1; } - if (volinfo->sub_count > 1) { + sub_count = volinfo->sub_count; + if (sub_count > 1) { switch (volinfo->type) { case GF_CLUSTER_TYPE_REPLICATE: cluster_args = replicate_args; @@ -1584,6 +1586,11 @@ client_graph_builder (volgen_graph_t *graph, glusterd_volinfo_t *volinfo, case GF_CLUSTER_TYPE_STRIPE: cluster_args = stripe_args; break; + case GF_CLUSTER_TYPE_STRIPE_REPLICATE: + /* Replicate after the clients, then stripe */ + sub_count = volinfo->replica_count; + cluster_args = replicate_args; + break; default: gf_log ("", GF_LOG_ERROR, "volume inconsistency: " "unrecognized clustering type"); @@ -1595,7 +1602,7 @@ client_graph_builder (volgen_graph_t *graph, glusterd_volinfo_t *volinfo, txl = first_of (graph); for (trav = txl; trav->next; trav = trav->next); for (;; trav = trav->prev) { - if (i % volinfo->sub_count == 0) { + if (i % sub_count == 0) { xl = volgen_graph_add_nolink (graph, cluster_args[0], cluster_args[1], @@ -1613,8 +1620,38 @@ client_graph_builder (volgen_graph_t *graph, glusterd_volinfo_t *volinfo, break; i++; } + + if (GF_CLUSTER_TYPE_STRIPE_REPLICATE == volinfo->type) { + sub_count = volinfo->stripe_count; + cluster_args = stripe_args; + + i = 0; + txl = first_of (graph); + for (trav = txl; --j; trav = trav->next); + for (;; trav = trav->prev) { + if (i % sub_count == 0) { + xl = volgen_graph_add_nolink (graph, + cluster_args[0], + cluster_args[1], + volname, j); + if (!xl) + return -1; + j++; + } + + ret = volgen_xlator_link (xl, trav); + if (ret) + return -1; + + if (trav == txl) + break; + i++; + } + + } } + if (volinfo->sub_count) dist_count = volinfo->brick_count / volinfo->sub_count; else diff --git a/xlators/mgmt/glusterd/src/glusterd.h b/xlators/mgmt/glusterd/src/glusterd.h index b1027c1714c..7cbb4bc56b6 100644 --- a/xlators/mgmt/glusterd/src/glusterd.h +++ b/xlators/mgmt/glusterd/src/glusterd.h @@ -187,6 +187,8 @@ struct glusterd_volinfo_ { struct list_head bricks; glusterd_volume_status status; int sub_count; + int stripe_count; + int replica_count; int port; glusterd_store_handle_t *shandle; -- cgit