21ab4e
From ddea13cfd96075170266022ed9a806726c7238fa Mon Sep 17 00:00:00 2001
21ab4e
From: Niels de Vos <ndevos@redhat.com>
21ab4e
Date: Fri, 6 Jan 2017 12:49:32 +0100
21ab4e
Subject: [PATCH 313/361] gfapi: add API to trigger events for debugging and
21ab4e
 troubleshooting
21ab4e
21ab4e
Introduce glfs_sysrq() as a generic API for triggering debug and
21ab4e
troubleshoot events. This interface will be used by the feature to get
21ab4e
statedumps for applications using libgfapi.
21ab4e
21ab4e
The current events that can be requested through this API are:
21ab4e
 - 'h'elp: log a mesage with all supported events
21ab4e
 - 's'tatedump: trigger a statedump for the passed glfs_t
21ab4e
21ab4e
In future, this API can be used by a CLI to trigger statedumps from
21ab4e
storage servers. At the moment it is limited to take statedumps, but it
21ab4e
is extensible to set the log-level, clear caches, force reconnects and
21ab4e
much more.
21ab4e
21ab4e
mainline:
21ab4e
> BUG: 1169302
21ab4e
> Reviewed-on: http://review.gluster.org/16414
21ab4e
> Original-author: Poornima G <pgurusid@redhat.com>
21ab4e
> Smoke: Gluster Build System <jenkins@build.gluster.org>
21ab4e
> NetBSD-regression: NetBSD Build System <jenkins@build.gluster.org>
21ab4e
> CentOS-regression: Gluster Build System <jenkins@build.gluster.org>
21ab4e
> Reviewed-by: Prashanth Pai <ppai@redhat.com>
21ab4e
> Reviewed-by: Kaleb KEITHLEY <kkeithle@redhat.com>
21ab4e
(cherry picked from commit dbeaa3a88514ce6cee39bfe0fd0c79f971d2bea8)
21ab4e
21ab4e
BUG: 1378085
21ab4e
Change-Id: I18858359a3957870cea5139c79efe1365a15a992
21ab4e
Signed-off-by: Niels de Vos <ndevos@redhat.com>
21ab4e
Reviewed-on: https://code.engineering.redhat.com/gerrit/101293
21ab4e
Tested-by: Milind Changire <mchangir@redhat.com>
21ab4e
Reviewed-by: Atin Mukherjee <amukherj@redhat.com>
21ab4e
---
21ab4e
 api/src/gfapi-messages.h       |  5 ++--
21ab4e
 api/src/gfapi.aliases          |  6 ++++
21ab4e
 api/src/gfapi.map              | 15 ++++++++++
21ab4e
 api/src/glfs.c                 | 64 ++++++++++++++++++++++++++++++++++++++++--
21ab4e
 api/src/glfs.h                 | 18 ++++++++++++
21ab4e
 tests/basic/gfapi/glfs_sysrq.c | 61 ++++++++++++++++++++++++++++++++++++++++
21ab4e
 tests/basic/gfapi/glfs_sysrq.t | 39 +++++++++++++++++++++++++
21ab4e
 7 files changed, 203 insertions(+), 5 deletions(-)
21ab4e
 create mode 100644 tests/basic/gfapi/glfs_sysrq.c
21ab4e
 create mode 100755 tests/basic/gfapi/glfs_sysrq.t
21ab4e
21ab4e
diff --git a/api/src/gfapi-messages.h b/api/src/gfapi-messages.h
21ab4e
index fd90ff4..6e131b5 100644
21ab4e
--- a/api/src/gfapi-messages.h
21ab4e
+++ b/api/src/gfapi-messages.h
21ab4e
@@ -40,8 +40,8 @@
21ab4e
  */
21ab4e
 
21ab4e
 #define GLFS_GFAPI_BASE             GLFS_MSGID_COMP_API
21ab4e
-#define GLFS_NUM_MESSAGES           48
21ab4e
-#define GLFS_MSGID_END              (GLFS_GFAPI_BASE + GLFS_NUM_MESSAGESi + 1)
21ab4e
+#define GLFS_NUM_MESSAGES           49
21ab4e
+#define GLFS_MSGID_END              (GLFS_GFAPI_BASE + GLFS_NUM_MESSAGES + 1)
21ab4e
 /* Messages with message IDs */
21ab4e
 #define glfs_msg_start_x GLFS_GFAPI_BASE, "Invalid: Start of messages"
21ab4e
 /*------------*/
21ab4e
@@ -94,6 +94,7 @@
21ab4e
 #define API_MSG_ALLOC_FAILED                    (GLFS_GFAPI_BASE + 46)
21ab4e
 #define API_MSG_CREATE_HANDLE_FAILED            (GLFS_GFAPI_BASE + 47)
