Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 6 Feb 2007 17:36:54 -0500
From:      John Baldwin <jhb@freebsd.org>
To:        "Poul-Henning Kamp" <phk@phk.freebsd.dk>
Cc:        Attilio Rao <attilio@freebsd.org>, arch@freebsd.org
Subject:   Re: Restoring crash dump ability for kvm_getswapinfo(3)
Message-ID:  <200702061736.54926.jhb@freebsd.org>
In-Reply-To: <94787.1170795720@critter.freebsd.dk>
References:  <94787.1170795720@critter.freebsd.dk>

next in thread | previous in thread | raw e-mail | index | archive | help
On Tuesday 06 February 2007 16:02, Poul-Henning Kamp wrote:
> In message <200702061557.24646.jhb@freebsd.org>, John Baldwin writes:
> 
> >Yes, as I mentioned, I would prefer that, but they were explicitly moved from 
> >swap_pager.h to swap_pager.c previously, so I'd like to make sure it is ok to 
> >move them back.
> 
> No objection from me.

Ok, cool.  This is the updated patch:

Index: lib/libkvm/kvm_getswapinfo.c
===================================================================
RCS file: /usr/cvs/src/lib/libkvm/kvm_getswapinfo.c,v
retrieving revision 1.26
diff -u -r1.26 kvm_getswapinfo.c
--- lib/libkvm/kvm_getswapinfo.c	31 Jul 2004 18:49:53 -0000	1.26
+++ lib/libkvm/kvm_getswapinfo.c	6 Feb 2007 21:27:52 -0000
@@ -33,6 +33,7 @@
 #include <sys/blist.h>
 #include <sys/sysctl.h>
 
+#include <vm/swap_pager.h>
 #include <vm/vm_param.h>
 
 #include <err.h>
@@ -49,18 +50,34 @@
 
 #include "kvm_private.h"
 
-#define NL_SWAPBLIST	0
-#define NL_SWDEVT	1
-#define NL_NSWDEV	2
-#define NL_DMMAX	3
+static struct nlist kvm_swap_nl[] = {
+	{ "_swtailq" },		/* list of swap devices and sizes */
+	{ "_dmmax" },		/* maximum size of a swap block */
+	{ NULL }
+};
+
+#define NL_SWTAILQ	0
+#define NL_DMMAX	1
 
 static int kvm_swap_nl_cached = 0;
 static int unswdev;  /* number of found swap dev's */
 static int dmmax;
 
+static int  kvm_getswapinfo_kvm(kvm_t *, struct kvm_swap *, int, int);
 static int  kvm_getswapinfo_sysctl(kvm_t *, struct kvm_swap *, int, int);
+static int  nlist_init(kvm_t *);
 static int  getsysctl(kvm_t *, char *, void *, size_t);
 
+#define KREAD(kd, addr, obj) \
+	(kvm_read(kd, addr, (char *)(obj), sizeof(*obj)) != sizeof(*obj))
+#define	KGET(idx, var)							\
+	KGET2(kvm_swap_nl[(idx)].n_value, var, kvm_swap_nl[(idx)].n_name)
+#define KGET2(addr, var, msg)						\
+	if (KREAD(kd, (u_long)(addr), (var))) {				\
+		_kvm_err(kd, kd->program, "cannot read %s", msg);	\
+		return (-1);						\
+	}
+	
 #define GETSWDEVNAME(dev, str, flags)					\
 	if (dev == NODEV) {						\
 		strlcpy(str, "[NFS swap]", sizeof(str));		\
@@ -91,8 +108,50 @@
 	if (ISALIVE(kd)) {
 		return kvm_getswapinfo_sysctl(kd, swap_ary, swap_max, flags);
 	} else {
-		return -1;
+		return kvm_getswapinfo_kvm(kd, swap_ary, swap_max, flags);
+	}
+}
+
+int
+kvm_getswapinfo_kvm(
+	kvm_t *kd,
+	struct kvm_swap *swap_ary,
+	int swap_max,
+	int flags
+) {
+	int i, ttl;
+	TAILQ_HEAD(, swdevt) swtailq;
+	struct swdevt *sp, swinfo;
+	struct kvm_swap tot;
+
+	if (!nlist_init(kd))
+		return (-1);
+
+	bzero(&tot, sizeof(tot));
+	KGET(NL_SWTAILQ, &swtailq);
+	sp = TAILQ_FIRST(&swtailq);
+	for (i = 0; sp != NULL; i++) {
+		KGET2(sp, &swinfo, "swinfo");
+		ttl = swinfo.sw_nblks - dmmax;
+		if (i < swap_max - 1) {
+			bzero(&swap_ary[i], sizeof(swap_ary[i]));
+			swap_ary[i].ksw_total = ttl;
+			swap_ary[i].ksw_used = swinfo.sw_used;
+			swap_ary[i].ksw_flags = swinfo.sw_flags;
+			GETSWDEVNAME(swinfo.sw_dev, swap_ary[i].ksw_devname,
+			     flags);
+		}
+		tot.ksw_total += ttl;
+		tot.ksw_used += swinfo.sw_used;
+		sp = TAILQ_NEXT(&swinfo, sw_list);
 	}
+
+	if (i >= swap_max)
+		i = swap_max - 1;
+	if (i >= 0)
+		swap_ary[i] = tot;
+
+        return(i);
 }
 
 #define	GETSYSCTL(kd, name, var)					\
