From ca796eba11a3f965bfbaa9bbffb5ef00c9bbb7ad Mon Sep 17 00:00:00 2001 From: "M. Mohan Kumar" Date: Thu, 29 Nov 2012 21:46:07 +0530 Subject: BD Backend: Volume creation support A new parameter type is added to volume create command. To use BD xlator one has to specify following argument in addition to normal volume create device vg brick: for example, $ gluster volume create lv_volume device vg host:/vg1 Changes from previous version * New type 'backend' added to volinfo structure to differentiate between posix and bd xlator * Most of the volume related commands are updated to handle BD xlator, like add-brick, heal-brick etc refuse to work when volume is BD xlator type * Only one VG (ie brick) can be specified for BD xlator during volume creation * volume info shows VG info if its of type BD xlator BUG: 805138 Change-Id: I0ff90aca04840c71f364fabb0ab43ce33f9278ce Signed-off-by: M. Mohan Kumar Reviewed-on: http://review.gluster.org/3717 Reviewed-by: Vijay Bellur Tested-by: Vijay Bellur --- cli/src/cli-cmd-parser.c | 52 ++++++++++++++++- cli/src/cli-cmd-volume.c | 2 +- cli/src/cli-rpc-ops.c | 19 ++++++- xlators/mgmt/glusterd/src/Makefile.am | 3 + xlators/mgmt/glusterd/src/glusterd-brick-ops.c | 9 +++ xlators/mgmt/glusterd/src/glusterd-handler.c | 7 +++ xlators/mgmt/glusterd/src/glusterd-replace-brick.c | 7 +++ xlators/mgmt/glusterd/src/glusterd-store.c | 12 ++++ xlators/mgmt/glusterd/src/glusterd-store.h | 1 + xlators/mgmt/glusterd/src/glusterd-volgen.c | 52 ++++++++++++----- xlators/mgmt/glusterd/src/glusterd-volume-ops.c | 65 +++++++++++++++++++++- xlators/mgmt/glusterd/src/glusterd.h | 7 +++ 12 files changed, 217 insertions(+), 19 deletions(-) diff --git a/cli/src/cli-cmd-parser.c b/cli/src/cli-cmd-parser.c index 4181e6c81..f7ee29a10 100644 --- a/cli/src/cli-cmd-parser.c +++ b/cli/src/cli-cmd-parser.c @@ -159,13 +159,21 @@ cli_cmd_volume_create_parse (const char **words, int wordcount, dict_t **options int32_t index = 0; char *bricks = NULL; int32_t brick_count = 0; - char *opwords[] = { "replica", "stripe", "transport", NULL }; + char *opwords[] = { "replica", "stripe", "transport", +#ifdef HAVE_BD_XLATOR + "device", +#endif + NULL }; + char *invalid_volnames[] = {"volume", "type", "subvolumes", "option", "end-volume", "all", NULL}; char *w = NULL; int op_count = 0; int32_t replica_count = 1; int32_t stripe_count = 1; +#ifdef HAVE_BD_XLATOR + char *dev_type = NULL; +#endif GF_ASSERT (words); GF_ASSERT (options); @@ -300,7 +308,26 @@ cli_cmd_volume_create_parse (const char **words, int wordcount, dict_t **options goto out; } index += 2; - } else { + } +#ifdef HAVE_BD_XLATOR + else if ((strcmp (w, "device")) == 0) { + if (dev_type) { + cli_err ("'device' option given more" + " than one time"); + goto out; + } + if ((strcasecmp (words[index+1], "vg") == 0)) { + dev_type = gf_strdup ("vg"); + } else { + gf_log ("", GF_LOG_ERROR, "incorrect" + " device type specified"); + ret = -1; + goto out; + } + index += 2; + } +#endif + else { GF_ASSERT (!"opword mismatch"); ret = -1; goto out; @@ -336,6 +363,19 @@ cli_cmd_volume_create_parse (const char **words, int wordcount, dict_t **options goto out; } + /* BD xlator does not support multiple bricks */ +#ifdef HAVE_BD_XLATOR + if (brick_count > 1 && dev_type) { + cli_err ("Block Device backend volume does not support multiple" + " bricks"); + gf_log ("", GF_LOG_ERROR, + "Block Device backend volumer does not support multiple" + " bricks"); + ret = -1; + goto out; + } +#endif + if (brick_count % sub_count) { if (type == GF_CLUSTER_TYPE_STRIPE) cli_err ("number of bricks is not a multiple of " @@ -369,6 +409,14 @@ cli_cmd_volume_create_parse (const char **words, int wordcount, dict_t **options if (ret) goto out; +#ifdef HAVE_BD_XLATOR + if (dev_type) { + ret = dict_set_dynstr (dict, "device", dev_type); + if (ret) + goto out; + } +#endif + ret = dict_set_int32 (dict, "count", brick_count); if (ret) goto out; diff --git a/cli/src/cli-cmd-volume.c b/cli/src/cli-cmd-volume.c index 5b02ef5d9..4dcb99ce2 100644 --- a/cli/src/cli-cmd-volume.c +++ b/cli/src/cli-cmd-volume.c @@ -1795,7 +1795,7 @@ struct cli_cmd volume_cmds[] = { cli_cmd_volume_info_cbk, "list information of all volumes"}, - { "volume create [stripe ] [replica ] [transport ] ...", + { "volume create [stripe ] [replica ] [device vg] [transport ] ...", cli_cmd_volume_create_cbk, "create a new volume of specified type with mentioned bricks"}, diff --git a/cli/src/cli-rpc-ops.c b/cli/src/cli-rpc-ops.c index 703289b5b..77e15ee29 100644 --- a/cli/src/cli-rpc-ops.c +++ b/cli/src/cli-rpc-ops.c @@ -62,6 +62,10 @@ char *cli_vol_status_str[] = {"Created", "Stopped", }; +char *cli_volume_backend[] = {"", + "Volume Group", +}; + int32_t gf_cli_get_volume (call_frame_t *frame, xlator_t *this, void *data); @@ -493,6 +497,7 @@ gf_cli_get_volume_cbk (struct rpc_req *req, struct iovec *iov, char key[1024] = {0}; char err_str[2048] = {0}; gf_cli_rsp rsp = {0}; + int32_t backend = 0; if (-1 == req->rpc_status) goto out; @@ -643,6 +648,9 @@ xml_output: if (ret) goto out; + snprintf (key, 256, "volume%d.backend", i); + ret = dict_get_int32 (dict, key, &backend); + vol_type = type; // Distributed (stripe/replicate/stripe-replica) setups @@ -654,16 +662,17 @@ xml_output: cli_out ("Volume ID: %s", volume_id_str); cli_out ("Status: %s", cli_vol_status_str[status]); + if (backend) + goto next; + if (type == GF_CLUSTER_TYPE_STRIPE_REPLICATE) { cli_out ("Number of Bricks: %d x %d x %d = %d", (brick_count / dist_count), stripe_count, replica_count, brick_count); - } else if (type == GF_CLUSTER_TYPE_NONE) { cli_out ("Number of Bricks: %d", brick_count); - } else { /* For both replicate and stripe, dist_count is good enough */ @@ -676,6 +685,12 @@ xml_output: ((transport == 0)?"tcp": (transport == 1)?"rdma": "tcp,rdma")); + +next: + if (backend) { + cli_out ("Backend Type: Block, %s", + cli_volume_backend[backend]); + } j = 1; GF_FREE (local->get_vol.volname); diff --git a/xlators/mgmt/glusterd/src/Makefile.am b/xlators/mgmt/glusterd/src/Makefile.am index 95d2aba9d..5ec9d2bef 100644 --- a/xlators/mgmt/glusterd/src/Makefile.am +++ b/xlators/mgmt/glusterd/src/Makefile.am @@ -2,6 +2,9 @@ xlator_LTLIBRARIES = glusterd.la xlatordir = $(libdir)/glusterfs/$(PACKAGE_VERSION)/xlator/mgmt glusterd_la_CPPFLAGS = $(AM_CPPFLAGS) "-DFILTERDIR=\"$(libdir)/glusterfs/$(PACKAGE_VERSION)/filter\"" glusterd_la_LDFLAGS = -module -avoidversion +if ENABLE_BD_XLATOR +glusterd_la_LDFLAGS += -llvm2app +endif glusterd_la_SOURCES = glusterd.c glusterd-handler.c glusterd-sm.c \ glusterd-op-sm.c glusterd-utils.c glusterd-rpc-ops.c \ glusterd-store.c glusterd-handshake.c glusterd-pmap.c \ diff --git a/xlators/mgmt/glusterd/src/glusterd-brick-ops.c b/xlators/mgmt/glusterd/src/glusterd-brick-ops.c index ade30fe95..a14828e98 100644 --- a/xlators/mgmt/glusterd/src/glusterd-brick-ops.c +++ b/xlators/mgmt/glusterd/src/glusterd-brick-ops.c @@ -1035,6 +1035,15 @@ glusterd_op_stage_add_brick (dict_t *dict, char **op_errstr) goto out; } + if (volinfo->backend == GD_VOL_BK_BD) { + snprintf (msg, sizeof (msg), "Add brick is not supported for " + "Block backend volume %s.", volname); + gf_log (THIS->name, GF_LOG_ERROR, "%s", msg); + *op_errstr = gf_strdup (msg); + ret = -1; + goto out; + } + ret = glusterd_validate_volume_id (dict, volinfo); if (ret) goto out; diff --git a/xlators/mgmt/glusterd/src/glusterd-handler.c b/xlators/mgmt/glusterd/src/glusterd-handler.c index cec94f89f..9433436d0 100644 --- a/xlators/mgmt/glusterd/src/glusterd-handler.c +++ b/xlators/mgmt/glusterd/src/glusterd-handler.c @@ -370,6 +370,13 @@ glusterd_add_volume_detail_to_dict (glusterd_volinfo_t *volinfo, if (ret) goto out; +#ifdef HAVE_BD_XLATOR + snprintf (key, 256, "volume%d.backend", count); + ret = dict_set_int32 (volumes, key, volinfo->backend); + if (ret) + goto out; +#endif + list_for_each_entry (brickinfo, &volinfo->bricks, brick_list) { char brick[1024] = {0,}; snprintf (key, 256, "volume%d.brick%d", count, i); diff --git a/xlators/mgmt/glusterd/src/glusterd-replace-brick.c b/xlators/mgmt/glusterd/src/glusterd-replace-brick.c index edc2627c1..bca306bd8 100644 --- a/xlators/mgmt/glusterd/src/glusterd-replace-brick.c +++ b/xlators/mgmt/glusterd/src/glusterd-replace-brick.c @@ -243,6 +243,13 @@ glusterd_op_stage_replace_brick (dict_t *dict, char **op_errstr, goto out; } + if (volinfo->backend == GD_VOL_BK_BD) { + snprintf (msg, sizeof (msg), "replace brick not supported " + "for Block backend volume"); + *op_errstr = gf_strdup (msg); + goto out; + } + if (GLUSTERD_STATUS_STARTED != volinfo->status) { ret = -1; snprintf (msg, sizeof (msg), "volume: %s is not started", diff --git a/xlators/mgmt/glusterd/src/glusterd-store.c b/xlators/mgmt/glusterd/src/glusterd-store.c index 471a24e66..413c8a39a 100644 --- a/xlators/mgmt/glusterd/src/glusterd-store.c +++ b/xlators/mgmt/glusterd/src/glusterd-store.c @@ -703,6 +703,15 @@ glusterd_volume_exclude_options_write (int fd, glusterd_volinfo_t *volinfo) if (ret) goto out; } + + if (volinfo->backend == GD_VOL_BK_BD) { + snprintf (buf, sizeof (buf), "%d", volinfo->backend); + ret = glusterd_store_save_value (fd, + GLUSTERD_STORE_KEY_VOL_BACKEND, buf); + if (ret) + goto out; + } + out: if (ret) gf_log ("", GF_LOG_ERROR, "Unable to write volume values" @@ -2341,6 +2350,9 @@ glusterd_store_retrieve_volume (char *volname) gf_log ("", GF_LOG_DEBUG, "Parsed as "GEOREP" " " slave:key=%s,value:%s", key, value); + } else if (!strncmp (key, GLUSTERD_STORE_KEY_VOL_BACKEND, + strlen (GLUSTERD_STORE_KEY_VOL_BACKEND))) { + volinfo->backend = atoi (value); } else { if (is_key_glusterd_hooks_friendly (key)) { diff --git a/xlators/mgmt/glusterd/src/glusterd-store.h b/xlators/mgmt/glusterd/src/glusterd-store.h index d8c1567a6..1ab398c0b 100644 --- a/xlators/mgmt/glusterd/src/glusterd-store.h +++ b/xlators/mgmt/glusterd/src/glusterd-store.h @@ -64,6 +64,7 @@ typedef enum glusterd_store_ver_ac_{ #define GLUSTERD_STORE_KEY_PEER_UUID "uuid" #define GLUSTERD_STORE_KEY_PEER_HOSTNAME "hostname" #define GLUSTERD_STORE_KEY_PEER_STATE "state" +#define GLUSTERD_STORE_KEY_VOL_BACKEND "backend" #define glusterd_for_each_entry(entry, dir) \ do {\ diff --git a/xlators/mgmt/glusterd/src/glusterd-volgen.c b/xlators/mgmt/glusterd/src/glusterd-volgen.c index 76172dd9b..f3de2feed 100644 --- a/xlators/mgmt/glusterd/src/glusterd-volgen.c +++ b/xlators/mgmt/glusterd/src/glusterd-volgen.c @@ -1574,6 +1574,8 @@ server_graph_builder (volgen_graph_t *graph, glusterd_volinfo_t *volinfo, char *password = NULL; char index_basepath[PATH_MAX] = {0}; char key[1024] = {0}; + char *vgname = NULL; + char *vg = NULL; path = param; volname = volinfo->volname; @@ -1591,23 +1593,47 @@ server_graph_builder (volgen_graph_t *graph, glusterd_volinfo_t *volinfo, } } - xl = volgen_graph_add (graph, "storage/posix", volname); - if (!xl) - return -1; + if (volinfo->backend == GD_VOL_BK_BD) { + xl = volgen_graph_add (graph, "storage/bd_map", volname); + if (!xl) + return -1; - ret = xlator_set_option (xl, "directory", path); - if (ret) - return -1; + ret = xlator_set_option (xl, "device", "vg"); + if (ret) + return -1; - ret = xlator_set_option (xl, "volume-id", - uuid_utoa (volinfo->volume_id)); - if (ret) - return -1; + vg = gf_strdup (path); + vgname = strrchr (vg, '/'); + if (strchr(vg, '/') != vgname) { + gf_log ("glusterd", GF_LOG_ERROR, + "invalid vg specified %s", path); + GF_FREE (vg); + goto out; + } + vgname++; + ret = xlator_set_option (xl, "export", vgname); + GF_FREE (vg); + if (ret) + return -1; + } else { + xl = volgen_graph_add (graph, "storage/posix", volname); + if (!xl) + return -1; - ret = check_and_add_debug_xl (graph, set_dict, volname, "posix"); - if (ret) - return -1; + ret = xlator_set_option (xl, "directory", path); + if (ret) + return -1; + ret = xlator_set_option (xl, "volume-id", + uuid_utoa (volinfo->volume_id)); + if (ret) + return -1; + + ret = check_and_add_debug_xl (graph, set_dict, volname, + "posix"); + if (ret) + return -1; + } xl = volgen_graph_add (graph, "features/access-control", volname); if (!xl) return -1; diff --git a/xlators/mgmt/glusterd/src/glusterd-volume-ops.c b/xlators/mgmt/glusterd/src/glusterd-volume-ops.c index d42694353..8c76c8f09 100644 --- a/xlators/mgmt/glusterd/src/glusterd-volume-ops.c +++ b/xlators/mgmt/glusterd/src/glusterd-volume-ops.c @@ -12,6 +12,10 @@ #include "config.h" #endif +#ifdef HAVE_BD_XLATOR +#include +#endif + #include "common-utils.h" #include "syscall.h" #include "cli1-xdr.h" @@ -554,6 +558,36 @@ out: return ret; } +#ifdef HAVE_BD_XLATOR +int +glusterd_is_valid_vg (const char *name) +{ + lvm_t handle = NULL; + vg_t vg = NULL; + char *vg_name = NULL; + int retval = -1; + + handle = lvm_init (NULL); + if (!handle) { + gf_log ("", GF_LOG_ERROR, "lvm_init failed"); + return -1; + } + vg_name = gf_strdup (name); + vg = lvm_vg_open (handle, basename (vg_name), "r", 0); + if (!vg) { + gf_log ("", GF_LOG_ERROR, "no such vg: %s", vg_name); + goto out; + } + retval = 0; +out: + if (vg) + lvm_vg_close (vg); + lvm_quit (handle); + GF_FREE (vg_name); + return retval; +} +#endif + /* op-sm */ int glusterd_op_stage_create_volume (dict_t *dict, char **op_errstr) @@ -575,7 +609,9 @@ glusterd_op_stage_create_volume (dict_t *dict, char **op_errstr) char msg[2048] = {0}; uuid_t volume_uuid; char *volume_uuid_str; - +#ifdef HAVE_BD_XLATOR + char *dev_type = NULL; +#endif this = THIS; if (!this) { gf_log ("glusterd", GF_LOG_ERROR, @@ -625,6 +661,11 @@ glusterd_op_stage_create_volume (dict_t *dict, char **op_errstr) goto out; } + +#ifdef HAVE_BD_XLATOR + ret = dict_get_str (dict, "device", &dev_type); +#endif + ret = dict_get_str (dict, "bricks", &bricks); if (ret) { gf_log ("", GF_LOG_ERROR, "Unable to get bricks"); @@ -670,6 +711,19 @@ glusterd_op_stage_create_volume (dict_t *dict, char **op_errstr) goto out; } +#ifdef HAVE_BD_XLATOR + if (dev_type) { + ret = glusterd_is_valid_vg (brick_info->path); + if (ret) { + snprintf (msg, sizeof(msg), "invalid vg %s", + brick_info->path); + *op_errstr = gf_strdup (msg); + goto out; + } + + break; + } else +#endif if (!uuid_compare (brick_info->uuid, MY_UUID)) { ret = glusterd_brick_create_path (brick_info->hostname, brick_info->path, @@ -1209,6 +1263,9 @@ glusterd_op_create_volume (dict_t *dict, char **op_errstr) char *str = NULL; char *username = NULL; char *password = NULL; +#ifdef HAVE_BD_XLATOR + char *device = NULL; +#endif this = THIS; GF_ASSERT (this); @@ -1261,6 +1318,12 @@ glusterd_op_create_volume (dict_t *dict, char **op_errstr) goto out; } +#ifdef HAVE_BD_XLATOR + ret = dict_get_str (dict, "device", &device); + if (!ret) + volinfo->backend = GD_VOL_BK_BD; +#endif + /* replica-count 1 means, no replication, file is in one brick only */ volinfo->replica_count = 1; /* stripe-count 1 means, no striping, file is present as a whole */ diff --git a/xlators/mgmt/glusterd/src/glusterd.h b/xlators/mgmt/glusterd/src/glusterd.h index 95353f065..ea0ea6061 100644 --- a/xlators/mgmt/glusterd/src/glusterd.h +++ b/xlators/mgmt/glusterd/src/glusterd.h @@ -229,6 +229,12 @@ struct _auth { typedef struct _auth auth_t; +typedef enum glusterd_vol_backend_ { + GD_VOL_BK_DEFAULT = 0, /* POSIX */ + GD_VOL_BK_BD = 1, +} glusterd_vol_backend_t; + + struct glusterd_volinfo_ { char volname[GLUSTERD_MAX_VOLUME_NAME]; int type; @@ -278,6 +284,7 @@ struct glusterd_volinfo_ { xlator_t *xl; gf_boolean_t memory_accounting; + glusterd_vol_backend_t backend; }; typedef enum gd_node_type_ { -- cgit