21ab4e
 #define API_MSG_INODE_LINK_FAILED               (GLFS_GFAPI_BASE + 48)
21ab4e
+#define API_MSG_STATEDUMP_FAILED                (GLFS_GFAPI_BASE + 49)
21ab4e
 
21ab4e
 /*------------*/
21ab4e
 #define glfs_msg_end_x GLFS_MSGID_END, "Invalid: End of messages"
21ab4e
diff --git a/api/src/gfapi.aliases b/api/src/gfapi.aliases
21ab4e
index a3eddda..c69d650 100644
21ab4e
--- a/api/src/gfapi.aliases
21ab4e
+++ b/api/src/gfapi.aliases
21ab4e
@@ -154,3 +154,9 @@ _pub_glfs_upcall_inode_get_pobject _glfs_upcall_inode_get_pobject$GFAPI_3.7.16
21ab4e
 _pub_glfs_upcall_inode_get_pstat _glfs_upcall_inode_get_pstat$GFAPI_3.7.16
21ab4e
 _pub_glfs_upcall_inode_get_oldpobject _glfs_upcall_inode_get_oldpobject$GFAPI_3.7.16
21ab4e
 _pub_glfs_upcall_inode_get_oldpstat _glfs_upcall_inode_get_oldpstat$GFAPI_3.7.16
21ab4e
+
21ab4e
+_pub_glfs_realpath _glfs_realpath$GFAPI_3.7.17
21ab4e
+
21ab4e
+_pub_glfs_sysrq _glfs_sysrq$GFAPI_3.10.0
21ab4e
+
21ab4e
+_pub_glfs_ipc _glfs_ipc$GFAPI_4.0.0
21ab4e
diff --git a/api/src/gfapi.map b/api/src/gfapi.map
21ab4e
index 02da0fe..3bf2ffe 100644
21ab4e
--- a/api/src/gfapi.map
21ab4e
+++ b/api/src/gfapi.map
21ab4e
@@ -187,3 +187,18 @@ GFAPI_3.7.16 {
21ab4e
 		glfs_upcall_inode_get_oldpobject;
21ab4e
 		glfs_upcall_inode_get_oldpstat;
21ab4e
 } GFAPI_3.7.15;
21ab4e
+
21ab4e
+GFAPI_3.7.17 {
21ab4e
+        global:
21ab4e
+                glfs_realpath;
21ab4e
+} GFAPI_3.7.16;
21ab4e
+
21ab4e
+GFAPI_3.10.0 {
21ab4e
+	global:
21ab4e
+		glfs_sysrq;
21ab4e
+} GFAPI_3.7.17;
21ab4e
+
21ab4e
+GFAPI_4.0.0 {
21ab4e
+        global:
21ab4e
+                glfs_ipc;
21ab4e
+} GFAPI_3.10.0;
21ab4e
diff --git a/api/src/glfs.c b/api/src/glfs.c
21ab4e
index 9f70cce..5474922 100644
21ab4e
--- a/api/src/glfs.c
21ab4e
+++ b/api/src/glfs.c
21ab4e
@@ -40,12 +40,13 @@
21ab4e
 #include "common-utils.h"
21ab4e
 #include "syncop.h"
21ab4e
 #include "call-stub.h"
21ab4e
-#include "gfapi-messages.h"
21ab4e
+#include "hashfn.h"
21ab4e
+#include "rpc-clnt.h"
21ab4e
+#include "statedump.h"
21ab4e
 
21ab4e
+#include "gfapi-messages.h"
21ab4e
 #include "glfs.h"
21ab4e
 #include "glfs-internal.h"
21ab4e
-#include "hashfn.h"
21ab4e
-#include "rpc-clnt.h"
21ab4e
 
21ab4e
 
21ab4e
 static gf_boolean_t
21ab4e
@@ -1408,3 +1409,60 @@ pub_glfs_upcall_inode_get_oldpstat (struct glfs_upcall_inode *arg)
21ab4e
         return &arg->oldp_buf;
21ab4e
 }
21ab4e
 GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_upcall_inode_get_oldpstat, 3.7.16);
