From 9c764c7fc306e18397030217602494b6937d91ed Mon Sep 17 00:00:00 2001 From: jhb Date: Wed, 7 Feb 2007 17:43:11 +0000 Subject: [PATCH] - 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 --- lib/libkvm/kvm_getswapinfo.c | 99 ++++++++++++++++++++++++++++++++++-- sys/vm/swap_pager.c | 31 ----------- sys/vm/swap_pager.h | 32 ++++++++++++ 3 files changed, 126 insertions(+), 36 deletions(-) diff --git a/lib/libkvm/kvm_getswapinfo.c b/lib/libkvm/kvm_getswapinfo.c index 9ba7a5c2cba..bc9d293b71e 100644 --- a/lib/libkvm/kvm_getswapinfo.c +++ b/lib/libkvm/kvm_getswapinfo.c @@ -33,6 +33,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include @@ -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) \ @@ -167,6 +226,36 @@ kvm_getswapinfo_sysctl( return(ti); } +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, diff --git a/sys/vm/swap_pager.c b/sys/vm/swap_pager.c index 46f49d24967..4167c6ba896 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 a254cc7ce93..c3366e8e877 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; -- 2.45.0