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 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  | 
