summaryrefslogtreecommitdiff
path: root/agent/mibgroup/hardware/fsys/hw_fsys.c
diff options
context:
space:
mode:
Diffstat (limited to 'agent/mibgroup/hardware/fsys/hw_fsys.c')
-rw-r--r--agent/mibgroup/hardware/fsys/hw_fsys.c349
1 files changed, 349 insertions, 0 deletions
diff --git a/agent/mibgroup/hardware/fsys/hw_fsys.c b/agent/mibgroup/hardware/fsys/hw_fsys.c
new file mode 100644
index 0000000..a6cd94d
--- /dev/null
+++ b/agent/mibgroup/hardware/fsys/hw_fsys.c
@@ -0,0 +1,349 @@
+#include <net-snmp/net-snmp-config.h>
+#include <net-snmp/net-snmp-features.h>
+#include <net-snmp/net-snmp-includes.h>
+#include <net-snmp/agent/net-snmp-agent-includes.h>
+#include <net-snmp/agent/hardware/fsys.h>
+#ifdef HAVE_INTTYPES_H
+#include <inttypes.h>
+#endif
+
+netsnmp_feature_child_of(hw_fsys_get_container, netsnmp_unused)
+
+extern void netsnmp_fsys_arch_load( void );
+extern void netsnmp_fsys_arch_init( void );
+static int _fsys_load( void );
+static void _fsys_free( void );
+
+static int _fsysAutoUpdate = 0; /* 0 means on-demand caching */
+static void _fsys_update_stats( unsigned int, void* );
+
+netsnmp_cache *_fsys_cache = NULL;
+netsnmp_container *_fsys_container = NULL;
+static int _fsys_idx = 0;
+static netsnmp_fsys_info * _fsys_create_entry( void );
+
+void init_hw_fsys( void ) {
+
+ if ( _fsys_container )
+ return; /* Already initialised */
+
+ DEBUGMSGTL(("fsys", "Initialise Hardware FileSystem module\n"));
+
+ /*
+ * Define a container to hold the list of filesystems
+ */
+ _fsys_container = netsnmp_container_find("fsysTable:table_container");
+ if ( NULL == _fsys_container ) {
+ snmp_log( LOG_ERR, "failed to create container for fsysTable");
+ return;
+ }
+ netsnmp_fsys_arch_init( );
+
+ /*
+ * If we're sampling the file system information automatically,
+ * then arrange for this to be triggered regularly.
+ *
+ * If we're not sampling these values regularly,
+ * create a suitable cache handler instead.
+ */
+ if ( _fsysAutoUpdate ) {
+ DEBUGMSGTL(("fsys", "Reloading Hardware FileSystems automatically (%d)\n",
+ _fsysAutoUpdate));
+ snmp_alarm_register( _fsysAutoUpdate, SA_REPEAT,
+ _fsys_update_stats, NULL );
+ }
+ else {
+ _fsys_cache = netsnmp_cache_create( 5, netsnmp_fsys_load,
+ netsnmp_fsys_free, NULL, 0 );
+ DEBUGMSGTL(("fsys", "Reloading Hardware FileSystems on-demand (%p)\n",
+ _fsys_cache));
+ }
+}
+
+void shutdown_hw_fsys( void ) {
+ _fsys_free();
+}
+
+#ifndef NETSNMP_FEATURE_REMOVE_HW_FSYS_GET_CONTAINER
+/*
+ * Return the main fsys container
+ */
+netsnmp_container *netsnmp_fsys_get_container( void ) { return _fsys_container; }
+#endif /* NETSNMP_FEATURE_REMOVE_HW_FSYS_GET_CONTAINER */
+
+/*
+ * Return the main fsys cache control structure (if defined)
+ */
+netsnmp_cache *netsnmp_fsys_get_cache( void ) { return _fsys_cache; }
+
+
+/*
+ * Wrapper routine for automatically updating fsys information
+ */
+void
+_fsys_update_stats( unsigned int clientreg, void *data )
+{
+ _fsys_free();
+ _fsys_load();
+}
+
+/*
+ * Wrapper routine for re-loading filesystem statistics on demand
+ */
+int
+netsnmp_fsys_load( netsnmp_cache *cache, void *data )
+{
+ /* XXX - check cache timeliness */
+ return _fsys_load();
+}
+
+/*
+ * Wrapper routine for releasing expired filesystem statistics
+ */
+void
+netsnmp_fsys_free( netsnmp_cache *cache, void *data )
+{
+ _fsys_free();
+}
+
+
+/*
+ * Architecture-independent processing of loading filesystem statistics
+ */
+static int
+_fsys_load( void )
+{
+ netsnmp_fsys_arch_load();
+ /* XXX - update cache timestamp */
+ return 0;
+}
+
+/*
+ * Architecture-independent release of filesystem statistics
+ */
+static void
+_fsys_free( void )
+{
+ netsnmp_fsys_info *sp;
+
+ for (sp = CONTAINER_FIRST( _fsys_container );
+ sp;
+ sp = CONTAINER_NEXT( _fsys_container, sp )) {
+
+ sp->flags &= ~NETSNMP_FS_FLAG_ACTIVE;
+ }
+}
+
+
+netsnmp_fsys_info *netsnmp_fsys_get_first( void ) {
+ return CONTAINER_FIRST( _fsys_container );
+}
+netsnmp_fsys_info *netsnmp_fsys_get_next( netsnmp_fsys_info *this_ptr ) {
+ return CONTAINER_NEXT( _fsys_container, this_ptr );
+}
+
+/*
+ * Retrieve a filesystem entry based on the path where it is mounted,
+ * or (optionally) insert a new one into the container
+ */
+netsnmp_fsys_info *
+netsnmp_fsys_by_path( char *path, int create_type )
+{
+ netsnmp_fsys_info *sp;
+
+ DEBUGMSGTL(("fsys:path", "Get filesystem entry (%s)\n", path));
+
+ /*
+ * Look through the list for a matching entry
+ */
+ /* .. or use a secondary index container ?? */
+ for (sp = CONTAINER_FIRST( _fsys_container );
+ sp;
+ sp = CONTAINER_NEXT( _fsys_container, sp )) {
+
+ if ( !strcmp( path, sp->path ))
+ return sp;
+ }
+
+ /*
+ * Not found...
+ */
+ if ( create_type == NETSNMP_FS_FIND_EXIST ) {
+ DEBUGMSGTL(("fsys:path", "No such filesystem entry\n"));
+ return NULL;
+ }
+
+ /*
+ * ... so let's create a new one
+ */
+ sp = _fsys_create_entry();
+ if (sp)
+ strlcpy(sp->path, path, sizeof(sp->path));
+ return sp;
+}
+
+
+/*
+ * Retrieve a filesystem entry based on the hardware device,
+ * (or exported path for remote mounts).
+ * (Optionally) insert a new one into the container.
+ */
+netsnmp_fsys_info *
+netsnmp_fsys_by_device( char *device, int create_type )
+{
+ netsnmp_fsys_info *sp;
+
+ DEBUGMSGTL(("fsys:device", "Get filesystem entry (%s)\n", device));
+
+ /*
+ * Look through the list for a matching entry
+ */
+ /* .. or use a secondary index container ?? */
+ for (sp = CONTAINER_FIRST( _fsys_container );
+ sp;
+ sp = CONTAINER_NEXT( _fsys_container, sp )) {
+
+ if ( !strcmp( device, sp->device ))
+ return sp;
+ }
+
+ /*
+ * Not found...
+ */
+ if ( create_type == NETSNMP_FS_FIND_EXIST ) {
+ DEBUGMSGTL(("fsys:device", "No such filesystem entry\n"));
+ return NULL;
+ }
+
+ /*
+ * ... so let's create a new one
+ */
+ sp = _fsys_create_entry();
+ if (sp)
+ strlcpy(sp->device, device, sizeof(sp->device));
+ return sp;
+}
+
+
+netsnmp_fsys_info *
+_fsys_create_entry( void )
+{
+ netsnmp_fsys_info *sp;
+
+ sp = SNMP_MALLOC_TYPEDEF( netsnmp_fsys_info );
+ if ( sp ) {
+ /*
+ * Set up the index value.
+ *
+ * All this trouble, just for a simple integer.
+ * Surely there must be a better way?
+ */
+ sp->idx.len = 1;
+ sp->idx.oids = SNMP_MALLOC_TYPEDEF( oid );
+ sp->idx.oids[0] = ++_fsys_idx;
+ }
+
+ DEBUGMSGTL(("fsys:new", "Create filesystem entry (index = %d)\n", _fsys_idx));
+ CONTAINER_INSERT( _fsys_container, sp );
+ return sp;
+}
+
+
+/*
+ * Convert fsys size information to 1K units
+ * (attempting to avoid 32-bit overflow!)
+ */
+unsigned long long
+_fsys_to_K( unsigned long long size, unsigned long long units )
+{
+ int factor = 1;
+
+ if ( units == 0 ) {
+ return 0; /* XXX */
+ } else if ( units == 1024 ) {
+ return size;
+ } else if ( units == 512 ) { /* To avoid unnecessary division */
+ return size/2;
+ } else if ( units < 1024 ) {
+ factor = 1024 / units; /* Assuming power of two */
+ return (size / factor);
+ } else {
+ factor = units / 1024; /* Assuming multiple of 1K */
+ return (size * factor);
+ }
+}
+
+unsigned long long
+netsnmp_fsys_size_ull( netsnmp_fsys_info *f) {
+ if ( !f ) {
+ return 0;
+ }
+ return _fsys_to_K( f->size, f->units );
+}
+
+unsigned long long
+netsnmp_fsys_used_ull( netsnmp_fsys_info *f) {
+ if ( !f ) {
+ return 0;
+ }
+ return _fsys_to_K( f->used, f->units );
+}
+
+unsigned long long
+netsnmp_fsys_avail_ull( netsnmp_fsys_info *f) {
+ if ( !f ) {
+ return 0;
+ }
+ return _fsys_to_K( f->avail, f->units );
+}
+
+
+int
+netsnmp_fsys_size( netsnmp_fsys_info *f) {
+ unsigned long long v = netsnmp_fsys_size_ull(f);
+ return (int)v;
+}
+
+int
+netsnmp_fsys_used( netsnmp_fsys_info *f) {
+ unsigned long long v = netsnmp_fsys_used_ull(f);
+ return (int)v;
+}
+
+int
+netsnmp_fsys_avail( netsnmp_fsys_info *f) {
+ unsigned long long v = netsnmp_fsys_avail_ull(f);
+ return (int)v;
+}
+
+#ifndef INT32_MAX
+#define INT32_MAX 0x7fffffff
+#endif
+
+#ifndef PRIu64
+#define PRIu64 "llu"
+#endif
+
+/* recalculate f->size_32, used_32, avail_32 and units_32 from f->size & comp.*/
+void
+netsnmp_fsys_calculate32(netsnmp_fsys_info *f)
+{
+ unsigned long long s = f->size;
+ unsigned shift = 0;
+
+ while (s > INT32_MAX) {
+ s = s >> 1;
+ shift++;
+ }
+
+ f->size_32 = s;
+ f->units_32 = f->units << shift;
+ f->avail_32 = f->avail >> shift;
+ f->used_32 = f->used >> shift;
+
+ DEBUGMSGTL(("fsys", "Results of 32-bit conversion: size %" PRIu64 " -> %lu;"
+ " units %" PRIu64 " -> %lu; avail %" PRIu64 " -> %lu;"
+ " used %" PRIu64 " -> %lu\n",
+ (uint64_t)f->size, f->size_32, (uint64_t)f->units, f->units_32,
+ (uint64_t)f->avail, f->avail_32, (uint64_t)f->used, f->used_32));
+}