summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cli/gluster-block.c106
-rw-r--r--rpc/block_svc_routines.c6
-rw-r--r--rpc/glfs-operations.c57
-rw-r--r--rpc/rpcl/block.x1
-rw-r--r--utils/utils.c20
-rw-r--r--utils/utils.h22
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 <volname/blockname> " \
"[ha <count>] [auth <enable|disable>] " \
- "[prealloc <full|no>] <HOST1[,HOST2,...]> " \
- "<size> [--json*]"
-
-# define GB_DELETE_HELP_STR "gluster-block delete <volname/blockname> [force] [--json*]"
+ "[prealloc <full|no>] [storage <filename>] " \
+ "<HOST1[,HOST2,...]> <size> [--json*]"
+# define GB_DELETE_HELP_STR "gluster-block delete <volname/blockname> " \
+ "[force] [--json*]"
# define GB_MODIFY_HELP_STR "gluster-block modify <volname/blockname> " \
"<auth enable|disable> [--json*]"
-# define GB_REPLACE_HELP_STR "gluster-block replace <volname/blockname> " \
+# define GB_REPLACE_HELP_STR "gluster-block replace <volname/blockname> " \
"<old-node> <new-node> [force] [--json*]"
# define GB_INFO_HELP_STR "gluster-block info <volname/blockname> [--json*]"
# define GB_LIST_HELP_STR "gluster-block list <volname> [--json*]"
@@ -202,6 +202,7 @@ glusterBlockHelp(void)
" create <volname/blockname> [ha <count>]\n"
" [auth <enable|disable>]\n"
" [prealloc <full|no>]\n"
+ " [storage <filename>]\n"
" <host1[,host2,...]> <size>\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 <full|no>] in combination with [storage <filename>] 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 <size> in combination with [storage <filename>] 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", "'<size>' 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", "'<size>' 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
@@ -50,6 +50,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)
{
int i;
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);