21ab4e
+
21ab4e
+
21ab4e
+/* definitions of the GLFS_SYSRQ_* chars are in glfs.h */
21ab4e
+static struct glfs_sysrq_help {
21ab4e
+        char  sysrq;
21ab4e
+        char *msg;
21ab4e
+} glfs_sysrq_help[] = {
21ab4e
+        { GLFS_SYSRQ_HELP,      "(H)elp" },
21ab4e
+        { GLFS_SYSRQ_STATEDUMP, "(S)tatedump" },
21ab4e
+        { 0,                    NULL }
21ab4e
+};
21ab4e
+
21ab4e
+int
21ab4e
+pub_glfs_sysrq (struct glfs *fs, char sysrq)
21ab4e
+{
21ab4e
+        glusterfs_ctx_t  *ctx = NULL;
21ab4e
+        int               ret = 0;
21ab4e
+
21ab4e
+        if (!fs || !fs->ctx) {
21ab4e
+                ret = -1;
21ab4e
+                errno = EINVAL;
21ab4e
+                goto out;
21ab4e
+        }
21ab4e
+
21ab4e
+        ctx = fs->ctx;
21ab4e
+
21ab4e
+        switch (sysrq) {
21ab4e
+        case GLFS_SYSRQ_HELP:
21ab4e
+        {
21ab4e
+                char msg[1024]; /* help text should not exceed 1024 chars */
21ab4e
+                struct glfs_sysrq_help *usage;
21ab4e
+
21ab4e
+                msg[0] = '\0';
21ab4e
+                for (usage = glfs_sysrq_help; usage->sysrq; usage++) {
21ab4e
+                        strncat (msg, usage->msg, 1024);
21ab4e
+                        strncat (msg, " ", 1024);
21ab4e
+                }
21ab4e
+
21ab4e
+                /* not really an 'error', but make sure it gets logged */
21ab4e
+                gf_log ("glfs", GF_LOG_ERROR, "available events: %s", msg);
21ab4e
+
21ab4e
+                break;
21ab4e
+        }
21ab4e
+        case GLFS_SYSRQ_STATEDUMP:
21ab4e
+                gf_proc_dump_info (SIGUSR1, ctx);
21ab4e
+                break;
21ab4e
+        default:
21ab4e
+                gf_msg ("glfs", GF_LOG_ERROR, ENOTSUP, API_MSG_INVALID_ENTRY,
21ab4e
+                        "'%c' is not a valid sysrq", sysrq);
21ab4e
+                errno = ENOTSUP;
21ab4e
+                ret = -1;
21ab4e
+        }
21ab4e
+out:
21ab4e
+        return ret;
21ab4e
+}
21ab4e
+
21ab4e
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_sysrq, 3.10.0);
21ab4e
diff --git a/api/src/glfs.h b/api/src/glfs.h
21ab4e
index 8b5782e..9780b52 100644
21ab4e
--- a/api/src/glfs.h
21ab4e
+++ b/api/src/glfs.h
21ab4e
@@ -772,11 +772,29 @@ glfs_fd_t *glfs_dup (glfs_fd_t *fd) __THROW
21ab4e
 void glfs_free (void *ptr) __THROW
21ab4e
         GFAPI_PUBLIC(glfs_free, 3.7.16);
21ab4e
 
21ab4e
+
21ab4e
+/*
21ab4e
+ * glfs_sysrq: send a system request to the @fs instance
21ab4e
+ *
21ab4e
+ * Different commands for @sysrq are possible, the defines for these are listed
21ab4e
+ * below the function definition.
21ab4e
+ *
21ab4e
+ * This function always returns success if the @sysrq is recognized. The return
21ab4e
+ * value does not way anythin about the result of the @sysrq execution. Not all
21ab4e
+ * @sysrq command will be able to return a success/failure status.
21ab4e
+ */
21ab4e
+int glfs_sysrq (glfs_t *fs, char sysrq) __THROW
21ab4e
+        GFAPI_PUBLIC(glfs_sysrq, 3.10.0);
21ab4e
+
21ab4e
+#define GLFS_SYSRQ_HELP 'h' /* log a message with supported sysrq commands */
21ab4e
+#define GLFS_SYSRQ_STATEDUMP 's' /* create a statedump */
21ab4e
+
21ab4e
 /*
21ab4e
  * No xdata support for now.  Nobody needs this call at all yet except for the
21ab4e
  * test script, and that doesn't need xdata.  Adding dict_t support and a new
21ab4e
  * header-file requirement doesn't seem worth it until the need is greater.
21ab4e
  */
21ab4e
+
21ab4e
 int glfs_ipc (glfs_fd_t *fd, int cmd) __THROW
21ab4e
         GFAPI_PUBLIC(glfs_ipc, 3.7.0);
21ab4e
 
