summaryrefslogtreecommitdiffstats
path: root/rpc/block_svc_routines.c
diff options
context:
space:
mode:
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;
+}