From 450f7e89116ed104f092dd1a709c0f057150a4f7 Mon Sep 17 00:00:00 2001 From: Prasanna Kumar Kalever Date: Wed, 7 Feb 2018 21:40:13 +0530 Subject: create: support [storage ] option $ gluster-block help gluster-block (0.3) usage: gluster-block [] [--json*] commands: create [ha ] [auth ] [prealloc ] [storage ] create block device [defaults: ha 1, auth disable, prealloc no, size in bytes] [...] supported JSON formats: --json|--json-plain|--json-spaced|--json-pretty Fixes: #18 Change-Id: I5d9b4abb58596bd2297cffb294c6d31f752d53e9 Signed-off-by: Prasanna Kumar Kalever --- cli/gluster-block.c | 106 +++++++++++++++++++++++++++-------------------- rpc/block_svc_routines.c | 6 +-- rpc/glfs-operations.c | 57 ++++++++++++++++++++++++- rpc/rpcl/block.x | 1 + utils/utils.c | 20 +++++++++ utils/utils.h | 22 ++++++++++ 6 files changed, 163 insertions(+), 49 deletions(-) diff --git a/cli/gluster-block.c b/cli/gluster-block.c index 33d4003..dcf22a1 100644 --- a/cli/gluster-block.c +++ b/cli/gluster-block.c @@ -16,13 +16,13 @@ # define GB_CREATE_HELP_STR "gluster-block create " \ "[ha ] [auth ] " \ - "[prealloc ] " \ - " [--json*]" - -# define GB_DELETE_HELP_STR "gluster-block delete [force] [--json*]" + "[prealloc ] [storage ] " \ + " [--json*]" +# define GB_DELETE_HELP_STR "gluster-block delete " \ + "[force] [--json*]" # define GB_MODIFY_HELP_STR "gluster-block modify " \ " [--json*]" -# define GB_REPLACE_HELP_STR "gluster-block replace " \ +# define GB_REPLACE_HELP_STR "gluster-block replace " \ " [force] [--json*]" # define GB_INFO_HELP_STR "gluster-block info [--json*]" # define GB_LIST_HELP_STR "gluster-block list [--json*]" @@ -202,6 +202,7 @@ glusterBlockHelp(void) " create [ha ]\n" " [auth ]\n" " [prealloc ]\n" + " [storage ]\n" " \n" " create block device [defaults: ha 1, auth disable, prealloc no, size in bytes]\n" "\n" @@ -356,6 +357,8 @@ glusterBlockCreate(int argcount, char **options, int json) int ret = -1; ssize_t sparse_ret; blockCreateCli cobj = {0, }; + bool TAKE_SIZE=true; + bool PREALLOC_OPT=false; if (argcount <= optind) { @@ -373,18 +376,12 @@ glusterBlockCreate(int argcount, char **options, int json) goto out; } - if (argcount - optind >= 2) { /* atleast 2 needed */ - /* if ha given then collect count which is next by 'ha' arg */ - if (!strcmp(options[optind], "ha")) { - optind++; + while (argcount - optind > 2) { + switch (glusterBlockCLICreateOptEnumParse(options[optind++])) { + case GB_CLI_CREATE_HA: sscanf(options[optind++], "%u", &cobj.mpath); - } - } - - if (argcount - optind >= 2) { /* atleast 2 needed */ - /* if auth given then collect boolean which is next by 'auth' arg */ - if (!strcmp(options[optind], "auth")) { - optind++; + break; + case GB_CLI_CREATE_AUTH: ret = convertStringToTrillianParse(options[optind++]); if(ret >= 0) { cobj.auth_mode = ret; @@ -396,16 +393,12 @@ glusterBlockCreate(int argcount, char **options, int json) cobj.volume, cobj.block_name); goto out; } - } - } - - if (argcount - optind >= 2) { /* atleast 2 needed */ - /* if prealloc given then collect boolean which is next by 'prealloc' arg */ - if (!strcmp(options[optind], "prealloc")) { - optind++; + break; + case GB_CLI_CREATE_PREALLOC: ret = convertStringToTrillianParse(options[optind++]); if(ret >= 0) { cobj.prealloc = ret; + PREALLOC_OPT=true; } else { MSG("%s\n", "'prealloc' option is incorrect"); MSG("%s\n", GB_CREATE_HELP_STR); @@ -414,39 +407,64 @@ glusterBlockCreate(int argcount, char **options, int json) cobj.volume, cobj.block_name); goto out; } + break; + case GB_CLI_CREATE_STORAGE: + GB_STRCPYSTATIC(cobj.storage, options[optind++]); + TAKE_SIZE=false; + break; } } - if (argcount - optind < 2) { /* left with servers and size so 2 */ - MSG("Inadequate arguments for create:\n%s\n", GB_CREATE_HELP_STR); - LOG("cli", GB_LOG_ERROR, - "failed creating block %s on volume %s with hosts %s", - cobj.block_name, cobj.volume, cobj.block_hosts); - goto out; + if (TAKE_SIZE) { + if (argcount - optind != 2) { + MSG("Inadequate arguments for create:\n%s\n", GB_CREATE_HELP_STR); + LOG("cli", GB_LOG_ERROR, + "failed with Inadequate args for create block %s on volume %s with hosts %s", + cobj.block_name, cobj.volume, cobj.block_hosts); + goto out; + } + } else { + if (PREALLOC_OPT) { + MSG("Inadequate arguments for create:\n%s\n", GB_CREATE_HELP_STR); + MSG("%s\n", "Hint: do not use [prealloc ] in combination with [storage ] option"); + LOG("cli", GB_LOG_ERROR, + "failed with Inadequate args for create block %s on volume %s with hosts %s", + cobj.block_name, cobj.volume, cobj.block_hosts); + goto out; + } + + if (argcount - optind != 1) { + MSG("Inadequate arguments for create:\n%s\n", GB_CREATE_HELP_STR); + MSG("%s\n", "Hint: do not use in combination with [storage ] option"); + LOG("cli", GB_LOG_ERROR, + "failed with Inadequate args for create block %s on volume %s with hosts %s", + cobj.block_name, cobj.volume, cobj.block_hosts); + goto out; + } } - /* next arg to 'ha count' will be servers */ if (GB_STRDUP(cobj.block_hosts, options[optind++]) < 0) { LOG("cli", GB_LOG_ERROR, "failed while parsing servers for block <%s/%s>", cobj.volume, cobj.block_name); goto out; } - /* last arg will be size */ - sparse_ret = glusterBlockParseSize("cli", options[optind]); - if (sparse_ret < 0) { - MSG("%s\n", "'' is incorrect"); - MSG("%s\n", GB_CREATE_HELP_STR); - LOG("cli", GB_LOG_ERROR, "failed while parsing size for block <%s/%s>", - cobj.volume, cobj.block_name); - goto out; - } else if (sparse_ret < GB_DEFAULT_SECTOR_SIZE) { - MSG("minimum acceptable block size is %d bytes\n", GB_DEFAULT_SECTOR_SIZE); - LOG("cli", GB_LOG_ERROR, "minimum acceptable block size is %d bytes <%s/%s>", - GB_DEFAULT_SECTOR_SIZE, cobj.volume, cobj.block_name); - goto out; + if (TAKE_SIZE) { + sparse_ret = glusterBlockParseSize("cli", options[optind]); + if (sparse_ret < 0) { + MSG("%s\n", "'' is incorrect"); + MSG("%s\n", GB_CREATE_HELP_STR); + LOG("cli", GB_LOG_ERROR, "failed while parsing size for block <%s/%s>", + cobj.volume, cobj.block_name); + goto out; + } else if (sparse_ret < GB_DEFAULT_SECTOR_SIZE) { + MSG("minimum acceptable block size is %d bytes\n", GB_DEFAULT_SECTOR_SIZE); + LOG("cli", GB_LOG_ERROR, "minimum acceptable block size is %d bytes <%s/%s>", + GB_DEFAULT_SECTOR_SIZE, cobj.volume, cobj.block_name); + goto out; + } + cobj.size = sparse_ret; /* size is unsigned long long */ } - cobj.size = sparse_ret; /* size is unsigned long long */ ret = glusterBlockCliRPC_1(&cobj, CREATE_CLI); if (ret) { diff --git a/rpc/block_svc_routines.c b/rpc/block_svc_routines.c index 0c32293..f6f532b 100644 --- a/rpc/block_svc_routines.c +++ b/rpc/block_svc_routines.c @@ -3009,9 +3009,9 @@ block_create_cli_1_svc_st(blockCreateCli *blk, struct svc_req *rqstp) GB_METAUPDATE_OR_GOTO(lock, glfs, blk->block_name, blk->volume, errCode, errMsg, exist, - "VOLUME: %s\nGBID: %s\nSIZE: %zu\n" + "VOLUME: %s\nGBID: %s\n" "HA: %d\nENTRYCREATE: INPROGRESS\n", - blk->volume, gbid, blk->size, blk->mpath); + blk->volume, gbid, blk->mpath); if (glusterBlockCreateEntry(glfs, blk, gbid, &errCode, &errMsg)) { LOG("mgmt", GB_LOG_ERROR, "%s volume: %s host: %s", @@ -3020,7 +3020,7 @@ block_create_cli_1_svc_st(blockCreateCli *blk, struct svc_req *rqstp) } GB_METAUPDATE_OR_GOTO(lock, glfs, blk->block_name, blk->volume, - errCode, errMsg, exist, "ENTRYCREATE: SUCCESS\n"); + errCode, errMsg, exist, "SIZE: %zu\nENTRYCREATE: SUCCESS\n", blk->size); GB_STRCPYSTATIC(cobj.volume, blk->volume); GB_STRCPYSTATIC(cobj.block_name, blk->block_name); diff --git a/rpc/glfs-operations.c b/rpc/glfs-operations.c index 838d3c7..341a6e2 100644 --- a/rpc/glfs-operations.c +++ b/rpc/glfs-operations.c @@ -91,6 +91,7 @@ glusterBlockCreateEntry(struct glfs *glfs, blockCreateCli *blk, char *gbid, int *errCode, char **errMsg) { struct glfs_fd *tgfd; + struct stat st; char *tmp; int ret; @@ -112,6 +113,56 @@ glusterBlockCreateEntry(struct glfs *glfs, blockCreateCli *blk, char *gbid, goto out; } + if (strlen(blk->storage)) { + ret = glfs_stat(glfs, blk->storage, &st); + if (ret) { + *errCode = errno; + if (*errCode == ENOENT) { + LOG("mgmt", GB_LOG_ERROR, + "storage file '/block-store/%s' doesn't exist in volume %s", + blk->storage, blk->volume); + GB_ASPRINTF(errMsg, + "storage file '/block-store/%s' doesn't exist in volume %s\n", + blk->storage, blk->volume); + } else { + LOG("mgmt", GB_LOG_ERROR, + "glfs_stat failed on /block-store/%s in volume %s [%s]", + blk->storage, blk->volume, strerror(*errCode)); + GB_ASPRINTF(errMsg, + "glfs_stat failed on /block-store/%s in volume %s [%s]", + blk->storage, blk->volume, strerror(*errCode)); + } + goto out; + } + blk->size = st.st_size; + + if (st.st_nlink == 1) { + ret = glfs_link(glfs, blk->storage, gbid); + if (ret) { + *errCode=errno; + LOG("mgmt", GB_LOG_ERROR, + "glfs_link(%s, %s) on volume %s for block %s failed [%s]", + blk->storage, gbid, blk->volume, blk->block_name, strerror(errno)); + GB_ASPRINTF(errMsg, + "glfs_link(%s, %s) on volume %s for block %s failed [%s]", + blk->storage, gbid, strerror(errno)); + goto out; + } + } else { + *errCode = EBUSY; + LOG("mgmt", GB_LOG_ERROR, + "storage file /block-store/%s is already in use in volume %s [%s]", + blk->storage, blk->volume, strerror(*errCode)); + GB_ASPRINTF(errMsg, + "storage file /block-store/%s is already in use in volume %s [%s]\n" + "hint: delete the hardlink file, make sure file is not in use\n", + blk->storage, blk->volume, strerror(*errCode)); + ret = -1; + goto out; + } + return 0; + } + tgfd = glfs_creat(glfs, gbid, O_WRONLY | O_CREAT | O_EXCL | O_SYNC, S_IRUSR | S_IWUSR); @@ -163,8 +214,10 @@ unlink: out: if (ret) { - GB_ASPRINTF (errMsg, "Not able to create storage for %s/%s [%s]", - blk->volume, blk->block_name, strerror(*errCode)); + if (!errMsg) { + GB_ASPRINTF (errMsg, "Not able to create storage for %s/%s [%s]", + blk->volume, blk->block_name, strerror(*errCode)); + } GB_ASPRINTF(&tmp, "%s/%s", GB_METADIR, blk->block_name); diff --git a/rpc/rpcl/block.x b/rpc/rpcl/block.x index 4ad0549..e3fcbd1 100644 --- a/rpc/rpcl/block.x +++ b/rpc/rpcl/block.x @@ -47,6 +47,7 @@ struct blockCreateCli { u_int mpath; /* HA request count */ bool auth_mode; bool prealloc; + char storage[255]; char block_name[255]; string block_hosts<>; enum JsonResponseFormat json_resp; diff --git a/utils/utils.c b/utils/utils.c index 13d61cc..3f52134 100644 --- a/utils/utils.c +++ b/utils/utils.c @@ -49,6 +49,26 @@ glusterBlockCLIOptEnumParse(const char *opt) } +int +glusterBlockCLICreateOptEnumParse(const char *opt) +{ + int i; + + + if (!opt) { + return GB_CLI_CREATE_OPT_MAX; + } + + for (i = 0; i < GB_CLI_CREATE_OPT_MAX; i++) { + if (!strcmp(opt, gbCliCreateOptLookup[i])) { + return i; + } + } + + return i; +} + + int glusterBlockDaemonOptEnumParse(const char *opt) { diff --git a/utils/utils.h b/utils/utils.h index 3362c10..905b9dd 100644 --- a/utils/utils.h +++ b/utils/utils.h @@ -374,6 +374,26 @@ static const char *const gbCliCmdlineOptLookup[] = { [GB_CLI_OPT_MAX] = NULL, }; +typedef enum gbCliCreateOptions { + GB_CLI_CREATE_UNKNOWN = 0, + GB_CLI_CREATE_HA = 1, + GB_CLI_CREATE_AUTH = 2, + GB_CLI_CREATE_PREALLOC = 3, + GB_CLI_CREATE_STORAGE = 4, + + GB_CLI_CREATE_OPT_MAX +} gbCliCreateOptions; + +static const char *const gbCliCreateOptLookup[] = { + [GB_CLI_CREATE_UNKNOWN] = "NONE", + [GB_CLI_CREATE_HA] = "ha", + [GB_CLI_CREATE_AUTH] = "auth", + [GB_CLI_CREATE_PREALLOC] = "prealloc", + [GB_CLI_CREATE_STORAGE] = "storage", + + [GB_CLI_CREATE_OPT_MAX] = NULL, +}; + typedef enum gbDaemonCmdlineOption { GB_DAEMON_UNKNOWN = 0, GB_DAEMON_HELP = 1, @@ -509,6 +529,8 @@ static const char *const RemoteCreateRespLookup[] = { int glusterBlockCLIOptEnumParse(const char *opt); +int glusterBlockCLICreateOptEnumParse(const char *opt); + int glusterBlockDaemonOptEnumParse(const char *opt); int blockLogLevelEnumParse(const char *opt); -- cgit