[Nagiosplug-devel] [patch] check_swap: swapctl(2) for tru64,solaris,*BSD,et c

sean finney seanius at seanius.net
Sun Aug 22 15:01:08 CEST 2004


hey folks,

here's a patch that uses the system call swapctl(2) to determine
swap usage statistics instead of the userland program equivalents.

fwict, there are two variants of swapctl, one i've called "SVR4" and
the other "BSD", based on the host's os and header comments on the
machines where they were found.  this patch affects the following os's
from what i can tell:

solaris 7-9 (SVR4)
tru64 unix (SVR4)
freebsd (BSD)
openbsd (BSD)
netbsd (BSD)

i've tested this on all of the above (plus my linux machine, just to
make sure the tests didn't break anything there), except for the
freebsd machine, due to a power outage and me not being able to 
power it back up until tomorrow.

for solaris, i removed the clause that detects the solaris output of
swap -l, but i've left the rest of them (plus the other HAVE_SWAP
commands) as they are until they too can be replaced.

from googling, it looks like unixware also has an SVR4 style swapctl,
but i don't have a box to test it on.  if anyone has a chance,
could they look into that?  like i said, i left in the previous
program checks, but it's possible that having both checks
succeed might do something wierd.


	sean
-------------- next part --------------
Index: configure.in
===================================================================
RCS file: /cvsroot/nagiosplug/nagiosplug/configure.in,v
retrieving revision 1.112
diff -u -r1.112 configure.in
--- configure.in	19 Aug 2004 19:05:48 -0000	1.112
+++ configure.in	22 Aug 2004 21:57:23 -0000
@@ -1303,18 +1303,16 @@
 		ac_cv_swap_conv=2048
 		AC_MSG_RESULT([using IRIX format swap])
 
-	elif [$PATH_TO_SWAP -l 2>/dev/null | egrep -i "^swapfile +dev +swaplo +blocks +free" >/dev/null]
-	then
-		ac_cv_swap_format=["%*s %*[0-9,-] %*d %d %d"]
-		ac_cv_swap_conv=2048
-		AC_MSG_RESULT([using Solaris format swap])
-
 	elif [$PATH_TO_SWAP -l 2>/dev/null | egrep -i "^path +dev +swaplo +blocks +free" >/dev/null]
 	then
 		ac_cv_swap_format=["%*s %*[0-9,-] %*d %d %d"]
 		ac_cv_swap_conv=2048
 		AC_MSG_RESULT([using Unixware format swap])
-
+	else
+		dnl if we don't know what format swap's output is
+		dnl we might as well pretend we didn't see it
+		ac_cv_have_swap=""
+		ac_cv_swap_command=""
 	fi
 fi
 dnl end if for PATH_TO_SWAP
@@ -1362,46 +1360,83 @@
 dnl end if for PATH_TO_SWAPINFO
 fi
 
-AC_PATH_PROG(PATH_TO_SWAPCTL,swapctl,,[$PATH:/sbin])
-if (test -n "$PATH_TO_SWAPCTL")
-then
-AC_MSG_CHECKING([for $PATH_TO_SWAPCTL format])
-if [$PATH_TO_SWAPCTL -l 2>&1 >/dev/null]
+dnl
+dnl test for swapctl system call, both the 2-arg and 3-arg variants
+dnl fwict, the 2-arg is an SVR4 standard, whereas the 3-arg is shared
+dnl in the various BSD's
+dnl
+
+AC_CHECK_HEADERS([sys/swap.h sys/stat.h sys/param.h])
+AC_CHECK_DECLS([swapctl],,,[
+               #include <unistd.h>
+               #include <sys/types.h>
+               #include <sys/stat.h>
+               #include <sys/swap.h>
+               ])
+AC_CHECK_TYPES([swaptbl_t, swapent_t],,,[
+               #include <sys/types.h>
+               #include <sys/stat.h>
+               #include <sys/swap.h>
+               ])
+AC_CHECK_MEMBERS([struct swapent.se_nblks],,,[
+               #include <unistd.h>
+               #include <sys/types.h>
+               #include <sys/stat.h>
+               #include <sys/swap.h>
+               ])
+
+if test "$ac_cv_have_decl_swapctl" = "yes"; 
 then
