Blob Blame History Raw
From e7bbd87a4c3892d70cb84a9c5cef33430112d7a4 Mon Sep 17 00:00:00 2001
From: Niels de Vos <ndevos@redhat.com>
Date: Fri, 6 Jan 2017 12:58:02 +0100
Subject: [PATCH 316/361] gfapi: create statedump when glusterd requests it

When GlusterD sends the STATEDUMP procedure to the libgfapi client, the
client checks if it matches the PID that should take the statedump. If
so, it will do a statedump for the glfs_t that is connected to this mgmt
connection.

See-also: http://review.gluster.org/9228
[ndevos: separated patch from 9228]

mainline:
> BUG: 1169302
> Reviewed-on: https://review.gluster.org/16415
> Smoke: Gluster Build System <jenkins@build.gluster.org>
> NetBSD-regression: NetBSD Build System <jenkins@build.gluster.org>
> CentOS-regression: Gluster Build System <jenkins@build.gluster.org>
> Reviewed-by: Niels de Vos <ndevos@redhat.com>
> Reviewed-by: Kaleb KEITHLEY <kkeithle@redhat.com>
> Reviewed-by: Prashanth Pai <ppai@redhat.com>
> Tested-by: Niels de Vos <ndevos@redhat.com>
(cherry picked from commit c9027e04456d724a3211e4b08084c96059798e1f)

BUG: 1378085
Change-Id: I70d6a1f4f19d525377aebc8fa57f51e513b92d84
Signed-off-by: Poornima G <pgurusid@redhat.com>
Reviewed-on: https://code.engineering.redhat.com/gerrit/101297
Tested-by: Milind Changire <mchangir@redhat.com>
Reviewed-by: Atin Mukherjee <amukherj@redhat.com>
---
 api/src/glfs-mgmt.c          | 61 ++++++++++++++++++++++++++++++++++
 tests/bugs/cli/bug-1169302.c | 78 ++++++++++++++++++++++++++++++++++++++++++++
 tests/bugs/cli/bug-1169302.t | 30 +++++++++++++----
 3 files changed, 162 insertions(+), 7 deletions(-)
 create mode 100644 tests/bugs/cli/bug-1169302.c

diff --git a/api/src/glfs-mgmt.c b/api/src/glfs-mgmt.c
index 8c9872c..9aa92d7 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 0000000..aa9f950
--- /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 92252aa..24355e5 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
-- 
1.8.3.1