summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRajesh Amaravathi <rajesh@redhat.com>2011-12-07 20:51:03 +0530
committerVijay Bellur <vijay@gluster.com>2012-01-12 01:58:26 -0800
commit169c73f28dae61236de54889edcaa8236d91da59 (patch)
treea4d74fc14c9198cbc78633a844480ab6c4ffdda3
parent4e40a7e48757feedc959c7982acf05c73f739a15 (diff)
cli: volume status enhancement
* Support "gluster volume status (all)" option to display all volumes' status. * On option "detail" appended to "gluster volume status *", amount of storage free, total storage, and backend filesystem details like inode size, inode count, free inodes, fs type, device name of each brick is displayed. * One can also obtain [detailed]status of only one brick. * Format of the enhanced volume status command is: "gluster volume status [all|<vol>] [<brick>] [detail]" * Some generic functions have been added to common-utils: skipword get_nth_word These functions enable parsing and fetching of words in a sentence. glusterd_get_brick_root (in glusterd) These are self explanatory. Change-Id: I6f40c1e19810f8504cd3b1786207364053d82e28 BUG: 765464 Signed-off-by: Rajesh Amaravathi <rajesh@redhat.com> Reviewed-on: http://review.gluster.com/777 Tested-by: Gluster Build System <jenkins@build.gluster.com> Reviewed-by: Amar Tumballi <amar@gluster.com>
-rw-r--r--cli/src/cli-cmd-parser.c71
-rw-r--r--cli/src/cli-cmd-volume.c166
-rw-r--r--cli/src/cli-rpc-ops.c169
-rw-r--r--cli/src/cli.h28
-rw-r--r--libglusterfs/src/common-utils.c49
-rw-r--r--libglusterfs/src/common-utils.h8
-rw-r--r--rpc/rpc-lib/src/protocol-common.h1
-rw-r--r--rpc/xdr/src/cli1-xdr.c11
-rw-r--r--rpc/xdr/src/cli1-xdr.h14
-rw-r--r--rpc/xdr/src/cli1-xdr.x13
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-handler.c28
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-op-sm.c172
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-utils.c375
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-utils.h11
14 files changed, 992 insertions, 124 deletions
diff --git a/cli/src/cli-cmd-parser.c b/cli/src/cli-cmd-parser.c
index fa46fa0..acbd960 100644
--- a/cli/src/cli-cmd-parser.c
+++ b/cli/src/cli-cmd-parser.c
@@ -1795,23 +1795,84 @@ out:
return ret;
}
-int32_t
+int
cli_cmd_volume_status_parse (const char **words, int wordcount,
- dict_t **options)
+ dict_t **options)
{
dict_t *dict = NULL;
int ret = -1;
+ int cmd = 0;
- GF_ASSERT (words);
GF_ASSERT (options);
dict = dict_new ();
if (!dict)
goto out;
- GF_ASSERT(words[2]);
+ switch (wordcount) {
+
+ case 2:
+ cmd = GF_CLI_STATUS_ALL;
+ ret = 0;
+ break;
+
+ case 3:
+ if (!strcmp (words[2], "all")) {
+
+ cmd = GF_CLI_STATUS_ALL;
+ ret = 0;
+
+ } else if (!strcmp (words[2], "detail")) {
+
+ cmd = GF_CLI_STATUS_ALL_DETAIL;
+ ret = 0;
+
+ } else {
+ cmd = GF_CLI_STATUS_VOL;
+ ret = dict_set_str (dict, "volname", (char *)words[2]);
+ }
+ break;
+
+ case 4:
+ if (!strcmp (words[2], "all") &&
+ !strcmp (words[3], "detail")) {
+
+ cmd = GF_CLI_STATUS_ALL_DETAIL;
+ ret = 0;
+
+ } else if (!strcmp (words[3], "detail")) {
+ cmd = GF_CLI_STATUS_VOL_DETAIL;
+ ret = dict_set_str (dict, "volname", (char *)words[2]);
+
+ } else {
+
+ cmd = GF_CLI_STATUS_BRICK;
+ ret = dict_set_str (dict, "volname", (char *)words[2]);
+ if (ret)
+ goto out;
+ ret = dict_set_str (dict, "brick", (char *)words[3]);
+ }
+ break;
+
+ case 5:
+ if (strcmp (words[4], "detail"))
+ goto out;
+
+ cmd = GF_CLI_STATUS_BRICK_DETAIL;
+ ret = dict_set_str (dict, "volname", (char *)words[2]);
+ if (ret)
+ goto out;
+ ret = dict_set_str (dict, "brick", (char *)words[3]);
+ break;
+
+ default:
+ goto out;
+ }
+
+ if (ret)
+ goto out;
- ret = dict_set_str (dict, "volname", (char *)words[2]);
+ ret = dict_set_int32 (dict, "cmd", cmd);
if (ret)
goto out;
diff --git a/cli/src/cli-cmd-volume.c b/cli/src/cli-cmd-volume.c
index 009896d..38c1679 100644
--- a/cli/src/cli-cmd-volume.c
+++ b/cli/src/cli-cmd-volume.c
@@ -1344,39 +1344,177 @@ out:
int
cli_cmd_volume_status_cbk (struct cli_state *state,
- struct cli_cmd_word *word,
- const char **words, int wordcount)
+ struct cli_cmd_word *word,
+ const char **words, int wordcount)
{
int ret = -1;
rpc_clnt_procedure_t *proc = NULL;
call_frame_t *frame = NULL;
dict_t *dict = NULL;
+ uint32_t cmd = 0;
- if (wordcount != 3) {
+ ret = cli_cmd_volume_status_parse (words, wordcount, &dict);
+
+ if (ret) {
cli_usage_out (word->pattern);
goto out;
}
- proc = &cli_rpc_prog->proctable[GLUSTER_CLI_STATUS_VOLUME];
+ ret = dict_get_uint32 (dict, "cmd", &cmd);
+ if (ret)
+ goto out;
+
+ if (!(cmd & GF_CLI_STATUS_ALL)) {
+ /* for one volume or brick */
+ proc = &cli_rpc_prog->proctable[GLUSTER_CLI_STATUS_VOLUME];
+ } else {
+ /* volume status all or all detail */
+ proc = &cli_rpc_prog->proctable[GLUSTER_CLI_STATUS_ALL];
+ }
+
+ if (!proc->fn)
+ goto out;
frame = create_frame (THIS, THIS->ctx->pool);
if (!frame)
goto out;
- ret = cli_cmd_volume_status_parse (words, wordcount, &dict);
+ ret = proc->fn (frame, THIS, dict);
+
+ out:
+ if (dict)
+ dict_unref (dict);
+ return ret;
+}
+
+
+int
+cli_get_detail_status (dict_t *dict, int i, cli_volume_status_t *status)
+{
+ uint64_t free = -1;
+ uint64_t total = -1;
+ char key[1024] = {0};
+ int ret = 0;
+
+ memset (key, 0, sizeof (key));
+ snprintf (key, sizeof (key), "brick%d.free", i);
+ ret = dict_get_uint64 (dict, key, &free);
if (ret)
goto out;
- if (proc->fn)
- ret = proc->fn (frame, THIS, dict);
+ status->free = gf_uint64_2human_readable (free);
+ if (!status->free)
+ goto out;
+
+ memset (key, 0, sizeof (key));
+ snprintf (key, sizeof (key), "brick%d.total", i);
+ ret = dict_get_uint64 (dict, key, &total);
+ if (ret)
+ goto out;
+
+ status->total = gf_uint64_2human_readable (total);
+ if (!status->total)
+ goto out;
+
+ memset (key, 0, sizeof (key));
+ snprintf (key, sizeof (key), "brick%d.device", i);
+ ret = dict_get_str (dict, key, &(status->device));
+ if (ret)
+ goto out;
+
+ memset (key, 0, sizeof (key));
+ snprintf (key, sizeof (key), "brick%d.block_size", i);
+ ret = dict_get_uint64 (dict, key, &(status->block_size));
+ if (ret)
+ goto out;
+
+ memset (key, 0, sizeof (key));
+ snprintf (key, sizeof (key), "brick%d.mnt_options", i);
+ ret = dict_get_str (dict, key, &(status->mount_options));
+ if (ret)
+ goto out;
+
+ memset (key, 0, sizeof (key));
+ snprintf (key, sizeof (key), "brick%d.fs_name", i);
+ ret = dict_get_str (dict, key, &(status->fs_name));
+ if (ret)
+ goto out;
+
+ if (IS_EXT_FS(status->fs_name) ||
+ !strcmp (status->fs_name, "xfs")) {
+
+ memset (key, 0, sizeof (key));
+ snprintf (key, sizeof (key), "brick%d.inode_size", i);
+ ret = dict_get_str (dict, key, &(status->inode_size));
+ if (ret)
+ status->inode_size = NULL;
+
+ memset (key, 0, sizeof (key));
+ snprintf (key, sizeof (key), "brick%d.total_inodes", i);
+ ret = dict_get_uint64 (dict, key, &(status->total_inodes));
+ if (ret)
+ goto out;
+
+ memset (key, 0, sizeof (key));
+ snprintf (key, sizeof (key), "brick%d.free_inodes", i);
+ ret = dict_get_uint64 (dict, key, &(status->free_inodes));
+ if (ret)
+ goto out;
+
+ } else {
+ status->inode_size = NULL;
+ status->total_inodes = 0;
+ status->free_inodes = 0;
+ }
out:
return ret;
}
+void
+cli_print_detailed_status (cli_volume_status_t *status)
+{
+ cli_out ("%-20s : %-20s", "Brick", status->brick);
+ cli_out ("%-20s : %-20d", "Port", status->port);
+ cli_out ("%-20s : %-20c", "Online", (status->online) ? 'Y' : 'N');
+ cli_out ("%-20s : %-20s", "Pid", status->pid_str);
+ cli_out ("%-20s : %-20s", "File System", status->fs_name);
+ cli_out ("%-20s : %-20s", "Device", status->device);
+
+ if (status->mount_options) {
+ cli_out ("%-20s : %-20s", "Mount Options",
+ status->mount_options);
+ } else {
+ cli_out ("%-20s : %-20s", "Mount Options", "N/A");
+ }
+
+ cli_out ("%-20s : %-20s", "Disk Space Free", status->free);
+ cli_out ("%-20s : %-20s", "Total Disk Space", status->total);
+
+ if (status->inode_size) {
+ cli_out ("%-20s : %-20s", "Inode Size",
+ status->inode_size);
+ } else {
+ cli_out ("%-20s : %-20s", "Inode Size", "N/A");
+ }
+
+ if (status->total_inodes) {
+ cli_out ("%-20s : %-20ld", "Inode Count",
+ status->total_inodes);
+ } else {
+ cli_out ("%-20s : %-20s", "Inode Count", "N/A");
+ }
+
+ if (status->free_inodes) {
+ cli_out ("%-20s : %-20ld", "Free Inodes",
+ status->free_inodes);
+ } else {
+ cli_out ("%-20s : %-20s", "Free Inodes", "N/A");
+ }
+}
int
-cli_print_brick_status (char *brick, int port, int online, char *pid)
+cli_print_brick_status (cli_volume_status_t *status)
{
int fieldlen = CLI_VOL_STATUS_BRICK_LEN;
char buf[80] = {0,};
@@ -1385,22 +1523,24 @@ cli_print_brick_status (char *brick, int port, int online, char *pid)
char *p = NULL;
int num_tabs = 0;
- bricklen = strlen (brick);
- p = brick;
+ bricklen = strlen (status->brick);
+ p = status->brick;
while (bricklen > 0) {
if (bricklen > fieldlen) {
i++;
strncpy (buf, p, fieldlen);
buf[strlen(buf) + 1] = '\0';
cli_out ("%s", buf);
- p = brick + i * fieldlen;
+ p = status->brick + i * fieldlen;
bricklen -= fieldlen;
} else {
num_tabs = (fieldlen - bricklen) / CLI_TAB_LENGTH + 1;
printf ("%s", p);
while (num_tabs-- != 0)
printf ("\t");
- cli_out ("%d\t%c\t%s", port, online?'Y':'N', pid);
+ cli_out ("%d\t%c\t%s",
+ status->port, status->online?'Y':'N',
+ status->pid_str);
bricklen = 0;
}
}
@@ -1597,7 +1737,7 @@ struct cli_cmd volume_cmds[] = {
cli_cmd_volume_top_cbk,
"volume top operations"},
- { "volume status <VOLNAME>",
+ { "volume status [all|<VOLNAME>] [brick] [detail]",
cli_cmd_volume_status_cbk,
"display status of specified volume"},
diff --git a/cli/src/cli-rpc-ops.c b/cli/src/cli-rpc-ops.c
index f6ae1d9..06c52da 100644
--- a/cli/src/cli-rpc-ops.c
+++ b/cli/src/cli-rpc-ops.c
@@ -3796,22 +3796,19 @@ out:
static int
gf_cli3_1_status_cbk (struct rpc_req *req, struct iovec *iov,
- int count, void *myframe)
+ int count, void *myframe)
{
- gf_cli_rsp rsp = {0,};
- int ret = -1;
- dict_t *dict = NULL;
- char *hostname = NULL;
- char *path = NULL;
- int i = 0;
- int port = 0;
- int online = 0;
- char key[1024] = {0,};
- int pid = -1;
- char *pid_str = NULL;
- char brick[8192] = {0,};
- char *volname = NULL;
-
+ int ret = -1;
+ int i = 0;
+ int pid = -1;
+ uint32_t cmd = 0;
+ char key[1024] = {0,};
+ char *hostname = NULL;
+ char *path = NULL;
+ char *volname = NULL;
+ dict_t *dict = NULL;
+ gf_cli_rsp rsp = {0,};
+ cli_volume_status_t status = {0};
if (req->rpc_status == -1)
goto out;
@@ -3839,16 +3836,39 @@ gf_cli3_1_status_cbk (struct rpc_req *req, struct iovec *iov,
if (ret)
goto out;
+ ret = dict_get_uint32 (dict, "cmd", &cmd);
+ if (ret)
+ goto out;
+
+ if ((cmd & GF_CLI_STATUS_ALL)) {
+ ((call_frame_t *)myframe)->local = dict;
+ ret = 0;
+ goto out;
+ }
ret = dict_get_int32 (dict, "count", &count);
if (ret)
goto out;
+ if (count == 0) {
+ ret = -1;
+ goto out;
+ }
+
+ status.brick = GF_CALLOC (1, PATH_MAX + 256, gf_common_mt_strdup);
ret = dict_get_str (dict, "volname", &volname);
+ if (ret)
+ goto out;
+
+ cli_out ("\nSTATUS OF VOLUME: %s", volname);
+
+ if ((cmd & GF_CLI_STATUS_DETAIL) == 0)
+ cli_out ("BRICK\t\t\t\t\t\t\tPORT\tONLINE\tPID");
- cli_out ("Brick status for volume: %s", volname);
- cli_out ("Brick\t\t\t\t\t\t\tPort\tOnline\tPID");
for (i = 0; i < count; i++) {
+
+ cli_print_line (CLI_BRICK_STATUS_LINE_LEN);
+
memset (key, 0, sizeof (key));
snprintf (key, sizeof (key), "brick%d.hostname", i);
ret = dict_get_str (dict, key, &hostname);
@@ -3861,15 +3881,19 @@ gf_cli3_1_status_cbk (struct rpc_req *req, struct iovec *iov,
if (ret)
goto out;
+ memset (status.brick, 0, PATH_MAX + 255);
+ snprintf (status.brick, PATH_MAX + 255, "%s:%s",
+ hostname, path);
+
memset (key, 0, sizeof (key));
snprintf (key, sizeof (key), "brick%d.port", i);
- ret = dict_get_int32 (dict, key, &port);
+ ret = dict_get_int32 (dict, key, &(status.port));
if (ret)
goto out;
memset (key, 0, sizeof (key));
snprintf (key, sizeof (key), "brick%d.status", i);
- ret = dict_get_int32 (dict, key, &online);
+ ret = dict_get_int32 (dict, key, &(status.online));
if (ret)
goto out;
@@ -3879,40 +3903,44 @@ gf_cli3_1_status_cbk (struct rpc_req *req, struct iovec *iov,
if (ret)
goto out;
if (pid == -1)
- ret = gf_asprintf (&pid_str, "%s", "N/A");
+ ret = gf_asprintf (&(status.pid_str), "%s", "N/A");
else
- ret = gf_asprintf (&pid_str, "%d", pid);
+ ret = gf_asprintf (&(status.pid_str), "%d", pid);
if (ret == -1)
goto out;
- snprintf (brick, sizeof (brick) -1, "%s:%s", hostname, path);
+ if ((cmd & GF_CLI_STATUS_DETAIL)) {
+ ret = cli_get_detail_status (dict, i, &status);
+ if (ret)
+ goto out;
+ cli_print_detailed_status (&status);
- cli_print_line (CLI_BRICK_STATUS_LINE_LEN);
- cli_print_brick_status (brick, port, online, pid_str);
- if (pid_str)
- GF_FREE (pid_str);
+ } else {
+ cli_print_brick_status (&status);
+ }
}
ret = rsp.op_ret;
out:
+ if (status.brick)
+ GF_FREE (status.brick);
+
cli_cmd_broadcast_response (ret);
return ret;
}
int32_t
gf_cli3_1_status_volume (call_frame_t *frame, xlator_t *this,
- void *data)
+ void *data)
{
gf_cli_req req = {{0,}};
- int ret = 0;
- dict_t *dict = NULL;
+ int ret = -1;
+ dict_t *dict = NULL;
- if (!frame || !this || !data) {
- ret = -1;
+ if (!frame || !this || !data)
goto out;
- }
dict = data;
@@ -3920,7 +3948,7 @@ gf_cli3_1_status_volume (call_frame_t *frame, xlator_t *this,
&req.dict.dict_val,
(size_t *)&req.dict.dict_len);
if (ret < 0) {
- gf_log (this->name, GF_LOG_ERROR,
+ gf_log ("cli", GF_LOG_ERROR,
"failed to serialize the data");
goto out;
@@ -3935,6 +3963,80 @@ gf_cli3_1_status_volume (call_frame_t *frame, xlator_t *this,
return ret;
}
+int
+gf_cli_status_volume_all (call_frame_t *frame, xlator_t *this, void *data)
+{
+ int i = 0;
+ int ret = -1;
+ int vol_count = -1;
+ uint32_t cmd = 0;
+ char key[1024] = {0};
+ char *volname = NULL;
+ dict_t *vol_dict = NULL;
+ dict_t *dict = NULL;
+
+ dict = (dict_t *)data;
+ ret = dict_get_uint32 (dict, "cmd", &cmd);
+ if (ret)
+ goto out;
+
+ ret = gf_cli3_1_status_volume (frame, this, data);
+ if (ret)
+ goto out;
+
+ vol_dict = (dict_t *)(frame->local);
+
+ ret = dict_get_int32 (vol_dict, "vol_count", &vol_count);
+ if (ret) {
+ cli_out ("Failed to get names of volumes");
+ goto out;
+ }
+
+ if (vol_count == 0) {
+ cli_out ("No volumes present");
+ ret = 0;
+ goto out;
+ }
+
+ /* remove the "all" flag in cmd */
+ cmd &= ~GF_CLI_STATUS_ALL;
+ cmd |= GF_CLI_STATUS_VOL;
+
+ for (i = 0; i < vol_count; i++) {
+
+ dict = dict_new ();
+ if (!dict)
+ goto out;
+
+ memset (key, 0, sizeof (key));
+ snprintf (key, sizeof (key), "vol%d", i);
+ ret = dict_get_str (vol_dict, key, &volname);
+ if (ret)
+ goto out;
+
+ ret = dict_set_dynstr (dict, "volname", volname);
+ if (ret)
+ goto out;
+
+ ret = dict_set_uint32 (dict, "cmd", cmd);
+ if (ret)
+ goto out;
+
+ ret = gf_cli3_1_status_volume (frame, this, dict);
+ if (ret)
+ goto out;
+
+ dict_unref (dict);
+ }
+
+ out:
+ if (ret)
+ gf_log ("cli", GF_LOG_ERROR, "status all failed");
+ if (ret && dict)
+ dict_unref (dict);
+ return ret;
+}
+
static int
gf_cli3_1_mount_cbk (struct rpc_req *req, struct iovec *iov,
int count, void *myframe)
@@ -4265,6 +4367,7 @@ struct rpc_clnt_procedure gluster_cli_actors[GLUSTER_CLI_MAXVALUE] = {
[GLUSTER_CLI_TOP_VOLUME] = {"TOP_VOLUME", gf_cli3_1_top_volume},
[GLUSTER_CLI_GETWD] = {"GETWD", gf_cli3_1_getwd},
[GLUSTER_CLI_STATUS_VOLUME] = {"STATUS_VOLUME", gf_cli3_1_status_volume},
+ [GLUSTER_CLI_STATUS_ALL] = {"STATUS_ALL", gf_cli_status_volume_all},
[GLUSTER_CLI_MOUNT] = {"MOUNT", gf_cli3_1_mount},
[GLUSTER_CLI_UMOUNT] = {"UMOUNT", gf_cli3_1_umount},
[GLUSTER_CLI_HEAL_VOLUME] = {"HEAL_VOLUME", gf_cli3_1_heal_volume},
diff --git a/cli/src/cli.h b/cli/src/cli.h
index 1d2e069..e091e70 100644
--- a/cli/src/cli.h
+++ b/cli/src/cli.h
@@ -37,7 +37,7 @@
#define DEFAULT_CLI_LOG_FILE_DIRECTORY DATADIR "/log/glusterfs"
#define CLI_VOL_STATUS_BRICK_LEN 55
#define CLI_TAB_LENGTH 8
-#define CLI_BRICK_STATUS_LINE_LEN 75
+#define CLI_BRICK_STATUS_LINE_LEN 78
enum argp_option_keys {
ARGP_DEBUG_KEY = 133,
@@ -124,6 +124,24 @@ struct cli_local {
dict_t *dict;
};
+struct cli_volume_status {
+ int port;
+ int online;
+ uint64_t block_size;
+ uint64_t total_inodes;
+ uint64_t free_inodes;
+ char *brick;
+ char *pid_str;
+ char *fs_name;
+ char *free;
+ char *total;
+ char *mount_options;
+ char *device;
+ char *inode_size;
+};
+
+typedef struct cli_volume_status cli_volume_status_t;
+
typedef struct cli_local cli_local_t;
typedef ssize_t (*cli_serialize_t) (struct iovec outmsg, void *args);
@@ -236,7 +254,13 @@ cli_cmd_volume_status_parse (const char **words, int wordcount,
dict_t **options);
int
-cli_print_brick_status (char *brick, int port, int online, char *pid);
+cli_print_brick_status (cli_volume_status_t *status);
+
+void
+cli_print_detailed_status (cli_volume_status_t *status);
+
+int
+cli_get_detail_status (dict_t *dict, int i, cli_volume_status_t *status);
void
cli_print_line (int len);
diff --git a/libglusterfs/src/common-utils.c b/libglusterfs/src/common-utils.c
index 1d0fb82..d22ebd2 100644
--- a/libglusterfs/src/common-utils.c
+++ b/libglusterfs/src/common-utils.c
@@ -1607,6 +1607,55 @@ nwstrtail (char *str, char *pattern)
return *pattern ? NULL : str;
}
+void
+skipword (char **s)
+{
+ if (!*s)
+ return;
+
+ skipwhite (s);
+
+ while (!isspace(**s))
+ (*s)++;
+}
+
+char *
+get_nth_word (const char *str, int n)
+{
+ char buf[4096] = {0};
+ char *start = NULL;
+ char *word = NULL;
+ int i = 0;
+ int word_len = 0;
+ const char *end = NULL;
+
+ if (!str)
+ goto out;
+
+ snprintf (buf, sizeof (buf), "%s", str);
+ start = buf;
+
+ for (i = 0; i < n-1; i++)
+ skipword (&start);
+
+ skipwhite (&start);
+ end = strpbrk ((const char *)start, " \t\n\0");
+
+ if (!end)
+ goto out;
+
+ word_len = abs (end - start);
+
+ word = GF_CALLOC (1, word_len + 1, gf_common_mt_strdup);
+ if (!word)
+ goto out;
+
+ strncpy (word, start, word_len);
+ *(word + word_len) = '\0';
+ out:
+ return word;
+}
+
/* RFC 1123 & 952 */
char
valid_host_name (char *address, int length)
diff --git a/libglusterfs/src/common-utils.h b/libglusterfs/src/common-utils.h
index 4cb3843..6045cd3 100644
--- a/libglusterfs/src/common-utils.h
+++ b/libglusterfs/src/common-utils.h
@@ -74,6 +74,11 @@ void trap (void);
#define WIPE(statp) do { typeof(*statp) z = {0,}; if (statp) *statp = z; } while (0)
+#define IS_EXT_FS(fs_name) \
+ (!strcmp (fs_name, "ext2") || \
+ !strcmp (fs_name, "ext3") || \
+ !strcmp (fs_name, "ext4"))
+
enum _gf_boolean
{
_gf_false = 0,
@@ -409,6 +414,9 @@ int get_checksum_for_path (char *path, uint32_t *checksum);
char *strtail (char *str, const char *pattern);
void skipwhite (char **s);
char *nwstrtail (char *str, char *pattern);
+void skip_word (char **str);
+/* returns a new string with nth word of given string. n>=1 */
+char *get_nth_word (const char *str, int n);
char valid_host_name (char *address, int length);
char valid_ipv4_address (char *address, int length);
diff --git a/rpc/rpc-lib/src/protocol-common.h b/rpc/rpc-lib/src/protocol-common.h
index 9b358f4..fd7c89a 100644
--- a/rpc/rpc-lib/src/protocol-common.h
+++ b/rpc/rpc-lib/src/protocol-common.h
@@ -148,6 +148,7 @@ enum gluster_cli_procnum {
GLUSTER_CLI_TOP_VOLUME,
GLUSTER_CLI_GETWD,
GLUSTER_CLI_STATUS_VOLUME,
+ GLUSTER_CLI_STATUS_ALL,
GLUSTER_CLI_MOUNT,
GLUSTER_CLI_UMOUNT,
GLUSTER_CLI_HEAL_VOLUME,
diff --git a/rpc/xdr/src/cli1-xdr.c b/rpc/xdr/src/cli1-xdr.c
index b0ac079..56562ee 100644
--- a/rpc/xdr/src/cli1-xdr.c
+++ b/rpc/xdr/src/cli1-xdr.c
@@ -177,6 +177,17 @@ xdr_gf1_cli_top_op (XDR *xdrs, gf1_cli_top_op *objp)
}
bool_t
+xdr_gf_cli_status_type (XDR *xdrs, gf_cli_status_type *objp)
+{
+ register int32_t *buf;
+ buf = NULL;
+
+ if (!xdr_enum (xdrs, (enum_t *) objp))
+ return FALSE;
+ return TRUE;
+}
+
+bool_t
xdr_gf_cli_req (XDR *xdrs, gf_cli_req *objp)
{
register int32_t *buf;
diff --git a/rpc/xdr/src/cli1-xdr.h b/rpc/xdr/src/cli1-xdr.h
index 1d0faa9..d559397 100644
--- a/rpc/xdr/src/cli1-xdr.h
+++ b/rpc/xdr/src/cli1-xdr.h
@@ -160,6 +160,18 @@ enum gf1_cli_top_op {
};
typedef enum gf1_cli_top_op gf1_cli_top_op;
+enum gf_cli_status_type {
+ GF_CLI_STATUS_NONE = 0x0000,
+ GF_CLI_STATUS_VOL = 0x0100,
+ GF_CLI_STATUS_ALL = 0x0200,
+ GF_CLI_STATUS_BRICK = 0x0400,
+ GF_CLI_STATUS_DETAIL = 0x0800,
+ GF_CLI_STATUS_VOL_DETAIL = 0x0900,
+ GF_CLI_STATUS_ALL_DETAIL = 0x0A00,
+ GF_CLI_STATUS_BRICK_DETAIL = 0x0C00,
+};
+typedef enum gf_cli_status_type gf_cli_status_type;
+
struct gf_cli_req {
struct {
u_int dict_len;
@@ -298,6 +310,7 @@ extern bool_t xdr_gf1_cli_op_flags (XDR *, gf1_cli_op_flags*);
extern bool_t xdr_gf1_cli_gsync_set (XDR *, gf1_cli_gsync_set*);
extern bool_t xdr_gf1_cli_stats_op (XDR *, gf1_cli_stats_op*);
extern bool_t xdr_gf1_cli_top_op (XDR *, gf1_cli_top_op*);
+extern bool_t xdr_gf_cli_status_type (XDR *, gf_cli_status_type*);
extern bool_t xdr_gf_cli_req (XDR *, gf_cli_req*);
extern bool_t xdr_gf_cli_rsp (XDR *, gf_cli_rsp*);
extern bool_t xdr_gf1_cli_probe_req (XDR *, gf1_cli_probe_req*);
@@ -329,6 +342,7 @@ extern bool_t xdr_gf1_cli_op_flags ();
extern bool_t xdr_gf1_cli_gsync_set ();
extern bool_t xdr_gf1_cli_stats_op ();
extern bool_t xdr_gf1_cli_top_op ();
+extern bool_t xdr_gf_cli_status_type ();
extern bool_t xdr_gf_cli_req ();
extern bool_t xdr_gf_cli_rsp ();
extern bool_t xdr_gf1_cli_probe_req ();
diff --git a/rpc/xdr/src/cli1-xdr.x b/rpc/xdr/src/cli1-xdr.x
index 129f5f9..5697310 100644
--- a/rpc/xdr/src/cli1-xdr.x
+++ b/rpc/xdr/src/cli1-xdr.x
@@ -103,6 +103,19 @@ enum gf1_cli_top_op {
GF_CLI_TOP_WRITE_PERF
};
+/* The unconventional hex numbers help us perform
+ bit-wise operations which reduces complexity */
+enum gf_cli_status_type {
+ GF_CLI_STATUS_NONE = 0x0000,
+ GF_CLI_STATUS_VOL = 0x0100,
+ GF_CLI_STATUS_ALL = 0x0200,
+ GF_CLI_STATUS_BRICK = 0x0400,
+ GF_CLI_STATUS_DETAIL = 0x0800,
+ GF_CLI_STATUS_VOL_DETAIL = 0x0900,
+ GF_CLI_STATUS_ALL_DETAIL = 0x0A00,
+ GF_CLI_STATUS_BRICK_DETAIL = 0x0C00
+};
+
struct gf_cli_req {
opaque dict<>;
} ;
diff --git a/xlators/mgmt/glusterd/src/glusterd-handler.c b/xlators/mgmt/glusterd/src/glusterd-handler.c
index 664798c..7817e1d 100644
--- a/xlators/mgmt/glusterd/src/glusterd-handler.c
+++ b/xlators/mgmt/glusterd/src/glusterd-handler.c
@@ -2511,10 +2511,11 @@ int
glusterd_handle_status_volume (rpcsvc_request_t *req)
{
int32_t ret = -1;
+ uint32_t cmd = 0;
+ dict_t *dict = NULL;
+ char *volname = 0;
gf_cli_req cli_req = {{0,}};
- dict_t *dict = NULL;
- glusterd_op_t cli_op = GD_OP_STATUS_VOLUME;
- char *volname = 0;
+ glusterd_op_t cli_op = GD_OP_STATUS_VOLUME;
GF_ASSERT (req);
@@ -2530,7 +2531,7 @@ glusterd_handle_status_volume (rpcsvc_request_t *req)
if (!dict)
goto out;
ret = dict_unserialize (cli_req.dict.dict_val,
- cli_req.dict.dict_len, &dict);
+ cli_req.dict.dict_len, &dict);
if (ret < 0) {
gf_log (THIS->name, GF_LOG_ERROR, "failed to "
"unserialize buffer");
@@ -2539,15 +2540,22 @@ glusterd_handle_status_volume (rpcsvc_request_t *req)
}
- ret = dict_get_str (dict, "volname", &volname);
- if (ret) {
- gf_log (THIS->name, GF_LOG_ERROR, "failed to get volname");
+ ret = dict_get_uint32 (dict, "cmd", &cmd);
+ if (ret)
goto out;
- }
- gf_log ("glusterd", GF_LOG_INFO, "Received status volume req "
- "for volume %s", volname);
+ if (!(cmd & GF_CLI_STATUS_ALL)) {
+ ret = dict_get_str (dict, "volname", &volname);
+ if (ret) {
+ gf_log (THIS->name, GF_LOG_ERROR,
+ "failed to get volname");
+ goto out;
+ }
+ gf_log (THIS->name, GF_LOG_INFO,
+ "Received status volume req "
+ "for volume %s", volname);
+ }
ret = glusterd_op_begin (req, GD_OP_STATUS_VOLUME, dict);
diff --git a/xlators/mgmt/glusterd/src/glusterd-op-sm.c b/xlators/mgmt/glusterd/src/glusterd-op-sm.c
index 8f2d55a..68a98b1 100644
--- a/xlators/mgmt/glusterd/src/glusterd-op-sm.c
+++ b/xlators/mgmt/glusterd/src/glusterd-op-sm.c
@@ -527,12 +527,16 @@ out:
static int
glusterd_op_stage_status_volume (dict_t *dict, char **op_errstr)
{
- int ret = -1;
- gf_boolean_t exists = _gf_false;
- char *volname = NULL;
- glusterd_conf_t *priv = NULL;
- xlator_t *this = NULL;
- char msg[2048] = {0,};
+ int ret = -1;
+ uint32_t cmd = 0;
+ char msg[2048] = {0,};
+ char *volname = NULL;
+ char *brick = NULL;
+ xlator_t *this = NULL;
+ glusterd_conf_t *priv = NULL;
+ glusterd_brickinfo_t *brickinfo = NULL;
+ glusterd_brickinfo_t *tmpbrickinfo = NULL;
+ glusterd_volinfo_t *volinfo = NULL;
GF_ASSERT (dict);
this = THIS;
@@ -540,30 +544,63 @@ glusterd_op_stage_status_volume (dict_t *dict, char **op_errstr)
priv = this->private;
GF_ASSERT(priv);
+ ret = dict_get_uint32 (dict, "cmd", &cmd);
+ if (ret)
+ goto out;
+
+ if (cmd & GF_CLI_STATUS_ALL)
+ goto out;
ret = dict_get_str (dict, "volname", &volname);
if (ret) {
- gf_log ("glusterd", GF_LOG_ERROR, "Unable to get volume name");
+ gf_log (THIS->name, GF_LOG_ERROR,
+ "Unable to get volume name");
goto out;
}
- exists = glusterd_check_volume_exists (volname);
- if (!exists) {
+ ret = glusterd_volinfo_find (volname, &volinfo);
+ if (ret) {
snprintf (msg, sizeof(msg), "Volume %s does not exist", volname);
- gf_log ("glusterd", GF_LOG_ERROR, "%s", msg);
-
+ gf_log (THIS->name, GF_LOG_ERROR, "%s", msg);
*op_errstr = gf_strdup(msg);
ret = -1;
goto out;
}
+ if ((cmd & GF_CLI_STATUS_BRICK) != 0) {
+ ret = dict_get_str (dict, "brick", &brick);
+ if (ret)
+ goto out;
+
+ ret = glusterd_brickinfo_from_brick (brick, &brickinfo);
+ if (ret)
+ goto out;
+
+ ret = glusterd_volume_brickinfo_get (NULL,
+ brickinfo->hostname,
+ brickinfo->path,
+ volinfo,
+ &tmpbrickinfo,
+ GF_PATH_COMPLETE);
+
+ if (ret) {
+ snprintf (msg, sizeof(msg), "No brick %s in"
+ " volume %s", brick, volname);
+ gf_log (THIS->name, GF_LOG_ERROR, "%s", msg);
+
+ *op_errstr = gf_strdup(msg);
+ ret = -1;
+ goto out;
+ }
+ }
+
ret = 0;
out:
if (ret && !(*op_errstr))
*op_errstr = gf_strdup ("Validation Failed for Status");
- gf_log ("glusterd", GF_LOG_DEBUG, "Returning: %d", ret);
+ gf_log (THIS->name, GF_LOG_DEBUG, "Returning: %d", ret);
return ret;
}
@@ -1203,15 +1240,17 @@ static int
glusterd_op_status_volume (dict_t *dict, char **op_errstr,
dict_t *rsp_dict)
{
- int ret = -1;
- char *volname = NULL;
- int count = 0;
- int brick_count = 0;
- glusterd_volinfo_t *volinfo = NULL;
- glusterd_brickinfo_t *brickinfo = NULL;
- glusterd_conf_t *priv = NULL;
- xlator_t *this = NULL;
- int32_t brick_index = 0;
+ int ret = -1;
+ int brick_count = 0;
+ int32_t brick_index = 0;
+ uint32_t cmd = 0;
+ char *volname = NULL;
+ char *brick = NULL;
+ xlator_t *this = NULL;
+ glusterd_volinfo_t *volinfo = NULL;
+ glusterd_brickinfo_t *brickinfo = NULL;
+ glusterd_brickinfo_t *tmpbrickinfo = NULL;
+ glusterd_conf_t *priv = NULL;
this = THIS;
GF_ASSERT (this);
@@ -1221,41 +1260,83 @@ glusterd_op_status_volume (dict_t *dict, char **op_errstr,
GF_ASSERT (dict);
-
- ret = dict_get_str (dict, "volname", &volname);
- if (!ret) {
- ret = glusterd_volinfo_find (volname, &volinfo);
- if (ret) {
- gf_log ("", GF_LOG_ERROR, "Volume with name: %s "
- "does not exist", volname);
- goto out;
- }
- }
+ ret = dict_get_uint32 (dict, "cmd", &cmd);
+ if (ret)
+ goto out;
if (!rsp_dict) {
//this should happen only on source
ret = 0;
rsp_dict = glusterd_op_get_ctx ();
+
+ if ((cmd & GF_CLI_STATUS_ALL)) {
+ ret = glusterd_get_all_volnames (rsp_dict);
+ if (ret)
+ gf_log (THIS->name, GF_LOG_ERROR,
+ "failed to get all volume "
+ "names for status");
+ }
+
}
- if (volname) {
- list_for_each_entry (brickinfo, &volinfo->bricks, brick_list) {
- if (!uuid_compare (brickinfo->uuid, priv->uuid)) {
- ret = glusterd_add_brick_to_dict (volinfo,
- brickinfo,
- rsp_dict,
- brick_index);
- count++;
- brick_count = count;
- }
- brick_index++;
+ ret = dict_set_uint32 (rsp_dict, "cmd", cmd);
+ if (ret)
+ goto out;
+
+ if (cmd & GF_CLI_STATUS_ALL)
+ goto out;
+
+ ret = dict_get_str (dict, "volname", &volname);
+ if (ret)
+ goto out;
+
+ ret = glusterd_volinfo_find (volname, &volinfo);
+ if (ret) {
+ gf_log (THIS->name, GF_LOG_ERROR, "Volume with name: %s "
+ "does not exist", volname);
+ goto out;
+ }
+
+ if ((cmd & GF_CLI_STATUS_BRICK) != 0) {
+ ret = dict_get_str (dict, "brick", &brick);
+ if (ret)
+ goto out;
+ ret = glusterd_brickinfo_from_brick (brick, &tmpbrickinfo);
+ if (ret)
+ goto out;
+ if (uuid_is_null (tmpbrickinfo->uuid) &&
+ glusterd_resolve_brick (tmpbrickinfo))
+ goto out;
+ }
+
+ list_for_each_entry (brickinfo, &volinfo->bricks, brick_list) {
+ if (!uuid_compare (brickinfo->uuid, priv->uuid)) {
+
+ if ((cmd & GF_CLI_STATUS_BRICK) != 0 &&
+ (strcmp (tmpbrickinfo->path,
+ brickinfo->path) ||
+ uuid_compare (tmpbrickinfo->uuid,
+ brickinfo->uuid)))
+ continue;
+
+ glusterd_add_brick_to_dict (volinfo, brickinfo,
+ rsp_dict, brick_index);
+
+ if (cmd & GF_CLI_STATUS_DETAIL)
+ glusterd_add_brick_detail_to_dict (volinfo,
+ brickinfo,
+ rsp_dict,
+ brick_index);
+ brick_count++;
}
+ if (!(cmd & GF_CLI_STATUS_BRICK))
+ brick_index++;
}
ret = dict_set_int32 (rsp_dict, "count", brick_count);
out:
- gf_log ("", GF_LOG_DEBUG, "Returning %d", ret);
+ gf_log (THIS->name, GF_LOG_DEBUG, "Returning %d", ret);
return ret;
}
@@ -2119,7 +2200,7 @@ glusterd_op_ac_commit_op (glusterd_op_sm_event_t *event, void *ctx)
rsp_dict);
if (status) {
- gf_log ("", GF_LOG_ERROR, "Commit failed: %d", status);
+ gf_log (THIS->name, GF_LOG_ERROR, "Commit failed: %d", status);
}
ret = glusterd_op_commit_send_resp (req_ctx->req, req_ctx->op,
@@ -2131,7 +2212,8 @@ glusterd_op_ac_commit_op (glusterd_op_sm_event_t *event, void *ctx)
if (rsp_dict)
dict_unref (rsp_dict);
- gf_log ("", GF_LOG_DEBUG, "Returning with %d", ret);
+
+ gf_log (THIS->name, GF_LOG_DEBUG, "Returning with %d", ret);
return ret;
}
diff --git a/xlators/mgmt/glusterd/src/glusterd-utils.c b/xlators/mgmt/glusterd/src/glusterd-utils.c
index 2eaf4f4..b2d0bcd 100644
--- a/xlators/mgmt/glusterd/src/glusterd-utils.c
+++ b/xlators/mgmt/glusterd/src/glusterd-utils.c
@@ -58,6 +58,9 @@
#include <rpc/pmap_clnt.h>
#include <unistd.h>
#include <fnmatch.h>
+#include <sys/statvfs.h>
+
+
#ifdef GF_SOLARIS_HOST_OS
#include <sys/sockio.h>
#endif
@@ -679,11 +682,11 @@ glusterd_brickinfo_from_brick (char *brick,
GF_ASSERT (brickinfo);
tmp_host = gf_strdup (brick);
- if (tmp_host)
- get_host_name (tmp_host, &hostname);
+ if (tmp_host && !get_host_name (tmp_host, &hostname))
+ goto out;
tmp_path = gf_strdup (brick);
- if (tmp_path)
- get_path_name (tmp_path, &path);
+ if (tmp_path && !get_path_name (tmp_path, &path))
+ goto out;
GF_ASSERT (hostname);
GF_ASSERT (path);
@@ -3084,21 +3087,331 @@ out:
return -1;
}
+int
+glusterd_get_brick_root (char *path, char **mount_point)
+{
+ char *ptr = NULL;
+ struct stat brickstat = {0};
+ struct stat buf = {0};
+
+ if (!path)
+ goto err;
+ *mount_point = gf_strdup (path);
+ if (!*mount_point)
+ goto err;
+ if (stat (*mount_point, &brickstat))
+ goto err;
+
+ while ((ptr = strrchr (*mount_point, '/')) &&
+ ptr != *mount_point) {
+
+ *ptr = '\0';
+ if (stat (*mount_point, &buf)) {
+ gf_log (THIS->name, GF_LOG_ERROR, "error in "
+ "stat: %s", strerror (errno));
+ goto err;
+ }
+
+ if (brickstat.st_dev != buf.st_dev) {
+ *ptr = '/';
+ break;
+ }
+ }
+
+ if (ptr == *mount_point) {
+ if (stat ("/", &buf)) {
+ gf_log (THIS->name, GF_LOG_ERROR, "error in "
+ "stat: %s", strerror (errno));
+ goto err;
+ }
+ if (brickstat.st_dev == buf.st_dev)
+ strcpy (*mount_point, "/");
+ }
+
+ return 0;
+
+ err:
+ if (*mount_point)
+ GF_FREE (*mount_point);
+ return -1;
+}
+
+static int
+glusterd_add_inode_size_to_dict (dict_t *dict, int count)
+{
+ int ret = -1;
+ int fd = -1;
+ char key[1024] = {0};
+ char buffer[4096] = {0};
+ char cmd_str[4096] = {0};
+ char *inode_size = NULL;
+ char *device = NULL;
+ char *fs_name = NULL;
+
+ memset (key, 0, sizeof (key));
+ snprintf (key, sizeof (key), "brick%d.device", count);
+ ret = dict_get_str (dict, key, &device);
+ if (ret)
+ goto out;
+
+ memset (key, 0, sizeof (key));
+ snprintf (key, sizeof (key), "brick%d.fs_name", count);
+ ret = dict_get_str (dict, key, &fs_name);
+ if (ret)
+ goto out;
+
+ /* get inode size for xfs or ext2/3/4 */
+ if (!strcmp (fs_name, "xfs")) {
+
+ snprintf (cmd_str, sizeof (cmd_str),
+ "xfs_info %s | "
+ "grep isize | "
+ "cut -d ' ' -f 2- | "
+ "cut -d '=' -f 2 | "
+ "cut -d ' ' -f 1 "
+ "> /tmp/gf_status.txt ",
+ device);
+
+ } else if (IS_EXT_FS(fs_name)) {
+
+ snprintf (cmd_str, sizeof (cmd_str),
+ "tune2fs -l %s | "
+ "grep -i 'inode size' | "
+ "awk '{print $3}' "
+ "> /tmp/gf_status.txt ",
+ device);
+
+ } else {
+ ret = 0;
+ gf_log (THIS->name, GF_LOG_INFO, "Skipped fetching "
+ "inode size for %s: FS type not recommended",
+ fs_name);
+ goto out;
+ }
+
+ ret = runcmd ("/bin/sh", "-c", cmd_str, NULL);
+ if (ret) {
+ gf_log (THIS->name, GF_LOG_ERROR, "could not get inode "
+ "size for %s : %s package missing", fs_name,
+ ((strcmp (fs_name, "xfs")) ?
+ "e2fsprogs" : "xfsprogs"));
+ goto out;
+ }
+
+ fd = open ("/tmp/gf_status.txt", O_RDONLY);
+ unlink ("/tmp/gf_status.txt");
+ if (fd < 0) {
+ ret = -1;
+ goto out;
+ }
+ memset (buffer, 0, sizeof (buffer));
+ ret = read (fd, buffer, sizeof (buffer));
+ if (ret < 2) {
+ ret = -1;
+ goto out;
+ }
+
+ memset (key, 0, sizeof (key));
+ snprintf (key, sizeof (key), "brick%d.inode_size", count);
+
+ inode_size = get_nth_word (buffer, 1);
+ if (!inode_size) {
+ ret = -1;
+ goto out;
+ }
+
+ ret = dict_set_dynstr (dict, key, inode_size);
+
+ out:
+ if (fd >= 0)
+ close (fd);
+ if (ret)
+ gf_log (THIS->name, GF_LOG_ERROR, "failed to get inode size");
+ return ret;
+}
+
+static int
+glusterd_add_brick_mount_details (glusterd_brickinfo_t *brickinfo,
+ dict_t *dict, int count)
+{
+ int ret = -1;
+ int fd = -1;
+ char key[1024] = {0};
+ char base_key[1024] = {0};
+ char buffer[4096] = {0};
+ char cmd_str[1024] = {0};
+ char *mnt_pt = NULL;
+ char *fs_name = NULL;
+ char *mnt_options = NULL;
+ char *device = NULL;
+ runner_t runner = {0};
+
+ snprintf (base_key, sizeof (base_key), "brick%d", count);
+
+ ret = glusterd_get_brick_root (brickinfo->path, &mnt_pt);
+ if (ret)
+ goto out;
+
+ /* get mount details of brick in back-end */
+ snprintf (cmd_str, sizeof (cmd_str), " %s ", mnt_pt);
+
+ runinit (&runner);
+ runner_add_args (&runner, "grep", cmd_str, "/etc/mtab", NULL);
+ runner_redir (&runner, STDOUT_FILENO, RUN_PIPE);
+
+ ret = runner_start (&runner);
+ if (ret)
+ goto out;
+
+ if (!fgets (buffer, sizeof(buffer),
+ runner_chio (&runner, STDOUT_FILENO))) {
+ ret = -1;
+ goto out;
+ }
+
+ runner_end (&runner);
+
+ /* get device file */
+ memset (key, 0, sizeof (key));
+ snprintf (key, sizeof (key), "%s.device", base_key);
+
+ device = get_nth_word (buffer, 1);
+ if (!device)
+ goto out;
+
+ ret = dict_set_dynstr (dict, key, device);
+ if (ret)
+ goto out;
+
+ /* fs type */
+ memset (key, 0, sizeof (key));
+ snprintf (key, sizeof (key), "%s.fs_name", base_key);
+
+ fs_name = get_nth_word (buffer, 3);
+ if (!fs_name)
+ goto out;
+
+ ret = dict_set_dynstr (dict, key, fs_name);
+ if (ret)
+ goto out;
+
+ /* mount options */
+ memset (key, 0, sizeof (key));
+ snprintf (key, sizeof (key), "%s.mnt_options", base_key);
+
+ mnt_options = get_nth_word (buffer, 4);
+ if (!mnt_options)
+ goto out;
+ ret = dict_set_dynstr (dict, key, mnt_options);
+
+ out:
+ if (mnt_pt)
+ GF_FREE (mnt_pt);
+ if (fd >= 0)
+ close (fd);
+ return ret;
+}
+
+int
+glusterd_add_brick_detail_to_dict (glusterd_volinfo_t *volinfo,
+ glusterd_brickinfo_t *brickinfo,
+ dict_t *dict, int count)
+{
+ int ret = -1;
+ uint64_t memtotal = 0;
+ uint64_t memfree = 0;
+ uint64_t inodes_total = 0;
+ uint64_t inodes_free = 0;
+ uint64_t block_size = 0;
+ char key[1024] = {0};
+ char base_key[1024] = {0};
+ struct statvfs brickstat = {0};
+
+ GF_ASSERT (volinfo);
+ GF_ASSERT (brickinfo);
+ GF_ASSERT (dict);
+
+ snprintf (base_key, sizeof (base_key), "brick%d", count);
+
+ ret = statvfs (brickinfo->path, &brickstat);
+ if (ret) {
+ gf_log (THIS->name, GF_LOG_ERROR, "statfs error: %s ",
+ strerror (errno));
+ goto out;
+ }
+
+ /* file system block size */
+ block_size = brickstat.f_bsize;
+ memset (key, 0, sizeof (key));
+ snprintf (key, sizeof (key), "%s.block_size", base_key);
+ ret = dict_set_uint64 (dict, key, block_size);
+ if (ret)
+ goto out;
+
+ /* free space in brick */
+ memfree = brickstat.f_bfree * brickstat.f_bsize;
+ memset (key, 0, sizeof (key));
+ snprintf (key, sizeof (key), "%s.free", base_key);
+ ret = dict_set_uint64 (dict, key, memfree);
+ if (ret)
+ goto out;
+
+ /* total space of brick */
+ memtotal = brickstat.f_blocks * brickstat.f_bsize;
+ memset (key, 0, sizeof (key));
+ snprintf (key, sizeof (key), "%s.total", base_key);
+ ret = dict_set_uint64 (dict, key, memtotal);
+ if (ret)
+ goto out;
+
+ /* inodes: total and free counts only for ext2/3/4 and xfs */
+ inodes_total = brickstat.f_files;
+ if (inodes_total) {
+ memset (key, 0, sizeof (key));
+ snprintf (key, sizeof (key), "%s.total_inodes", base_key);
+ ret = dict_set_uint64 (dict, key, inodes_total);
+ if (ret)
+ goto out;
+ }
+
+ inodes_free = brickstat.f_ffree;
+ if (inodes_free) {
+ memset (key, 0, sizeof (key));
+ snprintf (key, sizeof (key), "%s.free_inodes", base_key);
+ ret = dict_set_uint64 (dict, key, inodes_free);
+ if (ret)
+ goto out;
+ }
+
+ ret = glusterd_add_brick_mount_details (brickinfo, dict, count);
+ if (ret)
+ goto out;
+
+ ret = glusterd_add_inode_size_to_dict (dict, count);
+
+ out:
+ if (ret)
+ gf_log (THIS->name, GF_LOG_DEBUG, "Error adding brick"
+ " detail to dict: %s", strerror (errno));
+ return ret;
+}
+
int32_t
glusterd_add_brick_to_dict (glusterd_volinfo_t *volinfo,
glusterd_brickinfo_t *brickinfo,
dict_t *dict, int32_t count)
{
- int ret = -1;
- char key[8192] = {0,};
- char base_key[8192] = {0};
- char pidfile[PATH_MAX] = {0};
- char path[PATH_MAX] = {0};
- int32_t pid = -1;
- int32_t brick_online = -1;
- xlator_t *this = NULL;
- glusterd_conf_t *priv = NULL;
+ int ret = -1;
+ int32_t pid = -1;
+ int32_t brick_online = -1;
+ char key[1024] = {0};
+ char base_key[1024] = {0};
+ char pidfile[PATH_MAX] = {0};
+ char path[PATH_MAX] = {0};
+ xlator_t *this = NULL;
+ glusterd_conf_t *priv = NULL;
+
GF_ASSERT (volinfo);
GF_ASSERT (brickinfo);
@@ -3111,6 +3424,7 @@ glusterd_add_brick_to_dict (glusterd_volinfo_t *volinfo,
snprintf (base_key, sizeof (base_key), "brick%d", count);
snprintf (key, sizeof (key), "%s.hostname", base_key);
+
ret = dict_set_str (dict, key, brickinfo->hostname);
if (ret)
goto out;
@@ -3142,13 +3456,42 @@ glusterd_add_brick_to_dict (glusterd_volinfo_t *volinfo,
memset (key, 0, sizeof (key));
snprintf (key, sizeof (key), "%s.status", base_key);
ret = dict_set_int32 (dict, key, brick_online);
- if (ret)
- goto out;
out:
if (ret)
- gf_log ("", GF_LOG_DEBUG, "Returning %d", ret);
+ gf_log (THIS->name, GF_LOG_DEBUG, "Returning %d", ret);
+
+ return ret;
+}
+
+int32_t
+glusterd_get_all_volnames (dict_t *dict)
+{
+ int ret = -1;
+ int32_t vol_count = 0;
+ char key[256] = {0};
+ glusterd_volinfo_t *entry = NULL;
+ glusterd_conf_t *priv = NULL;
+ priv = THIS->private;
+ GF_ASSERT (priv);
+
+ list_for_each_entry (entry, &priv->volumes, vol_list) {
+ memset (key, sizeof (key), 0);
+ snprintf (key, sizeof (key), "vol%d", vol_count);
+ ret = dict_set_str (dict, key, entry->volname);
+ if (ret)
+ goto out;
+
+ vol_count++;
+ }
+
+ ret = dict_set_int32 (dict, "vol_count", vol_count);
+
+ out:
+ if (ret)
+ gf_log (THIS->name, GF_LOG_ERROR, "failed to get all "
+ "volume names for status");
return ret;
}
diff --git a/xlators/mgmt/glusterd/src/glusterd-utils.h b/xlators/mgmt/glusterd/src/glusterd-utils.h
index a34956b..0ce1745 100644
--- a/xlators/mgmt/glusterd/src/glusterd-utils.h
+++ b/xlators/mgmt/glusterd/src/glusterd-utils.h
@@ -347,11 +347,22 @@ glusterd_recreate_bricks (glusterd_conf_t *conf);
int32_t
glusterd_handle_upgrade_downgrade (dict_t *options, glusterd_conf_t *conf);
+int
+glusterd_get_brick_root (char *path, char **mount_point);
+
+int
+glusterd_add_brick_detail_to_dict (glusterd_volinfo_t *volinfo,
+ glusterd_brickinfo_t *brickinfo,
+ dict_t *dict, int32_t count);
+
int32_t
glusterd_add_brick_to_dict (glusterd_volinfo_t *volinfo,
glusterd_brickinfo_t *brickinfo,
dict_t *dict, int32_t count);
+int32_t
+glusterd_get_all_volnames (dict_t *dict);
+
gf_boolean_t
glusterd_is_fuse_available ();