7118090 snmpwalk of hrStorageIndex can take several minutes due to excessive ioctl calls for mnttab by snmpd
authorLijo George - Oracle Corporation - Bangalore India <lijo.x.george@oracle.com>
Fri, 31 Aug 2012 06:52:29 -0700
changeset 964 3193e50c7331
parent 963 8779eee0a489
child 965 9bd86858aaa1
7118090 snmpwalk of hrStorageIndex can take several minutes due to excessive ioctl calls for mnttab by snmpd
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	Fri Aug 31 06:52:29 2012 -0700
@@ -0,0 +1,217 @@
+/*
+ *  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.
+ */
+
+--- 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	2012-08-17 01:23:04.781860694 -0700
[email protected]@ -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>
[email protected]@ -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
[email protected]@ -563,6 +571,12 @@
+ void
+ Init_HR_FileSys(void)
+ {
++#ifdef solaris2
++	char buf[512]={NULL};
++	int lines=0, i=0;
++	struct stat file_stat;
++#endif
++
+ #if HAVE_GETFSSTAT
+ #if defined(HAVE_STATVFS) && defined(__NetBSD__)
+     fscount = getvfsstat(NULL, 0, ST_NOWAIT);
[email protected]@ -603,10 +617,62 @@
+         }
+     }
+ #else
+-    HRFS_index = 1;
+-    if (fp != NULL)
+-        fclose(fp);
+-    fp = fopen(ETC_MNTTAB, "r");
++    	HRFS_index = 1;
++	if (fp != NULL)
++        	fclose(fp);
++#ifdef solaris2
++	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;
++		}
++
++		while ( (fgets((char *)&buf,sizeof(buf),fp)) != NULL) {
++			lines++;
++		}	
++		fclose(fp);
++	
++		HRFS_list = (struct mnttab *) malloc (sizeof(struct mnttab) * lines);
++		
++		if(HRFS_list == NULL)
++		{
++			DEBUGMSGTL(("host/hr_filesys", "Memory allocation for mnttab cache failed.\n"));
++			return;
++		}				
++
++    		fp = fopen(ETC_MNTTAB, "r");
++		
++		if(fp == NULL)
++                {
++			DEBUGMSGTL(("host/hr_filesys", "fopen failed for mnttab.\n"));
++			free(HRFS_list);
++			return;
++                }
++
++		fscount = lines;
++		while (i < fscount)
++    		{
++			if (getmntent(fp, &HRFS_entry_struct) == 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++;
++        		}
++    		}
++	
++		HRFS_entry = HRFS_list;
++		last_access = file_stat.st_mtime;
++	}
++#else    
++	fp = fopen(ETC_MNTTAB, "r");
++#endif
++
+ #endif
+ }
+ 
[email protected]@ -699,21 +765,24 @@
+ #else
+     const char    **cpp;
+ 
+-    if (fp == NULL)
+-        return -1;
+ 
+ #ifdef solaris2
+-    if (getmntent(fp, HRFS_entry) != 0)
+-        return -1;
++
++	if (HRFS_index >= fscount)
++		return -1;
++	HRFS_entry = &HRFS_list[HRFS_index];
++		return ++HRFS_index;
++
+ #else
+-    HRFS_entry = getmntent(fp);
+-    if (HRFS_entry == NULL)
+-        return -1;
+-#endif                          /* solaris2 */
++	if (fp == NULL)
++                return -1;
++        HRFS_entry = getmntent(fp);
++        if (HRFS_entry == NULL)
++                return -1;
+ 
+-    for (cpp = HRFS_ignores; *cpp != NULL; ++cpp)
+-        if (!strcmp(HRFS_entry->HRFS_type, *cpp))
+-            return Get_Next_HR_FileSys();
++	for (cpp = HRFS_ignores; *cpp != NULL; ++cpp)
++		if (!strcmp(HRFS_entry->HRFS_type, *cpp))
++			return Get_Next_HR_FileSys();
+ 
+     /*
+      * Try and ensure that index values are persistent
[email protected]@ -728,6 +797,8 @@
+     }
+ 
+     return HRFS_index++;
++#endif
++
+ #endif                          /* HAVE_GETFSSTAT */
+ }
+ 
[email protected]@ -780,20 +851,34 @@
+ End_HR_FileSys(void)
+ {
+ #ifdef HAVE_GETFSSTAT
+-    if (fsstats)
+-        free((char *) fsstats);
+-    fsstats = NULL;
++	if (fsstats)
++		free((char *) fsstats);
++	fsstats = NULL;
+ #elif defined(aix4) || defined(aix5)
+-    if(aixmnt != NULL) {
+-        free(aixmnt);
+-        aixmnt = NULL;
+-        aixcurr = NULL;
+-        HRFS_entry = NULL;
+-    }
+-#else
+-    if (fp != NULL)
+-        fclose(fp);
+-    fp = NULL;
++	if(aixmnt != NULL) {
++		free(aixmnt);
++		aixmnt = NULL;
++		aixcurr = NULL;
++		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);
++#endif
++
+ #endif
+ }
+