Merge branch 'collectd-5.6'
authorFlorian Forster <octo@collectd.org>
Tue, 6 Sep 2016 06:42:41 +0000 (08:42 +0200)
committerFlorian Forster <octo@collectd.org>
Tue, 6 Sep 2016 06:42:41 +0000 (08:42 +0200)
17 files changed:
NEWS [deleted file]
README
TODO [deleted file]
configure.ac
contrib/redhat/collectd.spec
proto/collectd.proto
src/Makefile.am
src/ceph.c
src/collectd.conf.in
src/collectd.conf.pod
src/dbi.c
src/df.c
src/disk.c
src/grpc.cc
src/hugepages.c [new file with mode: 0644]
src/types.db
src/write_http.c

diff --git a/NEWS b/NEWS
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/README b/README
index ee909d6..e8f0ca1 100644 (file)
--- a/README
+++ b/README
@@ -134,6 +134,11 @@ Features
     - hddtemp
       Hard disk temperatures using hddtempd.
 
+    - hugepages
+      Report the number of used and free hugepages. More info on
+      hugepages can be found here:
+      https://www.kernel.org/doc/Documentation/vm/hugetlbpage.txt.
+
     - interface
       Interface traffic: Number of octets, packets and errors for each
       interface.
diff --git a/TODO b/TODO
deleted file mode 100644 (file)
index 009eb7f..0000000
--- a/TODO
+++ /dev/null
@@ -1,21 +0,0 @@
-* Finalize the onewire plugin.
-* Custom notification messages?
-* Implement moving-average calculation for the threshold stuff.
-
-src/battery.c: commend not working code.
-
-Wishlist:
-* Port nfs module to solaris
-* Port tape module to Linux
-* Port the apple_sensors plugin to Linux/PPC.
-* Maybe look into porting the serial module
-* Build Darwin package
-* Maybe let the network plugin configure whether or not notifications should be
-  sent/received.
-* Maybe find a way for processes connected to the unixsock plugin to receive
-  notifications, too.
-
-http://developer.apple.com/documentation/DeviceDrivers/Conceptual/AccessingHardware/AH_IOKitLib_API/chapter_5_section_1.html
-http://developer.apple.com/documentation/DeviceDrivers/Conceptual/IOKitFundamentals/index.html#//apple_ref/doc/uid/TP0000011
-http://www.gauchosoft.com/Software/X%20Resource%20Graph/
-http://johannes.sipsolutions.net/PowerBook/Apple_Motion_Sensor_Specification/
index 9a6da11..929205b 100644 (file)
@@ -5709,6 +5709,7 @@ plugin_fhcount="no"
 plugin_fscache="no"
 plugin_gps="no"
 plugin_grpc="no"
+plugin_hugepages="no"
 plugin_interface="no"
 plugin_ipmi="no"
 plugin_ipvs="no"
@@ -5757,6 +5758,7 @@ then
        plugin_entropy="yes"
        plugin_fhcount="yes"
        plugin_fscache="yes"
+       plugin_hugepages="yes"
        plugin_interface="yes"
        plugin_ipc="yes"
        plugin_irq="yes"
@@ -6163,6 +6165,7 @@ AC_PLUGIN([gmond],               [$with_libganglia],        [Ganglia plugin])
 AC_PLUGIN([gps],                 [$plugin_gps],             [GPS plugin])
 AC_PLUGIN([grpc],                [$plugin_grpc],            [gRPC plugin])
 AC_PLUGIN([hddtemp],             [yes],                     [Query hddtempd])
+AC_PLUGIN([hugepages],           [$plugin_hugepages],       [Hugepages statistics])
 AC_PLUGIN([interface],           [$plugin_interface],       [Interface traffic statistics])
 AC_PLUGIN([ipc],                 [$plugin_ipc],             [IPC statistics])
 AC_PLUGIN([ipmi],                [$plugin_ipmi],            [IPMI sensor statistics])
@@ -6593,6 +6596,7 @@ AC_MSG_RESULT([    gmond . . . . . . . . $enable_gmond])
 AC_MSG_RESULT([    gps . . . . . . . . . $enable_gps])
 AC_MSG_RESULT([    grpc  . . . . . . . . $enable_grpc])
 AC_MSG_RESULT([    hddtemp . . . . . . . $enable_hddtemp])
