15758982 SUNBT7118090 snmpwalk of hrStorageIndex takes minutes due to excessive ioctls
16439911 snmpd stuck looping on ioctl(13, MNTIOC_GETMNTENT,) wo traffic
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/components/net-snmp/patches/027.7118090.hr_filesys.patch Thu Mar 19 12:58:30 2015 -0700
@@ -0,0 +1,253 @@
+This fix has been submitted upstream as part of a combined patch
+which has fixes for this CR (15758982) and another CR (16439911)
+with corresponding patch 048.16439911.hr_filesys.patch
+This can be found in the following location.
+https://sourceforge.net/p/net-snmp/patches/1287/.
+
+This patch has not been accepted yet.
+/*
+ * 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.
+ */
+--- net-snmp-5.4.1.orig/agent/mibgroup/host/hr_filesys.c 2007-05-18 11:08:01.000000000 -0700
++++ net-snmp-5.4.1/agent/mibgroup/host/hr_filesys.c 2013-01-17 03:36:28.181493003 -0800
+@@ -31,6 +31,10 @@
+ #include <sys/mount.h>
+ #endif
+
++#ifdef solaris2
++#include <sys/stat.h>
++#endif
++
+ #include <ctype.h>
+ #if HAVE_STRING_H
+ #include <string.h>
+@@ -85,7 +89,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
+@@ -167,6 +175,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
+
+ /*********************
+ *
+@@ -606,8 +617,14 @@
+ HRFS_index = 1;
+ if (fp != NULL)
+ fclose(fp);
++#ifdef solaris2
++ if(!load_mnttab_cache_solaris())
++ return;
++#else
+ fp = fopen(ETC_MNTTAB, "r");
+ #endif
++
++#endif
+ }
+
+ const char *HRFS_ignores[] = {
+@@ -663,6 +680,117 @@
+ 0
+ };
+
++#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)
+ {
+@@ -699,17 +827,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))
+@@ -728,6 +857,8 @@
+ }
+
+ return HRFS_index++;
++#endif
++
+ #endif /* HAVE_GETFSSTAT */
+ }
+
+@@ -791,9 +922,24 @@
+ 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
+ }
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/components/net-snmp/patches/052.16439911.hr_filesys.patch Thu Mar 19 12:58:30 2015 -0700
@@ -0,0 +1,144 @@
+This fix has been submitted upstream as part of a combined patch
+which has fixes for CR15758982(027.7118090.hr_filesys.patch) and this CR(16439911).
+This can be found in the following location.
+https://sourceforge.net/p/net-snmp/patches/1287/.
+
+This patch has not been accepted yet.
+--- net-snmp-5.4.1.old/agent/mibgroup/host/hr_filesys.c 2014-07-15 01:53:05.131000348 -0700
++++ net-snmp-5.4.1/agent/mibgroup/host/hr_filesys.c 2014-07-15 01:48:04.221278640 -0700
+@@ -698,20 +698,25 @@
+ static int
+ load_mnttab_cache_solaris()
+ {
+- char buf[512] = {NULL};
++ char buf[MNT_LINE_MAX] = {NULL};
+ int i = 0;
+ struct stat file_stat;
+ const char **cpp;
+- char *ch;
++ char *ch, *token_ptr;
+ int token_flag = 0;
+ int skip_flag = 0;
+ int ignore_flag = 0;
+ int j = 0;
+ int lines = 0;
+ int ret = 0;
++ int chk_mnt = -1;
+ HRFS_index = 0;
+
+- stat(ETC_MNTTAB, &file_stat);
++ if(stat(ETC_MNTTAB, &file_stat) != 0)
++ {
++ DEBUGMSGTL(("host/hr_filesys", "stat failed for mnttab.\n"));
++ return -1;
++ }
+ if (last_access == -1 || last_access != file_stat.st_mtime) {
+ fp = fopen(ETC_MNTTAB, "r");
+ if(fp == NULL)
+@@ -731,7 +736,7 @@
+ * which determines the valid entries.
+ */
+
+- ch = strtok(buf, " \t");
++ ch = strtok_r(buf, " \t", &token_ptr);
+ while (ch != NULL) {
+ j++;
+ if(j == 3) {
+@@ -745,7 +750,7 @@
+ }
+ if(token_flag)
+ break;
+- ch = strtok(NULL, " \t");
++ ch = strtok_r(NULL, " \t", &token_ptr);
+ }
+ if(!skip_flag)
+ lines++;
+@@ -765,25 +770,43 @@
+ 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;
+- }
++ while ((chk_mnt = getmntent(fp, &HRFS_entry_struct)) != -1) {
++ if(chk_mnt != 0)
++ continue;
++ for (cpp = HRFS_ignores; *cpp != NULL; ++cpp) {
++ if (!strcmp(HRFS_entry_struct.mnt_fstype, *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++;
++ }
++ if(!ignore_flag) {
++ if(i >= fscount)
++ {
++ DEBUGMSGTL(("host/hr_filesys","increasing cachesize from %d to %d",fscount,i+1));
++ HRFS_list = realloc(HRFS_list, sizeof(struct mnttab) * (i+1));
++ fscount = i+1;
++ if(HRFS_list == NULL)
++ {
++ DEBUGMSGTL(("host/hr_filesys","\nrealloc failed for mnttab cache.\n"));
++ return -1;
++ }
+ }
+-
+- ignore_flag = 0;
++ 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;
++ }
++ if(i < fscount)
++ {
++ DEBUGMSGTL(("host/hr_filesys","\ndecreasing cachesize from %d to %d\n",fscount,i));
++ HRFS_list = realloc(HRFS_list, sizeof(struct mnttab) * i );
++ if(HRFS_list == NULL)
++ {
++ DEBUGMSGTL(("host/hr_filesys","\nrealloc failed for mnttab cache.\n"));
++ return -1;
+ }
+ }
+
+@@ -925,19 +948,19 @@
+ 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++;
+-}
++ int i = 0;
++ 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;