@@ -168,6 +227,36 @@
 }
 
 static int
+nlist_init(kvm_t *kd)
+{
+	TAILQ_HEAD(, swdevt) swtailq;
+	struct swdevt *sp, swinfo;
+
+	if (kvm_swap_nl_cached)
+		return (1);
+
+	if (kvm_nlist(kd, kvm_swap_nl) < 0)
+		return (0);
+
+	/* Required entries */
+	if (kvm_swap_nl[NL_SWTAILQ].n_value == 0) {
+		_kvm_err(kd, kd->program, "unable to find swtailq");
+		return (0);
+	}
+		
+	if (kvm_swap_nl[NL_DMMAX].n_value == 0) {
+		_kvm_err(kd, kd->program, "unable to find dmmax");
+		return (0);
+	}
+
+	/* Get globals, type of swap */
+	KGET(NL_DMMAX, &dmmax);
+
+	kvm_swap_nl_cached = 1;
+	return (1);
+}
+
+static int
 getsysctl (
 	kvm_t *kd,
 	char *name,
Index: sys/vm/swap_pager.c
===================================================================
RCS file: /usr/cvs/src/sys/vm/swap_pager.c,v
retrieving revision 1.286
diff -u -r1.286 swap_pager.c
--- sys/vm/swap_pager.c	5 Jan 2007 19:09:01 -0000	1.286
+++ sys/vm/swap_pager.c	6 Feb 2007 21:30:28 -0000
@@ -138,37 +138,6 @@
 #define SWAP_META_PAGES		(SWB_NPAGES * 2)
 #define SWAP_META_MASK		(SWAP_META_PAGES - 1)
 
-typedef	int32_t	swblk_t;	/*
-				 * swap offset.  This is the type used to
-				 * address the "virtual swap device" and
-				 * therefore the maximum swap space is
-				 * 2^32 pages.
-				 */
-
-struct swdevt;
-typedef void sw_strategy_t(struct buf *bp, struct swdevt *sw);
-typedef void sw_close_t(struct thread *td, struct swdevt *sw);
-
-/*
- * Swap device table
- */
-struct swdevt {
-	int	sw_flags;
-	int	sw_nblks;
-	int     sw_used;
-	dev_t	sw_dev;
-	struct vnode *sw_vp;
-	void	*sw_id;
-	swblk_t	sw_first;
-	swblk_t	sw_end;
-	struct blist *sw_blist;
-	TAILQ_ENTRY(swdevt)	sw_list;
-	sw_strategy_t		*sw_strategy;
-	sw_close_t		*sw_close;
-};
-
-#define	SW_CLOSING	0x04
-
 struct swblock {
 	struct swblock	*swb_hnext;
 	vm_object_t	swb_object;
Index: sys/vm/swap_pager.h
===================================================================
RCS file: /usr/cvs/src/sys/vm/swap_pager.h,v
retrieving revision 1.51
diff -u -r1.51 swap_pager.h
--- sys/vm/swap_pager.h	10 Apr 2006 10:03:41 -0000	1.51
+++ sys/vm/swap_pager.h	6 Feb 2007 21:27:33 -0000
@@ -38,6 +38,38 @@
 #ifndef	_VM_SWAP_PAGER_H_
 #define	_VM_SWAP_PAGER_H_ 1
 
+typedef	int32_t	swblk_t;	/*
+				 * swap offset.  This is the type used to
+				 * address the "virtual swap device" and
+				 * therefore the maximum swap space is
+				 * 2^32 pages.
+				 */
+
+struct buf;
+struct swdevt;
+typedef void sw_strategy_t(struct buf *, struct swdevt *);
+typedef void sw_close_t(struct thread *, struct swdevt *);
+
+/*
+ * Swap device table
+ */
+struct swdevt {
+	int	sw_flags;
+	int	sw_nblks;
+	int     sw_used;
+	dev_t	sw_dev;
+	struct vnode *sw_vp;
+	void	*sw_id;
+	swblk_t	sw_first;
+	swblk_t	sw_end;
+	struct blist *sw_blist;
+	TAILQ_ENTRY(swdevt)	sw_list;
+	sw_strategy_t		*sw_strategy;
+	sw_close_t		*sw_close;
+};
+
+#define	SW_CLOSING	0x04
+
 #ifdef _KERNEL
 
 extern int swap_pager_full;

-- 
John Baldwin



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200702061736.54926.jhb>