# HG changeset patch # User Lijo George # Date 1426795110 25200 # Node ID 8b170efb5356eb2f6763e0a9672daf849b218f81 # Parent cc7f2e59f3c05520e728519f5e33c5c4124de48c 15758982 SUNBT7118090 snmpwalk of hrStorageIndex takes minutes due to excessive ioctls 16439911 snmpd stuck looping on ioctl(13, MNTIOC_GETMNTENT,) wo traffic diff -r cc7f2e59f3c0 -r 8b170efb5356 components/net-snmp/patches/027.7118090.hr_filesys.patch --- /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 + #endif + ++#ifdef solaris2 ++#include ++#endif ++ + #include + #if HAVE_STRING_H + #include +@@ -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 + } + diff -r cc7f2e59f3c0 -r 8b170efb5356 components/net-snmp/patches/052.16439911.hr_filesys.patch --- /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;