#
# This patch fixes the performance issue observed while retrieving the
# hrStorage parameters in systems with large number of mountpoints
# parameters using snmpwalk.
#
# This issue is happening due to the overhead of large number of
# ioctl() system calls in getmntent() function called by the
# Get_Next_HR_FileSys() function.
#
# We see that in the Get_Next_HR_FileSys() function, inorder to access
# the last mountpoint, the /etc/mnttab is opened and we walk through
# all the mnttab entries for all filesystems till the end. This is the
# reason we find a large number of the MNTIOC_GETMNTENT ioctl() calls.
#
# To reduce the overhead of the getmntent() calls, we maintain a cache
# of all the /etc/mnttab entries and walk through the cache instead of
# opening /etc/mnttab and walking all the entries for each mountpoint.
# This functionality is provided by the load_mnttab_cache_solaris()
# function called from the Init_HR_FileSys() function.
#
# Developed in-house. Bug submitted upstream
# https://sourceforge.net/p/net-snmp/bugs/2588/
#
--- a/agent/mibgroup/host/hr_filesys.c Wed Feb 19 18:36:42 2014
+++ b/agent/mibgroup/host/hr_filesys.c Wed Nov 26 07:21:17 2014
@@ -46,6 +46,10 @@
#include <sys/mount.h>
#endif
+#ifdef solaris2
+#include <sys/stat.h>
+#endif
+
#include <ctype.h>
#if HAVE_STRING_H
#include <string.h>
@@ -108,7 +112,11 @@
#ifdef solaris2
struct mnttab HRFS_entry_struct;
-struct mnttab *HRFS_entry = &HRFS_entry_struct;
+struct mnttab *HRFS_entry;
+struct mnttab *HRFS_list;
+static int fscount;
+static time_t last_access = -1;
+
#define HRFS_name mnt_special
#define HRFS_mount mnt_mountp
#define HRFS_type mnt_fstype
@@ -207,6 +215,9 @@
static u_char *when_dumped(char *filesys, int level, size_t * length);
int header_hrfilesys(struct variable *, oid *, size_t *, int,
size_t *, WriteMethod **);
+#ifdef solaris2
+static int load_mnttab_cache_solaris(void);
+#endif
/*********************
*
@@ -662,11 +673,14 @@
HRFS_index = 1;
if (fp != NULL)
fclose(fp);
+#ifdef solaris2
+ if(!load_mnttab_cache_solaris())
+ return;
+#else
fp = fopen(ETC_MNTTAB, "r");
- if (!fp) {
- netsnmp_config_error("Can't open mnttab %s\n", ETC_MNTTAB);
- }
#endif
+
+#endif
}
const char *HRFS_ignores[] = {
@@ -722,6 +736,117 @@
NULL
};
+#ifdef solaris2
+
+/*
+ * This function has been introduced to reduce the overhead
+ * of the getmntent() calls used to fetch the details of
+ * the /etc/mnttab entries in Init_HR_FileSys().
+ *
+ * We maintain a cache of all the /etc/mnttab entries and
+ * walk through the cache instead of opening /etc/mnttab and
+ * walking all the entries for each mountpoint.
+ */
+
+static int
+load_mnttab_cache_solaris()
+{
+ char buf[512] = {NULL};
+ int i = 0;
+ struct stat file_stat;
+ const char **cpp;
+ char *ch;
+ int token_flag = 0;
+ int skip_flag = 0;
+ int ignore_flag = 0;
+ int j = 0;
+ int lines = 0;
+ int ret = 0;
+ HRFS_index = 0;
+
+ stat(ETC_MNTTAB, &file_stat);
+ if (last_access == -1 || last_access != file_stat.st_mtime) {
+ fp = fopen(ETC_MNTTAB, "r");
+ if(fp == NULL)
+ {
+ DEBUGMSGTL(("host/hr_filesys", "fopen failed for mnttab.\n"));
+ return -1;
+ }
+
+ /* find the number of valid entries in mnttab. */
+
+ while ((fgets((char *) &buf, sizeof(buf), fp)) != NULL) {
+ j = 0;
+ skip_flag = 0;
+ token_flag = 0;
+
+ /* tokenize the mnttab entries to fetch the fstype
+ * which determines the valid entries.
+ */
+
+ ch = strtok(buf, " \t");
+ while (ch != NULL) {
+ j++;
+ if(j == 3) {
+ for (cpp = HRFS_ignores; *cpp != NULL; ++cpp) {
+ if(!strncmp(ch, *cpp, strlen(ch))) {
+ skip_flag = 1;
+ break;
+ }
+ }
+ token_flag = 1;
+ }
+ if(token_flag)
+ break;
+ ch = strtok(NULL, " \t");
+ }
+ if(!skip_flag)
+ lines++;
+ }
+ fclose(fp);
+
+ fscount = lines;
+ HRFS_list = (struct mnttab *) malloc (sizeof(struct mnttab) * fscount);
+ if(HRFS_list == NULL) {
+ DEBUGMSGTL(("host/hr_filesys", "Memory allocation for mnttab cache failed.\n"));
+ return -1;
+ }
+
+ fp = fopen(ETC_MNTTAB, "r");
+ if(fp == NULL) {
+ DEBUGMSGTL(("host/hr_filesys", "fopen failed for mnttab.\n"));
+ free(HRFS_list);
+ return -1;
+ }
+
+ while (i < fscount) {
+ if (getmntent(fp, &HRFS_entry_struct) == 0) {
+ for (cpp = HRFS_ignores; *cpp != NULL; ++cpp) {
+ if (!strcmp(HRFS_entry_struct.HRFS_type, *cpp)) {
+ ignore_flag = 1;
+ break;
+ }
+ }
+
+ if(!ignore_flag) {
+ HRFS_list[i].mnt_special = strdup(HRFS_entry_struct.mnt_special);
+ HRFS_list[i].mnt_mountp = strdup(HRFS_entry_struct.mnt_mountp);
+ HRFS_list[i].mnt_fstype = strdup(HRFS_entry_struct.mnt_fstype);
+ HRFS_list[i].mnt_mntopts = strdup(HRFS_entry_struct.mnt_mntopts);
+ i++;
+ }
+
+ ignore_flag = 0;
+ }
+ }
+
+ HRFS_entry = HRFS_list;
+ last_access = file_stat.st_mtime;
+ }
+ return ret;
+}
+#endif
+
int
Get_Next_HR_FileSys(void)
{
@@ -758,17 +883,18 @@
#else
const char **cpp;
- if (fp == NULL)
- return -1;
#ifdef solaris2
- if (getmntent(fp, HRFS_entry) != 0)
+ if (HRFS_index >= fscount)
return -1;
+ HRFS_entry = &HRFS_list[HRFS_index];
+ return ++HRFS_index;
#else
+ if (fp == NULL)
+ return -1;
HRFS_entry = getmntent(fp);
if (HRFS_entry == NULL)
return -1;
-#endif /* solaris2 */
for (cpp = HRFS_ignores; *cpp != NULL; ++cpp)
if (!strcmp(HRFS_entry->HRFS_type, *cpp))
@@ -787,6 +913,8 @@
}
return HRFS_index++;
+#endif
+
#endif /* HAVE_GETFSSTAT */
}
@@ -854,10 +982,25 @@
HRFS_entry = NULL;
}
#else
+ int i = 0;
if (fp != NULL)
fclose(fp);
fp = NULL;
+
+#ifdef solaris2
+while (i < fscount) {
+ free(HRFS_list[i].mnt_special);
+ free(HRFS_list[i].mnt_mountp);
+ free(HRFS_list[i].mnt_fstype);
+ free(HRFS_list[i].mnt_mntopts);
+ i++;
+}
+ if (HRFS_list != NULL)
+ free(HRFS_list);
+ last_access = -1;
#endif
+
+#endif
}