summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjhb <jhb@FreeBSD.org>2007-02-07 17:43:11 +0000
committerjhb <jhb@FreeBSD.org>2007-02-07 17:43:11 +0000
commit9c764c7fc306e18397030217602494b6937d91ed (patch)
treea754087b619a680335a655d98e288052176274c4
parent61cc2fad7da1e9e31379d361767b26486acda39f (diff)
downloadFreeBSD-src-9c764c7fc306e18397030217602494b6937d91ed.zip
FreeBSD-src-9c764c7fc306e18397030217602494b6937d91ed.tar.gz
- Move 'struct swdevt' back into swap_pager.h and expose it to userland.
- Restore support for fetching swap information from crash dumps via kvm_get_swapinfo(3) to fix pstat -T/-s on crash dumps. Reviewed by: arch@, phk MFC after: 1 week
-rw-r--r--lib/libkvm/kvm_getswapinfo.c99
-rw-r--r--sys/vm/swap_pager.c31
-rw-r--r--sys/vm/swap_pager.h32
3 files changed, 126 insertions, 36 deletions
diff --git a/lib/libkvm/kvm_getswapinfo.c b/lib/libkvm/kvm_getswapinfo.c
index 9ba7a5c..bc9d293 100644
--- a/lib/libkvm/kvm_getswapinfo.c
+++ b/lib/libkvm/kvm_getswapinfo.c
@@ -33,6 +33,7 @@ __FBSDID("$FreeBSD$");
#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 @@ __FBSDID("$FreeBSD$");
#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 @@ kvm_getswapinfo(
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 @@ kvm_getswapinfo_sysctl(
}
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,
diff --git a/sys/vm/swap_pager.c b/sys/vm/swap_pager.c
index 46f49d2..4167c6b 100644
--- a/sys/vm/swap_pager.c
+++ b/sys/vm/swap_pager.c
@@ -138,37 +138,6 @@ __FBSDID("$FreeBSD$");
#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;
diff --git a/sys/vm/swap_pager.h b/sys/vm/swap_pager.h
index a254cc7..c3366e8 100644
--- a/sys/vm/swap_pager.h
+++ b/sys/vm/swap_pager.h
@@ -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;
OpenPOWER on IntegriCloud