From 698dbaced0b0a1bb2ff2d02c2eb31f248cf4a893 Mon Sep 17 00:00:00 2001 From: Xiubo Li Date: Fri, 31 May 2019 09:40:01 +0800 Subject: [PATCH] blksize: add hw block size setting support This will still need to depend the taregetcli's saveconfig support, the rtslib PR is open-iscsi/rtslib-fb#150. When creating the BV with the 'block-size ' option: In case all the ha nodes have supported the rtslib-fb#150: 1) if local node support the block-size, but if there is any of the remote nodes is not, it will fail with the cap not match error. 2) if local node does not support the block-size, no matter whether the remote nodes support it or not, it will always ignore the block-size option due to the exist bug. In case if there is any of the ha nodes does not support rtslib-fb#150: 3) if local node support the block-size, it will always fails with the cap not match error. 4) if local mode does not support the block-size, no matter whether the remote nodes support it or not, it will ignore the block-size option due to the exist bug. Signed-off-by: Xiubo Li Reviewed-by: Prasanna Kumar Kalever --- README.md | 3 +- cli/gluster-block.c | 27 +++++- daemon/gluster-blockd.c | 69 ++-------------- docs/gluster-block.8 | 10 ++- rpc/block_svc_routines.c | 151 ++++++++++++++++++++++++++-------- rpc/glfs-operations.c | 3 + rpc/glfs-operations.h | 1 + rpc/rpcl/block.x | 1 + tests/basic.t | 4 + utils/capabilities.c | 37 ++++++++- utils/capabilities.h | 3 + utils/common.c | 20 +++-- utils/common.h | 2 +- utils/gluster-block-caps.info | 11 +++ utils/utils.c | 65 +++++++++++++++ utils/utils.h | 24 ++++++ version.h | 8 +- 17 files changed, 323 insertions(+), 116 deletions(-) diff --git a/README.md b/README.md index f651569..61710b3 100644 --- a/README.md +++ b/README.md @@ -74,9 +74,10 @@ commands: [prealloc ] [storage ] [ring-buffer ] + [block-size ] [size] create block device [defaults: ha 1, auth disable, prealloc full, size in bytes, - ring-buffer default size dependends on kernel] + ring-buffer and block-size default size dependends on kernel] list list available block devices. diff --git a/cli/gluster-block.c b/cli/gluster-block.c index ce72b6d..412d02c 100644 --- a/cli/gluster-block.c +++ b/cli/gluster-block.c @@ -18,6 +18,7 @@ "[ha ] [auth ] " \ "[prealloc ] [storage ] " \ "[ring-buffer ] " \ + "[block-size ] " \ " [size] [--json*]" # define GB_DELETE_HELP_STR "gluster-block delete " \ "[unlink-storage ] [force] [--json*]" @@ -296,9 +297,10 @@ glusterBlockHelp(void) " [prealloc ]\n" " [storage ]\n" " [ring-buffer ]\n" + " [block-size ]\n" " [size]\n" " create block device [defaults: ha 1, auth disable, prealloc full, size in bytes,\n" - " ring-buffer default size dependends on kernel]\n" + " ring-buffer and block-size default size dependends on kernel]\n" "\n" " list \n" " list available block devices.\n" @@ -527,7 +529,7 @@ glusterBlockModify(int argcount, char **options, int json) } } else if (!strcmp(options[optind], "size")) { optind++; - sparse_ret = glusterBlockParseSize("cli", options[optind++]); + sparse_ret = glusterBlockParseSize("cli", options[optind++], 0); if (sparse_ret < 0) { MSG(stderr, "'' is incorrect"); MSG(stderr, GB_MODIFY_HELP_STR); @@ -669,6 +671,25 @@ glusterBlockCreate(int argcount, char **options, int json) goto out; } break; + case GB_CLI_CREATE_BLKSIZE: + if (isNumber(options[optind])) { + sscanf(options[optind++], "%u", &cobj.blk_size); + if (cobj.blk_size % 512) { + MSG(stderr, "'block-size' should be aligned to 512 bytes"); + MSG(stderr, GB_CREATE_HELP_STR); + LOG("cli", GB_LOG_ERROR, + "failed while parsing block-size aligned to 512 bytes for block <%s/%s>", + cobj.volume, cobj.block_name); + goto out; + } + } else { + MSG(stderr, "'block-size' option is incorrect, hint: should be uint type"); + MSG(stderr, GB_CREATE_HELP_STR); + LOG("cli", GB_LOG_ERROR, "failed while parsing block-size for block <%s/%s>", + cobj.volume, cobj.block_name); + goto out; + } + break; } } @@ -717,7 +738,7 @@ glusterBlockCreate(int argcount, char **options, int json) } if (TAKE_SIZE) { - sparse_ret = glusterBlockParseSize("cli", options[optind]); + sparse_ret = glusterBlockParseSize("cli", options[optind], cobj.blk_size); if (sparse_ret < 0) { MSG(stderr, "'[size]' is incorrect"); MSG(stderr, GB_CREATE_HELP_STR); diff --git a/daemon/gluster-blockd.c b/daemon/gluster-blockd.c index 66cb656..678d203 100644 --- a/daemon/gluster-blockd.c +++ b/daemon/gluster-blockd.c @@ -34,8 +34,6 @@ "logfile=%s auto_save_on_exit=false " \ "max_backup_files=100" -# define VERNUM_BUFLEN 8 - # define GB_DISTRO_CHECK "grep -P '(^ID=)' /etc/os-release" @@ -426,65 +424,6 @@ gbMinKernelVersionCheck(void) } -static bool -gbDependencyVersionCompare(int dependencyName, char *version) -{ - size_t vNum[VERNUM_BUFLEN] = {0, }; - char *verStr; - int i = 0, j; - char *token, *tmp; - bool done = false; - bool ret = false; - - - if (GB_STRDUP(verStr, version) < 0) { - LOG("mgmt", GB_LOG_ERROR, - "gbDependencyVersionCompare: failed to strdup (%s)", strerror(errno)); - return ret; - } - - token = strtok(verStr, ".-"); - while( token != NULL ) { - done = false; - for (j = 0; j < strlen(token); j++) { /* say if version is 2.1.fb49, parse fb49 */ - if (isdigit(token[j])) { - vNum[i] = atoi(token); - } else { - tmp = token; - for(; *tmp; ++tmp) { - if (isdigit(*tmp)) { - vNum[i] = atoi(tmp); /* feed 49 from fb49, so done = true */ - done = true; - break; - } - } - } - if (done) { - break; - } - } - token = strtok(NULL, ".-"); - i++; - } - - switch (dependencyName) { - case TCMURUNNER: - if (DEPENDENCY_VERSION(vNum[0], vNum[1], vNum[2]) >= GB_MIN_TCMURUNNER_VERSION_CODE) { - ret = true; - } - break; - case TARGETCLI: - if (DEPENDENCY_VERSION(vNum[0], vNum[1], vNum[2]) >= GB_MIN_TARGETCLI_VERSION_CODE) { - ret = true; - } - break; - } - - GB_FREE(verStr); - return ret; -} - - static void gbDependenciesVersionCheck(void) { @@ -511,6 +450,14 @@ gbDependenciesVersionCheck(void) LOG("mgmt", GB_LOG_INFO, "starting with targetcli version - %s", out); GB_FREE(out); + out = gbRunnerGetOutput("python -c 'from rtslib_fb import __version__; print(__version__)'"); + if (!strcmp(out, "GIT_VERSION")) { + LOG("mgmt", GB_LOG_INFO, "starting with rtslib version <= 2.1.69"); + } else { + LOG("mgmt", GB_LOG_INFO, "starting with rtslib version - %s", out); + } + GB_FREE(out); + return; out: diff --git a/docs/gluster-block.8 b/docs/gluster-block.8 index d7c2a88..43f1c75 100644 --- a/docs/gluster-block.8 +++ b/docs/gluster-block.8 @@ -26,7 +26,7 @@ Note that the gluster-blockd daemon is responsible for block management, hence t .SH COMMANDS .SS -\fBcreate\fR [ha ] [auth ] [prealloc ] [storage ] [ring-buffer ] [BYTES] +\fBcreate\fR [ha ] [auth ] [prealloc ] [storage ] [ring-buffer ] [block-size ] [BYTES] create block device. .TP [ha ] @@ -44,6 +44,9 @@ existing file(only name) in the gluster volume, that needs to be linked while cr [ring-buffer ] kernel ring buffer size for exchanging iSCSI commands, range [1MB - 64MB] (default: as per kernel) .TP +[block-size ] +kernel hw block size, aligns to 512 (default: as per kernel) +.TP servers in the pool where targets will be exported .TP @@ -134,9 +137,12 @@ To create a thinly-provisioned block device of size 1GiB To create a block device with existing file in blockVol .B # gluster-block create blockVol/sampleBlock storage 3c242959-9238-4ce0-a1ed-19086aa23c7b ${HOST} -To create a block device with ring buffer size 16MB +To create a block device with ring buffer size 16MiB .B # gluster-block create blockVol/sampleBlock ring-buffer 16 ${HOST} 1GiB +To create a block device with block size 1024 +.B # gluster-block create blockVol/sampleBlock block-size 1024 ${HOST} 1GiB + To create a block device of size 1GiB with multi-path(replica) 3 .B # gluster-block create blockVol/sampleBlock ha 3 ${HOST1},${HOST2},${HOST3} 1GiB diff --git a/rpc/block_svc_routines.c b/rpc/block_svc_routines.c index edd390a..e637f55 100644 --- a/rpc/block_svc_routines.c +++ b/rpc/block_svc_routines.c @@ -46,6 +46,7 @@ # define GB_ALUA_AO_TPG_NAME "glfs_tg_pt_gp_ao" # define GB_ALUA_ANO_TPG_NAME "glfs_tg_pt_gp_ano" # define GB_RING_BUFFER_STR "max_data_area_mb" +# define GB_BLOCK_SIZE_STR "hw_block_size" #define GB_CMD_TIME_OUT 130 @@ -538,7 +539,8 @@ glusterBlockCallRPC_1(char *host, void *cobj, cblk_v2 = (blockCreate2 *)cobj; GB_STRCPYSTATIC(cblk_v2->ipaddr, host); - if (cblk_v2->rb_size || cblk_v2->prio_path[0]) { + if (GB_XDATA_IS_MAGIC(((struct gbXdata*)cblk_v2->xdata.xdata_val)->magic) || + cblk_v2->rb_size || cblk_v2->prio_path[0]) { *rpc_sent = TRUE; if (block_create_v2_1(cblk_v2, &reply, clnt) != RPC_SUCCESS) { LOG("mgmt", GB_LOG_ERROR, "%son host %s", @@ -857,9 +859,11 @@ blockRemoteCapabilitiesRespParse(size_t count, blockRemoteObj *args, break; } } + if (!CAP_MATCH) { - GB_ASPRINTF(errMsg, "capability '%s' doesn't exit on %s", - gbCapabilitiesLookup[i], args[j].addr); + GB_ASPRINTF(errMsg, "the capability '%s' is not supported on host %s yet, %s.", + gbCapabilitiesLookup[i], args[j].addr, + i == GB_CREATE_BLOCK_SIZE_CAP ? "please upgrade rtslib >= 2.1.70" : "please upgrade"); if (resultCaps) { resultCaps[i] = true; break; @@ -900,11 +904,6 @@ glusterBlockCapabilityRemoteAsync(blockServerDef *servers, bool *minCaps, size_t i; - /* skip if nhosts = 1 */ - if (!servers || (servers->nhosts <= 1)) { - return 0; - } - if (GB_ALLOC_N(tid, servers->nhosts) < 0) { goto out; } @@ -1668,6 +1667,9 @@ glusterBlockBuildMinCaps(void *data, operations opt) if (cblk->rb_size) { minCaps[GB_CREATE_RING_BUFFER_CAP] = true; } + if (cblk->blk_size) { + minCaps[GB_CREATE_BLOCK_SIZE_CAP] = true; + } minCaps[GB_CREATE_LOAD_BALANCE_CAP] = true; if (cblk->json_resp) { minCaps[GB_JSON_CAP] = true; @@ -1732,8 +1734,7 @@ glusterBlockCheckCapabilities(void* blk, operations opt, blockServerDefPtr list, char *localErrMsg = NULL; - /* skip if nhosts = 1 */ - if (!list || (list->nhosts <= 1)) { + if (!list) { return 0; } @@ -1913,6 +1914,7 @@ glusterBlockReplaceNodeRemoteAsync(struct glfs *glfs, blockReplaceCli *blk, blockCreate2 *cobj = NULL; blockDelete *dobj = NULL; blockReplace *robj = NULL; + struct gbXdata *xdata = NULL; bool Flag = false; bool cCheck = false; bool dCheck = false; @@ -1937,8 +1939,27 @@ glusterBlockReplaceNodeRemoteAsync(struct glfs *glfs, blockReplaceCli *blk, goto out; } - cobj->xdata.xdata_len = strlen(gbConf->volServer); - cobj->xdata.xdata_val = (char *) gbConf->volServer; + if (info->blk_size) { // Create V3 + unsigned int len; + struct gbCreate3 *gbCreate3; + + len = sizeof(struct gbXdata) + sizeof(struct gbCreate3); + if (GB_ALLOC_N(xdata, len) < 0) { + goto out; + } + + xdata->magic = GB_XDATA_GEN_MAGIC(3); + gbCreate3 = (struct gbCreate3 *)(&xdata->data); + GB_STRCPY(gbCreate3->volServer, (char *)gbConf->volServer, sizeof(gbConf->volServer)); + gbCreate3->blk_size = info->blk_size; + + cobj->xdata.xdata_len = len; + cobj->xdata.xdata_val = (char *)xdata; + } else { // Create V2 + cobj->xdata.xdata_len = strlen(gbConf->volServer); + cobj->xdata.xdata_val = (char *) gbConf->volServer; + } + GB_STRCPYSTATIC(cobj->ipaddr, blk->new_node); GB_STRCPYSTATIC(cobj->volume, info->volume); GB_STRCPYSTATIC(cobj->gbid, info->gbid); @@ -2184,6 +2205,7 @@ glusterBlockReplaceNodeRemoteAsync(struct glfs *glfs, blockReplaceCli *blk, reply = NULL; } GB_FREE(tid); + GB_FREE(xdata); GB_FREE(cobj); GB_FREE(dobj); GB_FREE(robj); @@ -2674,6 +2696,7 @@ getSoObj(char *block, MetaInfo *info, blockGenConfigCli *blk) struct json_object *so_obj_alua_ano_tpg; struct json_object *so_obj_alua_tpgs_arr; struct json_object *so_obj_attr = json_object_new_object(); + int n = 0; // "alua_tpgs": [ @@ -2722,7 +2745,15 @@ getSoObj(char *block, MetaInfo *info, blockGenConfigCli *blk) } json_object_object_add(so_obj, "config", GB_JSON_OBJ_TO_STR(cfgstr[0]?cfgstr:NULL)); if (info->rb_size) { - snprintf(control, 1024, "%s=%zu", GB_RING_BUFFER_STR, info->rb_size); + n = snprintf(control, 1024, "%s=%zu", GB_RING_BUFFER_STR, info->rb_size); + } + if (info->blk_size) { + if (n) { + control[n++] = ','; + } + snprintf(control + n, 1024 - n, "%s=%zu", GB_BLOCK_SIZE_STR, info->blk_size); + } + if (control[0]) { json_object_object_add(so_obj, "control", GB_JSON_OBJ_TO_STR(control[0]?control:NULL)); } json_object_object_add(so_obj, "name", GB_JSON_OBJ_TO_STR(block)); @@ -3608,6 +3639,15 @@ block_modify_size_cli_1_svc_st(blockModifySizeCli *blk, struct svc_req *rqstp) goto out; } + if (info->blk_size && (blk->size % info->blk_size)) { + GB_ASPRINTF(&errMsg, "size (%lu) is incorrect, it should be aligned to block size (%lu)", + blk->size, info->blk_size); + LOG("mgmt", GB_LOG_ERROR, + "size (%lu) is incorrect, it should be aligned to block size (%lu)", + blk->size, info->blk_size); + goto out; + } + if ((info->size > blk->size && !blk->force) || info->size == blk->size) { cSize = glusterBlockFormatSize("mgmt", info->size); rSize = glusterBlockFormatSize("mgmt", blk->size); @@ -3876,12 +3916,14 @@ block_create_cli_1_svc_st(blockCreateCli *blk, struct svc_req *rqstp) char *errMsg = NULL; blockCreate2 cobj = {{0},}; bool *resultCaps = NULL; + struct gbXdata *xdata = NULL; LOG("mgmt", GB_LOG_INFO, "create cli request, volume=%s blockname=%s mpath=%d blockhosts=%s " - "authmode=%d size=%lu, rbsize=%d", blk->volume, blk->block_name, blk->mpath, - blk->block_hosts, blk->auth_mode, blk->size, blk->rb_size); + "authmode=%d size=%lu, rbsize=%d, blksize=%d", blk->volume, + blk->block_name, blk->mpath, blk->block_hosts, blk->auth_mode, blk->size, + blk->rb_size, blk->blk_size); if (GB_ALLOC(reply) < 0) { return NULL; @@ -3981,8 +4023,8 @@ 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, - "SIZE: %zu\nRINGBUFFER: %d\nENTRYCREATE: SUCCESS\n", - blk->size, blk->rb_size); + "SIZE: %zu\nRINGBUFFER: %u\nBLKSIZE: %u\nENTRYCREATE: SUCCESS\n", + blk->size, blk->rb_size, blk->blk_size); GB_STRCPYSTATIC(cobj.volume, blk->volume); GB_STRCPYSTATIC(cobj.block_name, blk->block_name); @@ -3990,8 +4032,27 @@ block_create_cli_1_svc_st(blockCreateCli *blk, struct svc_req *rqstp) cobj.rb_size = blk->rb_size; GB_STRCPYSTATIC(cobj.gbid, gbid); GB_STRDUP(cobj.block_hosts, blk->block_hosts); - cobj.xdata.xdata_len = strlen(gbConf->volServer); - cobj.xdata.xdata_val = (char *) gbConf->volServer; + + if (blk->blk_size) { // Create V3 + unsigned int len; + struct gbCreate3 *gbCreate3; + + len = sizeof(struct gbXdata) + sizeof(struct gbCreate3); + if (GB_ALLOC_N(xdata, len) < 0) { + goto exist; + } + + xdata->magic = GB_XDATA_GEN_MAGIC(3); + gbCreate3 = (struct gbCreate3 *)(&xdata->data); + GB_STRCPY(gbCreate3->volServer, (char *)gbConf->volServer, sizeof(gbConf->volServer)); + gbCreate3->blk_size = blk->blk_size; + + cobj.xdata.xdata_len = len; + cobj.xdata.xdata_val = (char *)xdata; + } else { // Create V2 + cobj.xdata.xdata_len = strlen(gbConf->volServer); + cobj.xdata.xdata_val = (char *)gbConf->volServer; + } if (blk->auth_mode) { uuid_generate(uuid); @@ -4045,6 +4106,7 @@ block_create_cli_1_svc_st(blockCreateCli *blk, struct svc_req *rqstp) blockCreateParsedRespFree(savereply); GB_FREE (cobj.block_hosts); GB_FREE(resultCaps); + GB_FREE(xdata); return reply; } @@ -4279,7 +4341,7 @@ out: blockResponse * -block_create_common(blockCreate *blk, char *rbsize, char *volServer, char *prio_path) +block_create_common(blockCreate *blk, char *control, char *volServer, char *prio_path) { char *tmp = NULL; char *backstore = NULL; @@ -4320,7 +4382,7 @@ block_create_common(blockCreate *blk, char *rbsize, char *volServer, char *prio_ if (GB_ASPRINTF(&backstore, "%s %s name=%s size=%zu cfgstring=%s@%s%s/%s%s wwn=%s", GB_TGCLI_GLFS_PATH, GB_CREATE, blk->block_name, blk->size, blk->volume, volServer?volServer:blk->ipaddr, GB_STOREDIR, - blk->gbid, rbsize ? rbsize: "", blk->gbid) == -1) { + blk->gbid, control ? control : "", blk->gbid) == -1) { goto out; } @@ -4533,9 +4595,8 @@ block_create_common(blockCreate *blk, char *rbsize, char *volServer, char *prio_ GB_FREE(backstore); GB_FREE(glfs_alua); GB_FREE(glfs_alua_type); - GB_FREE(rbsize); + GB_FREE(control); GB_FREE(backstore_attr); - GB_FREE(volServer); blockServerDefFree(list); GB_FREE(glfs_alua_sup); @@ -4553,29 +4614,47 @@ block_create_1_svc_st(blockCreate *blk, struct svc_req *rqstp) blockResponse * block_create_v2_1_svc_st(blockCreate2 *blk, struct svc_req *rqstp) { - char *rbsize= NULL; + char buf[1024] = {0,}; + char *control = NULL; blockCreate blk_v1 = {{0},}; char *volServer = NULL; size_t len = blk->xdata.xdata_len; + size_t blk_size = 0; + struct gbXdata *xdata_val = (struct gbXdata*)blk->xdata.xdata_val; + struct gbCreate3 *gbCreate3 = (struct gbCreate3 *)xdata_val->data; + int n = 0; + if (len > 0 && xdata_val && GB_XDATA_IS_MAGIC(xdata_val->magic)) { + if (GB_XDATA_GET_MAGIC_VER(xdata_val->magic) == 3) { + blk_size = gbCreate3->blk_size; + volServer = gbCreate3->volServer; + } + } else if (len > 0 && len <= HOST_NAME_MAX) { + volServer = (char *)blk->xdata.xdata_val; + volServer[len] = '\0'; + } + + if (blk->rb_size || blk_size) { + n = snprintf(buf, 1024, " control="); + } if (blk->rb_size) { - GB_ASPRINTF(&rbsize, " control='%s=%d'", GB_RING_BUFFER_STR, blk->rb_size); + n += snprintf(buf + n, 1024 - n, "%s=%u,", GB_RING_BUFFER_STR, blk->rb_size); + } + + if (blk_size) { + n += snprintf(buf + n, 1024 - n, "%s=%lu", GB_BLOCK_SIZE_STR, blk_size); + } + + if (n) { + if (GB_STRDUP(control, buf) < 0) { + return NULL; + } } convertTypeCreate2ToCreate(blk, &blk_v1); - if (len > 0 && len <= HOST_NAME_MAX) { - if (strncmp(blk->xdata.xdata_val, "localhost", 9)) { - if (GB_ALLOC_N(volServer, len) < 0) - goto err; - strncpy(volServer, blk->xdata.xdata_val, len); - } - } - return block_create_common(&blk_v1, rbsize, volServer, blk->prio_path); - -err: - return NULL; + return block_create_common(&blk_v1, control, volServer, blk->prio_path); } diff --git a/rpc/glfs-operations.c b/rpc/glfs-operations.c index dadc514..0b434ff 100644 --- a/rpc/glfs-operations.c +++ b/rpc/glfs-operations.c @@ -606,6 +606,9 @@ blockStuffMetaInfo(MetaInfo *info, char *line) case GB_META_RINGBUFFER: sscanf(strchr(line, ' '), "%zu", &info->rb_size); break; + case GB_META_BLKSIZE: + sscanf(strchr(line, ' '), "%zu", &info->blk_size); + break; case GB_META_HA: sscanf(strchr(line, ' '), "%zu", &info->mpath); break; diff --git a/rpc/glfs-operations.h b/rpc/glfs-operations.h index 0b3e564..bbc5fa4 100644 --- a/rpc/glfs-operations.h +++ b/rpc/glfs-operations.h @@ -33,6 +33,7 @@ typedef struct MetaInfo { char gbid[38]; size_t size; size_t rb_size; + size_t blk_size; char prio_path[255]; size_t mpath; char entry[16]; /* possible strings for ENTRYCREATE: INPROGRESS|SUCCESS|FAIL */ diff --git a/rpc/rpcl/block.x b/rpc/rpcl/block.x index 7ddb544..0a3dd9f 100644 --- a/rpc/rpcl/block.x +++ b/rpc/rpcl/block.x @@ -66,6 +66,7 @@ struct blockCreateCli { char volume[255]; u_quad_t size; u_int rb_size; /* TCMU Ring Buffer size in kernel */ + u_int blk_size; /* TCMU hw block size in kernel */ u_int mpath; /* HA request count */ bool auth_mode; bool prealloc; diff --git a/tests/basic.t b/tests/basic.t index 99ddc52..a1f17e9 100755 --- a/tests/basic.t +++ b/tests/basic.t @@ -125,6 +125,10 @@ TEST gluster-block delete ${VOLNAME}/${BLKNAME} TEST gluster-block create ${VOLNAME}/${BLKNAME} ring-buffer 32 ${HOST} 1MiB TEST gluster-block delete ${VOLNAME}/${BLKNAME} +# Block create with 'block-size' set/delete +TEST gluster-block create ${VOLNAME}/${BLKNAME} block-size 1024 ${HOST} 1MiB +TEST gluster-block delete ${VOLNAME}/${BLKNAME} + # Block create with 'storage' set and delete with 'unlink-storage no' set TEST gluster-block create ${VOLNAME}/${BLKNAME} ${HOST} 1MiB LINK=`eval gluster-block info ${VOLNAME}/${BLKNAME} | grep GBID | awk -F' ' '{print $2}'` diff --git a/utils/capabilities.c b/utils/capabilities.c index 778539f..fcbbfdc 100644 --- a/utils/capabilities.c +++ b/utils/capabilities.c @@ -10,6 +10,7 @@ # include "capabilities.h" +# include "version.h" gbCapObj *globalCapabilities; @@ -35,6 +36,23 @@ gbCapabilitiesEnumParse(const char *cap) } +static bool +gbBlockSizeDependenciesVersionCheck(void) +{ + char *out = NULL; + int ret = true; + + + out = gbRunnerGetOutput("python -c 'from rtslib_fb import __version__; print(__version__)'"); + if (!gbDependencyVersionCompare(RTSLIB_BLKSIZE, out)) { + ret = false; + } + + GB_FREE(out); + return ret; +} + + void gbSetCapabilties(void) { @@ -50,7 +68,8 @@ gbSetCapabilties(void) fp = fopen(GB_CAPS_FILE, "r"); if (fp == NULL) { LOG("mgmt", GB_LOG_ERROR, - "gbSetCapabilties: fopen() failed (%s)", strerror(errno)); + "gbSetCapabilties: fopen(\"%s\") failed (%s)", GB_CAPS_FILE, + strerror(errno)); goto out; } @@ -78,6 +97,22 @@ gbSetCapabilties(void) if (ret != GB_CAP_MAX) { GB_STRCPYSTATIC(caps[count].cap, gbCapabilitiesLookup[ret]); + /* + * If the rtslib version doesn't support hw_block_size option + * then disable the hw_block_size capability + */ + if (ret == GB_CREATE_BLOCK_SIZE_CAP) { + if (!gbBlockSizeDependenciesVersionCheck()) { + LOG ("mgmt", GB_LOG_INFO, + "the 'hw_block_size' needs atleast rtslib >= %s, so disable its capability", + GB_MIN_RTSLIB_BLKSIZE_VERSION); + caps[count].status = 0; + count++; + GB_FREE(line); + continue; + } + } + /* Part after ':' and before '\n' */ p = sep + 1; sep = strchr(p, '\n'); diff --git a/utils/capabilities.h b/utils/capabilities.h index a878a73..19169ec 100644 --- a/utils/capabilities.h +++ b/utils/capabilities.h @@ -46,6 +46,8 @@ enum gbCapabilities { GB_JSON_CAP, + GB_CREATE_BLOCK_SIZE_CAP, + GB_CAP_MAX }; @@ -57,6 +59,7 @@ static const char *const gbCapabilitiesLookup[] = { [GB_CREATE_AUTH_CAP] = "create_auth", [GB_CREATE_RING_BUFFER_CAP] = "create_ring_buffer", [GB_CREATE_LOAD_BALANCE_CAP] = "create_load_balance", + [GB_CREATE_BLOCK_SIZE_CAP] = "create_block_size", [GB_DELETE_CAP] = "delete", [GB_DELETE_FORCE_CAP] = "delete_force", diff --git a/utils/common.c b/utils/common.c index 40d0ee8..f9ce81f 100644 --- a/utils/common.c +++ b/utils/common.c @@ -45,7 +45,7 @@ jsonResponseFormatParse(const char *opt) (_a - (_a % _b)); }) ssize_t -glusterBlockParseSize(const char *dom, char *value) +glusterBlockParseSize(const char *dom, char *value, int blksize) { char *postfix; char *tmp; @@ -66,6 +66,10 @@ glusterBlockParseSize(const char *dom, char *value) tmp = tmp + 1; } + if (!blksize) { + blksize = GB_DEFAULT_SECTOR_SIZE; + } + switch (tolower(*tmp)) { case 'y': sizef *= 1024; @@ -93,20 +97,20 @@ glusterBlockParseSize(const char *dom, char *value) /* fall through */ case 'b': case '\0': - if (sizef < GB_DEFAULT_SECTOR_SIZE) { - MSG(stderr, "minimum acceptable block size is %d bytes", GB_DEFAULT_SECTOR_SIZE); + if (sizef < blksize) { + MSG(stderr, "minimum acceptable block size is %d bytes", blksize); LOG(dom, GB_LOG_ERROR, "minimum acceptable block size is %d bytes", - GB_DEFAULT_SECTOR_SIZE); + blksize); return -1; } - if (sizef % GB_DEFAULT_SECTOR_SIZE) { + if (sizef % blksize) { MSG(stdout, "The size %ld will align to sector size %d bytes", - sizef, GB_DEFAULT_SECTOR_SIZE); + sizef, blksize); LOG(dom, GB_LOG_ERROR, "The target device size %ld will align to the sector size %d", - sizef, GB_DEFAULT_SECTOR_SIZE); - sizef = round_down(sizef, GB_DEFAULT_SECTOR_SIZE); + sizef, blksize); + sizef = round_down(sizef, blksize); } break; default: diff --git a/utils/common.h b/utils/common.h index d281a88..6c75c9f 100644 --- a/utils/common.h +++ b/utils/common.h @@ -97,7 +97,7 @@ void strToCharArrayDefFree(strToCharArrayDefPtr arr); enum JsonResponseFormat jsonResponseFormatParse(const char *opt); -ssize_t glusterBlockParseSize(const char *dom, char *value); +ssize_t glusterBlockParseSize(const char *dom, char *value, int blksize); char* glusterBlockFormatSize(const char *dom, size_t bytes); diff --git a/utils/gluster-block-caps.info b/utils/gluster-block-caps.info index f8b39c6..c2697ad 100644 --- a/utils/gluster-block-caps.info +++ b/utils/gluster-block-caps.info @@ -138,3 +138,14 @@ create_ring_buffer: true # Since: 0.4 ## create_load_balance: true + +## +# Nature: cli sub-command +# +# Label: 'block-size' +# +# Description: capability to create block with given block size +# +# Since: 0.5 +## +create_block_size: true diff --git a/utils/utils.c b/utils/utils.c index 75d991b..358b65d 100644 --- a/utils/utils.c +++ b/utils/utils.c @@ -19,6 +19,7 @@ # include "utils.h" # include "lru.h" # include "config.h" +# include "version.h" const char *argp_program_version = "" \ PACKAGE_NAME" ("PACKAGE_VERSION")" \ @@ -348,6 +349,70 @@ fetchGlfsVolServerFromEnv() } +bool +gbDependencyVersionCompare(int dependencyName, char *version) +{ + size_t vNum[VERNUM_BUFLEN] = {0, }; + char *verStr; + int i = 0, j; + char *token, *tmp; + bool done = false; + bool ret = false; + + + if (GB_STRDUP(verStr, version) < 0) { + LOG("mgmt", GB_LOG_ERROR, + "gbDependencyVersionCompare: failed to strdup (%s)", strerror(errno)); + return ret; + } + + token = strtok(verStr, ".-"); + while( token != NULL ) { + done = false; + for (j = 0; j < strlen(token); j++) { /* say if version is 2.1.fb49, parse fb49 */ + if (isdigit(token[j])) { + vNum[i] = atoi(token); + } else { + tmp = token; + for(; *tmp; ++tmp) { + if (isdigit(*tmp)) { + vNum[i] = atoi(tmp); /* feed 49 from fb49, so done = true */ + done = true; + break; + } + } + } + if (done) { + break; + } + } + token = strtok(NULL, ".-"); + i++; + } + + switch (dependencyName) { + case TCMURUNNER: + if (DEPENDENCY_VERSION(vNum[0], vNum[1], vNum[2]) >= GB_MIN_TCMURUNNER_VERSION_CODE) { + ret = true; + } + break; + case TARGETCLI: + if (DEPENDENCY_VERSION(vNum[0], vNum[1], vNum[2]) >= GB_MIN_TARGETCLI_VERSION_CODE) { + ret = true; + } + break; + case RTSLIB_BLKSIZE: + if (DEPENDENCY_VERSION(vNum[0], vNum[1], vNum[2]) >= GB_MIN_RTSLIB_BLKSIZE_VERSION_CODE) { + ret = true; + } + break; + } + + GB_FREE(verStr); + return ret; +} + + static int glusterLogrotateConfigSet(char *logDir) { diff --git a/utils/utils.h b/utils/utils.h index 33c2700..0c797f7 100644 --- a/utils/utils.h +++ b/utils/utils.h @@ -26,6 +26,7 @@ # include # include # include +# include # include "list.h" @@ -157,6 +158,22 @@ struct gbConf { char volServer[HOST_NAME_MAX]; }; +# define GB_XDATA_MAGIC_NUM 0xABCD2019DCBA +# define GB_XDATA_GET_MAGIC_NUM(magic) ((magic) >> 16) +# define GB_XDATA_GET_MAGIC_VER(magic) ((magic) & 0xFFFF) +# define GB_XDATA_GEN_MAGIC(ver) ((GB_XDATA_MAGIC_NUM << 16) | ((ver) & 0xFFFF)) +# define GB_XDATA_IS_MAGIC(magic) (GB_XDATA_GET_MAGIC_NUM(magic) == GB_XDATA_MAGIC_NUM) + +struct gbXdata { + uint64_t magic; + char data[]; +}; + +struct gbCreate3 { + char volServer[HOST_NAME_MAX]; + size_t blk_size; +}; + extern struct gbConf *gbConf; # define LOG(str, level, fmt, ...) \ @@ -447,6 +464,7 @@ typedef enum gbCliCreateOptions { GB_CLI_CREATE_PREALLOC = 3, GB_CLI_CREATE_STORAGE = 4, GB_CLI_CREATE_RBSIZE = 5, + GB_CLI_CREATE_BLKSIZE = 6, GB_CLI_CREATE_OPT_MAX } gbCliCreateOptions; @@ -458,6 +476,7 @@ static const char *const gbCliCreateOptLookup[] = { [GB_CLI_CREATE_PREALLOC] = "prealloc", [GB_CLI_CREATE_STORAGE] = "storage", [GB_CLI_CREATE_RBSIZE] = "ring-buffer", + [GB_CLI_CREATE_BLKSIZE] = "block-size", [GB_CLI_CREATE_OPT_MAX] = NULL, }; @@ -530,6 +549,7 @@ typedef enum Metakey { GB_META_PASSWD = 6, GB_META_RINGBUFFER = 7, GB_META_PRIOPATH = 8, + GB_META_BLKSIZE = 9, GB_METAKEY_MAX } Metakey; @@ -544,6 +564,7 @@ static const char *const MetakeyLookup[] = { [GB_META_PASSWD] = "PASSWORD", [GB_META_RINGBUFFER] = "RINGBUFFER", [GB_META_PRIOPATH] = "PRIOPATH", + [GB_META_BLKSIZE] = "BLKSIZE", [GB_METAKEY_MAX] = NULL }; @@ -632,6 +653,7 @@ typedef struct gbConfig { typedef enum gbDependencies { TCMURUNNER = 1, TARGETCLI = 2, + RTSLIB_BLKSIZE = 3, } gbDependencies; int initGbConfig(void); @@ -659,6 +681,8 @@ void logTimeNow(char* buf, size_t bufSize); void fetchGlfsVolServerFromEnv(void); +bool gbDependencyVersionCompare(int dependencyName, char *version); + bool glusterBlockSetLogDir(char *logDir); int initLogging(void); diff --git a/version.h b/version.h index d3c5b8a..f5040fc 100644 --- a/version.h +++ b/version.h @@ -20,13 +20,15 @@ # define GLUSTER_BLOCK_VERSION "0.4" +# define VERNUM_BUFLEN 8 /* Other dependencies versions */ # define GB_MIN_TCMURUNNER_VERSION "1.1.3" # define GB_MIN_TARGETCLI_VERSION "2.1.fb49" +# define GB_MIN_RTSLIB_BLKSIZE_VERSION "2.1.69" -# define GB_MIN_TCMURUNNER_VERSION_CODE 65795 -# define GB_MIN_TARGETCLI_VERSION_CODE 131377 - +# define GB_MIN_TCMURUNNER_VERSION_CODE DEPENDENCY_VERSION(1, 1, 3) +# define GB_MIN_TARGETCLI_VERSION_CODE DEPENDENCY_VERSION(2, 1, 49) +# define GB_MIN_RTSLIB_BLKSIZE_VERSION_CODE DEPENDENCY_VERSION(2, 1, 69) # endif /* _VERSION_H */