Blob Blame History Raw
From ddea13cfd96075170266022ed9a806726c7238fa Mon Sep 17 00:00:00 2001
From: Niels de Vos <ndevos@redhat.com>
Date: Fri, 6 Jan 2017 12:49:32 +0100
Subject: [PATCH 313/361] gfapi: add API to trigger events for debugging and
 troubleshooting

Introduce glfs_sysrq() as a generic API for triggering debug and
troubleshoot events. This interface will be used by the feature to get
statedumps for applications using libgfapi.

The current events that can be requested through this API are:
 - 'h'elp: log a mesage with all supported events
 - 's'tatedump: trigger a statedump for the passed glfs_t

In future, this API can be used by a CLI to trigger statedumps from
storage servers. At the moment it is limited to take statedumps, but it
is extensible to set the log-level, clear caches, force reconnects and
much more.

mainline:
> BUG: 1169302
> Reviewed-on: http://review.gluster.org/16414
> Original-author: Poornima G <pgurusid@redhat.com>
> 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: Prashanth Pai <ppai@redhat.com>
> Reviewed-by: Kaleb KEITHLEY <kkeithle@redhat.com>
(cherry picked from commit dbeaa3a88514ce6cee39bfe0fd0c79f971d2bea8)

BUG: 1378085
Change-Id: I18858359a3957870cea5139c79efe1365a15a992
Signed-off-by: Niels de Vos <ndevos@redhat.com>
Reviewed-on: https://code.engineering.redhat.com/gerrit/101293
Tested-by: Milind Changire <mchangir@redhat.com>
Reviewed-by: Atin Mukherjee <amukherj@redhat.com>
---
 api/src/gfapi-messages.h       |  5 ++--
 api/src/gfapi.aliases          |  6 ++++
 api/src/gfapi.map              | 15 ++++++++++
 api/src/glfs.c                 | 64 ++++++++++++++++++++++++++++++++++++++++--
 api/src/glfs.h                 | 18 ++++++++++++
 tests/basic/gfapi/glfs_sysrq.c | 61 ++++++++++++++++++++++++++++++++++++++++
 tests/basic/gfapi/glfs_sysrq.t | 39 +++++++++++++++++++++++++
 7 files changed, 203 insertions(+), 5 deletions(-)
 create mode 100644 tests/basic/gfapi/glfs_sysrq.c
 create mode 100755 tests/basic/gfapi/glfs_sysrq.t

diff --git a/api/src/gfapi-messages.h b/api/src/gfapi-messages.h
index fd90ff4..6e131b5 100644
--- a/api/src/gfapi-messages.h
+++ b/api/src/gfapi-messages.h
@@ -40,8 +40,8 @@
  */
 
 #define GLFS_GFAPI_BASE             GLFS_MSGID_COMP_API
-#define GLFS_NUM_MESSAGES           48
-#define GLFS_MSGID_END              (GLFS_GFAPI_BASE + GLFS_NUM_MESSAGESi + 1)
+#define GLFS_NUM_MESSAGES           49
+#define GLFS_MSGID_END              (GLFS_GFAPI_BASE + GLFS_NUM_MESSAGES + 1)
 /* Messages with message IDs */
 #define glfs_msg_start_x GLFS_GFAPI_BASE, "Invalid: Start of messages"
 /*------------*/
@@ -94,6 +94,7 @@
 #define API_MSG_ALLOC_FAILED                    (GLFS_GFAPI_BASE + 46)
 #define API_MSG_CREATE_HANDLE_FAILED            (GLFS_GFAPI_BASE + 47)
 #define API_MSG_INODE_LINK_FAILED               (GLFS_GFAPI_BASE + 48)
+#define API_MSG_STATEDUMP_FAILED                (GLFS_GFAPI_BASE + 49)
 
 /*------------*/
 #define glfs_msg_end_x GLFS_MSGID_END, "Invalid: End of messages"
diff --git a/api/src/gfapi.aliases b/api/src/gfapi.aliases
index a3eddda..c69d650 100644
--- a/api/src/gfapi.aliases
+++ b/api/src/gfapi.aliases
@@ -154,3 +154,9 @@ _pub_glfs_upcall_inode_get_pobject _glfs_upcall_inode_get_pobject$GFAPI_3.7.16
 _pub_glfs_upcall_inode_get_pstat _glfs_upcall_inode_get_pstat$GFAPI_3.7.16
 _pub_glfs_upcall_inode_get_oldpobject _glfs_upcall_inode_get_oldpobject$GFAPI_3.7.16
 _pub_glfs_upcall_inode_get_oldpstat _glfs_upcall_inode_get_oldpstat$GFAPI_3.7.16