+AC_MSG_RESULT([    hugepages . . . . . . $enable_hugepages])
 AC_MSG_RESULT([    interface . . . . . . $enable_interface])
 AC_MSG_RESULT([    ipc . . . . . . . . . $enable_ipc])
 AC_MSG_RESULT([    ipmi  . . . . . . . . $enable_ipmi])
index 2061573..73e69c7 100644 (file)
@@ -73,6 +73,7 @@
 %define with_gmond 0%{!?_without_gmond:1}
 %define with_gps 0%{!?_without_gps:1}
 %define with_hddtemp 0%{!?_without_hddtemp:1}
+%define with_hugepages 0%{!?_without_hugepages:1}
 %define with_interface 0%{!?_without_interface:1}
 %define with_ipc 0%{!?_without_ipc:1}
 %define with_ipmi 0%{!?_without_ipmi:1}
 
 Summary:       Statistics collection and monitoring daemon
 Name:          collectd
-Version:       5.6.0
+Version:       5.7.0
 Release:       2%{?dist}
 URL:           https://collectd.org
 Source:                https://collectd.org/files/%{name}-%{version}.tar.bz2
@@ -1134,6 +1135,12 @@ Collectd utilities
 %define _with_hddtemp --disable-hddtemp
 %endif
 
+%if %{with_hugepages}
+%define _with_hugepages --enable-hugepages
+%else
+%define _with_hugepages --disable-hugepages
+%endif
+
 %if %{with_interface}
 %define _with_interface --enable-interface
 %else
@@ -1762,6 +1769,7 @@ Collectd utilities
        %{?_with_gps} \
        %{?_with_grpc} \
        %{?_with_hddtemp} \
+       %{?_with_hugepages} \
        %{?_with_interface} \
        %{?_with_ipc} \
        %{?_with_ipmi} \
@@ -2045,6 +2053,9 @@ fi
 %if %{with_fscache}
 %{_libdir}/%{name}/fscache.so
 %endif
+%if %{with_hugepages}
+%{_libdir}/%{name}/hugepages.so
+%endif
 %if %{with_interface}
 %{_libdir}/%{name}/interface.so
 %endif
@@ -2512,6 +2523,10 @@ fi
 %doc contrib/
 
 %changelog
+* Tue Aug 23 2016 Marc Fournier <marc.fournier@camptocamp.com> - 5.7.0-1
+- New PRE-RELEASE version
+- New plugins enabled by default: hugepages
+
 * Sun Aug 14 2016 Ruben Kerkhof <ruben@rubenkerkhof.com> - 5.6.0-1
 - New PRE-RELEASE version
 - New plugins enabled by default: chrony, cpusleep, gps, lua, mqtt, notify_nagios
index 917c5de..614d1bd 100644 (file)
@@ -30,25 +30,25 @@ option go_package = "collectd.org/rpc/proto";
 import "types.proto";
 
 service Collectd {
-  // DispatchValues reads the value lists from the DispatchValuesRequest stream.
+  // PutValues reads the value lists from the PutValuesRequest stream.
   // The gRPC server embedded into collectd will inject them into the system
   // just like the network plugin.
-  rpc DispatchValues(stream DispatchValuesRequest)
-      returns (DispatchValuesResponse);
+  rpc PutValues(stream PutValuesRequest)
+      returns (PutValuesResponse);
 
   // QueryValues returns a stream of matching value lists from collectd's
   // internal cache.
   rpc QueryValues(QueryValuesRequest) returns (stream QueryValuesResponse);
 }
 