21ab4e
diff --git a/tests/basic/gfapi/glfs_sysrq.c b/tests/basic/gfapi/glfs_sysrq.c
21ab4e
new file mode 100644
21ab4e
index 0000000..c843c2a
21ab4e
--- /dev/null
21ab4e
+++ b/tests/basic/gfapi/glfs_sysrq.c
21ab4e
@@ -0,0 +1,61 @@
21ab4e
+/** glfs_sysrq.c
21ab4e
+ *
21ab4e
+ * Simple test application to run all glfs_syqrq() debugging calls.
21ab4e
+ *
21ab4e
+ * Usage: ./glfs_sysrq <host> <volume> <logfile>
21ab4e
+ */
21ab4e
+#include <errno.h>
21ab4e
+#include <stdio.h>
21ab4e
+
21ab4e
+#include <glusterfs/api/glfs.h>
21ab4e
+
21ab4e
+int
21ab4e
+main (int argc, char *argv[])
21ab4e
+{
21ab4e
+        /* cmdline arguments */
21ab4e
+        char   *host    = NULL;
21ab4e
+        char   *volume  = NULL;
21ab4e
+        char   *logfile = NULL;
21ab4e
+
21ab4e
+        /* other variables */
21ab4e
+        glfs_t *fs      = NULL;
21ab4e
+        int     ret     = 0;
21ab4e
+
21ab4e
+        if (argc != 4) {
21ab4e
+                fprintf (stderr, "Usage: %s <host> <volume> <logfile>\n",
21ab4e
+                         argv[0]);
21ab4e
+                return -1;
21ab4e
+        }
21ab4e
+
21ab4e
+        host = argv[1];
21ab4e
+        volume = argv[2];
21ab4e
+        logfile = argv[3];
21ab4e
+
21ab4e
+        fs = glfs_new (volume);
21ab4e
+        if (!fs) {
21ab4e
+                return -1;
21ab4e
+        }
21ab4e
+
21ab4e
+        ret = glfs_set_logging (fs, logfile, 7);
21ab4e
+        if (ret < 0) {
21ab4e
+                return -1;
21ab4e
+        }
21ab4e
+
21ab4e
+        ret = glfs_set_volfile_server (fs, "tcp", host, 24007);
21ab4e
+        if (ret < 0) {
21ab4e
+                return -1;
21ab4e
+        }
21ab4e
+
21ab4e
+        ret = glfs_init (fs);
21ab4e
+        if (ret < 0) {
21ab4e
+                return -1;
21ab4e
+        }
21ab4e
+
21ab4e
+        /* checking of the results is easier in the script running this test */
21ab4e
+        glfs_sysrq (fs, GLFS_SYSRQ_HELP);
21ab4e
+        glfs_sysrq (fs, GLFS_SYSRQ_STATEDUMP);
21ab4e
+
21ab4e
+        glfs_fini (fs);
21ab4e
+
21ab4e
+        return 0;
21ab4e
+}
21ab4e
diff --git a/tests/basic/gfapi/glfs_sysrq.t b/tests/basic/gfapi/glfs_sysrq.t
21ab4e
new file mode 100755
21ab4e
index 0000000..d1a0e9b
21ab4e
--- /dev/null
21ab4e
+++ b/tests/basic/gfapi/glfs_sysrq.t
21ab4e
@@ -0,0 +1,39 @@
21ab4e
+#!/bin/bash
21ab4e
+#
21ab4e
+# Run glfs_sysrq, a gfapi applications calling all glfs_sysrq() commands.
21ab4e
+# Each command generates a specific log message, or something else that can be
21ab4e
+# tested for existance.
21ab4e
+#
21ab4e
+
21ab4e
+. $(dirname $0)/../../include.rc
21ab4e
+. $(dirname $0)/../../volume.rc
21ab4e
+
21ab4e
+cleanup
21ab4e
+
21ab4e
+TEST glusterd
21ab4e
+TEST pidof glusterd
21ab4e
+TEST $CLI volume create $V0 $H0:$B0/brick1
21ab4e
+EXPECT 'Created' volinfo_field $V0 'Status'
21ab4e
+
21ab4e
+TEST $CLI volume start $V0;
21ab4e
+EXPECT 'Started' volinfo_field $V0 'Status'
21ab4e
+
21ab4e
+logdir=$(gluster --print-logdir)
21ab4e
+
21ab4e
+# clear all statedumps
21ab4e
+cleanup_statedump
21ab4e
+TEST ! test -e $statedumpdir/*.dump.*
21ab4e
+# vim friendly command */
21ab4e
+
21ab4e
+build_tester $(dirname $0)/glfs_sysrq.c -lgfapi
21ab4e
+TEST $(dirname $0)/glfs_sysrq $H0 $V0 $logdir/glfs_sysrq.log
21ab4e
+
21ab4e
+# check for the help message in the log
21ab4e
+TEST grep -q '"(H)elp"' $logdir/glfs_sysrq.log
21ab4e
+
21ab4e
+# see if there is a statedump
21ab4e
+TEST test -e $statedumpdir/*.dump.*
21ab4e
+# vim friendly command */
21ab4e
+
21ab4e
+cleanup_tester $(dirname $0)/glfs_sysrq
21ab4e
+cleanup
21ab4e
-- 
21ab4e
1.8.3.1
21ab4e