+
+_pub_glfs_realpath _glfs_realpath$GFAPI_3.7.17
+
+_pub_glfs_sysrq _glfs_sysrq$GFAPI_3.10.0
+
+_pub_glfs_ipc _glfs_ipc$GFAPI_4.0.0
diff --git a/api/src/gfapi.map b/api/src/gfapi.map
index 02da0fe..3bf2ffe 100644
--- a/api/src/gfapi.map
+++ b/api/src/gfapi.map
@@ -187,3 +187,18 @@ GFAPI_3.7.16 {
 		glfs_upcall_inode_get_oldpobject;
 		glfs_upcall_inode_get_oldpstat;
 } GFAPI_3.7.15;
+
+GFAPI_3.7.17 {
+        global:
+                glfs_realpath;
+} GFAPI_3.7.16;
+
+GFAPI_3.10.0 {
+	global:
+		glfs_sysrq;
+} GFAPI_3.7.17;
+
+GFAPI_4.0.0 {
+        global:
+                glfs_ipc;
+} GFAPI_3.10.0;
diff --git a/api/src/glfs.c b/api/src/glfs.c
index 9f70cce..5474922 100644
--- a/api/src/glfs.c
+++ b/api/src/glfs.c
@@ -40,12 +40,13 @@
 #include "common-utils.h"
 #include "syncop.h"
 #include "call-stub.h"
-#include "gfapi-messages.h"
+#include "hashfn.h"
+#include "rpc-clnt.h"
+#include "statedump.h"
 
+#include "gfapi-messages.h"
 #include "glfs.h"
 #include "glfs-internal.h"
-#include "hashfn.h"
-#include "rpc-clnt.h"
 
 
 static gf_boolean_t
@@ -1408,3 +1409,60 @@ pub_glfs_upcall_inode_get_oldpstat (struct glfs_upcall_inode *arg)
         return &arg->oldp_buf;
 }
 GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_upcall_inode_get_oldpstat, 3.7.16);
+
+
+/* definitions of the GLFS_SYSRQ_* chars are in glfs.h */
+static struct glfs_sysrq_help {
+        char  sysrq;
+        char *msg;
+} glfs_sysrq_help[] = {
+        { GLFS_SYSRQ_HELP,      "(H)elp" },
+        { GLFS_SYSRQ_STATEDUMP, "(S)tatedump" },
+        { 0,                    NULL }
+};
+
+int
+pub_glfs_sysrq (struct glfs *fs, char sysrq)
+{
+        glusterfs_ctx_t  *ctx = NULL;
+        int               ret = 0;
+
+        if (!fs || !fs->ctx) {
+                ret = -1;
+                errno = EINVAL;
+                goto out;
+        }
+
+        ctx = fs->ctx;
+
+        switch (sysrq) {
+        case GLFS_SYSRQ_HELP:
+        {
+                char msg[1024]; /* help text should not exceed 1024 chars */
+                struct glfs_sysrq_help *usage;
+
+                msg[0] = '\0';
+                for (usage = glfs_sysrq_help; usage->sysrq; usage++) {
+                        strncat (msg, usage->msg, 1024);
+                        strncat (msg, " ", 1024);
+                }
+
+                /* not really an 'error', but make sure it gets logged */
+                gf_log ("glfs", GF_LOG_ERROR, "available events: %s", msg);
+
+                break;
+        }
+        case GLFS_SYSRQ_STATEDUMP:
+                gf_proc_dump_info (SIGUSR1, ctx);
+                break;
+        default:
+                gf_msg ("glfs", GF_LOG_ERROR, ENOTSUP, API_MSG_INVALID_ENTRY,
+                        "'%c' is not a valid sysrq", sysrq);
+                errno = ENOTSUP;
+                ret = -1;
+        }
+out:
+        return ret;
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_sysrq, 3.10.0);
diff --git a/api/src/glfs.h b/api/src/glfs.h
index 8b5782e..9780b52 100644
--- a/api/src/glfs.h
+++ b/api/src/glfs.h
@@ -772,11 +772,29 @@ glfs_fd_t *glfs_dup (glfs_fd_t *fd) __THROW
 void glfs_free (void *ptr) __THROW
         GFAPI_PUBLIC(glfs_free, 3.7.16);
 