-	ac_cv_have_swap=yes
-	ac_cv_swap_command="$PATH_TO_SWAPCTL -l"
-	if [$PATH_TO_SWAPCTL -l 2>/dev/null | \
-		egrep -i "^Device +1K-blocks +Used +Avail +Capacity +Priority" >/dev/null ]
+	EXTRAS="$EXTRAS check_swap"
+	AC_MSG_CHECKING([for 2-arg (SVR4) swapctl])
+	if test "$ac_cv_type_swaptbl_t" = "yes" -a \
+	        "$ac_cv_type_swapent_t" = "yes"; 
 	then
-		ac_cv_swap_format=["%*s %llu %*d %llu %*d"]
-		ac_cv_swap_conv=1024
-		AC_MSG_RESULT([using 1K BSD format swapctl])
-
-	elif [$PATH_TO_SWAPCTL -l 2>/dev/null | \
-		egrep -i "^Device +512-blocks +Used +Avail +Capacity +Priority" >/dev/null ]
+		AC_MSG_RESULT([yes])
+		ac_cv_check_swap_swapctl_svr4="1";
+		AC_DEFINE([CHECK_SWAP_SWAPCTL_SVR4],1,
+		          [Define if 2-argument SVR4 swapctl exists])
+	else
+		AC_MSG_RESULT([no])
+		AC_MSG_CHECKING([for 3-arg (*BSD) swapctl])
+		if test "$ac_cv_member_struct_swapent_se_nblks" = "yes"; 
+		then
+			AC_MSG_RESULT([yes])
+			AC_DEFINE([CHECK_SWAP_SWAPCTL_BSD],1,
+			          [Define if 3-argument BSD swapctl exists])
+		else
+			AC_MSG_RESULT([no])
+		fi
+	fi
+	AC_MSG_CHECKING([for whether swapctl uses blocks or pages])
+	if test "$ac_cv_check_swap_swapctl_svr4" = "1";
 	then
-		ac_cv_swap_format=["%*s %llu %*d %llu %*d"]
+		dnl
+		dnl the SVR4 spec returns values in pages
+		dnl
+		AC_MSG_RESULT([page])
+		AC_CHECK_DECLS([sysconf])
+		AC_MSG_CHECKING([for system page size])
+		if test "$ac_cv_have_decl_sysconf" = "yes";
+		then
+			AC_MSG_RESULT([determined by sysconf(3)])
+			ac_cv_swap_conv="(1048576/sysconf(_SC_PAGESIZE))"
+		else
+			AC_MSG_WARN([don't know. guessing 4096k])
+			ac_cv_swap_conv=256
+		fi
+	else
+		dnl
+		dnl the BSD spec returns values in blocks
+		dnl
+		AC_MSG_RESULT([blocks (assuming 512b)])
 		ac_cv_swap_conv=2048
-		AC_MSG_RESULT([using 512 byte BSD format swapctl])
 	fi
+	AC_DEFINE_UNQUOTED(SWAP_CONVERSION,$ac_cv_swap_conv,
+		[Conversion factor to MB])
 fi
-dnl end if for PATH_TO_SWAPCTL
-fi
-
-dnl
-dnl test for swapctl system call, as found in tru64 and solaris
-dnl note: the way the ifdef logic in check_swap is right now,
-dnl this will only affect systems that don't pass one of the
-dnl earlier tests.
-dnl
-AC_CHECK_HEADERS([sys/swap.h sys/stat.h sys/param.h])
-AC_CHECK_DECLS([swapctl],,,[
-	#include <sys/types.h>
-	#include <sys/stat.h>
-	#include <sys/swap.h>
-	])
 dnl
-dnl end test for swapctl system call
+dnl end tests for the swapctl system calls
 dnl
 
 
Index: plugins/check_swap.c
===================================================================
RCS file: /cvsroot/nagiosplug/nagiosplug/plugins/check_swap.c,v
retrieving revision 1.30
diff -u -r1.30 check_swap.c
--- plugins/check_swap.c	19 Aug 2004 19:05:49 -0000	1.30
+++ plugins/check_swap.c	22 Aug 2004 21:57:23 -0000
@@ -56,29 +56,37 @@
 	int result = STATE_OK;
 	char input_buffer[MAX_INPUT_BUFFER];
 	char *perf;
+	int conv_factor = SWAP_CONVERSION;
 #ifdef HAVE_PROC_MEMINFO
 	FILE *fp;
 #else
 # ifdef HAVE_SWAP
-	int conv_factor;		/* Convert to MBs */
 	char *temp_buffer;
 	char *swap_command;
 	char *swap_format;
 # else
 #  ifdef HAVE_DECL_SWAPCTL
-	int i=0, nswaps=0;
-	swaptbl_t tbl;
+	int i=0, nswaps=0, swapctl_res=0;
+#   ifdef CHECK_SWAP_SWAPCTL_SVR4
+	swaptbl_t *tbl=NULL;
+	swapent_t *ent=NULL;
+#   else
+#    ifdef CHECK_SWAP_SWAPCTL_BSD
+	struct swapent *ent;
+#    endif /* CHECK_SWAP_SWAPCTL_BSD */
+#   endif /* CHECK_SWAP_SWAPCTL_SVR4 */
 #  endif /* HAVE_DECL_SWAPCTL */
 # endif
 #endif
 	char str[32];
-	char *status;
+	char *status, *tmp_status;
 
 	setlocale (LC_ALL, "");
 	bindtextdomain (PACKAGE, LOCALEDIR);
 	textdomain (PACKAGE);
 
 	status = strdup ("");
+	tmp_status = strdup ("");
 	perf = strdup ("");
 
 	if (process_arguments (argc, argv) != OK)
@@ -122,7 +130,6 @@
 # ifdef HAVE_SWAP
 	asprintf(&swap_command, "%s", SWAP_COMMAND);
 	asprintf(&swap_format, "%s", SWAP_FORMAT);
-	conv_factor = SWAP_CONVERSION;
 
 /* These override the command used if a summary (and thus ! allswaps) is required */
 /* The summary flag returns more accurate information about swap usage on these OSes */
@@ -132,14 +139,6 @@
 		asprintf(&swap_format, "%s", "%d%*s %d");
 		conv_factor = 1;
 	}
-#  else
-#   ifdef sun
-	if (!allswaps) {
-		asprintf(&swap_command, "%s", "/usr/sbin/swap -s");
-		asprintf(&swap_format, "%s", "%*s %*dk %*s %*s + %*dk %*s = %dk %*s %dk %*s");
-		conv_factor = 2048;
-	}
-#   endif
 #  endif
 
 	if (verbose >= 2)
@@ -183,15 +182,6 @@
 		if (verbose >= 3)
 			printf (_("total=%d, used=%d, free=%d\n"), total_swap, used_swap, free_swap);
 	} else {
-#  else
-#   ifdef sun
-	if (!allswaps) {
-		sscanf (input_buffer, swap_format, &used_swap, &free_swap);
-		used_swap = used_swap / 1024;
-		free_swap = free_swap / 1024;
-		total_swap = used_swap + free_swap;
-	} else {
-#   endif
 #  endif
 		while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_process)) {
 			sscanf (input_buffer, swap_format, &dsktotal, &dskfree);
@@ -219,10 +209,6 @@
 		}
 #  ifdef _AIX
 	}
