summaryrefslogtreecommitdiffstats
path: root/rpc/block_svc_routines.c
diff options
context:
space:
mode:
authorPrasanna Kumar Kalever <prasanna.kalever@redhat.com>2017-02-05 20:23:20 +0530
committerPrasanna Kumar Kalever <prasanna.kalever@redhat.com>2017-02-07 13:29:05 +0530
commit23b12455796ec453ca35e94ab49e7629d7f9aced (patch)
tree0d69ce51ad68b56a753fa8e4a021bec2a3cc5f4a /rpc/block_svc_routines.c
parentbbcbaf494ad406ceea4f0175b91cf67966d32a27 (diff)
gluster-block: migrate build to libtoolz and create rpm
Till now we had simple makefile for checking dependencies and building. Using libtoolz will give more control on dependency checks and flexibility. This patch also introduce rpm build feature. Compiling: $ ./autogen.sh $ ./configure $ make -j $ make install Building RPMS: $ make rpms Running: $ systemctl start gluster-blockd.service Using CLI: $ gluster-block help Signed-off-by: Prasanna Kumar Kalever <prasanna.kalever@redhat.com>
Diffstat (limited to 'rpc/block_svc_routines.c')
-rw-r--r--rpc/block_svc_routines.c832
1 files changed, 832 insertions, 0 deletions
diff --git a/rpc/block_svc_routines.c b/rpc/block_svc_routines.c
new file mode 100644
index 0000000..91ad630
--- /dev/null
+++ b/rpc/block_svc_routines.c
@@ -0,0 +1,832 @@
+/*
+ Copyright (c) 2016 Red Hat, Inc. <http://www.redhat.com>
+ This file is part of gluster-block.
+
+ This file is licensed to you under your choice of the GNU Lesser
+ General Public License, version 3 or any later version (LGPLv3 or
+ later), or the GNU General Public License, version 2 (GPLv2), in all
+ cases as published by the Free Software Foundation.
+*/
+
+
+# include "common.h"
+# include "glfs-operations.h"
+
+# include <netdb.h>
+# include <uuid/uuid.h>
+
+
+# define UUID_BUF_SIZE 38
+
+# define CREATE "create"
+# define DELETE "delete"
+
+# define GLFS_PATH "/backstores/user:glfs"
+# define TARGETCLI_GLFS "targetcli "GLFS_PATH
+# define TARGETCLI_ISCSI "targetcli /iscsi"
+# define TARGETCLI_SAVE "targetcli / saveconfig"
+# define ATTRIBUTES "generate_node_acls=1 demo_mode_write_protect=0"
+# define IQN_PREFIX "iqn.2016-12.org.gluster-block:"
+
+# define MSERVER_DELIMITER ","
+
+
+
+int
+glusterBlockCallRPC_1(char *host, void *cobj,
+ operations opt, char **out)
+{
+ CLIENT *clnt = NULL;
+ int ret = -1;
+ int sockfd;
+ blockResponse *reply;
+ struct hostent *server;
+ struct sockaddr_in sain;
+
+
+ if ((sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
+ LOG("mgmt", GB_LOG_ERROR, "socket creation failed (%s)",
+ strerror (errno));
+ goto out;
+ }
+
+ server = gethostbyname(host);
+ if (!server) {
+ LOG("mgmt", GB_LOG_ERROR, "gethostbyname failed (%s)",
+ strerror (errno));
+ goto out;
+ }
+
+ bzero((char *) &sain, sizeof(sain));
+ sain.sin_family = AF_INET;
+ bcopy((char *)server->h_addr, (char *)&sain.sin_addr.s_addr,
+ server->h_length);
+ sain.sin_port = htons(24006);
+
+ if (connect(sockfd, (struct sockaddr *) &sain, sizeof(sain)) < 0) {
+ LOG("mgmt", GB_LOG_ERROR, "connect failed (%s)", strerror (errno));
+ goto out;
+ }
+
+ clnt = clnttcp_create ((struct sockaddr_in *) &sain, GLUSTER_BLOCK,
+ GLUSTER_BLOCK_VERS, &sockfd, 0, 0);
+ if (!clnt) {
+ LOG("mgmt", GB_LOG_ERROR, "%s, inet host %s",
+ clnt_spcreateerror("client create failed"), host);
+ goto out;
+ }
+
+ switch(opt) {
+ case CREATE_SRV:
+ reply = block_create_1((blockCreate *)cobj, clnt);
+ if (!reply) {
+ LOG("mgmt", GB_LOG_ERROR, "%s",
+ clnt_sperror(clnt, "block create failed"));
+ goto out;
+ }
+ break;
+ case DELETE_SRV:
+ reply = block_delete_1((blockDelete *)cobj, clnt);
+ if (!reply) {
+ LOG("mgmt", GB_LOG_ERROR, "%s",
+ clnt_sperror(clnt, "block delete failed"));
+ goto out;
+ }
+ break;
+ }
+
+ if (GB_STRDUP(*out, reply->out) < 0){
+ goto out;
+ }
+ ret = reply->exit;
+
+ out:
+ if (clnt) {
+ if (!reply ||
+ !clnt_freeres(clnt, (xdrproc_t)xdr_blockResponse, (char *)reply)) {
+ LOG("mgmt", GB_LOG_ERROR, "%s",
+ clnt_sperror(clnt, "clnt_freeres failed"));
+
+ clnt_destroy (clnt);
+ }
+ }
+
+ close(sockfd);
+
+ return ret;
+}
+
+
+void
+blockServerDefFree(blockServerDefPtr blkServers)
+{
+ size_t i;
+
+
+ if (!blkServers) {
+ return;
+ }
+
+ for (i = 0; i < blkServers->nhosts; i++) {
+ GB_FREE(blkServers->hosts[i]);
+ }
+ GB_FREE(blkServers->hosts);
+ GB_FREE(blkServers);
+}
+
+
+static blockServerDefPtr
+blockServerParse(char *blkServers)
+{
+ blockServerDefPtr list;
+ char *tmp = blkServers;
+ size_t i = 0;
+
+
+ if (GB_ALLOC(list) < 0) {
+ return NULL;
+ }
+
+ if (!blkServers) {
+ blkServers = "localhost";
+ }
+
+ /* count number of servers */
+ while (*tmp) {
+ if (*tmp == ',') {
+ list->nhosts++;
+ }
+ tmp++;
+ }
+ list->nhosts++;
+ tmp = blkServers; /* reset addr */
+
+
+ if (GB_ALLOC_N(list->hosts, list->nhosts) < 0) {
+ goto fail;
+ }
+
+ for (i = 0; tmp != NULL; i++) {
+ if (GB_STRDUP(list->hosts[i], strsep(&tmp, MSERVER_DELIMITER)) < 0) {
+ goto fail;
+ }
+ }
+
+ return list;
+
+ fail:
+ blockServerDefFree(list);
+ return NULL;
+}
+
+
+static void
+glusterBlockCreateRemote(struct glfs_fd *tgmfd, char *volume,
+ blockCreate *cobj, char *addr, char **reply)
+{
+ int ret;
+ char *out = NULL;
+ char *tmp = *reply;
+
+
+ GB_METAUPDATE_OR_GOTO(tgmfd, cobj->gbid, volume, ret, out,
+ "%s: CONFIGINPROGRESS\n", addr);
+
+ ret = glusterBlockCallRPC_1(addr, cobj, CREATE_SRV, &out);
+ if (ret) {
+ GB_METAUPDATE_OR_GOTO(tgmfd, cobj->gbid, volume, ret, out,
+ "%s: CONFIGFAIL\n", addr);
+ LOG("mgmt", GB_LOG_ERROR, "%s on host: %s", FAILED_CREATE, addr);
+ goto out;
+ }
+
+ GB_METAUPDATE_OR_GOTO(tgmfd, cobj->gbid, volume, ret, out,
+ "%s: CONFIGSUCCESS\n", addr);
+
+ out:
+ asprintf(reply, "%s%s\n", (tmp==NULL?"":tmp), out);
+ GB_FREE(tmp);
+ GB_FREE(out);
+}
+
+
+static int
+glusterBlockAuditRequest(struct glfs *glfs,
+ struct glfs_fd *tgmfd,
+ blockCreateCli *blk,
+ blockCreate *cobj,
+ blockServerDefPtr list,
+ char **reply)
+{
+ int ret = -1;
+ size_t i;
+ size_t successcnt = 0;
+ size_t failcnt = 0;
+ size_t spent;
+ size_t spare;
+ size_t morereq;
+ MetaInfo *info;
+
+
+ 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 GB_CONFIG_SUCCESS:
+ successcnt++;
+ break;
+ case GB_CONFIG_INPROGRESS:
+ case GB_CONFIG_FAIL:
+ failcnt++;
+ }
+ }
+
+ /* check if mpath is satisfied */
+ if (blk->mpath == successcnt) {
+ ret = 0;
+ goto out;
+ } else {
+ spent = successcnt + failcnt; /* total spent */
+ spare = list->nhosts - spent; /* spare after spent */
+ morereq = blk->mpath - successcnt; /* needed nodes to complete req */
+ if (spare == 0) {
+ LOG("mgmt", GB_LOG_WARNING, "%s",
+ "No Spare nodes: rewining the creation of target");
+ ret = -1;
+ goto out;
+ } else if (spare < morereq) {
+ LOG("mgmt", GB_LOG_WARNING, "%s",
+ "Not enough Spare nodes: rewining the creation of target");
+ ret = -1;
+ goto out;
+ } else {
+ /* create on spare */
+ LOG("mgmt", GB_LOG_INFO, "%s",
+ "trying to serve the mpath from spare machines");
+ for (i = spent; i < list->nhosts; i++) {
+ glusterBlockCreateRemote(tgmfd, info->volume, cobj,
+ list->hosts[i], reply);
+ }
+ }
+ }
+
+ ret = glusterBlockAuditRequest(glfs, tgmfd, blk, cobj, list, reply);
+
+ out:
+ blockFreeMetaInfo(info);
+ return ret;
+}
+
+
+static void
+glusterBlockDeleteRemote(struct glfs_fd *tgmfd, MetaInfo *info,
+ blockDelete *cobj, char *addr, char **reply)
+{
+ int ret = -1;
+ char *out = NULL;
+ char *tmp = *reply;
+
+
+ GB_METAUPDATE_OR_GOTO(tgmfd, info->gbid, info->volume, ret, out,
+ "%s: CLEANUPINPROGRES\n", addr);
+ ret = glusterBlockCallRPC_1(addr, cobj, DELETE_SRV, &out);
+ if (ret) {
+ GB_METAUPDATE_OR_GOTO(tgmfd, info->gbid, info->volume, ret, out,
+ "%s: CLEANUPFAIL\n", addr);
+ LOG("mgmt", GB_LOG_ERROR, "%s on host: %s",
+ FAILED_GATHERING_INFO, addr);
+ goto out;
+ }
+ GB_METAUPDATE_OR_GOTO(tgmfd, info->gbid, info->volume, ret, out,
+ "%s: CLEANUPSUCCESS\n", addr);
+
+ out:
+ asprintf(reply, "%s%s\n", (tmp==NULL?"":tmp), out);
+ GB_FREE(tmp);
+ GB_FREE(out);
+}
+
+
+static int
+glusterBlockCleanUp(struct glfs *glfs, char *blockname,
+ bool deleteall, char **reply)
+{
+ int ret = -1;
+ size_t i;
+ static blockDelete cobj;
+ struct glfs_fd *tgmfd = NULL;
+ size_t cleanupsuccess = 0;
+ MetaInfo *info;
+
+
+ if (GB_ALLOC(info) < 0) {
+ goto out;
+ }
+
+ ret = blockGetMetaInfo(glfs, blockname, info);
+ if (ret) {
+ goto out;
+ }
+
+ strcpy(cobj.block_name, blockname);
+ strcpy(cobj.gbid, info->gbid);
+
+ tgmfd = glfs_open(glfs, blockname, O_WRONLY|O_APPEND);
+ if (!tgmfd) {
+ LOG("mgmt", GB_LOG_ERROR, "%s", "glfs_open: failed");
+ goto out;
+ }
+
+ for (i = 0; i < info->nhosts; i++) {
+ switch (blockMetaStatusEnumParse(info->list[i]->status)) {
+ case GB_CLEANUP_INPROGRES:
+ case GB_CLEANUP_FAIL:
+ case GB_CONFIG_FAIL:
+ case GB_CONFIG_INPROGRESS:
+ glusterBlockDeleteRemote(tgmfd, info, &cobj,
+ info->list[i]->addr, reply);
+ break;
+ }
+ if (deleteall &&
+ blockMetaStatusEnumParse(info->list[i]->status) == GB_CONFIG_SUCCESS) {
+ glusterBlockDeleteRemote(tgmfd, info, &cobj,
+ info->list[i]->addr, reply);
+ }
+ }
+ blockFreeMetaInfo(info);
+
+ if (GB_ALLOC(info) < 0)
+ goto out;
+
+ ret = blockGetMetaInfo(glfs, blockname, info);
+ if (ret)
+ goto out;
+
+ for (i = 0; i < info->nhosts; i++) {
+ if (blockMetaStatusEnumParse(info->list[i]->status) == GB_CLEANUP_SUCCESS) {
+ cleanupsuccess++;
+ }
+ }
+
+ if (cleanupsuccess == info->nhosts) {
+ if (glusterBlockDeleteEntry(info->volume, info->gbid)) {
+ LOG("mgmt", GB_LOG_ERROR, "%s volume: %s host: %s",
+ FAILED_DELETING_FILE, info->volume, "localhost");
+ }
+ ret = glfs_unlink(glfs, blockname);
+ if (ret && errno != ENOENT) {
+ LOG("mgmt", GB_LOG_ERROR, "%s", "glfs_unlink: failed");
+ goto out;
+ }
+ }
+
+ out:
+ blockFreeMetaInfo(info);
+
+ if (glfs_close(tgmfd) != 0) {
+ LOG("mgmt", GB_LOG_ERROR, "%s", "glfs_close: failed");
+ }
+
+ return ret;
+}
+
+
+blockResponse *
+block_create_cli_1_svc(blockCreateCli *blk, struct svc_req *rqstp)
+{
+ int ret = -1;
+ size_t i;
+ uuid_t uuid;
+ char *savereply = NULL;
+ char gbid[UUID_BUF_SIZE];
+ static blockCreate cobj;
+ static blockResponse *reply;
+ struct glfs *glfs;
+ struct glfs_fd *lkfd = NULL;
+ struct glfs_fd *tgmfd = NULL;
+ blockServerDefPtr list = NULL;
+
+
+ if (GB_ALLOC(reply) < 0) {
+ goto out;
+ }
+
+ list = blockServerParse(blk->block_hosts);
+
+ /* Fail if mpath > list->nhosts */
+ if (blk->mpath > list->nhosts) {
+ LOG("mgmt", GB_LOG_ERROR, "block multipath request:%d is greater "
+ "than provided block-hosts:%s",
+ blk->mpath, blk->block_hosts);
+ asprintf(&reply->out, "multipath req: %d > block-hosts: %s\n",
+ blk->mpath, blk->block_hosts);
+ reply->exit = ENODEV;
+ goto optfail;
+ }
+
+ glfs = glusterBlockVolumeInit(blk->volume, blk->volfileserver);
+ if (!glfs) {
+ LOG("mgmt", GB_LOG_ERROR, "%s", "glusterBlockVolumeInit failed");
+ goto out;
+ }
+
+ lkfd = glusterBlockCreateMetaLockFile(glfs, blk->volume);
+ if (!lkfd) {
+ LOG("mgmt", GB_LOG_ERROR, "%s",
+ "glusterBlockCreateMetaLockFile failed");
+ goto out;
+ }
+
+ GB_METALOCK_OR_GOTO(lkfd, blk->volume, ret, out);
+
+ if (!glfs_access(glfs, blk->block_name, F_OK)) {
+ asprintf(&reply->out, "BLOCK with name: '%s' already EXIST\n",
+ blk->block_name);
+ ret = EEXIST;
+ goto exist;
+ }
+
+ tgmfd = glfs_creat(glfs, blk->block_name, O_RDWR, S_IRUSR | S_IWUSR);
+ if (!tgmfd) {
+ LOG("mgmt", GB_LOG_ERROR, "%s", "glfs_creat: failed");
+ goto out;
+ }
+
+ uuid_generate(uuid);
+ uuid_unparse(uuid, gbid);
+
+ GB_METAUPDATE_OR_GOTO(tgmfd, blk->block_name, blk->volume, ret, exist,
+ "VOLUME: %s\nGBID: %s\nSIZE: %zu\nHA: %d\n"
+ "ENTRYCREATE: INPROGRESS\n",
+ blk->volume, gbid, blk->size, blk->mpath);
+
+ ret = glusterBlockCreateEntry(blk, gbid);
+ if (ret) {
+ GB_METAUPDATE_OR_GOTO(tgmfd, blk->block_name, blk->volume, ret,
+ exist, "ENTRYCREATE: FAIL\n");
+ LOG("mgmt", GB_LOG_ERROR, "%s volume: %s host: %s",
+ FAILED_CREATING_FILE, blk->volume, blk->volfileserver);
+ goto out;
+ }
+
+ GB_METAUPDATE_OR_GOTO(tgmfd, blk->block_name, blk->volume, ret, exist,
+ "ENTRYCREATE: SUCCESS\n");
+
+ strcpy(cobj.volume, blk->volume);
+ strcpy(cobj.volfileserver, blk->volfileserver);
+ strcpy(cobj.block_name, blk->block_name);
+ cobj.size = blk->size;
+ strcpy(cobj.gbid, gbid);
+
+ for (i = 0; i < blk->mpath; i++) {
+ glusterBlockCreateRemote(tgmfd, blk->volume, &cobj,
+ list->hosts[i], &savereply);
+ }
+
+ /* Check Point */
+ ret = glusterBlockAuditRequest(glfs, tgmfd, blk,
+ &cobj, list, &savereply);
+ if (ret) {
+ LOG("mgmt", GB_LOG_ERROR, "%s",
+ "even spare nodes have exhausted rewinding");
+ ret = glusterBlockCleanUp(glfs,
+ blk->block_name, FALSE, &savereply);
+ }
+
+ out:
+ reply->out = savereply;
+
+ if (glfs_close(tgmfd) != 0)
+ LOG("mgmt", GB_LOG_ERROR, "%s", "glfs_close: failed");
+
+ exist:
+ GB_METAUNLOCK(lkfd, blk->volume, ret);
+
+ reply->exit = ret;
+
+ if (glfs_close(lkfd) != 0) {
+ LOG("mgmt", GB_LOG_ERROR, "%s", "glfs_close: failed");
+ }
+
+ glfs_fini(glfs);
+
+ optfail:
+ blockServerDefFree(list);
+
+ return reply;
+}
+
+
+blockResponse *
+block_create_1_svc(blockCreate *blk, struct svc_req *rqstp)
+{
+ FILE *fp;
+ char *backstore;
+ char *iqn;
+ char *lun;
+ char *attr;
+ char *exec;
+ blockResponse *reply = NULL;
+
+
+ asprintf(&backstore, "%s %s %s %zu %s@%s/%s %s", TARGETCLI_GLFS,
+ CREATE, blk->block_name, blk->size, blk->volume,
+ blk->volfileserver, blk->gbid, blk->gbid);
+
+ asprintf(&iqn, "%s %s %s%s", TARGETCLI_ISCSI, CREATE,
+ IQN_PREFIX, blk->gbid);
+
+
+ asprintf(&lun, "%s/%s%s/tpg1/luns %s %s/%s", TARGETCLI_ISCSI,
+ IQN_PREFIX, blk->gbid, CREATE, GLFS_PATH, blk->block_name);
+
+ asprintf(&attr, "%s/%s%s/tpg1 set attribute %s",
+ TARGETCLI_ISCSI, IQN_PREFIX, blk->gbid, ATTRIBUTES);
+
+
+ asprintf(&exec, "%s && %s && %s && %s && %s", backstore, iqn, lun,
+ attr, TARGETCLI_SAVE);
+
+ if (GB_ALLOC(reply) < 0) {
+ goto out;
+ }
+
+ if (GB_ALLOC_N(reply->out, 4096) < 0) {
+ GB_FREE(reply);
+ goto out;
+ }
+
+ fp = popen(exec, "r");
+ if (fp != NULL) {
+ size_t newLen = fread(reply->out, sizeof(char), 4096, fp);
+ if (ferror( fp ) != 0) {
+ LOG("mgmt", GB_LOG_ERROR, "Reading command %s output", exec);
+ } else {
+ reply->out[newLen++] = '\0';
+ }
+ reply->exit = WEXITSTATUS(pclose(fp));
+ }
+
+ out:
+ GB_FREE(exec);
+ GB_FREE(attr);
+ GB_FREE(lun);
+ GB_FREE(iqn);
+ GB_FREE(backstore);
+
+ return reply;
+}
+
+
+blockResponse *
+block_delete_cli_1_svc(blockDeleteCli *blk, struct svc_req *rqstp)
+{
+ int ret = -1;
+ char *savereply = NULL;
+ static blockResponse *reply = NULL;
+ struct glfs *glfs;
+ struct glfs_fd *lkfd;
+
+
+ if (GB_ALLOC(reply) < 0) {
+ return NULL;
+ }
+
+ glfs = glusterBlockVolumeInit(blk->volume, "localhost");
+ if (!glfs) {
+ LOG("mgmt", GB_LOG_ERROR, "%s", "glusterBlockVolumeInit failed");
+ goto out;
+ }
+
+ lkfd = glusterBlockCreateMetaLockFile(glfs, blk->volume);
+ if (!lkfd) {
+ LOG("mgmt", GB_LOG_ERROR, "%s",
+ "glusterBlockCreateMetaLockFile failed");
+ goto out;
+ }
+
+ GB_METALOCK_OR_GOTO(lkfd, blk->volume, ret, out);
+
+ if (glfs_access(glfs, blk->block_name, F_OK)) {
+ GB_STRDUP(reply->out, "BLOCK Doesn't EXIST");
+ reply->exit = ENOENT;
+ goto out;
+ }
+
+ ret = glusterBlockCleanUp(glfs, blk->block_name, TRUE, &savereply);
+
+ out:
+ reply->out = savereply;
+
+ GB_METAUNLOCK(lkfd, blk->volume, ret);
+
+ reply->exit = ret;
+
+ if (glfs_close(lkfd) != 0)
+ LOG("mgmt", GB_LOG_ERROR, "%s", "glfs_close: failed");
+
+ glfs_fini(glfs);
+
+ return reply;
+}
+
+
+blockResponse *
+block_delete_1_svc(blockDelete *blk, struct svc_req *rqstp)
+{
+ FILE *fp;
+ char *iqn;
+ char *backstore;
+ char *exec;
+ blockResponse *reply = NULL;
+
+
+ asprintf(&iqn, "%s %s %s%s", TARGETCLI_ISCSI, DELETE,
+ IQN_PREFIX, blk->gbid);
+
+ asprintf(&backstore, "%s %s %s", TARGETCLI_GLFS,
+ DELETE, blk->block_name);
+
+ asprintf(&exec, "%s && %s && %s", backstore, iqn, TARGETCLI_SAVE);
+
+ if (GB_ALLOC(reply) < 0) {
+ goto out;
+ }
+
+ if (GB_ALLOC_N(reply->out, 4096) < 0) {
+ GB_FREE(reply);
+ goto out;
+ }
+
+ fp = popen(exec, "r");
+ if (fp != NULL) {
+ size_t newLen = fread(reply->out, sizeof(char), 4096, fp);
+ if (ferror( fp ) != 0) {
+ LOG("mgmt", GB_LOG_ERROR, "reading command %s output", exec);
+ } else {
+ reply->out[newLen++] = '\0';
+ }
+ reply->exit = WEXITSTATUS(pclose(fp));
+ }
+
+ out:
+ GB_FREE(exec);
+ GB_FREE(backstore);
+ GB_FREE(iqn);
+
+ return reply;
+}
+
+
+blockResponse *
+block_list_cli_1_svc(blockListCli *blk, struct svc_req *rqstp)
+{
+ blockResponse *reply;
+ struct glfs *glfs;
+ struct glfs_fd *lkfd = NULL;
+ struct glfs_fd *tgmfd = NULL;
+ struct dirent *entry;
+ char *tmp = NULL;
+ char *filelist = NULL;
+ int ret = -1;
+
+
+ glfs = glusterBlockVolumeInit(blk->volume, "localhost");
+ if (!glfs) {
+ LOG("mgmt", GB_LOG_ERROR, "%s", "glusterBlockVolumeInit failed");
+ goto out;
+ }
+
+ lkfd = glusterBlockCreateMetaLockFile(glfs, blk->volume);
+ if (!lkfd) {
+ LOG("mgmt", GB_LOG_ERROR, "%s",
+ "glusterBlockCreateMetaLockFile failed");
+ goto out;
+ }
+
+ GB_METALOCK_OR_GOTO(lkfd, blk->volume, ret, out);
+
+ tgmfd = glfs_opendir (glfs, "/block-meta");
+ if (!tgmfd) {
+ LOG("mgmt", GB_LOG_ERROR, "%s", "glusterBlockVolumeInit failed");
+ goto out;
+ }
+
+ while ((entry = glfs_readdir (tgmfd))) {
+ if (strcmp(entry->d_name, ".") &&
+ strcmp(entry->d_name, "..") &&
+ strcmp(entry->d_name, "meta.lock")) {
+ asprintf(&filelist, "%s%s\n", (tmp==NULL?"":tmp), entry->d_name);
+ GB_FREE(tmp);
+ tmp = filelist;
+ }
+ }
+
+ ret = 0;
+
+ out:
+ if (GB_ALLOC(reply) < 0) {
+ return NULL;
+ }
+
+ reply->out = filelist? filelist:strdup("*Nil*\n");
+
+ glfs_closedir (tgmfd);
+
+ GB_METAUNLOCK(lkfd, blk->volume, ret);
+
+ reply->exit = ret;
+
+ if (glfs_close(lkfd) != 0) {
+ LOG("mgmt", GB_LOG_ERROR, "%s", "glfs_close: failed");
+ }
+
+ glfs_fini(glfs);
+
+ return reply;
+}
+
+
+blockResponse *
+block_info_cli_1_svc(blockInfoCli *blk, struct svc_req *rqstp)
+{
+ blockResponse *reply;
+ char *out = NULL;
+ char *tmp = NULL;
+ struct glfs *glfs;
+ struct glfs_fd *lkfd = NULL;
+ MetaInfo *info = NULL;
+ int ret = -1;
+ size_t i;
+
+
+ glfs = glusterBlockVolumeInit(blk->volume, "localhost");
+ if (!glfs) {
+ LOG("mgmt", GB_LOG_ERROR, "%s", "glusterBlockVolumeInit failed");
+ goto out;
+ }
+
+ lkfd = glusterBlockCreateMetaLockFile(glfs, blk->volume);
+ if (!lkfd) {
+ LOG("mgmt", GB_LOG_ERROR, "%s",
+ "glusterBlockCreateMetaLockFile failed");
+ goto out;
+ }
+
+ GB_METALOCK_OR_GOTO(lkfd, blk->volume, ret, out);
+
+ if (GB_ALLOC(info) < 0) {
+ goto out;
+ }
+
+ ret = blockGetMetaInfo(glfs, blk->block_name, info);
+ if (ret) {
+ goto out;
+ }
+
+ asprintf(&tmp, "NAME: %s\nVOLUME: %s\nGBID: %s\nSIZE: %zu\n"
+ "MULTIPATH: %zu\nBLOCK CONFIG NODE(S):",
+ blk->block_name, info->volume, info->gbid,
+ info->size, info->mpath);
+ for (i = 0; i < info->nhosts; i++) {
+ if (blockMetaStatusEnumParse(info->list[i]->status) == GB_CONFIG_SUCCESS) {
+ asprintf(&out, "%s %s", (tmp==NULL?"":tmp), info->list[i]->addr);
+ GB_FREE(tmp);
+ tmp = out;
+ }
+ }
+ asprintf(&out, "%s\n", tmp);
+ ret = 0;
+
+ out:
+ if (GB_ALLOC(reply) < 0) {
+ return NULL;
+ }
+
+ if (!out) {
+ asprintf(&out, "No Block with name %s", blk->block_name);
+ }
+
+ reply->out = out;
+
+ GB_METAUNLOCK(lkfd, blk->volume, ret);
+
+ reply->exit = ret;
+
+ if (glfs_close(lkfd) != 0) {
+ LOG("mgmt", GB_LOG_ERROR, "%s", "glfs_close: failed");
+ }
+
+ glfs_fini(glfs);
+
+ blockFreeMetaInfo(info);
+
+ return reply;
+}