summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPrasanna Kumar Kalever <prasanna.kalever@redhat.com>2017-01-27 23:28:59 +0530
committerPrasanna Kumar Kalever <prasanna.kalever@redhat.com>2017-01-30 19:31:50 +0530
commitf25b4e7326838c73d0a7a71bd64c8658e44f4219 (patch)
tree0be4325936644bfc7be6cec74761fc4beb305642
parentaa861a01de2f89aec61dddeba13b929222143a52 (diff)
gluster-blockd: consider spare nodes to satisfy the multipath request
In case if number of block hosts are more than the multipath request, consider that spare nodes to satify the request. Lets say we need multipath of 3, but the admin provides 5 block-hosts. If any of the node fail to configure target from first three, then consider configuring fourth node to satify the HA request. Signed-off-by: Prasanna Kumar Kalever <prasanna.kalever@redhat.com>
-rw-r--r--glfs-operations.c26
-rw-r--r--glfs-operations.h19
-rw-r--r--gluster-block.c10
-rw-r--r--gluster-blockd.c168
-rw-r--r--rpc/block.h1
-rw-r--r--rpc/block.x1
-rw-r--r--rpc/block_xdr.c2
-rw-r--r--utils.c37
-rw-r--r--utils.h44
9 files changed, 229 insertions, 79 deletions
diff --git a/glfs-operations.c b/glfs-operations.c
index d567605..d530096 100644
--- a/glfs-operations.c
+++ b/glfs-operations.c
@@ -145,24 +145,6 @@ glusterBlockCreateMetaLockFile(struct glfs *glfs)
}
-static int
-blockEnumParse(const char *opt)
-{
- int i;
-
- if (!opt) {
- return METAKEY__MAX;
- }
-
- for (i = 0; i < METAKEY__MAX; i++) {
- if (!strcmp(opt, MetakeyLookup[i])) {
- return i;
- }
- }
-
- return i;
-}
-
void
blockFreeMetaInfo(MetaInfo *info)
{
@@ -175,6 +157,7 @@ blockFreeMetaInfo(MetaInfo *info)
GB_FREE(info);
}
+
static void
blockStuffMetaInfo(MetaInfo *info, char *line)
{
@@ -183,7 +166,7 @@ blockStuffMetaInfo(MetaInfo *info, char *line)
int Flag = 0;
size_t i;
- switch (blockEnumParse(opt)) {
+ switch (blockMetaKeyEnumParse(opt)) {
case GBID:
strcpy(info->gbid, strchr(line, ' ')+1);
break;
@@ -228,7 +211,7 @@ blockStuffMetaInfo(MetaInfo *info, char *line)
GB_FREE(tmp);
}
-void
+int
blockGetMetaInfo(struct glfs* glfs, char* metafile, MetaInfo *info)
{
size_t count = 0;
@@ -239,6 +222,7 @@ blockGetMetaInfo(struct glfs* glfs, char* metafile, MetaInfo *info)
tgfd = glfs_open(glfs, metafile, O_RDWR);
if (!tgfd) {
ERROR("%s", "glfs_open failed");
+ return -1;
}
while (glfs_read (tgfd, line, 48, 0) > 0) {
@@ -249,4 +233,6 @@ blockGetMetaInfo(struct glfs* glfs, char* metafile, MetaInfo *info)
}
glfs_close(tgfd);
+
+ return 0;
}
diff --git a/glfs-operations.h b/glfs-operations.h
index c2bf076..abfcb27 100644
--- a/glfs-operations.h
+++ b/glfs-operations.h
@@ -22,15 +22,6 @@
# include "rpc/block.h"
-typedef enum Metakey {
- GBID = 0,
- SIZE = 1,
- HA = 2,
- ENTRYCREATE = 3,
-
- METAKEY__MAX = 4 /* Updata this when add new Key */
-} Metakey;
-
typedef struct NodeInfo {
char addr[255];
@@ -47,14 +38,6 @@ typedef struct MetaInfo {
NodeInfo **list;
} MetaInfo;
-static const char *const MetakeyLookup[] = {
- [GBID] = "GBID",
- [SIZE] = "SIZE",
- [HA] = "HA",
- [ENTRYCREATE] = "ENTRYCREATE",
- [METAKEY__MAX] = NULL,
-};
-
struct glfs *
glusterBlockVolumeInit(char *volume, char *volfileserver);
@@ -68,7 +51,7 @@ glusterBlockDeleteEntry(char *volume, char *gbid);
struct glfs_fd *
glusterBlockCreateMetaLockFile(struct glfs *glfs);
-void
+int
blockGetMetaInfo(struct glfs *glfs, char *metafile, MetaInfo *info);
void
diff --git a/gluster-block.c b/gluster-block.c
index b8e64b9..af131a1 100644
--- a/gluster-block.c
+++ b/gluster-block.c
@@ -115,6 +115,7 @@ glusterBlockHelp(void)
" -c, --create <name> Create the gluster block\n"
" -h, --host <gluster-node> node addr from gluster pool\n"
" -s, --size <size> block storage size in KiB|MiB|GiB|TiB..\n"
+ " -m, --multipath <count> multi path requirement for high availablity\n"
"\n"
" -l, --list List available gluster blocks\n"
"\n"
@@ -151,6 +152,7 @@ glusterBlockCreate(int count, char **options, char *name)
{"volume", required_argument, 0, 'v'},
{"host", required_argument, 0, 'h'},
{"size", required_argument, 0, 's'},
+ {"multipath", required_argument, 0, 'm'},
{"block-host", required_argument, 0, 'b'},
{0, 0, 0, 0}
};
@@ -165,9 +167,15 @@ glusterBlockCreate(int count, char **options, char *name)
break;
switch (c) {
+ case 'm':
+ sscanf(optarg, "%u", &cobj.mpath);
+ ret++;
+ break;
+
case 'b':
if (GB_STRDUP(cobj.block_hosts, optarg) < 0)
return -1;
+ ret++;
break;
case 'v':
@@ -211,7 +219,7 @@ glusterBlockCreate(int count, char **options, char *name)
goto out;
}
- if (ret != 3) {
+ if (ret != 5) {
ERROR("%s", "Insufficient arguments supplied for"
"'gluster-block create'\n");
ret = -1;
diff --git a/gluster-blockd.c b/gluster-blockd.c
index 27602fa..3e0ab91 100644
--- a/gluster-blockd.c
+++ b/gluster-blockd.c
@@ -173,15 +173,108 @@ fail:
return NULL;
}
+static int
+block_create_remote(struct glfs_fd *tgfd, blockCreate *cobj, char *addr, char **reply)
+{
+ char *write = NULL;
+ char *out = NULL;
+ char *tmp = NULL;
+ int ret;
+
+ METAUPDATE(tgfd, write, "%s: CONFIGINPROGRESS\n", addr);
+
+ ret = gluster_block_1(addr, cobj, CREATE_SRV, &out);
+ if (ret) {
+ METAUPDATE(tgfd, write, "%s: CONFIGFAIL\n", addr);
+ ERROR("%s on host: %s", FAILED_CREATE, addr);
+
+ *reply = out;
+ goto out;
+ }
+
+ METAUPDATE(tgfd, write, "%s: CONFIGSUCCESS\n", addr);
+
+ asprintf(reply, "%s%s\n", (tmp==NULL?"":tmp), out);
+ if (tmp)
+ GB_FREE(tmp);
+ tmp = *reply;
+ GB_FREE(out);
+
+ out:
+ return ret;
+}
+
+static int
+block_cross_check_request(struct glfs *glfs,
+ struct glfs_fd *tgfd,
+ blockCreateCli *blk,
+ blockCreate *cobj,
+ blockServerDefPtr list,
+ char **reply)
+{
+ MetaInfo *info;
+ size_t success_count = 0;
+ size_t fail_count = 0;
+ size_t spent;
+ size_t spare;
+ size_t morereq;
+ size_t i;
+ int ret;
+
+ if (GB_ALLOC(info) < 0)
+ goto out;
+
+ ret = blockGetMetaInfo(glfs, blk->block_name, info);
+ if(ret)
+ goto out;
+
+ for (i = 0; i < info->nhosts; i++) {
+ switch (blockMetaStatusEnumParse(info->list[i]->status)) {
+ case CONFIGSUCCESS:
+ success_count++;
+ break;
+ case CONFIGINPROGRESS:
+ case CONFIGFAIL:
+ fail_count++;
+ }
+ }
+
+ /* check if mpath is satisfied */
+ if(blk->mpath == success_count) {
+ return 0;
+ } else {
+ spent = success_count + fail_count; /* total spent */
+ spare = list->nhosts - spent; /* spare after spent */
+ morereq = blk->mpath - success_count; /* needed nodes to complete req */
+ if (spare == 0) {
+ ERROR("%s", "No Spare nodes: rewining the creation of target");
+ return -1;
+ } else if (spare < morereq) {
+ ERROR("%s", "Not enough Spare nodes: rewining the creation of target");
+ return -1;
+ } else {
+ /* create on spare */
+ MSG("%s", "trying to serve the mpath from spare machines");
+ for(i = spent; i < list->nhosts; i++) {
+ block_create_remote(tgfd, cobj, list->hosts[i], reply);
+ }
+ }
+ }
+
+ blockFreeMetaInfo(info);
+ ret = block_cross_check_request(glfs, tgfd, blk, cobj, list, reply);
+
+ out:
+ return ret;
+}
+
blockResponse *
block_create_cli_1_svc(blockCreateCli *blk, struct svc_req *rqstp)
{
int ret = -1;
size_t i = 0;
- char *out = NULL;
char *savereply = NULL;
- char *tmp = NULL;
uuid_t uuid;
static blockCreate *cobj;
static blockResponse *reply = NULL;
@@ -210,9 +303,6 @@ block_create_cli_1_svc(blockCreateCli *blk, struct svc_req *rqstp)
uuid_generate(uuid);
uuid_unparse(uuid, gbid);
- if(GB_ALLOC(reply) < 0)
- goto out;
-
if (!glfs_access(glfs, blk->block_name, F_OK)) {
GB_STRDUP(reply->out, "BLOCK Already EXIST");
@@ -227,8 +317,8 @@ block_create_cli_1_svc(blockCreateCli *blk, struct svc_req *rqstp)
}
METAUPDATE(tgfd, write,
- "GBID: %s\nSIZE: %zu\nHA: %d\nENTRYCREATE: INPROGRESS\n",
- gbid, blk->size, 1);
+ "GBID: %s\nSIZE: %zu\nHA: %d\nENTRYCREATE: CONFIGINPROGRESS\n",
+ gbid, blk->size, blk->mpath);
ret = glusterBlockCreateEntry(blk, gbid);
if (ret) {
@@ -237,7 +327,7 @@ block_create_cli_1_svc(blockCreateCli *blk, struct svc_req *rqstp)
goto out;
}
- METAUPDATE(tgfd, write, "ENTRYCREATE: SUCCESS\n");
+ METAUPDATE(tgfd, write, "ENTRYCREATE: CONFIGSUCCESS\n");
if(GB_ALLOC(cobj) < 0)
goto out;
@@ -250,29 +340,22 @@ block_create_cli_1_svc(blockCreateCli *blk, struct svc_req *rqstp)
list = blockServerParse(blk->block_hosts);
- for (i = 0; i < list->nhosts; i++) {
- METAUPDATE(tgfd, write, "%s: INPROGRESS\n", list->hosts[i]);
+ /* TODO: Fail if mpath > list->nhosts */
- ret = gluster_block_1(list->hosts[i], cobj, CREATE_SRV, &out);
- if (ret) {
- METAUPDATE(tgfd, write, "%s: FAIL\n", list->hosts[i]);
- ERROR("%s on host: %s",
- FAILED_CREATE, list->hosts[i]);
- }
+ for (i = 0; i < blk->mpath; i++) {
+ block_create_remote(tgfd, cobj, list->hosts[i], &savereply);
+ }
- METAUPDATE(tgfd, write, "%s: SUCCESS\n", list->hosts[i]);
+ /* Check Point */
+ ret = block_cross_check_request(glfs, tgfd, blk, cobj, list, &savereply);
- asprintf(&savereply, "%s%s\n", (tmp==NULL?"":tmp), out);
- if (tmp)
- GB_FREE(tmp);
- tmp = savereply;
- GB_FREE(out);
- }
+out:
+ if(GB_ALLOC(reply) < 0)
+ goto out;
reply->out = savereply;
reply->exit = ret;
-out:
if (glfs_close(tgfd) != 0)
ERROR("%s", "glfs_close: failed");
@@ -395,7 +478,9 @@ block_delete_cli_1_svc(blockDeleteCli *blk, struct svc_req *rqstp)
if (GB_ALLOC(info) < 0)
goto out;
- blockGetMetaInfo(glfs, blk->block_name, info);
+ ret = blockGetMetaInfo(glfs, blk->block_name, info);
+ if(ret)
+ goto out;
if(GB_ALLOC(cobj) < 0)
goto out;
@@ -428,13 +513,13 @@ block_delete_cli_1_svc(blockDeleteCli *blk, struct svc_req *rqstp)
FAILED_DELETING_FILE, blk->volume, "localhost");
}
+ out:
if (GB_ALLOC(reply) < 0)
goto out;
reply->out = savereply;
reply->exit = ret;
-out:
if (glfs_close(tgfd) != 0)
ERROR("%s", "glfs_close: failed");
@@ -547,13 +632,14 @@ block_list_cli_1_svc(blockListCli *blk, struct svc_req *rqstp)
}
}
- if (GB_ALLOC(reply) < 0)
- goto out;
-
- reply->out = filelist;
ret = 0;
out:
+ if (GB_ALLOC(reply) < 0)
+ goto out;
+
+ reply->out = filelist? filelist:strdup("*Nil*");
+ reply->exit = ret;
glfs_closedir (tgfd);
@@ -564,8 +650,6 @@ out:
glfs_fini(glfs);
- reply->exit = ret;
-
return reply;
}
@@ -574,6 +658,7 @@ blockResponse *
block_info_cli_1_svc(blockInfoCli *blk, struct svc_req *rqstp)
{
blockResponse *reply = NULL;
+ char *out = NULL;
struct glfs *glfs;
struct glfs_fd *lkfd;
struct flock lock = {0, };
@@ -597,17 +682,24 @@ block_info_cli_1_svc(blockInfoCli *blk, struct svc_req *rqstp)
if (GB_ALLOC(info) < 0)
goto out;
- blockGetMetaInfo(glfs, blk->block_name, info);
-
- if (GB_ALLOC(reply) < 0)
+ ret = blockGetMetaInfo(glfs, blk->block_name, info);
+ if(ret)
goto out;
- asprintf(&reply->out, "NAME: %s\nVOLUME: %s\nGBID: %s\nSIZE: %zu\nMULTIPATH: %zu",
+ asprintf(&out, "NAME: %s\nVOLUME: %s\nGBID: %s\nSIZE: %zu\nMULTIPATH: %zu\n",
blk->block_name, blk->volume, info->gbid, info->size, info->mpath);
-
ret = 0;
out:
+ if (GB_ALLOC(reply) < 0)
+ goto out;
+
+ if(!out)
+ asprintf(&out, "No Block with name %s", blk->block_name);
+
+ reply->out = out;
+ reply->exit = ret;
+
METAUNLOCK(lock, lkfd);
if (glfs_close(lkfd) != 0)
@@ -617,7 +709,5 @@ block_info_cli_1_svc(blockInfoCli *blk, struct svc_req *rqstp)
blockFreeMetaInfo(info);
- reply->exit = ret;
-
return reply;
}
diff --git a/rpc/block.h b/rpc/block.h
index 98ec806..9c3ee9e 100644
--- a/rpc/block.h
+++ b/rpc/block.h
@@ -28,6 +28,7 @@ struct blockCreateCli {
char volume[255];
char volfileserver[255];
u_quad_t size;
+ u_int mpath;
char block_name[255];
char *block_hosts;
};
diff --git a/rpc/block.x b/rpc/block.x
index 21c30aa..a5dce19 100644
--- a/rpc/block.x
+++ b/rpc/block.x
@@ -10,6 +10,7 @@ struct blockCreateCli {
char volume[255];
char volfileserver[255];
u_quad_t size;
+ u_int mpath; /* HA request count */
char block_name[255];
string block_hosts<>;
};
diff --git a/rpc/block_xdr.c b/rpc/block_xdr.c
index 3bc0afc..8d05f3a 100644
--- a/rpc/block_xdr.c
+++ b/rpc/block_xdr.c
@@ -36,6 +36,8 @@ xdr_blockCreateCli (XDR *xdrs, blockCreateCli *objp)
return FALSE;
if (!xdr_u_quad_t (xdrs, &objp->size))
return FALSE;
+ if (!xdr_u_int (xdrs, &objp->mpath))
+ return FALSE;
if (!xdr_vector (xdrs, (char *)objp->block_name, 255,
sizeof (char), (xdrproc_t) xdr_char))
return FALSE;
diff --git a/utils.c b/utils.c
index 9e71a73..aa2e3b8 100644
--- a/utils.c
+++ b/utils.c
@@ -12,6 +12,43 @@
# include "utils.h"
+int
+blockMetaKeyEnumParse(const char *opt)
+{
+ int i;
+
+ if (!opt) {
+ return METAKEY__MAX;
+ }
+
+ for (i = 0; i < METAKEY__MAX; i++) {
+ if (!strcmp(opt, MetakeyLookup[i])) {
+ return i;
+ }
+ }
+
+ return i;
+}
+
+
+int
+blockMetaStatusEnumParse(const char *opt)
+{
+ int i;
+
+ if (!opt) {
+ return METASTATUS__MAX;
+ }
+
+ for (i = 0; i < METASTATUS__MAX; i++) {
+ if (!strcmp(opt, MetaStatusLookup[i])) {
+ return i;
+ }
+ }
+
+ return i;
+}
+
int
gbAlloc(void *ptrptr, size_t size,
diff --git a/utils.h b/utils.h
index d4801ae..6a98e67 100644
--- a/utils.h
+++ b/utils.h
@@ -91,7 +91,49 @@
# define GB_FREE(ptr) gbFree(1 ? (void *) &(ptr) : (ptr))
-
+typedef enum Metakey {
+ GBID = 0,
+ SIZE = 1,
+ HA = 2,
+ ENTRYCREATE = 3,
+
+ METAKEY__MAX = 4 /* Updata this when add new Key */
+} Metakey;
+
+static const char *const MetakeyLookup[] = {
+ [GBID] = "GBID",
+ [SIZE] = "SIZE",
+ [HA] = "HA",
+ [ENTRYCREATE] = "ENTRYCREATE",
+ [METAKEY__MAX] = NULL,
+};
+
+typedef enum MetaStatus {
+ CONFIGSUCCESS = 0,
+ CONFIGFAIL = 1,
+ CONFIGINPROGRESS = 2,
+ CLEANUPSUCCESS = 3,
+ CLEANUPFAIL = 4,
+ CLEANUPINPROGRES = 5,
+
+ METASTATUS__MAX = 6 /* Updata this when add new Status type */
+} MetaStatus;
+
+static const char *const MetaStatusLookup[] = {
+ [CONFIGINPROGRESS] = "CONFIGINPROGRESS",
+ [CONFIGSUCCESS] = "CONFIGSUCCESS",
+ [CONFIGFAIL] = "CONFIGFAIL",
+ [CLEANUPINPROGRES] = "CLEANUPINPROGRESS",
+ [CLEANUPSUCCESS] = "CLEANUPSUCCESS",
+ [CLEANUPFAIL] = "CLEANUPFAIL",
+
+ [METASTATUS__MAX] = NULL,
+};
+
+
+int blockMetaKeyEnumParse(const char *opt);
+
+int blockMetaStatusEnumParse(const char *opt);
int gbAlloc(void *ptrptr, size_t size,
const char *filename, const char *funcname, size_t linenr);