summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--api/src/glfs-mgmt.c61
-rw-r--r--tests/bugs/cli/bug-1169302.c78
-rwxr-xr-xtests/bugs/cli/bug-1169302.t30
3 files changed, 162 insertions, 7 deletions
diff --git a/api/src/glfs-mgmt.c b/api/src/glfs-mgmt.c
index b03d9808679..045080d667a 100644
--- a/api/src/glfs-mgmt.c
+++ b/api/src/glfs-mgmt.c
@@ -29,6 +29,7 @@
#include "portmap-xdr.h"
#include "xdr-common.h"
#include "xdr-generic.h"
+#include "rpc-common-xdr.h"
#include "syncop.h"
#include "xlator.h"
@@ -116,11 +117,71 @@ mgmt_cbk_event (struct rpc_clnt *rpc, void *mydata, void *data)
return 0;
}
+static int
+mgmt_cbk_statedump (struct rpc_clnt *rpc, void *mydata, void *data)
+{
+ struct glfs *fs = NULL;
+ xlator_t *this = NULL;
+ gf_statedump target_pid = {0, };
+ struct iovec *iov = NULL;
+ int ret = -1;
+
+ this = mydata;
+ if (!this) {
+ gf_msg ("glfs", GF_LOG_ERROR, EINVAL,
+ API_MSG_STATEDUMP_FAILED, "NULL mydata");
+ errno = EINVAL;
+ goto out;
+ }
+
+ fs = this->private;
+ if (!fs) {
+ gf_msg ("glfs", GF_LOG_ERROR, EINVAL,
+ API_MSG_STATEDUMP_FAILED, "NULL glfs");
+ errno = EINVAL;
+ goto out;
+ }
+
+ iov = (struct iovec *)data;
+ if (!iov) {
+ gf_msg ("glfs", GF_LOG_ERROR, EINVAL,
+ API_MSG_STATEDUMP_FAILED, "NULL iovec data");
+ errno = EINVAL;
+ goto out;
+ }
+
+ ret = xdr_to_generic (*iov, &target_pid,
+ (xdrproc_t)xdr_gf_statedump);
+ if (ret < 0) {
+ gf_msg ("glfs", GF_LOG_ERROR, EINVAL,
+ API_MSG_STATEDUMP_FAILED,
+ "Failed to decode xdr response for GF_CBK_STATEDUMP");
+ goto out;
+ }
+
+ gf_msg_trace ("glfs", 0, "statedump requested for pid: %d",
+ target_pid.pid);
+
+ if ((uint64_t)getpid() == target_pid.pid) {
+ gf_msg_debug ("glfs", 0, "Taking statedump for pid: %d",
+ target_pid.pid);
+
+ ret = glfs_sysrq (fs, GLFS_SYSRQ_STATEDUMP);
+ if (ret < 0) {
+ gf_msg ("glfs", GF_LOG_INFO, 0,
+ API_MSG_STATEDUMP_FAILED,
+ "statedump failed");
+ }
+ }
+out:
+ return ret;
+}
rpcclnt_cb_actor_t mgmt_cbk_actors[GF_CBK_MAXVALUE] = {
[GF_CBK_FETCHSPEC] = {"FETCHSPEC", GF_CBK_FETCHSPEC, mgmt_cbk_spec },
[GF_CBK_EVENT_NOTIFY] = {"EVENTNOTIFY", GF_CBK_EVENT_NOTIFY,
mgmt_cbk_event},
+ [GF_CBK_STATEDUMP] = {"STATEDUMP", GF_CBK_STATEDUMP, mgmt_cbk_statedump},
};
diff --git a/tests/bugs/cli/bug-1169302.c b/tests/bugs/cli/bug-1169302.c
new file mode 100644
index 00000000000..aa9f950abf2
--- /dev/null
+++ b/tests/bugs/cli/bug-1169302.c
@@ -0,0 +1,78 @@
+#include <errno.h>
+#include <stdio.h>
+#include <signal.h>
+
+#include <glusterfs/api/glfs.h>
+#include <glusterfs/api/glfs-handles.h>
+
+int keep_running = 1;
+
+void stop_running(int sig)
+{
+ if (sig == SIGTERM)
+ keep_running = 0;
+}
+
+int
+main (int argc, char *argv[])
+{
+ glfs_t *fs = NULL;
+ int ret = 0;
+ glfs_fd_t *fd = NULL;
+ char *filename = NULL;
+ char *logfile = NULL;
+ char *host = NULL;
+
+ if (argc != 5) {
+ return -1;
+ }
+
+ host = argv[2];
+ logfile = argv[3];
+ filename = argv[4];
+
+ /* setup signal handler for exiting */
+ signal (SIGTERM, stop_running);
+
+ fs = glfs_new (argv[1]);
+ if (!fs) {
+ return -1;
+ }
+
+ ret = glfs_set_volfile_server (fs, "tcp", host, 24007);
+ if (ret < 0) {
+ return -1;
+ }
+
+ ret = glfs_set_logging (fs, logfile, 7);
+ if (ret < 0) {
+ return -1;
+ }
+
+ ret = glfs_init (fs);
+ if (ret < 0) {
+ return -1;
+ }
+
+ fd = glfs_creat (fs, filename, O_RDWR, 0644);
+ if (!fd) {
+ return -1;
+ }
+
+ /* sleep until SIGTERM has been received */
+ while (keep_running) {
+ sleep (1);
+ }
+
+ ret = glfs_close (fd);
+ if (ret < 0) {
+ return -1;
+ }
+
+ ret = glfs_fini (fs);
+ if (ret < 0) {
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/tests/bugs/cli/bug-1169302.t b/tests/bugs/cli/bug-1169302.t
index 92252aa7887..24355e55646 100755
--- a/tests/bugs/cli/bug-1169302.t
+++ b/tests/bugs/cli/bug-1169302.t
@@ -7,7 +7,7 @@
function check_peers {
$CLI_1 peer status | grep 'Peer in Cluster (Connected)' | wc -l
}
-cleanup;
+cleanup
#setup cluster and test volume
TEST launch_cluster 3; # start 3-node virtual cluster
@@ -19,16 +19,32 @@ EXPECT_WITHIN $PROBE_TIMEOUT 2 check_peers;
TEST $CLI_1 volume create $V0 $H1:$B1/$V0 $H2:$B2/$V0 $H3:$B3/$V0
TEST $CLI_1 volume start $V0
-# there is no gfapi application to take statedumps yet, it will get added in
-# the next patch, this only tests the CLI for correctness
-
-cleanup_statedump
-
+# test CLI parameter acceptance
TEST ! $CLI_1 volume statedump $V0 client $H2:0
TEST ! $CLI_2 volume statedump $V0 client $H2:-1
TEST $CLI_3 volume statedump $V0 client $H2:765
TEST ! $CLI_1 volume statedump $V0 client $H2:
TEST ! $CLI_2 volume statedump $V0 client
+TEST ! $CLI_3 volume statedump $V0 client $H2 $GFAPI_PID
+
+# build and run a gfapi appliction for triggering a statedump
+logdir=`gluster --print-logdir`
+STATEDUMP_TIMEOUT=60
+
+build_tester $(dirname $0)/bug-1169302.c -lgfapi
+$(dirname $0)/bug-1169302 $V0 $H1 $logdir/bug-1169302.log testfile & GFAPI_PID=$!
+
+cleanup_statedump
+
+# Take the statedump of the process connected to $H1, it should match the
+# hostname or IP-address with the connection from the bug-1169302 executable.
+# In our CI it seems not possible to use $H0, 'localhost', $(hostname --fqdn)
+# or even "127.0.0.1"....
+TEST $CLI_3 volume statedump $V0 client $H1:$GFAPI_PID
+EXPECT_WITHIN $STATEDUMP_TIMEOUT "Y" path_exists $statedumpdir/glusterdump.$GFAPI_PID*
+
+kill $GFAPI_PID
cleanup_statedump
-cleanup;
+cleanup_tester $(dirname $0)/bug-1169302
+cleanup