-#  else
-#   ifdef sun
-	}
-#   endif
 #  endif
 
 	/* If we get anything on STDERR, at least set warning */
@@ -236,31 +222,38 @@
 	if (spclose (child_process))
 		result = max_state (result, STATE_WARNING);
 # else
-#  ifdef HAVE_DECL_SWAPCTL
-
-	/* initialize swap table entries */
-	memset(&tbl, 0, sizeof(swaptbl_t));
-	tbl.swt_ent[0].ste_path=(char*)malloc(sizeof(char)*(MAXPATHLEN+1));
-	memset(tbl.swt_ent[0].ste_path, 0, sizeof(char)*(MAXPATHLEN+1));
-	tbl.swt_n=1;
+#  ifdef CHECK_SWAP_SWAPCTL_SVR4
 
 	/* get the number of active swap devices */
 	nswaps=swapctl(SC_GETNSWP, NULL);
 
+	/* initialize swap table + entries */
+	tbl=(swaptbl_t*)malloc(sizeof(swaptbl_t)+(sizeof(swapent_t)*nswaps));
+	memset(tbl, 0, sizeof(swaptbl_t)+(sizeof(swapent_t)*nswaps));
+	tbl->swt_n=nswaps;
+	for(i=0;i<nswaps;i++){
+		ent=&tbl->swt_ent[i];
+		ent->ste_path=(char*)malloc(sizeof(char)*MAXPATHLEN);
+	}
+
 	/* and now, tally 'em up */
