Restoring crash dump ability for kvm_getswapinfo(3)
John Baldwin
jhb at freebsd.org
Tue Feb 6 20:37:34 UTC 2007
The patch below fixes kvm_getswapinfo(3) (and thus pstat -T/pstat -s/swapinfo)
on crash dumps. The one ugliness in it is that since 'struct swdevt' was
moved into swap_pager.c, there is no longer a header that I can include to
get it (used to be in vm/swap_pager.h) so I have a copy of the structure in
kvm_getswapinfo.c. I'd prefer to move the structures back into
vm/swap_pager.h.
Index: 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
--- kvm_getswapinfo.c 31 Jul 2004 18:49:53 -0000 1.26
+++ kvm_getswapinfo.c 6 Feb 2007 20:31:09 -0000
@@ -49,18 +49,59 @@
#include "kvm_private.h"
-#define NL_SWAPBLIST 0
-#define NL_SWDEVT 1
-#define NL_NSWDEV 2
-#define NL_DMMAX 3
+/* Grrr, this is hidden in swap_pager.c now, how annoying. */
+typedef int32_t swblk_t;
+
+struct buf;
+struct blist;
+
+struct swdevt;
+typedef void sw_strategy_t(struct buf *bp, struct swdevt *sw);
+typedef void sw_close_t(struct thread *td, struct swdevt *sw);
+
+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;
+};
+
+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 +132,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 +251,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,
--
John Baldwin
More information about the freebsd-arch
mailing list