diff options
author | alc <alc@FreeBSD.org> | 2017-09-30 19:54:30 +0000 |
---|---|---|
committer | alc <alc@FreeBSD.org> | 2017-09-30 19:54:30 +0000 |
commit | 6de538b4bedf70c504cbe3ad1afc7d774d94f63b (patch) | |
tree | 8088082fb5b304007607bed87bb676f75ed11caa /sys/vm | |
parent | 70383b3a940d90e7d084b81f97f0be5bf5b2fda4 (diff) | |
download | FreeBSD-src-6de538b4bedf70c504cbe3ad1afc7d774d94f63b.zip FreeBSD-src-6de538b4bedf70c504cbe3ad1afc7d774d94f63b.tar.gz |
MFC r323391
To analyze the allocation of swap blocks by blist functions, add a method
for analyzing the radix tree structures and reporting on the number, and
sizes, of maximal intervals of free blocks. The report includes the number
of maximal intervals, and also the number of them in each of several size
ranges, from small (size 1, or 3 to 4) to large (28657 to 46367) with size
boundaries defined by Fibonacci numbers. The report is written in the test
tool with the 's' command, or in a running kernel by sysctl.
The analysis of the radix tree frequently computes the position of the lone
bit set in a u_daddr_t, a computation that also appears in leaf allocation.
That computation has been moved into a function of its own, and optimized
for cases where an inlined machine instruction can replace the usual binary
search.
Diffstat (limited to 'sys/vm')
-rw-r--r-- | sys/vm/swap_pager.c | 35 |
1 files changed, 35 insertions, 0 deletions
diff --git a/sys/vm/swap_pager.c b/sys/vm/swap_pager.c index f663ce1..f9a4f59 100644 --- a/sys/vm/swap_pager.c +++ b/sys/vm/swap_pager.c @@ -91,6 +91,7 @@ __FBSDID("$FreeBSD$"); #include <sys/resource.h> #include <sys/resourcevar.h> #include <sys/rwlock.h> +#include <sys/sbuf.h> #include <sys/sysctl.h> #include <sys/sysproto.h> #include <sys/blist.h> @@ -322,6 +323,10 @@ static int sysctl_swap_async_max(SYSCTL_HANDLER_ARGS); SYSCTL_PROC(_vm, OID_AUTO, swap_async_max, CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, NULL, 0, sysctl_swap_async_max, "I", "Maximum running async swap ops"); +static int sysctl_swap_fragmentation(SYSCTL_HANDLER_ARGS); +SYSCTL_PROC(_vm, OID_AUTO, swap_fragmentation, CTLTYPE_STRING | CTLFLAG_RD | + CTLFLAG_MPSAFE, NULL, 0, sysctl_swap_fragmentation, "A", + "Swap Fragmentation Info"); static struct sx sw_alloc_sx; @@ -779,6 +784,36 @@ swp_pager_freeswapspace(daddr_t blk, int npages) } /* + * SYSCTL_SWAP_FRAGMENTATION() - produce raw swap space stats + */ +static int +sysctl_swap_fragmentation(SYSCTL_HANDLER_ARGS) +{ + struct sbuf sbuf; + struct swdevt *sp; + const char *devname; + int error; + + error = sysctl_wire_old_buffer(req, 0); + if (error != 0) + return (error); + sbuf_new_for_sysctl(&sbuf, NULL, 128, req); + mtx_lock(&sw_dev_mtx); + TAILQ_FOREACH(sp, &swtailq, sw_list) { + if (vn_isdisk(sp->sw_vp, NULL)) + devname = devtoname(sp->sw_vp->v_rdev); + else + devname = "[file]"; + sbuf_printf(&sbuf, "\nFree space on device %s:\n", devname); + blist_stats(sp->sw_blist, &sbuf); + } + mtx_unlock(&sw_dev_mtx); + error = sbuf_finish(&sbuf); + sbuf_delete(&sbuf); + return (error); +} + +/* * SWAP_PAGER_FREESPACE() - frees swap blocks associated with a page * range within an object. * |