+	swapctl_res=swapctl(SC_LIST, tbl);
+	if(swapctl_res < 0){
+		perror("swapctl failed: ");
+		result = STATE_WARNING;
+	}
+
 	for(i=0;i<nswaps;i++){
-		swapctl(SC_LIST, &tbl);
-		/* on tru64, swap is stored in 8k pages.  i'd
-		   use conv_factor or SWAP_CONVERSION, but they're
-		   both buried under a bunch of ifdef's.  ideally
-		   all functions could call getpagesize(2)...  */
-		dsktotal = tbl.swt_ent[0].ste_pages / 128;
-		dskfree = tbl.swt_ent[0].ste_free / 128;
-		dskused = ( total_swap - free_swap );
+		dsktotal = tbl->swt_ent[i].ste_pages / SWAP_CONVERSION;
+		dskfree = tbl->swt_ent[i].ste_free /  SWAP_CONVERSION;
+		dskused = ( dsktotal - dskfree );
 
 		if(allswaps && dsktotal > 0){
 			percent = 100 * (((double) dskused) / ((double) dsktotal));
 			result = max_state (result, check_swap (percent, dskfree));
+			if (verbose) {
+				asprintf (&status, "%s [%d (%d%%)]", status, (int)dskfree, 100 - percent);
+			}
 		}
 
 		total_swap += dsktotal;
@@ -269,16 +262,58 @@
 	}
 
 	/* and clean up after ourselves */
-	free(tbl.swt_ent[0].ste_path);
+	for(i=0;i<nswaps;i++){
+		free(tbl->swt_ent[i].ste_path);
+	}
+	free(tbl);
+#  else
+#   ifdef CHECK_SWAP_SWAPCTL_BSD
 
-#  endif /* HAVE_DECL_SWAPCTL */
+	/* get the number of active swap devices */
+	nswaps=swapctl(SWAP_NSWAP, NULL, 0);
+
+	/* initialize swap table + entries */
+	ent=(struct swapent*)malloc(sizeof(struct swapent)*nswaps);
+
+	/* and now, tally 'em up */
+	swapctl_res=swapctl(SWAP_STATS, ent, nswaps);
+	if(swapctl_res < 0){
+		perror("swapctl failed: ");
+		result = STATE_WARNING;
+	}
+
+	for(i=0;i<nswaps;i++){
+		dsktotal = ent->se_nblks / conv_factor;
+		dskused = ent->se_inuse / conv_factor;
+		dskfree = ( dsktotal - dskused );
+
+		if(allswaps && dsktotal > 0){
+			percent = 100 * (((double) dskused) / ((double) dsktotal));
+			result = max_state (result, check_swap (percent, dskfree));
+			if (verbose) {
+				asprintf (&status, "%s [%d (%d%%)]", status, (int)dskfree, 100 - percent);
+			}
+		}
+
+		total_swap += dsktotal;
+		free_swap += dskfree;
+		used_swap += dskused;
+	}
+
+	/* and clean up after ourselves */
+	free(ent);
+
+#   endif /* CHECK_SWAP_SWAPCTL_BSD */
+#  endif /* CHECK_SWAP_SWAPCTL_SVR4 */
 # endif /* HAVE_SWAP */
 #endif /* HAVE_PROC_MEMINFO */
 
 	percent_used = 100 * ((double) used_swap) / ((double) total_swap);
 	result = max_state (result, check_swap (percent_used, free_swap));
-	asprintf (&status, _(" %d%% free (%llu MB out of %llu MB)%s"),
-						(100 - percent_used), free_swap, total_swap, status);
+	/* broken into two steps because of funkiness with builtin asprintf */
+	asprintf (&tmp_status, _(" %d%% free (%llu MB out of %llu MB)"),
+						(100 - percent_used), free_swap, total_swap);
+	asprintf (&status, "%s%s", tmp_status, status);
 
 	asprintf (&perf, "%s", perfdata ("swap", (long) free_swap, "MB",
 		TRUE, (long) max (warn_size/1024, warn_percent/100.0*total_swap),
Index: plugins/common.h
===================================================================
RCS file: /cvsroot/nagiosplug/nagiosplug/plugins/common.h,v
retrieving revision 1.12
diff -u -r1.12 common.h
--- plugins/common.h	19 Aug 2004 19:05:49 -0000	1.12
+++ plugins/common.h	22 Aug 2004 21:57:23 -0000
@@ -110,6 +110,10 @@
 # endif
 #endif
 
+#ifndef SWAP_CONVERSION
+# define SWAP_CONVERSION 1
+#endif
+
 /*
  *
  * Missing Functions
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 189 bytes
Desc: Digital signature
URL: <https://www.monitoring-plugins.org/archive/devel/attachments/20040822/ef089c7e/attachment.sig>


More information about the Devel mailing list