-// The arguments to DispatchValues.
-message DispatchValuesRequest {
+// The arguments to PutValues.
+message PutValuesRequest {
   // value_list is the metric to be sent to the server.
   collectd.types.ValueList value_list = 1;
 }
 
-// The response from DispatchValues.
-message DispatchValuesResponse {}
+// The response from PutValues.
+message PutValuesResponse {}
 
 // The arguments to QueryValues.
 message QueryValuesRequest {
index dbd5bb9..bc5f429 100644 (file)
@@ -470,6 +470,12 @@ hddtemp_la_LIBADD += -lsocket
 endif
 endif
 
+if BUILD_PLUGIN_HUGEPAGES
+pkglib_LTLIBRARIES += hugepages.la
+hugepages_la_SOURCES = hugepages.c
+hugepages_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+endif
+
 if BUILD_PLUGIN_INTERFACE
 pkglib_LTLIBRARIES += interface.la
 interface_la_SOURCES = interface.c
index e6d3767..64d8785 100644 (file)
@@ -1468,15 +1468,22 @@ static int cconn_main_loop(uint32_t request_type)
     struct timeval end_tv;
     struct cconn io_array[g_num_daemons];
 
-    DEBUG("ceph plugin: entering cconn_main_loop(request_type = %d)", request_type);
+    DEBUG ("ceph plugin: entering cconn_main_loop(request_type = %"PRIu32")", request_type);
+
+    if (g_num_daemons < 1)
+    {
+        ERROR ("ceph plugin: No daemons configured. See the \"Daemon\" config option.");
+        return ENOENT;
+    }
 
     /* create cconn array */
-    memset(io_array, 0, sizeof(io_array));
-    for(size_t i = 0; i < g_num_daemons; ++i)
+    for (size_t i = 0; i < g_num_daemons; i++)
     {
-        io_array[i].d = g_daemons[i];
-        io_array[i].request_type = request_type;
-        io_array[i].state = CSTATE_UNCONNECTED;
+        io_array[i] = (struct cconn) {
+            .d = g_daemons[i],
+            .request_type = request_type,
+            .state = CSTATE_UNCONNECTED,
+        };
     }
 
     /** Calculate the time at which we should give up */
index f689811..16b6648 100644 (file)
 #@BUILD_PLUGIN_GPS_TRUE@LoadPlugin gps
 #@BUILD_PLUGIN_GRPC_TRUE@LoadPlugin grpc
 #@BUILD_PLUGIN_HDDTEMP_TRUE@LoadPlugin hddtemp
+#@BUILD_PLUGIN_HUGEPAGES_TRUE@LoadPlugin hugepages
 @BUILD_PLUGIN_INTERFACE_TRUE@@BUILD_PLUGIN_INTERFACE_TRUE@LoadPlugin interface
 #@BUILD_PLUGIN_IPC_TRUE@LoadPlugin ipc
 #@BUILD_PLUGIN_IPMI_TRUE@LoadPlugin ipmi
 #  Port "7634"
 #</Plugin>
 
+#<Plugin hugepages>
+#    ReportPerNodeHP "true"
+#    ReportRootHP "true"
+#</Plugin>
+
 #<Plugin interface>
 #      Interface "eth0"
 #      IgnoreSelected false
index 4c0a84c..2919099 100644 (file)
@@ -2813,6 +2813,32 @@ TCP-Port to connect to. Defaults to B<7634>.
 
 =back
 
+=head2 Plugin C<hugepages>
+
+To collect B<hugepages> information, collectd reads directories
+"/sys/devices/system/node/*/hugepages" and
+"/sys/kernel/mm/hugepages".
+Reading of these directories can be disabled by the following
+options (default is enabled).
+
+=over 4
+
+=item B<ReportPerNodeHP> I<true>|I<false>
+
+If enabled, information will be collected from the hugepage
+counters in "/sys/devices/system/node/*/hugepages".
+This is used to check the per-node hugepage statistics on
+a NUMA system.
+
+=item B<ReportRootHP> I<true>|I<false>
+
+If enabled, information will be collected from the hugepage
+counters in "/sys/kernel/mm/hugepages".
+This can be used on both NUMA and non-NUMA systems to check
+the overall hugepage statistics.
+
+=back
+
 =head2 Plugin C<interface>
 
 =over 4
index 068bf4d..19d4b0a 100644 (file)
--- a/src/dbi.c
+++ b/src/dbi.c
@@ -452,14 +452,14 @@ static int cdbi_init (void) /* {{{ */
   if (queries_num == 0)
   {
     ERROR ("dbi plugin: No <Query> blocks have been found. Without them, "
-        "this plugin can't do anything useful, so we will returns an error.");
+        "this plugin can't do anything useful, so we will return an error.");
     return (-1);
   }
 
   if (databases_num == 0)
   {
     ERROR ("dbi plugin: No <Database> blocks have been found. Without them, "
-        "this plugin can't do anything useful, so we will returns an error.");
+        "this plugin can't do anything useful, so we will return an error.");
     return (-1);
   }
 
index 4a86799..af54c92 100644 (file)
--- a/src/df.c
+++ b/src/df.c
@@ -229,7 +229,10 @@ static int df_read (void)
                        }
 
                        /* Duplicate found: leave non-NULL dup_ptr. */
-                       if (by_device && (strcmp (mnt_ptr->spec_device, dup_ptr->spec_device) == 0))
+                       if (by_device
+                            && (mnt_ptr->spec_device != NULL)
+                            && (dup_ptr->spec_device != NULL)
+                            && (strcmp (mnt_ptr->spec_device, dup_ptr->spec_device) == 0))
                                break;
                        else if (!by_device && (strcmp (mnt_ptr->dir, dup_ptr->dir) == 0))
                                break;
