diff options
-rw-r--r-- | api/src/glfs-mgmt.c | 61 | ||||
-rw-r--r-- | tests/bugs/cli/bug-1169302.c | 78 | ||||
-rwxr-xr-x | tests/bugs/cli/bug-1169302.t | 30 |
3 files changed, 162 insertions, 7 deletions
diff --git a/api/src/glfs-mgmt.c b/api/src/glfs-mgmt.c index 1a6eb4b6981..3302a7c5813 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 |