};
static int ds_num = 4;
-#ifdef KERNEL_SOLARIS
+#if KERNEL_LINUX
+/* No global variables */
+/* #endif KERNEL_LINUX */
+
+#elif HAVE_LIBKSTAT
-- static int pagesize;
++ static unsigned long long pagesize;
static kstat_t *ksp;
-#endif /* KERNEL_SOLARIS */
+/* #endif HAVE_LIBKSTAT */
+
+#elif defined(VM_SWAPUSAGE)
+/* No global variables */
+/* #endif defined(VM_SWAPUSAGE) */
+
+#elif HAVE_LIBKVM
+static kvm_t *kvm_obj = NULL;
+int kvm_pagesize;
+/* #endif HAVE_LIBKVM */
+
+#elif HAVE_LIBSTATGRAB
+/* No global variables */
+#endif /* HAVE_LIBSTATGRAB */
static void swap_init (void)
{
-#ifdef KERNEL_SOLARIS
+#if KERNEL_LINUX
+ /* No init stuff */
+/* #endif KERNEL_LINUX */
+
+#elif HAVE_LIBKSTAT
/* getpagesize(3C) tells me this does not fail.. */
-- pagesize = getpagesize ();
++ pagesize = (unsigned long long) getpagesize ();
if (get_kstat (&ksp, "unix", 0, "system_pages"))
ksp = NULL;
-#endif /* KERNEL_SOLARIS */
+/* #endif HAVE_LIBKSTAT */
+
+#elif defined(VM_SWAPUSAGE)
+ /* No init stuff */
+/* #endif defined(VM_SWAPUSAGE) */
+
+#elif HAVE_LIBKVM
+ if (kvm_obj != NULL)
+ {
+ kvm_close (kvm_obj);
+ kvm_obj = NULL;
+ }
+
+ kvm_pagesize = getpagesize ();
+
+ if ((kvm_obj = kvm_open (NULL, /* execfile */
+ NULL, /* corefile */
+ NULL, /* swapfile */
+ O_RDONLY, /* flags */
+ NULL)) /* errstr */
+ == NULL)
+ {
+ syslog (LOG_ERR, "swap plugin: kvm_open failed.");
+ return;
+ }
+/* #endif HAVE_LIBKVM */
+
+#elif HAVE_LIBSTATGRAB
+ /* No init stuff */
+#endif /* HAVE_LIBSTATGRAB */
return;
}
struct anoninfo ai;
if (swapctl (SC_AINFO, &ai) == -1)
++ {
++ syslog (LOG_ERR, "swap plugin: swapctl failed: %s",
++ strerror (errno));
return;
++ }
-- availrmem = get_kstat_value (ksp, "availrmem");
-- swapfs_minfree = get_kstat_value (ksp, "minfree");
--
-- if ((availrmem < 0LL) || (swapfs_minfree < 0LL))
-- return;
--
-- /*
-- * Calculations learned by reading
-- * http://www.itworld.com/Comp/2377/UIR980701perf/
++ /*
++ * Calculations from:
++ * http://cvs.opensolaris.org/source/xref/on/usr/src/cmd/swap/swap.c
++ * Also see:
++ * http://www.itworld.com/Comp/2377/UIR980701perf/ (outdated?)
++ * /usr/include/vm/anon.h
++ *
++ * In short, swap -s shows: allocated + reserved = used, available
++ *
++ * However, Solaris does not allow to allocated/reserved more than the
++ * available swap (physical memory + disk swap), so the pedant may
++ * prefer: allocated + unallocated = reserved, available
++ *
++ * We map the above to: used + resv = n/a, free
*
-- * swap_resv += ani_resv
-- * swap_alloc += MAX(ani_resv, ani_max) - ani_free
-- * swap_avail += MAX(ani_max - ani_resv, 0) + (availrmem - swapfs_minfree)
-- * swap_free += ani_free + (availrmem - swapfs_minfree)
++ * Does your brain hurt yet? - Christophe Kalt
*
-- * To clear up the terminology a bit:
-- * resv = reserved (but not neccessarily used)
-- * alloc = used (neccessarily reserved)
-- * avail = not reserved (neccessarily free)
-- * free = not allocates (possibly reserved)
++ * Oh, and in case you wonder,
++ * swap_alloc = pagesize * ( ai.ani_max - ai.ani_free );
++ * can suffer from a 32bit overflow.
*/
-- swap_resv = pagesize * ai.ani_resv;
-- swap_alloc = pagesize * (MAX(ai.ani_resv, ai.ani_max) - ai.ani_free);
-- swap_avail = pagesize * (MAX(ai.ani_max - ai.ani_resv, 0) + (availrmem - swapfs_minfree));
-- /* swap_free = pagesize * (ai.ani_free + (availrmem - swapfs_minfree)); */
++ swap_alloc = ai.ani_max - ai.ani_free;
++ swap_alloc *= pagesize;
++ swap_resv = ai.ani_resv + ai.ani_free - ai.ani_max;
++ swap_resv *= pagesize;
++ swap_avail = ai.ani_max - ai.ani_resv;
++ swap_avail *= pagesize;
- swap_submit (swap_alloc, swap_avail, -1LL, swap_resv);
-/* #endif defined(KERNEL_SOLARIS) */
+ swap_submit (swap_alloc, swap_avail, -1LL, swap_resv - swap_alloc);
+/* #endif HAVE_LIBKSTAT */
+
+#elif defined(VM_SWAPUSAGE)
+ int mib[3];
+ size_t mib_len;
+ struct xsw_usage sw_usage;
+ size_t sw_usage_len;
+ int status;
+
+ mib_len = 2;
+ mib[0] = CTL_VM;
+ mib[1] = VM_SWAPUSAGE;
+
+ sw_usage_len = sizeof (struct xsw_usage);
+
+ if (sysctl (mib, mib_len, &sw_usage, &sw_usage_len, NULL, 0) != 0)
+ return;
+
+ /* The returned values are bytes. */
+ swap_submit (sw_usage.xsu_used, sw_usage.xsu_avail, -1LL, -1LL);
+/* #endif VM_SWAPUSAGE */
+
+#elif HAVE_LIBKVM
+ struct kvm_swap data_s;
+ int status;
+
+ unsigned long long used;
+ unsigned long long free;
+ unsigned long long total;
+
+ if (kvm_obj == NULL)
+ return;
+
+ /* only one structure => only get the grand total, no details */
+ status = kvm_getswapinfo (kvm_obj, &data_s, 1, 0);
+ if (status == -1)
+ return;
+
+ total = (unsigned long long) data_s.ksw_total;
+ used = (unsigned long long) data_s.ksw_used;
+
+ total *= (unsigned long long) kvm_pagesize;
+ used *= (unsigned long long) kvm_pagesize;
+
+ free = total - used;
+
+ swap_submit (used, free, -1LL, -1LL);
+/* #endif HAVE_LIBKVM */
-#elif defined(HAVE_LIBSTATGRAB)
+#elif HAVE_LIBSTATGRAB
sg_swap_stats *swap;
if ((swap = sg_get_swap_stats ()) != NULL)