index d7eb0a5..465b005 100644 (file)
@@ -128,7 +128,7 @@ static int numdisk = 0;
 /* #endif HAVE_LIBKSTAT */
 
 #elif defined(HAVE_LIBSTATGRAB)
-/* #endif HAVE_LIBKSTATGRAB */
+/* #endif HAVE_LIBSTATGRAB */
 
 #elif HAVE_PERFSTAT
 static perfstat_disk_t * stat_disk;
index 8b76954..3b1891f 100644 (file)
@@ -47,8 +47,8 @@ extern "C" {
 
 using collectd::Collectd;
 
-using collectd::DispatchValuesRequest;
-using collectd::DispatchValuesResponse;
+using collectd::PutValuesRequest;
+using collectd::PutValuesResponse;
 using collectd::QueryValuesRequest;
 using collectd::QueryValuesResponse;
 
@@ -283,10 +283,10 @@ public:
                return status;
        }
 
-       grpc::Status DispatchValues(grpc::ServerContext *ctx,
-                                                               grpc::ServerReader<DispatchValuesRequest> *reader,
-                                                               DispatchValuesResponse *res) override {
-               DispatchValuesRequest req;
+       grpc::Status PutValues(grpc::ServerContext *ctx,
+                                                  grpc::ServerReader<PutValuesRequest> *reader,
+                                                  PutValuesResponse *res) override {
+               PutValuesRequest req;
 
                while (reader->Read(&req)) {
                        value_list_t vl = VALUE_LIST_INIT;
@@ -426,18 +426,18 @@ public:
        CollectdClient(std::shared_ptr<grpc::ChannelInterface> channel) : stub_(Collectd::NewStub(channel)) {
        }
 
-       int DispatchValues(value_list_t const *vl) {
+       int PutValues(value_list_t const *vl) {
                grpc::ClientContext ctx;
 
-               DispatchValuesRequest req;
+               PutValuesRequest req;
                auto status = marshal_value_list(vl, req.mutable_value_list());
                if (!status.ok()) {
                        ERROR("grpc: Marshalling value_list_t failed.");
                        return -1;
                }
 
-               DispatchValuesResponse res;
-               auto stream = stub_->DispatchValues(&ctx, &res);
+               PutValuesResponse res;
+               auto stream = stub_->PutValues(&ctx, &res);
                if (!stream->Write(req)) {
                        NOTICE("grpc: Broken stream.");
                        /* intentionally not returning. */
@@ -451,7 +451,7 @@ public:
                }
 
                return 0;
-       } /* int DispatchValues */
+       } /* int PutValues */
 
 private:
        std::unique_ptr<Collectd::Stub> stub_;
@@ -471,7 +471,7 @@ extern "C" {
                        value_list_t const *vl,
                        user_data_t *ud) {
                CollectdClient *c = (CollectdClient *) ud->data;
-               return c->DispatchValues(vl);
+               return c->PutValues(vl);
        }
 
        static int c_grpc_config_listen(oconfig_item_t *ci)
diff --git a/src/hugepages.c b/src/hugepages.c
new file mode 100644 (file)
index 0000000..ac9441d
--- /dev/null
@@ -0,0 +1,290 @@
+/*-
+ * collectd - src/hugepages.c
+ * MIT License
+ *
+ * Copyright(c) 2016 Intel Corporation. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is furnished to do
+ * so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Authors:
+ *   Jaroslav Safka <jaroslavx.safka@intel.com>
+ *   Kim-Marie Jones <kim-marie.jones@intel.com>
+ */
+
+#include "collectd.h"
+#include "common.h" /* auxiliary functions */
+#include "plugin.h" /* plugin_register_*, plugin_dispatch_values */
+
+static const char g_plugin_name[] = "hugepages";
+static const char g_cfg_rpt_numa[] = "ReportPerNodeHP";
+static const char g_cfg_rpt_mm[] = "ReportRootHP";
+
+static const char *g_config_keys[] = {
+  g_cfg_rpt_numa,
+  g_cfg_rpt_mm,
+};
+static size_t g_config_keys_num = STATIC_ARRAY_SIZE(g_config_keys);
+static int g_flag_rpt_numa = 1;
+static int g_flag_rpt_mm = 1;
+
+struct entry_info {
+  char *d_name;
+  const char *node;
+};
+
+static int huge_config_callback(const char *key, const char *val)
+{
+  DEBUG("%s: HugePages config key='%s', val='%s'", g_plugin_name, key, val);
+
+  if (strcasecmp(key, g_cfg_rpt_numa) == 0) {
+    g_flag_rpt_numa = IS_TRUE(val);
+    return 0;
+  }
+  if (strcasecmp(key, g_cfg_rpt_mm) == 0) {
+    g_flag_rpt_mm = IS_TRUE(val);
+    return 0;
+  }
+
+  return -1;
+}
+
+static void submit_hp(const char *plug_inst, const char *type,
+  const char *type_instance, gauge_t free_value, gauge_t used_value)
+{
+  value_t values[2];
+  value_list_t vl = VALUE_LIST_INIT;
+
+  values[0].gauge = free_value;
+  values[1].gauge = used_value;
+
+  vl.values = values;
+  vl.values_len = 2;
+  sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+  sstrncpy (vl.plugin, g_plugin_name, sizeof (vl.plugin));
+  sstrncpy (vl.plugin_instance, plug_inst, sizeof (vl.plugin_instance));
+  sstrncpy (vl.type, type, sizeof (vl.type));
+
+  if (type_instance != NULL) {
+    sstrncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
+  }
+
+  DEBUG("submit_hp pl_inst:%s, inst_type %s, type %s, free=%lf, used=%lf",
+      plug_inst, type_instance, type, free_value, used_value);
+
+  plugin_dispatch_values (&vl);
+}
+
+static int read_hugepage_entry(const char *path, const char *entry,
+    void *e_info)
+{
+  char path2[PATH_MAX];
+  static const char type[] = "hugepages";
+  static const char partial_type_inst[] = "free_used";
+  char type_instance[PATH_MAX];
+  char *strin;
+  struct entry_info *hpsize_plinst = e_info;
+  static int flag = 0;
+  static double used_hp = 0;
+  static double free_hp = 0;
+  double value;
+
+  ssnprintf(path2, sizeof(path2), "%s/%s", path, entry);
+
+  FILE *fh = fopen(path2, "rt");
+  if (fh == NULL) {
+    ERROR("%s: cannot open %s", g_plugin_name, path2);
+    return -1;
+  }
+
+  if (fscanf(fh, "%lf", &value) !=1) {
+    ERROR("%s: cannot parse file %s", g_plugin_name, path2);
+    fclose(fh);
+    return -1;
+  }
+
+  if (strcmp(entry, "nr_hugepages") == 0) {
+    used_hp += value;
+    flag++;
+  } else if (strcmp(entry, "surplus_hugepages") == 0) {
+    used_hp += value;
+    flag++;
+  } else if (strcmp(entry, "free_hugepages") == 0) {
+    used_hp -= value;
+    free_hp = value;
+    flag++;
+  }
+
+  if (flag == 3) {
+    /* Can now submit "used" and "free" values.
+     * 0x2D is the ASCII "-" character, after which the string
+     *   contains "<size>kB"
+     * The string passed as param 3 to submit_hp is of the format:
+     *   <type>-<partial_type_inst>-<size>kB
+     */
+    strin = strchr(hpsize_plinst->d_name, 0x2D);
+    if (strin != NULL) {
+      ssnprintf(type_instance, sizeof(type_instance), "%s%s", partial_type_inst, strin);
+    } else {
+      ssnprintf(type_instance, sizeof(type_instance), "%s%s", partial_type_inst,
+          hpsize_plinst->d_name);
+    }
+    submit_hp(hpsize_plinst->node, type, type_instance, free_hp, used_hp);
+
+    /* Reset for next time */
+    flag = 0;
+    used_hp = 0;
+    free_hp = 0;
+  }
+
+  fclose(fh);
+  return 0;
+}
+
+static int read_syshugepages(const char* path, const char* node)
+{
+  static const char hugepages_dir[] = "hugepages";
+  DIR *dir;
+  struct dirent *result;
+  char path2[PATH_MAX];
+  struct entry_info e_info;
+  long lim;
+
+  dir = opendir(path);
+  if (dir == NULL) {
+    ERROR("%s: cannot open directory %s", g_plugin_name, path);
+    return -1;
+  }
+
+  errno = 0;
+  if ((lim = pathconf(path, _PC_NAME_MAX)) == -1) {
+    /* Limit not defined if errno == 0, otherwise error */
+    if (errno != 0) {
+      ERROR("%s: pathconf failed", g_plugin_name);
+      closedir(dir);
+      return -1;
+    } else {
+      lim = PATH_MAX;
+    }
+  }
+
+  /* read "hugepages-XXXXXkB" entries */
+  while ((result = readdir(dir)) != NULL) {
+    if (strncmp(result->d_name, hugepages_dir, sizeof(hugepages_dir)-1)) {
+      /* not node dir */
+      errno = 0;
+      continue;
+    }
+
+    /* /sys/devices/system/node/node?/hugepages/ */
+    ssnprintf(path2, (size_t) lim, "%s/%s", path, result->d_name);
+
+    e_info.d_name = result->d_name;
+    e_info.node = node;
+    walk_directory(path2, read_hugepage_entry, &e_info, 0);
+    errno = 0;
+  }
+
+  /* Check if NULL return from readdir() was an error */
+  if (errno != 0) {
+      ERROR("%s: readdir failed", g_plugin_name);
+      closedir(dir);
+      return -1;
+  }
+
+  closedir(dir);
+  return 0;
+}
+
+static int read_nodes(void)
+{
+  static const char sys_node[] = "/sys/devices/system/node";
+  static const char node_string[] = "node";
+  static const char sys_node_hugepages[] = "/sys/devices/system/node/%s/hugepages";
+  DIR *dir;
+  struct dirent *result;
+  char path[PATH_MAX];
+  long lim;
+
+  dir = opendir(sys_node);
+  if (dir == NULL) {
+    ERROR("%s: cannot open directory %s", g_plugin_name, sys_node);
+    return -1;
+  }
+
+  errno = 0;
+  if ((lim = pathconf(sys_node, _PC_NAME_MAX)) == -1) {
+    /* Limit not defined if errno == 0, otherwise error */
+    if (errno != 0) {
+      ERROR("%s: pathconf failed", g_plugin_name);
+      closedir(dir);
+      return -1;
+    } else {
+      lim = PATH_MAX;
+    }
+  }
+
+  while ((result = readdir(dir)) != NULL) {
+    if (strncmp(result->d_name, node_string, sizeof(node_string)-1)) {
+      /* not node dir */
+      errno = 0;
+      continue;
+    }
+
+    ssnprintf(path, (size_t) lim, sys_node_hugepages, result->d_name);
+    read_syshugepages(path, result->d_name);
+    errno = 0;
+  }
+
+  /* Check if NULL return from readdir() was an error */
+  if (errno != 0) {
+      ERROR("%s: readdir failed", g_plugin_name);
+      closedir(dir);
+      return -1;
+  }
+
+  closedir(dir);
+  return 0;
+}
+
+
+static int huge_read(void)
+{
+  static const char sys_mm_hugepages[] = "/sys/kernel/mm/hugepages";
+
+  if (g_flag_rpt_mm) {
+    if (read_syshugepages(sys_mm_hugepages, "mm") != 0) {
+      return -1;
+    }
+  }
+  if (g_flag_rpt_numa) {
+    if (read_nodes() != 0) {
+      return -1;
+    }
+  }
+
+  return 0;
+}
+
+void module_register(void)
+{
+  plugin_register_config(g_plugin_name, huge_config_callback, g_config_keys,
+      g_config_keys_num);
+  plugin_register_read(g_plugin_name, huge_read);
+}
+
index cc79af0..1ab1d7c 100644 (file)
@@ -92,6 +92,7 @@ hash_collisions         value:DERIVE:0:U
 http_request_methods    value:DERIVE:0:U
 http_requests           value:DERIVE:0:U
 http_response_codes     value:DERIVE:0:U
+hugepages               free:GAUGE:0:4294967295, used:GAUGE:0:4294967295
 humidity                value:GAUGE:0:100
 if_collisions           value:DERIVE:0:U
 if_dropped              rx:DERIVE:0:U, tx:DERIVE:0:U
index 41615d3..3d1fe3d 100644 (file)
@@ -419,6 +419,9 @@ static int wh_write_command (const data_set_t *ds, const value_list_t *vl, /* {{
         }
         assert (command_len < cb->send_buffer_free);
 
+        /* Make scan-build happy. */
+        assert (cb->send_buffer != NULL);
+
         /* `command_len + 1' because `command_len' does not include the
          * trailing null byte. Neither does `send_buffer_fill'. */
         memcpy (cb->send_buffer + cb->send_buffer_fill,