summaryrefslogtreecommitdiffstats
path: root/contrib/fuse-lib/mount.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/fuse-lib/mount.c')
-rw-r--r--contrib/fuse-lib/mount.c528
1 files changed, 528 insertions, 0 deletions
diff --git a/contrib/fuse-lib/mount.c b/contrib/fuse-lib/mount.c
new file mode 100644
index 00000000000..c9e2035d467
--- /dev/null
+++ b/contrib/fuse-lib/mount.c
@@ -0,0 +1,528 @@
+/*
+ FUSE: Filesystem in Userspace
+ Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu>
+ Copyright (c) 2009 Z RESEARCH, Inc. <http://www.zresearch.com>
+
+ This program can be distributed under the terms of the GNU LGPLv2.
+ See the file COPYING.LIB.
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <stddef.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <mntent.h>
+#include <sys/poll.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <sys/wait.h>
+#include <sys/mount.h>
+
+#include "glusterfs.h"
+#include "logging.h"
+#include "common-utils.h"
+
+#define FUSERMOUNT_PROG "fusermount"
+#define FUSE_COMMFD_ENV "_FUSE_COMMFD"
+
+#define GFFUSE_LOGERR(...) \
+ gf_log ("glusterfs-fuse", GF_LOG_ERROR, ## __VA_ARGS__)
+
+/*
+ * Functions below, until following note, were taken from libfuse
+ * (http://git.gluster.com/?p=users/csaba/fuse.git;a=commit;h=b988bbf9)
+ * almost verbatim. What has been changed:
+ * - style adopted to that of glusterfs
+ * - s/fprintf/gf_log/
+ * - s/free/FREE/, s/malloc/MALLOC/
+ * - there are some other minor things
+ */
+
+static int
+mtab_needs_update (const char *mnt)
+{
+ int res;
+ struct stat stbuf;
+
+ /* If mtab is within new mount, don't touch it */
+ if (strncmp (mnt, _PATH_MOUNTED, strlen (mnt)) == 0 &&
+ _PATH_MOUNTED[strlen (mnt)] == '/')
+ return 0;
+
+ /*
+ * Skip mtab update if /etc/mtab:
+ *
+ * - doesn't exist,
+ * - is a symlink,
+ * - is on a read-only filesystem.
+ */
+ res = lstat (_PATH_MOUNTED, &stbuf);
+ if (res == -1) {
+ if (errno == ENOENT)
+ return 0;
+ } else {
+ if (S_ISLNK (stbuf.st_mode))
+ return 0;
+
+ res = access (_PATH_MOUNTED, W_OK);
+ if (res == -1 && errno == EROFS)
+ return 0;
+ }
+
+ return 1;
+}
+
+static int
+fuse_mnt_add_mount (const char *progname, const char *fsname,
+ const char *mnt, const char *type, const char *opts)
+{
+ int res;
+ int status;
+ sigset_t blockmask;
+ sigset_t oldmask;
+
+ if (!mtab_needs_update (mnt))
+ return 0;
+
+ sigemptyset (&blockmask);
+ sigaddset (&blockmask, SIGCHLD);
+ res = sigprocmask (SIG_BLOCK, &blockmask, &oldmask);
+ if (res == -1) {
+ GFFUSE_LOGERR ("%s: sigprocmask: %s",
+ progname, strerror (errno));
+ return -1;
+ }
+
+ res = fork ();
+ if (res == -1) {
+ GFFUSE_LOGERR ("%s: fork: %s", progname, strerror (errno));
+ goto out_restore;
+ }
+ if (res == 0) {
+ char templ[] = "/tmp/fusermountXXXXXX";
+ char *tmp;
+
+ sigprocmask (SIG_SETMASK, &oldmask, NULL);
+ setuid (geteuid ());
+
+ /*
+ * hide in a directory, where mount isn't able to resolve
+ * fsname as a valid path
+ */
+ tmp = mkdtemp (templ);
+ if (!tmp) {
+ GFFUSE_LOGERR ("%s: failed to create temporary directory",
+ progname);
+ exit (1);
+ }
+ if (chdir (tmp)) {
+ GFFUSE_LOGERR ("%s: failed to chdir to %s: %s",
+ progname, tmp, strerror (errno));
+ exit (1);
+ }
+ rmdir (tmp);
+ execl ("/bin/mount", "/bin/mount", "-i", "-f", "-t", type,
+ "-o", opts, fsname, mnt, NULL);
+ GFFUSE_LOGERR ("%s: failed to execute /bin/mount: %s",
+ progname, strerror (errno));
+ exit (1);
+ }
+ res = waitpid (res, &status, 0);
+ if (res == -1)
+ GFFUSE_LOGERR ("%s: waitpid: %s", progname, strerror (errno));
+
+ if (status != 0)
+ res = -1;
+
+ out_restore:
+ sigprocmask (SIG_SETMASK, &oldmask, NULL);
+ return res;
+}
+
+static char
+*fuse_mnt_resolve_path (const char *progname, const char *orig)
+{
+ char buf[PATH_MAX];
+ char *copy;
+ char *dst;
+ char *end;
+ char *lastcomp;
+ const char *toresolv;
+
+ if (!orig[0]) {
+ GFFUSE_LOGERR ("%s: invalid mountpoint '%s'", progname, orig);
+ return NULL;
+ }
+
+ copy = strdup (orig);
+ if (copy == NULL) {
+ GFFUSE_LOGERR ("%s: failed to allocate memory", progname);
+ return NULL;
+ }
+
+ toresolv = copy;
+ lastcomp = NULL;
+ for (end = copy + strlen (copy) - 1; end > copy && *end == '/'; end --);
+ if (end[0] != '/') {
+ char *tmp;
+ end[1] = '\0';
+ tmp = strrchr (copy, '/');
+ if (tmp == NULL) {
+ lastcomp = copy;
+ toresolv = ".";
+ } else {
+ lastcomp = tmp + 1;
+ if (tmp == copy)
+ toresolv = "/";
+ }
+ if (strcmp (lastcomp, ".") == 0 || strcmp (lastcomp, "..") == 0) {
+ lastcomp = NULL;
+ toresolv = copy;
+ }
+ else if (tmp)
+ tmp[0] = '\0';
+ }
+ if (realpath (toresolv, buf) == NULL) {
+ GFFUSE_LOGERR ("%s: bad mount point %s: %s", progname, orig,
+ strerror (errno));
+ FREE (copy);
+ return NULL;
+ }
+ if (lastcomp == NULL)
+ dst = strdup (buf);
+ else {
+ dst = (char *) MALLOC (strlen (buf) + 1 + strlen (lastcomp) + 1);
+ if (dst) {
+ unsigned buflen = strlen (buf);
+ if (buflen && buf[buflen-1] == '/')
+ sprintf (dst, "%s%s", buf, lastcomp);
+ else
+ sprintf (dst, "%s/%s", buf, lastcomp);
+ }
+ }
+ FREE (copy);
+ if (dst == NULL)
+ GFFUSE_LOGERR ("%s: failed to allocate memory", progname);
+ return dst;
+}
+
+/* return value:
+ * >= 0 => fd
+ * -1 => error
+ */
+static int
+receive_fd (int fd)
+{
+ struct msghdr msg;
+ struct iovec iov;
+ char buf[1];
+ int rv;
+ size_t ccmsg[CMSG_SPACE (sizeof (int)) / sizeof (size_t)];
+ struct cmsghdr *cmsg;
+
+ iov.iov_base = buf;
+ iov.iov_len = 1;
+
+ msg.msg_name = 0;
+ msg.msg_namelen = 0;
+ msg.msg_iov = &iov;
+ msg.msg_iovlen = 1;
+ /* old BSD implementations should use msg_accrights instead of
+ * msg_control; the interface is different. */
+ msg.msg_control = ccmsg;
+ msg.msg_controllen = sizeof (ccmsg);
+
+ while (((rv = recvmsg (fd, &msg, 0)) == -1) && errno == EINTR);
+ if (rv == -1) {
+ GFFUSE_LOGERR ("recvmsg failed: %s", strerror (errno));
+ return -1;
+ }
+ if (!rv) {
+ /* EOF */
+ return -1;
+ }
+
+ cmsg = CMSG_FIRSTHDR (&msg);
+ if (!cmsg->cmsg_type == SCM_RIGHTS) {
+ GFFUSE_LOGERR ("got control message of unknown type %d",
+ cmsg->cmsg_type);
+ return -1;
+ }
+ return *(int*)CMSG_DATA (cmsg);
+}
+
+static int
+fuse_mount_fusermount (const char *mountpoint, const char *opts)
+{
+ int fds[2], pid;
+ int res;
+ int rv;
+
+ res = socketpair (PF_UNIX, SOCK_STREAM, 0, fds);
+ if (res == -1) {
+ GFFUSE_LOGERR ("socketpair() failed: %s", strerror (errno));
+ return -1;
+ }
+
+ pid = fork ();
+ if (pid == -1) {
+ GFFUSE_LOGERR ("fork() failed: %s", strerror (errno));
+ close (fds[0]);
+ close (fds[1]);
+ return -1;
+ }
+
+ if (pid == 0) {
+ char env[10];
+ const char *argv[32];
+ int a = 0;
+
+ argv[a++] = FUSERMOUNT_PROG;
+ if (opts) {
+ argv[a++] = "-o";
+ argv[a++] = opts;
+ }
+ argv[a++] = "--";
+ argv[a++] = mountpoint;
+ argv[a++] = NULL;
+
+ close (fds[1]);
+ fcntl (fds[0], F_SETFD, 0);
+ snprintf (env, sizeof (env), "%i", fds[0]);
+ setenv (FUSE_COMMFD_ENV, env, 1);
+ execvp (FUSERMOUNT_PROG, (char **)argv);
+ GFFUSE_LOGERR ("failed to exec fusermount: %s",
+ strerror (errno));
+ _exit (1);
+ }
+
+ close (fds[0]);
+ rv = receive_fd (fds[1]);
+ close (fds[1]);
+ waitpid (pid, NULL, 0); /* bury zombie */
+
+ return rv;
+}
+
+static int
+fuse_mnt_umount (const char *progname, const char *mnt, int lazy)
+{
+ int res;
+ int status;
+ sigset_t blockmask;
+ sigset_t oldmask;
+
+ if (!mtab_needs_update (mnt)) {
+ res = umount2 (mnt, lazy ? 2 : 0);
+ if (res == -1)
+ GFFUSE_LOGERR ("%s: failed to unmount %s: %s",
+ progname, mnt, strerror (errno));
+ return res;
+ }
+
+ sigemptyset (&blockmask);
+ sigaddset (&blockmask, SIGCHLD);
+ res = sigprocmask (SIG_BLOCK, &blockmask, &oldmask);
+ if (res == -1) {
+ GFFUSE_LOGERR ("%s: sigprocmask: %s", progname,
+ strerror (errno));
+ return -1;
+ }
+
+ res = fork ();
+ if (res == -1) {
+ GFFUSE_LOGERR ("%s: fork: %s", progname, strerror (errno));
+ goto out_restore;
+ }
+ if (res == 0) {
+ sigprocmask (SIG_SETMASK, &oldmask, NULL);
+ setuid (geteuid ());
+ execl ("/bin/umount", "/bin/umount", "-i", mnt,
+ lazy ? "-l" : NULL, NULL);
+ GFFUSE_LOGERR ("%s: failed to execute /bin/umount: %s",
+ progname, strerror (errno));
+ exit (1);
+ }
+ res = waitpid (res, &status, 0);
+ if (res == -1)
+ GFFUSE_LOGERR ("%s: waitpid: %s", progname, strerror (errno));
+
+ if (status != 0)
+ res = -1;
+
+ out_restore:
+ sigprocmask (SIG_SETMASK, &oldmask, NULL);
+ return res;
+}
+
+void
+gf_fuse_unmount (const char *mountpoint, int fd)
+{
+ int res;
+ int pid;
+
+ if (!mountpoint)
+ return;
+
+ if (fd != -1) {
+ struct pollfd pfd;
+
+ pfd.fd = fd;
+ pfd.events = 0;
+ res = poll (&pfd, 1, 0);
+ /* If file poll returns POLLERR on the device file descriptor,
+ then the filesystem is already unmounted */
+ if (res == 1 && (pfd.revents & POLLERR))
+ return;
+
+ /* Need to close file descriptor, otherwise synchronous umount
+ would recurse into filesystem, and deadlock */
+ close (fd);
+ }
+
+ if (geteuid () == 0) {
+ fuse_mnt_umount ("fuse", mountpoint, 1);
+ return;
+ }
+
+ res = umount2 (mountpoint, 2);
+ if (res == 0)
+ return;
+
+ pid = fork ();
+ if (pid == -1)
+ return;
+
+ if (pid == 0) {
+ const char *argv[] = { FUSERMOUNT_PROG, "-u", "-q", "-z",
+ "--", mountpoint, NULL };
+
+ execvp (FUSERMOUNT_PROG, (char **)argv);
+ _exit (1);
+ }
+ waitpid (pid, NULL, 0);
+}
+
+/*
+ * Functions below are loosely modelled after similar functions of libfuse
+ */
+
+static int
+fuse_mount_sys (const char *mountpoint, char *fsname, char *mnt_param)
+{
+ int fd = -1, ret = -1;
+ unsigned mounted = 0;
+ char *mnt_param_mnt = NULL;
+ char *fstype = "fuse.glusterfs";
+ char *source = fsname;
+
+ fd = open ("/dev/fuse", O_RDWR);
+ if (fd == -1) {
+ GFFUSE_LOGERR ("cannot open /dev/fuse (%s)", strerror (errno));
+
+ return -1;
+ }
+
+ ret = asprintf (&mnt_param_mnt,
+ "%s,fd=%i,rootmode=%o,user_id=%i,group_id=%i",
+ mnt_param, fd, S_IFDIR, getuid (), getgid ());
+ if (ret == -1) {
+ GFFUSE_LOGERR ("Out of memory");
+
+ goto out;
+ }
+ ret = mount (source, mountpoint, fstype, 0,
+ mnt_param_mnt);
+ if (ret == -1 && errno == ENODEV) {
+ /* fs subtype support was added by 79c0b2df aka
+ v2.6.21-3159-g79c0b2d. Probably we have an
+ older kernel ... */
+ fstype = "fuse";
+ ret = asprintf (&source, "glusterfs#%s", fsname);
+ if (ret == -1) {
+ GFFUSE_LOGERR ("Out of memory");
+
+ goto out;
+ }
+ ret = mount (source, mountpoint, fstype, 0,
+ mnt_param_mnt);
+ }
+ if (ret == -1)
+ goto out;
+ else
+ mounted = 1;
+
+ if (geteuid () == 0) {
+ char *newmnt = fuse_mnt_resolve_path ("fuse", mountpoint);
+
+ if (!newmnt) {
+ ret = -1;
+
+ goto out;
+ }
+
+ ret = fuse_mnt_add_mount ("fuse", source, newmnt, fstype,
+ mnt_param);
+ FREE (newmnt);
+ if (ret == -1) {
+ GFFUSE_LOGERR ("failed to add mtab entry");
+
+ goto out;
+ }
+ }
+
+ out:
+ if (ret == -1) {
+ if (mounted)
+ umount2 (mountpoint, 2); /* lazy umount */
+ close (fd);
+ fd = -1;
+ }
+ FREE (mnt_param_mnt);
+ if (source != fsname)
+ FREE (source);
+ return fd;
+}
+
+int
+gf_fuse_mount (const char *mountpoint, char *fsname, char *mnt_param)
+{
+ int fd = -1, rv = -1;
+ char *fm_mnt_params = NULL, *p = NULL;
+
+ fd = fuse_mount_sys (mountpoint, fsname, mnt_param);
+ if (fd == -1) {
+ gf_log ("glusterfs-fuse", GF_LOG_NORMAL,
+ "direct mount failed (%s), "
+ "retry to mount via fusermount",
+ strerror (errno));
+
+ rv = asprintf (&fm_mnt_params,
+ "%s,fsname=%s,nonempty,subtype=glusterfs",
+ mnt_param, fsname);
+
+ if (rv == -1) {
+ GFFUSE_LOGERR ("Out of memory");
+
+ return -1;
+ }
+
+ fd = fuse_mount_fusermount (mountpoint, fm_mnt_params);
+ if (fd == -1) {
+ p = fm_mnt_params + strlen (fm_mnt_params);
+ while (*--p != ',');
+ *p = '\0';
+
+ fd = fuse_mount_fusermount (mountpoint, fm_mnt_params);
+ }
+
+ FREE (fm_mnt_params);
+
+ if (fd == -1)
+ GFFUSE_LOGERR ("mount failed");
+ }
+
+ return fd;
+}
_ret == -1) { if (strcmp (rsp.op_errstr, "")) snprintf (msg, sizeof (msg), "%s", rsp.op_errstr); else snprintf (msg, sizeof (msg), "rebalance volume %s stop failed", volname); } else { snprintf (msg, sizeof (msg), "Stopped rebalance process on volume %s \n" "(after rebalancing %"PRId64" bytes - " "%"PRId64" files)", volname, size, files); } goto done; } if (cmd == GF_DEFRAG_CMD_STATUS) { if (rsp.op_ret == -1) { if (strcmp (rsp.op_errstr, "")) snprintf (msg, sizeof (msg), "%s", rsp.op_errstr); else snprintf (msg, sizeof (msg), "Failed to get the status of " "rebalance process"); goto done; } switch (rsp.op_errno) { case GF_DEFRAG_STATUS_NOT_STARTED: status = "not started"; break; case GF_DEFRAG_STATUS_STARTED: status = "in progress"; break; case GF_DEFRAG_STATUS_STOPPED: status = "stopped"; break; case GF_DEFRAG_STATUS_COMPLETE: status = "completed"; break; case GF_DEFRAG_STATUS_FAILED: status = "failed"; break; } if (files || size || lookup) { snprintf (msg, sizeof(msg), "Rebalance %s: rebalanced %"PRId64 " files of size %"PRId64" (total files" " scanned %"PRId64")", status, files, size, lookup); goto done; } snprintf (msg, sizeof (msg), "Rebalance %s", status); goto done; } /* All other possibility is about starting a volume */ if (rsp.op_ret && strcmp (rsp.op_errstr, "")) snprintf (msg, sizeof (msg), "%s", rsp.op_errstr); else snprintf (msg, sizeof (msg), "Starting rebalance on volume %s has been %s", volname, (rsp.op_ret) ? "unsuccessful": "successful"); done: #if (HAVE_LIB_XML) if (global_state->mode & GLUSTER_MODE_XML) { ret = cli_xml_output_str ("volRebalance", msg, rsp.op_ret, rsp.op_errno, rsp.op_errstr); if (ret) gf_log ("cli", GF_LOG_ERROR, "Error outputting to xml"); goto out; } #endif cli_out ("%s", msg); ret = rsp.op_ret; out: if (rsp.op_errstr) free (rsp.op_errstr); //malloced by xdr if (rsp.dict.dict_val) free (rsp.dict.dict_val); //malloced by xdr if (dict) dict_unref (dict); if (local_dict) dict_unref (local_dict); if (local) cli_local_wipe (local); cli_cmd_broadcast_response (ret); return ret; } int gf_cli3_1_rename_volume_cbk (struct rpc_req *req, struct iovec *iov, int count, void *myframe) { gf_cli_rsp rsp = {0,}; int ret = -1; char msg[1024] = {0,}; if (-1 == req->rpc_status) { goto out; } ret = xdr_to_generic (*iov, &rsp, (xdrproc_t)xdr_gf_cli_rsp); if (ret < 0) { gf_log ("", GF_LOG_ERROR, "error"); goto out; } gf_log ("cli", GF_LOG_INFO, "Received resp to probe"); snprintf (msg, sizeof (msg), "Rename volume %s", (rsp.op_ret) ? "unsuccessful": "successful"); #if (HAVE_LIB_XML) if (global_state->mode & GLUSTER_MODE_XML) { ret = cli_xml_output_str ("volRename", msg, rsp.op_ret, rsp.op_errno, rsp.op_errstr); if (ret) gf_log ("cli", GF_LOG_ERROR, "Error outputting to xml"); goto out; } #endif cli_out ("%s", msg); ret = rsp.op_ret; out: cli_cmd_broadcast_response (ret); return ret; } int gf_cli3_1_reset_volume_cbk (struct rpc_req *req, struct iovec *iov, int count, void *myframe) { gf_cli_rsp rsp = {0,}; int ret = -1; char msg[1024] = {0,}; if (-1 == req->rpc_status) { goto out; } ret = xdr_to_generic (*iov, &rsp, (xdrproc_t)xdr_gf_cli_rsp); if (ret < 0) { gf_log ("", GF_LOG_ERROR, "error"); goto out; } gf_log ("cli", GF_LOG_INFO, "Received resp to reset"); if (rsp.op_ret && strcmp (rsp.op_errstr, "")) snprintf (msg, sizeof (msg), "%s", rsp.op_errstr); else snprintf (msg, sizeof (msg), "reset volume %s", (rsp.op_ret) ? "unsuccessful": "successful"); #if (HAVE_LIB_XML) if (global_state->mode & GLUSTER_MODE_XML) { ret = cli_xml_output_str ("volReset", msg, rsp.op_ret, rsp.op_errno, rsp.op_errstr); if (ret) gf_log ("cli", GF_LOG_ERROR, "Error outputting to xml"); goto out; } #endif cli_out ("%s", msg); ret = rsp.op_ret; out: cli_cmd_broadcast_response (ret); return ret; } int gf_cli3_1_set_volume_cbk (struct rpc_req *req, struct iovec *iov, int count, void *myframe) { gf_cli_rsp rsp = {0,}; int ret = -1; dict_t *dict = NULL; char *help_str = NULL; char msg[1024] = {0,}; if (-1 == req->rpc_status) { goto out; } ret = xdr_to_generic (*iov, &rsp, (xdrproc_t)xdr_gf_cli_rsp); if (ret < 0) { gf_log ("", GF_LOG_ERROR, "error"); goto out; } gf_log ("cli", GF_LOG_INFO, "Received resp to set"); if (rsp.op_ret && strcmp (rsp.op_errstr, "")) snprintf (msg, sizeof (msg), "%s", rsp.op_errstr); dict = dict_new (); if (!dict) { ret = -1; goto out; } ret = dict_unserialize (rsp.dict.dict_val, rsp.dict.dict_len, &dict); if (ret) goto out; if (dict_get_str (dict, "help-str", &help_str)) snprintf (msg, sizeof (msg), "Set volume %s", (rsp.op_ret) ? "unsuccessful": "successful"); #if (HAVE_LIB_XML) if ((global_state->mode & GLUSTER_MODE_XML) && (help_str == NULL)) { ret = cli_xml_output_str ("volSet", msg, rsp.op_ret, rsp.op_errno, rsp.op_errstr); if (ret) gf_log ("cli", GF_LOG_ERROR, "Error outputting to xml"); goto out; } #endif cli_out ("%s", ((help_str == NULL) ? msg : help_str)); ret = rsp.op_ret; out: cli_cmd_broadcast_response (ret); return ret; } int gf_cli3_1_add_brick_cbk (struct rpc_req *req, struct iovec *iov, int count, void *myframe) { gf_cli_rsp rsp = {0,}; int ret = -1; char msg[1024] = {0,}; if (-1 == req->rpc_status) { goto out; } ret = xdr_to_generic (*iov, &rsp, (xdrproc_t)xdr_gf_cli_rsp); if (ret < 0) { gf_log ("", GF_LOG_ERROR, "error"); goto out; } gf_log ("cli", GF_LOG_INFO, "Received resp to add brick"); if (rsp.op_ret && strcmp (rsp.op_errstr, "")) snprintf (msg, sizeof (msg), "%s", rsp.op_errstr); else snprintf (msg, sizeof (msg), "Add Brick %s", (rsp.op_ret) ? "unsuccessful": "successful"); #if (HAVE_LIB_XML) if (global_state->mode & GLUSTER_MODE_XML) { ret = cli_xml_output_str ("volAddBrick", msg, rsp.op_ret, rsp.op_errno, rsp.op_errstr); if (ret) gf_log ("cli", GF_LOG_ERROR, "Error outputting to xml"); goto out; } #endif cli_out ("%s", msg); ret = rsp.op_ret; out: cli_cmd_broadcast_response (ret); if (rsp.dict.dict_val) free (rsp.dict.dict_val); if (rsp.op_errstr) free (rsp.op_errstr); return ret; } int gf_cli3_remove_brick_status_cbk (struct rpc_req *req, struct iovec *iov, int count, void *myframe) { gf_cli_rsp rsp = {0,}; char *status = "unknown"; int ret = -1; uint64_t files = 0; uint64_t size = 0; dict_t *dict = NULL; char msg[1024] = {0,}; if (-1 == req->rpc_status) { goto out; } ret = xdr_to_generic (*iov, &rsp, (xdrproc_t)xdr_gf_cli_rsp); if (ret < 0) { gf_log ("", GF_LOG_ERROR, "error"); goto out; } ret = rsp.op_ret; if (rsp.op_ret == -1) { if (strcmp (rsp.op_errstr, "")) cli_out ("%s", rsp.op_errstr); else cli_out ("failed to get the status of " "remove-brick process"); goto out; } switch (rsp.op_errno) { case GF_DEFRAG_STATUS_NOT_STARTED: status = "not started"; break; case GF_DEFRAG_STATUS_STARTED: status = "in progress"; break; case GF_DEFRAG_STATUS_STOPPED: status = "stopped"; break; case GF_DEFRAG_STATUS_COMPLETE: status = "completed"; break; case GF_DEFRAG_STATUS_FAILED: status = "failed"; break; } if (rsp.dict.dict_len) { /* Unserialize the dictionary */ dict = dict_new (); ret = dict_unserialize (rsp.dict.dict_val, rsp.dict.dict_len, &dict); if (ret < 0) { gf_log ("glusterd", GF_LOG_ERROR, "failed to " "unserialize req-buffer to dictionary"); goto out; } } ret = dict_get_uint64 (dict, "files", &files); if (ret) gf_log (THIS->name, GF_LOG_TRACE, "failed to get file count"); ret = dict_get_uint64 (dict, "size", &size); if (ret) gf_log (THIS->name, GF_LOG_TRACE, "failed to get size of xfer"); if (files && (rsp.op_errno == 1)) { snprintf (msg, sizeof (msg), "remove-brick %s: fixed layout %"PRId64, status,files); goto out; } if (files && (rsp.op_errno == 6)) { snprintf (msg, sizeof (msg), "remove-brick %s: fixed layout %"PRId64, status, files); goto out; } if (files) { snprintf (msg, sizeof (msg), "remove-brick %s: decommissioned %"PRId64 " files of size %"PRId64, status, files, size); goto out; } snprintf (msg, sizeof (msg), "remove-brick %s", status); #if (HAVE_LIB_XML) if (global_state->mode & GLUSTER_MODE_XML) { ret = cli_xml_output_str ("volRemoveBrick", msg, rsp.op_ret, rsp.op_errno, rsp.op_errstr); if (ret) gf_log ("cli", GF_LOG_ERROR, "Error outputting to xml"); goto out; } #endif cli_out ("%s", msg); out: if (rsp.dict.dict_val) free (rsp.dict.dict_val); //malloced by xdr if (dict) dict_unref (dict); cli_cmd_broadcast_response (ret); return ret; } int gf_cli3_1_remove_brick_cbk (struct rpc_req *req, struct iovec *iov, int count, void *myframe) { gf_cli_rsp rsp = {0,}; int ret = -1; char msg[1024] = {0,}; if (-1 == req->rpc_status) { goto out; } ret = xdr_to_generic (*iov, &rsp, (xdrproc_t)xdr_gf_cli_rsp); if (ret < 0) { gf_log ("", GF_LOG_ERROR, "error"); goto out; } gf_log ("cli", GF_LOG_INFO, "Received resp to remove brick"); if (rsp.op_ret && strcmp (rsp.op_errstr, "")) snprintf (msg, sizeof (msg), "%s", rsp.op_errstr); else snprintf (msg, sizeof (msg), "Remove Brick %s", (rsp.op_ret) ? "unsuccessful": "successful"); #if (HAVE_LIB_XML) if (global_state->mode & GLUSTER_MODE_XML) { ret = cli_xml_output_str ("volRemoveBrick", msg, rsp.op_ret, rsp.op_errno, rsp.op_errstr); if (ret) gf_log ("cli", GF_LOG_ERROR, "Error outputting to xml"); goto out; } #endif cli_out ("%s", msg); ret = rsp.op_ret; out: cli_cmd_broadcast_response (ret); if (rsp.dict.dict_val) free (rsp.dict.dict_val); if (rsp.op_errstr) free (rsp.op_errstr); return ret; } int gf_cli3_1_replace_brick_cbk (struct rpc_req *req, struct iovec *iov, int count, void *myframe) { gf_cli_rsp rsp = {0,}; int ret = -1; cli_local_t *local = NULL; call_frame_t *frame = NULL; dict_t *dict = NULL; char *src_brick = NULL; char *dst_brick = NULL; char *status_reply = NULL; gf1_cli_replace_op replace_op = 0; char *rb_operation_str = NULL; dict_t *rsp_dict = NULL; char msg[1024] = {0,}; if (-1 == req->rpc_status) { goto out; } frame = (call_frame_t *) myframe; ret = xdr_to_generic (*iov, &rsp, (xdrproc_t)xdr_gf_cli_rsp); if (ret < 0) { gf_log ("", GF_LOG_ERROR, "error"); goto out; } local = frame->local; GF_ASSERT (local); dict = local->dict; ret = dict_get_int32 (dict, "operation", (int32_t *)&replace_op); if (ret) { gf_log ("", GF_LOG_DEBUG, "dict_get on operation failed"); goto out; } switch (replace_op) { case GF_REPLACE_OP_START: if (rsp.op_ret) rb_operation_str = "replace-brick failed to start"; else rb_operation_str = "replace-brick started successfully"; break; case GF_REPLACE_OP_STATUS: if (rsp.op_ret || ret) rb_operation_str = "replace-brick status unknown"; else { if (rsp.dict.dict_len) { /* Unserialize the dictionary */ rsp_dict = dict_new (); ret = dict_unserialize (rsp.dict.dict_val, rsp.dict.dict_len, &rsp_dict); if (ret < 0) { gf_log ("glusterd", GF_LOG_ERROR, "failed to " "unserialize req-buffer to dictionary"); goto out; } } ret = dict_get_str (rsp_dict, "status-reply", &status_reply); if (ret) { gf_log (THIS->name, GF_LOG_ERROR, "failed to" "get status"); goto out; } rb_operation_str = status_reply; } break; case GF_REPLACE_OP_PAUSE: if (rsp.op_ret) rb_operation_str = "replace-brick pause failed"; else rb_operation_str = "replace-brick paused successfully"; break; case GF_REPLACE_OP_ABORT: if (rsp.op_ret) rb_operation_str = "replace-brick abort failed"; else rb_operation_str = "replace-brick aborted successfully"; break; case GF_REPLACE_OP_COMMIT: case GF_REPLACE_OP_COMMIT_FORCE: ret = dict_get_str (dict, "src-brick", &src_brick); if (ret) { gf_log ("", GF_LOG_DEBUG, "dict_get on src-brick failed"); goto out; } ret = dict_get_str (dict, "dst-brick", &dst_brick); if (ret) { gf_log ("", GF_LOG_DEBUG, "dict_get on dst-brick failed"); goto out; } if (rsp.op_ret || ret) rb_operation_str = "replace-brick commit failed"; else rb_operation_str = "replace-brick commit successful"; break; default: gf_log ("", GF_LOG_DEBUG, "Unknown operation"); break; } if (rsp.op_ret && (strcmp (rsp.op_errstr, ""))) { rb_operation_str = rsp.op_errstr; } gf_log ("cli", GF_LOG_INFO, "Received resp to replace brick"); snprintf (msg,sizeof (msg), "%s", rb_operation_str ? rb_operation_str : "Unknown operation"); #if (HAVE_LIB_XML) if (global_state->mode & GLUSTER_MODE_XML) { ret = cli_xml_output_str ("volReplaceBrick", msg, rsp.op_ret, rsp.op_errno, rsp.op_errstr); if (ret) gf_log ("cli", GF_LOG_ERROR, "Error outputting to xml"); goto out; } #endif cli_out ("%s", msg); ret = rsp.op_ret; out: if (local) { dict_unref (local->dict); cli_local_wipe (local); } cli_cmd_broadcast_response (ret); if (rsp.dict.dict_val) free (rsp.dict.dict_val); if (rsp_dict) dict_unref (rsp_dict); return ret; } static int gf_cli3_1_log_rotate_cbk (struct rpc_req *req, struct iovec *iov, int count, void *myframe) { gf_cli_rsp rsp = {0,}; int ret = -1; char msg[1024] = {0,}; if (-1 == req->rpc_status) { goto out; } ret = xdr_to_generic (*iov, &rsp, (xdrproc_t)xdr_gf_cli_rsp); if (ret < 0) { gf_log ("", GF_LOG_ERROR, "error"); goto out; } gf_log ("cli", GF_LOG_DEBUG, "Received resp to log rotate"); if (rsp.op_ret && strcmp (rsp.op_errstr, "")) snprintf (msg, sizeof (msg), "%s", rsp.op_errstr); else snprintf (msg, sizeof (msg), "log rotate %s", (rsp.op_ret) ? "unsuccessful": "successful"); #if (HAVE_LIB_XML) if (global_state->mode & GLUSTER_MODE_XML) { ret = cli_xml_output_str ("volLogRotate", msg, rsp.op_ret, rsp.op_errno, rsp.op_errstr); if (ret) gf_log ("cli", GF_LOG_ERROR, "Error outputting to xml"); goto out; } #endif cli_out ("%s", msg); ret = rsp.op_ret; out: cli_cmd_broadcast_response (ret); if (rsp.dict.dict_val) free (rsp.dict.dict_val); return ret; } static int gf_cli3_1_sync_volume_cbk (struct rpc_req *req, struct iovec *iov, int count, void *myframe) { gf_cli_rsp rsp = {0,}; int ret = -1; char msg[1024] = {0,}; if (-1 == req->rpc_status) { goto out; } ret = xdr_to_generic (*iov, &rsp, (xdrproc_t)xdr_gf_cli_rsp); if (ret < 0) { gf_log ("", GF_LOG_ERROR, "error"); goto out; } gf_log ("cli", GF_LOG_DEBUG, "Received resp to sync"); if (rsp.op_ret && strcmp (rsp.op_errstr, "")) snprintf (msg, sizeof (msg), "%s", rsp.op_errstr); else snprintf (msg, sizeof (msg), "volume sync: %s", (rsp.op_ret) ? "unsuccessful": "successful"); #if (HAVE_LIB_XML) if (global_state->mode & GLUSTER_MODE_XML) { ret = cli_xml_output_str ("volSync", msg, rsp.op_ret, rsp.op_errno, rsp.op_errstr); if (ret) gf_log ("cli", GF_LOG_ERROR, "Error outputting to xml"); goto out; } #endif cli_out ("%s", msg); ret = rsp.op_ret; out: cli_cmd_broadcast_response (ret); return ret; } int32_t gf_cli3_1_print_limit_list (char *volname, char *limit_list, char *op_errstr) { int64_t size = 0; int64_t limit_value = 0; int32_t i, j, k; int32_t len = 0, ret = -1; char *size_str = NULL; char path [PATH_MAX] = {0, }; char ret_str [1024] = {0, }; char value [1024] = {0, }; char mountdir [] = "/tmp/mntXXXXXX"; char abspath [PATH_MAX] = {0, }; runner_t runner = {0,}; GF_VALIDATE_OR_GOTO ("cli", volname, out); GF_VALIDATE_OR_GOTO ("cli", limit_list, out); if (!connected) goto out; len = strlen (limit_list); if (len == 0) { cli_out ("%s", op_errstr?op_errstr:"quota limit not set "); goto out; } if (mkdtemp (mountdir) == NULL) { gf_log ("cli", GF_LOG_WARNING, "failed to create a temporary " "mount directory"); ret = -1; goto out; } /* Mount a temporary client to fetch the disk usage * of the directory on which the limit is set. */ ret = runcmd (SBIN_DIR"/glusterfs", "-s", "localhost", "--volfile-id", volname, "-l", DEFAULT_LOG_FILE_DIRECTORY"/quota-list.log", mountdir, NULL); if (ret) { gf_log ("cli", GF_LOG_WARNING, "failed to mount glusterfs client"); ret = -1; goto rm_dir; } len = strlen (limit_list); if (len == 0) { cli_out ("quota limit not set "); goto unmount; } i = 0; cli_out ("\tpath\t\t limit_set\t size"); cli_out ("-----------------------------------------------------------" "-----------------------"); while (i < len) { j = 0; k = 0; while (limit_list [i] != ':') { path [k++] = limit_list [i++]; } path [k] = '\0'; i++; //skip ':' while (limit_list [i] != ',' && limit_list [i] != '\0') { value [j++] = limit_list[i++]; } value [j] = '\0'; snprintf (abspath, sizeof (abspath), "%s/%s", mountdir, path); ret = sys_lgetxattr (abspath, "trusted.limit.list", (void *) ret_str, 4096); if (ret < 0) { cli_out ("%-20s %10s", path, value); } else { sscanf (ret_str, "%"PRId64",%"PRId64, &size, &limit_value); size_str = gf_uint64_2human_readable ((uint64_t) size); if (size_str == NULL) { cli_out ("%-20s %10s %20"PRId64, path, value, size); } else { cli_out ("%-20s %10s %20s", path, value, size_str); GF_FREE (size_str); } } i++; } unmount: runinit (&runner); runner_add_args (&runner, "umount", #if GF_LINUX_HOST_OS "-l", #endif mountdir, NULL); ret = runner_run_reuse (&runner); if (ret) runner_log (&runner, "cli", GF_LOG_WARNING, "error executing"); runner_end (&runner); rm_dir: rmdir (mountdir); out: return ret; } int gf_cli3_1_quota_cbk (struct rpc_req *req, struct iovec *iov, int count, void *myframe) { gf_cli_rsp rsp = {0,}; int ret = -1; dict_t *dict = NULL; char *volname = NULL; char *limit_list = NULL; int32_t type = 0; if (-1 == req->rpc_status) { goto out; } ret = xdr_to_generic (*iov, &rsp, (xdrproc_t)xdr_gf_cli_rsp); if (ret < 0) { gf_log ("", GF_LOG_ERROR, "error"); goto out; } if (rsp.op_ret && strcmp (rsp.op_errstr, "") == 0) { cli_out ("command unsuccessful %s", rsp.op_errstr); goto out; } if (rsp.dict.dict_len) { /* Unserialize the dictionary */ dict = dict_new (); ret = dict_unserialize (rsp.dict.dict_val, rsp.dict.dict_len, &dict); if (ret < 0) { gf_log ("glusterd", GF_LOG_ERROR, "failed to " "unserialize req-buffer to dictionary"); goto out; } } ret = dict_get_str (dict, "volname", &volname); if (ret) gf_log (THIS->name, GF_LOG_TRACE, "failed to get volname"); ret = dict_get_str (dict, "limit_list", &limit_list); if (ret) gf_log (THIS->name, GF_LOG_TRACE, "failed to get limit_list"); ret = dict_get_int32 (dict, "type", &type); if (ret) gf_log (THIS->name, GF_LOG_TRACE, "failed to get type"); if (type == GF_QUOTA_OPTION_TYPE_LIST) { if (limit_list) { gf_cli3_1_print_limit_list (volname, limit_list, rsp.op_errstr); } else { gf_log ("cli", GF_LOG_INFO, "Received resp to quota " "command "); if (rsp.op_errstr) cli_out ("%s", rsp.op_errstr); } } else { gf_log ("cli", GF_LOG_INFO, "Received resp to quota command "); if (rsp.op_errstr) cli_out ("%s", rsp.op_errstr); else cli_out ("%s", "successful"); } out: ret = rsp.op_ret; cli_cmd_broadcast_response (ret); if (rsp.dict.dict_val) free (rsp.dict.dict_val); return ret; } int gf_cli3_1_getspec_cbk (struct rpc_req *req, struct iovec *iov, int count, void *myframe) { gf_getspec_rsp rsp = {0,}; int ret = -1; char *spec = NULL; if (-1 == req->rpc_status) { goto out; } ret = xdr_to_generic (*iov, &rsp, (xdrproc_t)xdr_gf_getspec_rsp); if (ret < 0 || rsp.op_ret == -1) { gf_log ("", GF_LOG_ERROR, "error"); goto out; } gf_log ("cli", GF_LOG_INFO, "Received resp to getspec"); spec = GF_MALLOC (rsp.op_ret + 1, cli_mt_char); if (!spec) { gf_log("", GF_LOG_ERROR, "out of memory"); goto out; } memcpy (spec, rsp.spec, rsp.op_ret); spec[rsp.op_ret] = '\0'; cli_out ("%s", spec); GF_FREE (spec); ret = 0; out: cli_cmd_broadcast_response (ret); return ret; } int gf_cli3_1_pmap_b2p_cbk (struct rpc_req *req, struct iovec *iov, int count, void *myframe) { pmap_port_by_brick_rsp rsp = {0,}; int ret = -1; char *spec = NULL; if (-1 == req->rpc_status) { goto out; } ret = xdr_to_generic (*iov, &rsp, (xdrproc_t)xdr_pmap_port_by_brick_rsp); if (ret < 0 || rsp.op_ret == -1) { gf_log ("", GF_LOG_ERROR, "error"); goto out; } gf_log ("cli", GF_LOG_INFO, "Received resp to pmap b2p"); cli_out ("%d", rsp.port); GF_FREE (spec); ret = rsp.op_ret; out: cli_cmd_broadcast_response (ret); return ret; } int32_t gf_cli3_1_probe (call_frame_t *frame, xlator_t *this, void *data) { gf1_cli_probe_req req = {0,}; int ret = 0; dict_t *dict = NULL; char *hostname = NULL; int port = 0; if (!frame || !this || !data) { ret = -1; goto out; } dict = data; ret = dict_get_str (dict, "hostname", &hostname); if (ret) goto out; ret = dict_get_int32 (dict, "port", &port); if (ret) port = CLI_GLUSTERD_PORT; req.hostname = hostname; req.port = port; ret = cli_cmd_submit (&req, frame, cli_rpc_prog, GLUSTER_CLI_PROBE, NULL, this, gf_cli3_1_probe_cbk, (xdrproc_t)xdr_gf1_cli_probe_req); out: gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); return ret; } int32_t gf_cli3_1_deprobe (call_frame_t *frame, xlator_t *this, void *data) { gf1_cli_deprobe_req req = {0,}; int ret = 0; dict_t *dict = NULL; char *hostname = NULL; int port = 0; int flags = 0; if (!frame || !this || !data) { ret = -1; goto out; } dict = data; ret = dict_get_str (dict, "hostname", &hostname); if (ret) goto out; ret = dict_get_int32 (dict, "port", &port); if (ret) port = CLI_GLUSTERD_PORT; ret = dict_get_int32 (dict, "flags", &flags); if (ret) flags = 0; req.hostname = hostname; req.port = port; req.flags = flags; ret = cli_cmd_submit (&req, frame, cli_rpc_prog, GLUSTER_CLI_DEPROBE, NULL, this, gf_cli3_1_deprobe_cbk, (xdrproc_t)xdr_gf1_cli_deprobe_req); out: gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); return ret; } int32_t gf_cli3_1_list_friends (call_frame_t *frame, xlator_t *this, void *data) { gf1_cli_peer_list_req req = {0,}; int ret = 0; if (!frame || !this) { ret = -1; goto out; } req.flags = GF_CLI_LIST_ALL; ret = cli_cmd_submit (&req, frame, cli_rpc_prog, GLUSTER_CLI_LIST_FRIENDS, NULL, this, gf_cli3_1_list_friends_cbk, (xdrproc_t) xdr_gf1_cli_peer_list_req); out: gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); return ret; } int32_t gf_cli3_1_get_next_volume (call_frame_t *frame, xlator_t *this, void *data) { int ret = 0; cli_cmd_volume_get_ctx_t *ctx = NULL; cli_local_t *local = NULL; if (!frame || !this || !data) { ret = -1; goto out; } ctx = data; ret = gf_cli3_1_get_volume (frame, this, data); local = frame->local; if (!local || !local->get_vol.volname) { cli_out ("No volumes present"); goto out; } ctx->volname = local->get_vol.volname; while (ctx->volname) { ret = gf_cli3_1_get_volume (frame, this, ctx); if (ret) goto out; ctx->volname = local->get_vol.volname; } out: return ret; } int32_t gf_cli3_1_get_volume (call_frame_t *frame, xlator_t *this, void *data) { gf_cli_req req = {{0,}}; int ret = 0; cli_cmd_volume_get_ctx_t *ctx = NULL; dict_t *dict = NULL; int32_t flags = 0; if (!frame || !this || !data) { ret = -1; goto out; } ctx = data; dict = dict_new (); if (!dict) goto out; if (ctx->volname) { ret = dict_set_str (dict, "volname", ctx->volname); if (ret) goto out; } flags = ctx->flags; ret = dict_set_int32 (dict, "flags", flags); if (ret) { gf_log (THIS->name, GF_LOG_ERROR, "failed to set flags"); goto out; } ret = dict_allocate_and_serialize (dict, &req.dict.dict_val, (size_t *)&req.dict.dict_len); ret = cli_cmd_submit (&req, frame, cli_rpc_prog, GLUSTER_CLI_GET_VOLUME, NULL, this, gf_cli3_1_get_volume_cbk, (xdrproc_t) xdr_gf_cli_req); out: if (dict) dict_unref (dict); if (req.dict.dict_val) GF_FREE (req.dict.dict_val); gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); return ret; } int32_t gf_cli3_1_create_volume (call_frame_t *frame, xlator_t *this, void *data) { gf_cli_req req = {{0,}}; int ret = 0; dict_t *dict = NULL; cli_local_t *local = NULL; if (!frame || !this || !data) { ret = -1; goto out; } dict = dict_ref ((dict_t *)data); ret = dict_allocate_and_serialize (dict, &req.dict.dict_val, (size_t *)&req.dict.dict_len); if (ret < 0) { gf_log (this->name, GF_LOG_DEBUG, "failed to get serialized length of dict"); goto out; } local = cli_local_get (); if (local) { local->dict = dict_ref (dict); frame->local = local; } ret = cli_cmd_submit (&req, frame, cli_rpc_prog, GLUSTER_CLI_CREATE_VOLUME, NULL, this, gf_cli3_1_create_volume_cbk, (xdrproc_t) xdr_gf_cli_req); out: gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); if (dict) dict_unref (dict); if (req.dict.dict_val) { GF_FREE (req.dict.dict_val); } return ret; } int32_t gf_cli3_1_delete_volume (call_frame_t *frame, xlator_t *this, void *data) { gf_cli_req req = {{0,}}; int ret = 0; cli_local_t *local = NULL; dict_t *dict = NULL; if (!frame || !this || !data) { ret = -1; goto out; } local = cli_local_get (); dict = dict_new (); ret = dict_set_str (dict, "volname", data); if (ret) { gf_log (THIS->name, GF_LOG_WARNING, "dict set failed"); goto out; } if (local) { local->dict = dict_ref (dict); frame->local = local; } ret = dict_allocate_and_serialize (dict, &req.dict.dict_val, (size_t *)&req.dict.dict_len); if (ret < 0) { gf_log (this->name, GF_LOG_ERROR, "failed to get serialize dict"); goto out; } ret = cli_cmd_submit (&req, frame, cli_rpc_prog, GLUSTER_CLI_DELETE_VOLUME, NULL, this, gf_cli3_1_delete_volume_cbk, (xdrproc_t)xdr_gf_cli_req); out: if (dict) dict_unref (dict); if (req.dict.dict_val) GF_FREE (req.dict.dict_val); gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); return ret; } int32_t gf_cli3_1_start_volume (call_frame_t *frame, xlator_t *this, void *data) { gf_cli_req req = {{0,}}; int ret = 0; cli_local_t *local = NULL; dict_t *dict = NULL; if (!frame || !this || !data) { ret = -1; goto out; } dict = data; local = cli_local_get (); ret = dict_allocate_and_serialize (dict, &req.dict.dict_val, (size_t *)&req.dict.dict_len); if (ret < 0) { gf_log (this->name, GF_LOG_ERROR, "failed to serialize dict"); goto out; } if (local) { local->dict = dict_ref (dict); frame->local = local; } ret = cli_cmd_submit (&req, frame, cli_rpc_prog, GLUSTER_CLI_START_VOLUME, NULL, this, gf_cli3_1_start_volume_cbk, (xdrproc_t) xdr_gf_cli_req); out: gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); return ret; } int32_t gf_cli3_1_stop_volume (call_frame_t *frame, xlator_t *this, void *data) { gf_cli_req req = {{0,}}; int ret = 0; cli_local_t *local = NULL; dict_t *dict = data; if (!frame || !this || !data) { ret = -1; goto out; } local = cli_local_get (); dict = data; if (local) { local->dict = dict_ref (dict); frame->local = local; } ret = dict_allocate_and_serialize (dict, &req.dict.dict_val, (size_t *) &req.dict.dict_len); if (ret < 0) { gf_log (this->name, GF_LOG_ERROR, "failed to serialize the data"); goto out; } ret = cli_cmd_submit (&req, frame, cli_rpc_prog, GLUSTER_CLI_STOP_VOLUME, NULL, this, gf_cli3_1_stop_volume_cbk, (xdrproc_t) xdr_gf_cli_req); out: gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); return ret; } int32_t gf_cli3_1_defrag_volume (call_frame_t *frame, xlator_t *this, void *data) { gf_cli_req req = {{0,}}; int ret = 0; cli_local_t *local = NULL; char *volname = NULL; char *cmd_str = NULL; dict_t *dict = NULL; gf_cli_defrag_type cmd = 0; dict_t *req_dict = NULL; if (!frame || !this || !data) { ret = -1; goto out; } dict = data; ret = dict_get_str (dict, "volname", &volname); if (ret) gf_log ("", GF_LOG_DEBUG, "error"); ret = dict_get_str (dict, "command", &cmd_str); if (ret) { gf_log ("", GF_LOG_DEBUG, "error"); goto out; } if (strcmp (cmd_str, "start") == 0) { cmd = GF_DEFRAG_CMD_START; ret = dict_get_str (dict, "option", &cmd_str); if (!ret) { if (strcmp (cmd_str, "force") == 0) { cmd = GF_DEFRAG_CMD_START_FORCE; } } goto done; } if (strcmp (cmd_str, "fix-layout") == 0) { cmd = GF_DEFRAG_CMD_START_LAYOUT_FIX; goto done; } if (strcmp (cmd_str, "stop") == 0) { cmd = GF_DEFRAG_CMD_STOP; goto done; } if (strcmp (cmd_str, "status") == 0) { cmd = GF_DEFRAG_CMD_STATUS; } done: local = cli_local_get (); req_dict = dict_new (); if (!req_dict) { ret = -1; goto out; } ret = dict_set_str (req_dict, "volname", volname); if (ret) { gf_log (THIS->name, GF_LOG_ERROR, "Failed to set dict"); goto out; } ret = dict_set_int32 (req_dict, "rebalance-command", (int32_t) cmd); if (ret) { gf_log (THIS->name, GF_LOG_ERROR, "Failed to set dict"); goto out; } if (local) { local->dict = dict_ref (req_dict); frame->local = local; } ret = dict_allocate_and_serialize (req_dict, &req.dict.dict_val, (size_t *) &req.dict.dict_len); if (ret < 0) { gf_log (this->name, GF_LOG_ERROR, "failed to serialize the data"); goto out; } ret = cli_cmd_submit (&req, frame, cli_rpc_prog, GLUSTER_CLI_DEFRAG_VOLUME, NULL, this, gf_cli3_1_defrag_volume_cbk, (xdrproc_t) xdr_gf_cli_req); out: gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); return ret; } int32_t gf_cli3_1_rename_volume (call_frame_t *frame, xlator_t *this, void *data) { gf_cli_req req = {{0,}}; int ret = 0; dict_t *dict = NULL; if (!frame || !this || !data) { ret = -1; goto out; } dict = data; ret = dict_allocate_and_serialize (dict, &req.dict.dict_val, (size_t *) &req.dict.dict_len); if (ret < 0) { gf_log (this->name, GF_LOG_ERROR, "failed to serialize the data"); goto out; } ret = cli_cmd_submit (&req, frame, cli_rpc_prog, GLUSTER_CLI_RENAME_VOLUME, NULL, this, gf_cli3_1_rename_volume_cbk, (xdrproc_t) xdr_gf_cli_req); out: gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); return ret; } int32_t gf_cli3_1_reset_volume (call_frame_t *frame, xlator_t *this, void *data) { gf_cli_req req = {{0,}}; int ret = 0; dict_t *dict = NULL; if (!frame || !this || !data) { ret = -1; goto out; } dict = data; ret = dict_allocate_and_serialize (dict, &req.dict.dict_val, (size_t *)&req.dict.dict_len); if (ret < 0) { gf_log (this->name, GF_LOG_ERROR, "failed to get serialized length of dict"); goto out; } ret = cli_cmd_submit (&req, frame, cli_rpc_prog, GLUSTER_CLI_RESET_VOLUME, NULL, this, gf_cli3_1_reset_volume_cbk, (xdrproc_t) xdr_gf_cli_req); out: gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); return ret; } int32_t gf_cli3_1_set_volume (call_frame_t *frame, xlator_t *this, void *data) { gf_cli_req req = {{0,}}; int ret = 0; dict_t *dict = NULL; if (!frame || !this || !data) { ret = -1; goto out; } dict = data; ret = dict_allocate_and_serialize (dict, &req.dict.dict_val, (size_t *)&req.dict.dict_len); if (ret < 0) { gf_log (this->name, GF_LOG_DEBUG, "failed to get serialized length of dict"); goto out; } ret = cli_cmd_submit (&req, frame, cli_rpc_prog, GLUSTER_CLI_SET_VOLUME, NULL, this, gf_cli3_1_set_volume_cbk, (xdrproc_t) xdr_gf_cli_req); out: gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); return ret; } int32_t gf_cli3_1_add_brick (call_frame_t *frame, xlator_t *this, void *data) { gf_cli_req req = {{0,}}; int ret = 0; dict_t *dict = NULL; char *volname = NULL; int32_t count = 0; if (!frame || !this || !data) { ret = -1; goto out; } dict = data; ret = dict_get_str (dict, "volname", &volname); if (ret) goto out; ret = dict_get_int32 (dict, "count", &count); if (ret) goto out; ret = dict_allocate_and_serialize (dict, &req.dict.dict_val, (size_t *)&req.dict.dict_len); if (ret < 0) { gf_log (this->name, GF_LOG_DEBUG, "failed to get serialized length of dict"); goto out; } ret = cli_cmd_submit (&req, frame, cli_rpc_prog, GLUSTER_CLI_ADD_BRICK, NULL, this, gf_cli3_1_add_brick_cbk, (xdrproc_t) xdr_gf_cli_req); out: gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); if (req.dict.dict_val) { GF_FREE (req.dict.dict_val); } return ret; } int32_t gf_cli3_1_remove_brick (call_frame_t *frame, xlator_t *this, void *data) { gf_cli_req req = {{0,}};; gf_cli_req status_req = {{0,}};; int ret = 0; dict_t *dict = NULL; int32_t command = 0; char *volname = NULL; dict_t *req_dict = NULL; int32_t cmd = 0; if (!frame || !this || !data) { ret = -1; goto out; } dict = data; ret = dict_get_str (dict, "volname", &volname); if (ret) goto out; ret = dict_get_int32 (dict, "command", &command); if (ret) goto out; if (command != GF_OP_CMD_STATUS) { ret = dict_allocate_and_serialize (dict, &req.dict.dict_val, (size_t *)&req.dict.dict_len); if (ret < 0) { gf_log (this->name, GF_LOG_DEBUG, "failed to get serialized length of dict"); goto out; } ret = cli_cmd_submit (&req, frame, cli_rpc_prog, GLUSTER_CLI_REMOVE_BRICK, NULL, this, gf_cli3_1_remove_brick_cbk, (xdrproc_t) xdr_gf_cli_req); } else { /* Need rebalance status to e sent :-) */ req_dict = dict_new (); if (!req_dict) { ret = -1; goto out; } ret = dict_set_str (req_dict, "volname", volname); if (ret) { gf_log (THIS->name, GF_LOG_ERROR, "Failed to set dict"); goto out; } cmd |= GF_DEFRAG_CMD_STATUS; ret = dict_set_int32 (req_dict, "rebalance-command", (int32_t) cmd); if (ret) { gf_log (THIS->name, GF_LOG_ERROR, "Failed to set dict"); goto out; } ret = dict_allocate_and_serialize (req_dict, &status_req.dict.dict_val, (size_t *) &status_req.dict.dict_len); if (ret < 0) { gf_log (this->name, GF_LOG_ERROR, "failed to serialize the data"); goto out; } ret = cli_cmd_submit (&status_req, frame, cli_rpc_prog, GLUSTER_CLI_DEFRAG_VOLUME, NULL, this, gf_cli3_remove_brick_status_cbk, (xdrproc_t) xdr_gf_cli_req); } out: gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); if (req.dict.dict_val) { GF_FREE (req.dict.dict_val); } if (status_req.dict.dict_val) GF_FREE (status_req.dict.dict_val); if (req_dict) dict_unref (req_dict); return ret; } int32_t gf_cli3_1_replace_brick (call_frame_t *frame, xlator_t *this, void *data) { gf_cli_req req = {{0,}}; int ret = 0; cli_local_t *local = NULL; dict_t *dict = NULL; char *src_brick = NULL; char *dst_brick = NULL; char *volname = NULL; int32_t op = 0; if (!frame || !this || !data) { ret = -1; goto out; } dict = data; local = cli_local_get (); if (!local) { ret = -1; gf_log (this->name, GF_LOG_ERROR, "Out of memory"); goto out; } local->dict = dict_ref (dict); frame->local = local; ret = dict_get_int32 (dict, "operation", &op); if (ret) { gf_log (this->name, GF_LOG_DEBUG, "dict_get on operation failed"); goto out; } ret = dict_get_str (dict, "volname", &volname); if (ret) { gf_log (this->name, GF_LOG_DEBUG, "dict_get on volname failed"); goto out; } ret = dict_get_str (dict, "src-brick", &src_brick); if (ret) { gf_log (this->name, GF_LOG_DEBUG, "dict_get on src-brick failed"); goto out; } ret = dict_get_str (dict, "dst-brick", &dst_brick); if (ret) { gf_log (this->name, GF_LOG_DEBUG, "dict_get on dst-brick failed"); goto out; } gf_log (this->name, GF_LOG_DEBUG, "Received command replace-brick %s with " "%s with operation=%d", src_brick, dst_brick, op); ret = dict_allocate_and_serialize (dict, &req.dict.dict_val, (size_t *)&req.dict.dict_len); if (ret < 0) { gf_log (this->name, GF_LOG_DEBUG, "failed to get serialized length of dict"); goto out; } ret = cli_cmd_submit (&req, frame, cli_rpc_prog, GLUSTER_CLI_REPLACE_BRICK, NULL, this, gf_cli3_1_replace_brick_cbk, (xdrproc_t) xdr_gf_cli_req); out: gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); if (req.dict.dict_val) { GF_FREE (req.dict.dict_val); } return ret; } int32_t gf_cli3_1_log_rotate (call_frame_t *frame, xlator_t *this, void *data) { gf_cli_req req = {{0,}}; int ret = 0; dict_t *dict = NULL; if (!frame || !this || !data) { ret = -1; goto out; } dict = data; ret = dict_allocate_and_serialize (dict, &req.dict.dict_val, (size_t *)&req.dict.dict_len); if (ret < 0) { gf_log (THIS->name, GF_LOG_ERROR, "failed to serialize dict"); goto out; } ret = cli_cmd_submit (&req, frame, cli_rpc_prog, GLUSTER_CLI_LOG_ROTATE, NULL, this, gf_cli3_1_log_rotate_cbk, (xdrproc_t) xdr_gf_cli_req); out: gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); if (req.dict.dict_val) GF_FREE (req.dict.dict_val); return ret; } int32_t gf_cli3_1_sync_volume (call_frame_t *frame, xlator_t *this, void *data) { int ret = 0; gf_cli_req req = {{0,}}; dict_t *dict = NULL; if (!frame || !this || !data) { ret = -1; goto out; } dict = data; ret = dict_allocate_and_serialize (dict, &req.dict.dict_val, (size_t *)&req.dict.dict_len); if (ret < 0) { gf_log (THIS->name, GF_LOG_ERROR, "failed to serialize dict"); goto out; } ret = cli_cmd_submit (&req, frame, cli_rpc_prog, GLUSTER_CLI_SYNC_VOLUME, NULL, this, gf_cli3_1_sync_volume_cbk, (xdrproc_t) xdr_gf_cli_req); out: gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); if (req.dict.dict_val) GF_FREE (req.dict.dict_val); return ret; } int32_t gf_cli3_1_getspec (call_frame_t *frame, xlator_t *this, void *data) { gf_getspec_req req = {0,}; int ret = 0; dict_t *dict = NULL; if (!frame || !this || !data) { ret = -1; goto out; } dict = data; ret = dict_get_str (dict, "volid", &req.key); if (ret) goto out; ret = cli_cmd_submit (&req, frame, &cli_handshake_prog, GF_HNDSK_GETSPEC, NULL, this, gf_cli3_1_getspec_cbk, (xdrproc_t) xdr_gf_getspec_req); out: gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); return ret; } int32_t gf_cli3_1_quota (call_frame_t *frame, xlator_t *this, void *data) { gf_cli_req req = {{0,}}; int ret = 0; dict_t *dict = NULL; if (!frame || !this || !data) { ret = -1; goto out; } dict = data; ret = dict_allocate_and_serialize (dict, &req.dict.dict_val, (size_t *)&req.dict.dict_len); if (ret < 0) { gf_log (this->name, GF_LOG_ERROR, "failed to get serialized length of dict"); goto out; } ret = cli_cmd_submit (&req, frame, cli_rpc_prog, GLUSTER_CLI_QUOTA, NULL, this, gf_cli3_1_quota_cbk, (xdrproc_t) xdr_gf_cli_req); GF_FREE (req.dict.dict_val); out: return ret; } int32_t gf_cli3_1_pmap_b2p (call_frame_t *frame, xlator_t *this, void *data) { pmap_port_by_brick_req req = {0,}; int ret = 0; dict_t *dict = NULL; if (!frame || !this || !data) { ret = -1; goto out; } dict = data; ret = dict_get_str (dict, "brick", &req.brick); if (ret) goto out; ret = cli_cmd_submit (&req, frame, &cli_pmap_prog, GF_PMAP_PORTBYBRICK, NULL, this, gf_cli3_1_pmap_b2p_cbk, (xdrproc_t) xdr_pmap_port_by_brick_req); out: gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); return ret; } static int gf_cli3_1_fsm_log_cbk (struct rpc_req *req, struct iovec *iov, int count, void *myframe) { gf1_cli_fsm_log_rsp rsp = {0,}; int ret = -1; dict_t *dict = NULL; int tr_count = 0; char key[256] = {0}; int i = 0; char *old_state = NULL; char *new_state = NULL; char *event = NULL; char *time = NULL; if (-1 == req->rpc_status) { goto out; } ret = xdr_to_generic (*iov, &rsp, (xdrproc_t)xdr_gf1_cli_fsm_log_rsp); if (ret < 0) { gf_log ("", GF_LOG_ERROR, "error"); goto out; } if (rsp.op_ret) { if (strcmp (rsp.op_errstr, "")) cli_out ("%s", rsp.op_errstr); cli_out ("fsm log unsuccessful"); ret = rsp.op_ret; goto out; } dict = dict_new (); if (!dict) { ret = -1; goto out; } ret = dict_unserialize (rsp.fsm_log.fsm_log_val, rsp.fsm_log.fsm_log_len, &dict); if (ret) { cli_out ("bad response"); goto out; } ret = dict_get_int32 (dict, "count", &tr_count); if (tr_count) cli_out("number of transitions: %d", tr_count); else cli_out("No transitions"); for (i = 0; i < tr_count; i++) { memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "log%d-old-state", i); ret = dict_get_str (dict, key, &old_state); if (ret) goto out; memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "log%d-event", i); ret = dict_get_str (dict, key, &event); if (ret) goto out; memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "log%d-new-state", i); ret = dict_get_str (dict, key, &new_state); if (ret) goto out; memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "log%d-time", i); ret = dict_get_str (dict, key, &time); if (ret) goto out; cli_out ("Old State: [%s]\n" "New State: [%s]\n" "Event : [%s]\n" "timestamp: [%s]\n", old_state, new_state, event, time); } ret = rsp.op_ret; out: cli_cmd_broadcast_response (ret); return ret; } int32_t gf_cli3_1_fsm_log (call_frame_t *frame, xlator_t *this, void *data) { int ret = -1; gf1_cli_fsm_log_req req = {0,}; GF_ASSERT (frame); GF_ASSERT (this); GF_ASSERT (data); if (!frame || !this || !data) goto out; req.name = data; ret = cli_cmd_submit (&req, frame, cli_rpc_prog, GLUSTER_CLI_FSM_LOG, NULL, this, gf_cli3_1_fsm_log_cbk, (xdrproc_t) xdr_gf1_cli_fsm_log_req); out: gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); return ret; } int gf_cli3_1_gsync_config_command (dict_t *dict) { runner_t runner = {0,}; char *subop = NULL; char *gwd = NULL; char *slave = NULL; char *master = NULL; char *op_name = NULL; if (dict_get_str (dict, "subop", &subop) != 0) return -1; if (strcmp (subop, "get") != 0 && strcmp (subop, "get-all") != 0) { cli_out (GEOREP" config updated successfully"); return 0; } if (dict_get_str (dict, "glusterd_workdir", &gwd) != 0 || dict_get_str (dict, "slave", &slave) != 0) return -1; if (dict_get_str (dict, "master", &master) != 0) master = NULL; if (dict_get_str (dict, "op_name", &op_name) != 0) op_name = NULL; runinit (&runner); runner_add_args (&runner, GSYNCD_PREFIX"/gsyncd", "-c", NULL); runner_argprintf (&runner, "%s/"GSYNC_CONF, gwd); if (master) runner_argprintf (&runner, ":%s", master); runner_add_arg (&runner, slave); runner_argprintf (&runner, "--config-%s", subop); if (op_name) runner_add_arg (&runner, op_name); return runner_run (&runner); } int gf_cli3_1_gsync_out_status (dict_t *dict) { int gsync_count = 0; int i = 0; int ret = 0; char mst[PATH_MAX] = {0, }; char slv[PATH_MAX]= {0, }; char sts[PATH_MAX] = {0, }; char hyphens[81] = {0, }; char *mst_val = NULL; char *slv_val = NULL; char *sts_val = NULL; cli_out ("%-20s %-50s %-10s", "MASTER", "SLAVE", "STATUS"); for (i=0; irpc_status == -1) { ret = -1; goto out; } ret = xdr_to_generic (*iov, &rsp, (xdrproc_t)xdr_gf_cli_rsp); if (ret < 0) { gf_log ("", GF_LOG_ERROR, "Unable to get response structure"); goto out; } dict = dict_new (); if (!dict) { ret = -1; goto out; } ret = dict_unserialize (rsp.dict.dict_val, rsp.dict.dict_len, &dict); if (ret) goto out; #if (HAVE_LIB_XML) if (global_state->mode & GLUSTER_MODE_XML) { ret = cli_xml_output_dict ("volGeoRep", dict, rsp.op_ret, rsp.op_errno, rsp.op_errstr); if (ret) gf_log ("cli", GF_LOG_ERROR, "Error outputting to xml"); goto out; } #endif if (rsp.op_ret) { cli_out ("%s", rsp.op_errstr ? rsp.op_errstr : GEOREP" command unsuccessful"); ret = rsp.op_ret; goto out; } ret = dict_get_str (dict, "gsync-status", &gsync_status); if (!ret) cli_out ("%s", gsync_status); else ret = 0; ret = dict_get_int32 (dict, "type", &type); if (ret) { gf_log (THIS->name, GF_LOG_ERROR, "failed to get type"); goto out; } switch (type) { case GF_GSYNC_OPTION_TYPE_START: case GF_GSYNC_OPTION_TYPE_STOP: if (dict_get_str (dict, "master", &master) != 0) master = "???"; if (dict_get_str (dict, "slave", &slave) != 0) slave = "???"; cli_out ("%s " GEOREP " session between %s & %s" " has been successful", type == GF_GSYNC_OPTION_TYPE_START ? "Starting" : "Stopping", master, slave); break; case GF_GSYNC_OPTION_TYPE_CONFIG: ret = gf_cli3_1_gsync_config_command (dict); break; case GF_GSYNC_OPTION_TYPE_STATUS: ret = gf_cli3_1_gsync_out_status (dict); goto out; default: cli_out (GEOREP" command executed successfully"); } out: cli_cmd_broadcast_response (ret); if (rsp.dict.dict_val) free (rsp.dict.dict_val); return ret; } int32_t gf_cli3_1_gsync_set (call_frame_t *frame, xlator_t *this, void *data) { int ret = 0; dict_t *dict = NULL; gf_cli_req req = {{0,}}; if (!frame || !this || !data) { ret = -1; goto out; } dict = data; ret = dict_allocate_and_serialize (dict, &req.dict.dict_val, (size_t *) &req.dict.dict_len); if (ret < 0) { gf_log (this->name, GF_LOG_ERROR, "failed to serialize the data"); goto out; } ret = cli_cmd_submit (&req, frame, cli_rpc_prog, GLUSTER_CLI_GSYNC_SET, NULL, this, gf_cli3_1_gsync_set_cbk, (xdrproc_t) xdr_gf_cli_req); out: if (req.dict.dict_val) GF_FREE (req.dict.dict_val); return ret; } int cli_profile_info_percentage_cmp (void *a, void *b) { cli_profile_info_t *ia = NULL; cli_profile_info_t *ib = NULL; int ret = 0; ia = a; ib = b; if (ia->percentage_avg_latency < ib->percentage_avg_latency) ret = -1; else if (ia->percentage_avg_latency > ib->percentage_avg_latency) ret = 1; else ret = 0; return ret; } void cmd_profile_volume_brick_out (dict_t *dict, int count, int interval) { char key[256] = {0}; int i = 0; uint64_t sec = 0; uint64_t r_count = 0; uint64_t w_count = 0; char *brick = NULL; uint64_t rb_counts[32] = {0}; uint64_t wb_counts[32] = {0}; cli_profile_info_t profile_info[GF_FOP_MAXVALUE] = {{0}}; char output[128] = {0}; int per_line = 0; char read_blocks[128] = {0}; char write_blocks[128] = {0}; int index = 0; int is_header_printed = 0; int ret = 0; double total_percentage_latency = 0; memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "%d-brick", count); ret = dict_get_str (dict, key, &brick); for (i = 0; i < 32; i++) { memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "%d-%d-read-%d", count, interval, (1 << i)); ret = dict_get_uint64 (dict, key, &rb_counts[i]); } for (i = 0; i < 32; i++) { memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "%d-%d-write-%d", count, interval, (1<rpc_status) { goto out; } gf_log ("cli", GF_LOG_DEBUG, "Received resp to profile"); ret = xdr_to_generic (*iov, &rsp, (xdrproc_t)xdr_gf_cli_rsp); if (ret < 0) { gf_log ("", GF_LOG_ERROR, "error"); goto out; } dict = dict_new (); if (!dict) { ret = -1; goto out; } ret = dict_unserialize (rsp.dict.dict_val, rsp.dict.dict_len, &dict); if (ret) { gf_log ("", GF_LOG_ERROR, "Unable to allocate memory"); goto out; } else { dict->extra_stdfree = rsp.dict.dict_val; } #if (HAVE_LIB_XML) if (global_state->mode & GLUSTER_MODE_XML) { ret = cli_xml_output_vol_profile (dict, rsp.op_ret, rsp.op_errno, rsp.op_errstr); if (ret) gf_log ("cli", GF_LOG_ERROR, "Error outputting to xml"); goto out; } #endif ret = dict_get_str (dict, "volname", &volname); if (ret) goto out; ret = dict_get_int32 (dict, "op", (int32_t*)&op); if (ret) goto out; if (rsp.op_ret && strcmp (rsp.op_errstr, "")) { cli_out ("%s", rsp.op_errstr); } else { switch (op) { case GF_CLI_STATS_START: cli_out ("Starting volume profile on %s has been %s ", volname, (rsp.op_ret) ? "unsuccessful": "successful"); break; case GF_CLI_STATS_STOP: cli_out ("Stopping volume profile on %s has been %s ", volname, (rsp.op_ret) ? "unsuccessful": "successful"); break; case GF_CLI_STATS_INFO: break; default: cli_out ("volume profile on %s has been %s ", volname, (rsp.op_ret) ? "unsuccessful": "successful"); break; } } if (rsp.op_ret) { ret = rsp.op_ret; goto out; } if (op != GF_CLI_STATS_INFO) { ret = 0; goto out; } ret = dict_get_int32 (dict, "count", &brick_count); if (ret) goto out; if (!brick_count) { cli_out ("All bricks of volume %s are down.", volname); goto out; } while (i <= brick_count) { snprintf (key, sizeof (key), "%d-cumulative", i); ret = dict_get_int32 (dict, key, &interval); if (ret == 0) { cmd_profile_volume_brick_out (dict, i, interval); } snprintf (key, sizeof (key), "%d-interval", i); ret = dict_get_int32 (dict, key, &interval); if (ret == 0) { cmd_profile_volume_brick_out (dict, i, interval); } i++; } ret = rsp.op_ret; out: if (dict) dict_unref (dict); if (rsp.op_errstr) free (rsp.op_errstr); cli_cmd_broadcast_response (ret); return ret; } int32_t gf_cli3_1_profile_volume (call_frame_t *frame, xlator_t *this, void *data) { int ret = -1; gf_cli_req req = {{0,}}; dict_t *dict = NULL; GF_ASSERT (frame); GF_ASSERT (this); GF_ASSERT (data); if (!frame || !this || !data) goto out; dict = data; ret = dict_allocate_and_serialize (dict, &req.dict.dict_val, (size_t *)&req.dict.dict_len); if (ret < 0) { gf_log (this->name, GF_LOG_ERROR, "failed to serialize the data"); goto out; } ret = cli_cmd_submit (&req, frame, cli_rpc_prog, GLUSTER_CLI_PROFILE_VOLUME, NULL, this, gf_cli3_1_profile_volume_cbk, (xdrproc_t) xdr_gf_cli_req); out: gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); if (req.dict.dict_val) GF_FREE (req.dict.dict_val); return ret; } int32_t gf_cli3_1_top_volume_cbk (struct rpc_req *req, struct iovec *iov, int count, void *myframe) { gf_cli_rsp rsp = {0,}; int ret = -1; dict_t *dict = NULL; gf1_cli_stats_op op = GF_CLI_STATS_NONE; char key[256] = {0}; int i = 0; int32_t brick_count = 0; char brick[1024]; int32_t members = 0; char *filename; char *bricks; uint64_t value = 0; int32_t j = 0; gf1_cli_top_op top_op = GF_CLI_TOP_NONE; uint64_t nr_open = 0; uint64_t max_nr_open = 0; double throughput = 0; double time = 0; long int time_sec = 0; long int time_usec = 0; struct tm *tm = NULL; char timestr[256] = {0, }; char *openfd_str = NULL; if (-1 == req->rpc_status) { goto out; } gf_log ("cli", GF_LOG_DEBUG, "Received resp to top"); ret = xdr_to_generic (*iov, &rsp, (xdrproc_t)xdr_gf_cli_rsp); if (ret < 0) { gf_log ("", GF_LOG_ERROR, "Unable to decode response"); goto out; } if (rsp.op_ret) { if (strcmp (rsp.op_errstr, "")) cli_out ("%s", rsp.op_errstr); cli_out ("volume top unsuccessful"); ret = rsp.op_ret; goto out; } dict = dict_new (); if (!dict) { ret = -1; goto out; } ret = dict_unserialize (rsp.dict.dict_val, rsp.dict.dict_len, &dict); if (ret) { gf_log ("", GF_LOG_ERROR, "Unable to allocate memory"); goto out; } ret = dict_get_int32 (dict, "op", (int32_t*)&op); if (op != GF_CLI_STATS_TOP) { ret = 0; goto out; } #if (HAVE_LIB_XML) if (global_state->mode & GLUSTER_MODE_XML) { ret = cli_xml_output_vol_top (dict, rsp.op_ret, rsp.op_errno, rsp.op_errstr); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Error outputting to xml"); } goto out; } #endif ret = dict_get_int32 (dict, "count", &brick_count); if (ret) goto out; snprintf (key, sizeof (key), "%d-top-op", 1); ret = dict_get_int32 (dict, key, (int32_t*)&top_op); if (ret) goto out; while (i < brick_count) { i++; snprintf (brick, sizeof (brick), "%d-brick", i); ret = dict_get_str (dict, brick, &bricks); if (ret) goto out; cli_out ("Brick: %s", bricks); snprintf(key, sizeof (key), "%d-members", i); ret = dict_get_int32 (dict, key, &members); switch (top_op) { case GF_CLI_TOP_OPEN: snprintf (key, sizeof (key), "%d-current-open", i); ret = dict_get_uint64 (dict, key, &nr_open); if (ret) break; snprintf (key, sizeof (key), "%d-max-open", i); ret = dict_get_uint64 (dict, key, &max_nr_open); if (ret) goto out; snprintf (key, sizeof (key), "%d-max-openfd-time", i); ret = dict_get_str (dict, key, &openfd_str); if (ret) goto out; cli_out ("Current open fds: %"PRIu64", Max open" " fds: %"PRIu64", Max openfd time: %s", nr_open, max_nr_open, openfd_str); case GF_CLI_TOP_READ: case GF_CLI_TOP_WRITE: case GF_CLI_TOP_OPENDIR: case GF_CLI_TOP_READDIR: if (!members) { continue; } cli_out ("Count\t\tfilename\n======================="); break; case GF_CLI_TOP_READ_PERF: case GF_CLI_TOP_WRITE_PERF: snprintf (key, sizeof (key), "%d-throughput", i); ret = dict_get_double (dict, key, &throughput); if (!ret) { snprintf (key, sizeof (key), "%d-time", i); ret = dict_get_double (dict, key, &time); } if (!ret) cli_out ("Throughput %.2f MBps time %.4f secs", throughput, time / 1e6); if (!members) { continue; } cli_out ("%*s %-*s %-*s", VOL_TOP_PERF_SPEED_WIDTH, "MBps", VOL_TOP_PERF_FILENAME_DEF_WIDTH, "Filename", VOL_TOP_PERF_TIME_WIDTH, "Time"); cli_out ("%*s %-*s %-*s", VOL_TOP_PERF_SPEED_WIDTH, "====", VOL_TOP_PERF_FILENAME_DEF_WIDTH, "========", VOL_TOP_PERF_TIME_WIDTH, "===="); break; default: goto out; } for (j = 1; j <= members; j++) { snprintf (key, sizeof (key), "%d-filename-%d", i, j); ret = dict_get_str (dict, key, &filename); if (ret) break; snprintf (key, sizeof (key), "%d-value-%d", i, j); ret = dict_get_uint64 (dict, key, &value); if (ret) goto out; if ( top_op == GF_CLI_TOP_READ_PERF || top_op == GF_CLI_TOP_WRITE_PERF) { snprintf (key, sizeof (key), "%d-time-sec-%d", i, j); ret = dict_get_int32 (dict, key, (int32_t *)&time_sec); if (ret) goto out; snprintf (key, sizeof (key), "%d-time-usec-%d", i, j); ret = dict_get_int32 (dict, key, (int32_t *)&time_usec); if (ret) goto out; tm = localtime (&time_sec); if (!tm) goto out; strftime (timestr, 256, "%Y-%m-%d %H:%M:%S", tm); snprintf (timestr + strlen (timestr), 256 - strlen (timestr), ".%"GF_PRI_SUSECONDS, time_usec); if (strlen (filename) < VOL_TOP_PERF_FILENAME_DEF_WIDTH) cli_out ("%*"PRIu64" %-*s %-*s", VOL_TOP_PERF_SPEED_WIDTH, value, VOL_TOP_PERF_FILENAME_DEF_WIDTH, filename, VOL_TOP_PERF_TIME_WIDTH, timestr); else cli_out ("%*"PRIu64" ...%-*s %-*s", VOL_TOP_PERF_SPEED_WIDTH, value, VOL_TOP_PERF_FILENAME_ALT_WIDTH , filename + strlen (filename) - VOL_TOP_PERF_FILENAME_ALT_WIDTH, VOL_TOP_PERF_TIME_WIDTH, timestr); } else { cli_out ("%"PRIu64"\t\t%s", value, filename); } } } ret = rsp.op_ret; out: cli_cmd_broadcast_response (ret); if (dict) dict_unref (dict); if (rsp.dict.dict_val) free (rsp.dict.dict_val); return ret; } int32_t gf_cli3_1_top_volume (call_frame_t *frame, xlator_t *this, void *data) { int ret = -1; gf_cli_req req = {{0,}}; dict_t *dict = NULL; GF_ASSERT (frame); GF_ASSERT (this); GF_ASSERT (data); if (!frame || !this || !data) goto out; dict = data; ret = dict_allocate_and_serialize (dict, &req.dict.dict_val, (size_t *)&req.dict.dict_len); if (ret < 0) { gf_log (this->name, GF_LOG_ERROR, "failed to serialize the data"); goto out; } ret = cli_cmd_submit (&req, frame, cli_rpc_prog, GLUSTER_CLI_PROFILE_VOLUME, NULL, this, gf_cli3_1_top_volume_cbk, (xdrproc_t) xdr_gf_cli_req); out: gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); if (req.dict.dict_val) GF_FREE (req.dict.dict_val); return ret; } int gf_cli3_1_getwd_cbk (struct rpc_req *req, struct iovec *iov, int count, void *myframe) { gf1_cli_getwd_rsp rsp = {0,}; int ret = -1; if (-1 == req->rpc_status) { goto out; } ret = xdr_to_generic (*iov, &rsp, (xdrproc_t)xdr_gf1_cli_getwd_rsp); if (ret < 0 || rsp.op_ret == -1) { gf_log ("", GF_LOG_ERROR, "error"); goto out; } gf_log ("cli", GF_LOG_INFO, "Received resp to getwd"); cli_out ("%s", rsp.wd); ret = 0; out: cli_cmd_broadcast_response (ret); return ret; } int32_t gf_cli3_1_getwd (call_frame_t *frame, xlator_t *this, void *data) { int ret = -1; gf1_cli_getwd_req req = {0,}; GF_ASSERT (frame); GF_ASSERT (this); if (!frame || !this) goto out; ret = cli_cmd_submit (&req, frame, cli_rpc_prog, GLUSTER_CLI_GETWD, NULL, this, gf_cli3_1_getwd_cbk, (xdrproc_t) xdr_gf1_cli_getwd_req); out: gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); return ret; } void cli_print_volume_status_mempool (dict_t *dict, char *prefix) { int ret = -1; int32_t mempool_count = 0; char *name = NULL; int32_t hotcount = 0; int32_t coldcount = 0; uint64_t paddedsizeof = 0; uint64_t alloccount = 0; int32_t maxalloc = 0; uint64_t pool_misses = 0; int32_t maxstdalloc = 0; char key[1024] = {0,}; int i = 0; GF_ASSERT (dict); GF_ASSERT (prefix); memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "%s.mempool-count",prefix); ret = dict_get_int32 (dict, key, &mempool_count); if (ret) goto out; cli_out ("Mempool Stats\n-------------"); cli_out ("%-30s %9s %9s %12s %10s %8s %8s %12s", "Name", "HotCount", "ColdCount", "PaddedSizeof", "AllocCount", "MaxAlloc", "Misses", "Max-StdAlloc"); cli_out ("%-30s %9s %9s %12s %10s %8s %8s %12s", "----", "--------", "---------", "------------", "----------", "--------", "--------", "------------"); for (i = 0; i < mempool_count; i++) { memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "%s.pool%d.name", prefix, i); ret = dict_get_str (dict, key, &name); if (ret) goto out; memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "%s.pool%d.hotcount", prefix, i); ret = dict_get_int32 (dict, key, &hotcount); if (ret) goto out; memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "%s.pool%d.coldcount", prefix, i); ret = dict_get_int32 (dict, key, &coldcount); if (ret) goto out; memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "%s.pool%d.paddedsizeof", prefix, i); ret = dict_get_uint64 (dict, key, &paddedsizeof); if (ret) goto out; memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "%s.pool%d.alloccount", prefix, i); ret = dict_get_uint64 (dict, key, &alloccount); if (ret) goto out; memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "%s.pool%d.max_alloc", prefix, i); ret = dict_get_int32 (dict, key, &maxalloc); if (ret) goto out; memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "%s.pool%d.max-stdalloc", prefix, i); ret = dict_get_int32 (dict, key, &maxstdalloc); if (ret) goto out; memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "%s.pool%d.pool-misses", prefix, i); ret = dict_get_uint64 (dict, key, &pool_misses); if (ret) goto out; cli_out ("%-30s %9d %9d %12"PRIu64" %10"PRIu64" %8d %8"PRIu64 " %12d", name, hotcount, coldcount, paddedsizeof, alloccount, maxalloc, pool_misses, maxstdalloc); } out: return; } void cli_print_volume_status_mem (dict_t *dict) { int ret = -1; char *volname = NULL; char *hostname = NULL; char *path = NULL; int online = -1; char key[1024] = {0,}; int brick_count = 0; int val = 0; int i = 0; GF_ASSERT (dict); ret = dict_get_str (dict, "volname", &volname); if (ret) goto out; cli_out ("Memory status for volu