diff options
Diffstat (limited to 'agent/mibgroup/hardware/fsys/hw_fsys.c')
-rw-r--r-- | agent/mibgroup/hardware/fsys/hw_fsys.c | 349 |
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)); +} |