+
+/*
+ * glfs_sysrq: send a system request to the @fs instance
+ *
+ * Different commands for @sysrq are possible, the defines for these are listed
+ * below the function definition.
+ *
+ * This function always returns success if the @sysrq is recognized. The return
+ * value does not way anythin about the result of the @sysrq execution. Not all
+ * @sysrq command will be able to return a success/failure status.
+ */
+int glfs_sysrq (glfs_t *fs, char sysrq) __THROW
+        GFAPI_PUBLIC(glfs_sysrq, 3.10.0);
+
+#define GLFS_SYSRQ_HELP 'h' /* log a message with supported sysrq commands */
+#define GLFS_SYSRQ_STATEDUMP 's' /* create a statedump */
+
 /*
  * No xdata support for now.  Nobody needs this call at all yet except for the
  * test script, and that doesn't need xdata.  Adding dict_t support and a new
  * header-file requirement doesn't seem worth it until the need is greater.
  */
+
 int glfs_ipc (glfs_fd_t *fd, int cmd) __THROW
         GFAPI_PUBLIC(glfs_ipc, 3.7.0);
 
diff --git a/tests/basic/gfapi/glfs_sysrq.c b/tests/basic/gfapi/glfs_sysrq.c
new file mode 100644
index 0000000..c843c2a
--- /dev/null
+++ b/tests/basic/gfapi/glfs_sysrq.c
@@ -0,0 +1,61 @@
+/** glfs_sysrq.c
+ *
+ * Simple test application to run all glfs_syqrq() debugging calls.
+ *
+ * Usage: ./glfs_sysrq <host> <volume> <logfile>
+ */
+#include <errno.h>
+#include <stdio.h>
+
+#include <glusterfs/api/glfs.h>
+
+int
+main (int argc, char *argv[])
+{
+        /* cmdline arguments */
+        char   *host    = NULL;
+        char   *volume  = NULL;
+        char   *logfile = NULL;
+
+        /* other variables */
+        glfs_t *fs      = NULL;
+        int     ret     = 0;
+
+        if (argc != 4) {
+                fprintf (stderr, "Usage: %s <host> <volume> <logfile>\n",
+                         argv[0]);
+                return -1;
+        }
+
+        host = argv[1];
+        volume = argv[2];
+        logfile = argv[3];
+
+        fs = glfs_new (volume);
+        if (!fs) {
+                return -1;
+        }
+
+        ret = glfs_set_logging (fs, logfile, 7);
+        if (ret < 0) {
+                return -1;
+        }
+
+        ret = glfs_set_volfile_server (fs, "tcp", host, 24007);
+        if (ret < 0) {
+                return -1;
+        }
+
+        ret = glfs_init (fs);
+        if (ret < 0) {
+                return -1;
+        }
+
+        /* checking of the results is easier in the script running this test */
+        glfs_sysrq (fs, GLFS_SYSRQ_HELP);
+        glfs_sysrq (fs, GLFS_SYSRQ_STATEDUMP);
+
+        glfs_fini (fs);
+
+        return 0;
+}
diff --git a/tests/basic/gfapi/glfs_sysrq.t b/tests/basic/gfapi/glfs_sysrq.t
new file mode 100755
index 0000000..d1a0e9b
--- /dev/null
+++ b/tests/basic/gfapi/glfs_sysrq.t
@@ -0,0 +1,39 @@
+#!/bin/bash
+#
+# Run glfs_sysrq, a gfapi applications calling all glfs_sysrq() commands.
+# Each command generates a specific log message, or something else that can be
+# tested for existance.
+#
+
+. $(dirname $0)/../../include.rc
+. $(dirname $0)/../../volume.rc
+
+cleanup
+
+TEST glusterd
+TEST pidof glusterd
+TEST $CLI volume create $V0 $H0:$B0/brick1
+EXPECT 'Created' volinfo_field $V0 'Status'
+
+TEST $CLI volume start $V0;
+EXPECT 'Started' volinfo_field $V0 'Status'
+
+logdir=$(gluster --print-logdir)
+
+# clear all statedumps
+cleanup_statedump
+TEST ! test -e $statedumpdir/*.dump.*
+# vim friendly command */
+
+build_tester $(dirname $0)/glfs_sysrq.c -lgfapi
+TEST $(dirname $0)/glfs_sysrq $H0 $V0 $logdir/glfs_sysrq.log
+
+# check for the help message in the log
+TEST grep -q '"(H)elp"' $logdir/glfs_sysrq.log
+
+# see if there is a statedump
+TEST test -e $statedumpdir/*.dump.*
+# vim friendly command */
+
+cleanup_tester $(dirname $0)/glfs_sysrq
+cleanup
-- 
1.8.3.1