* Swapinfo will provide some information about the state of the swap
* space for the system. It'll determine the number of swap areas,
* their original size, and their utilization.
* Kevin Lahey, February 16, 1993
static struct nlist nl
[] = {{"_swapmap"}, /* list of free swap areas */
{"_swdevt"}, /* list of swap devices and sizes */
{"_nswap"}, /* size of largest swap device */
{"_nswdev"}, /* number of swap devices */
{"_dmmax"}, /* maximum size of a swap block */
char *getbsize
__P((char *, int *, long *));
int i
, total_avail
, total_free
, total_partitions
, *by_device
,
nswap
, nswdev
, dmmax
, ch
;
/* We are trying to be simple here: */
while ((ch
= getopt(argc
, argv
, "k")) != EOF
)
/* Open up /dev/kmem for reading. */
if (kvm_openfiles (NULL
, NULL
, NULL
) == -1) {
fprintf (stderr
, "%s: kvm_openfiles: %s\n",
/* Figure out the offset of the various structures we'll need. */
if (kvm_nlist (nl
) == -1) {
fprintf (stderr
, "%s: kvm_nlist: %s\n",
if (kvm_read (nl
[VM_NSWAP
].n_value
, &nswap
, sizeof (nswap
)) !=
fprintf (stderr
, "%s: didn't read all of nswap\n",
if (kvm_read (nl
[VM_NSWDEV
].n_value
, &nswdev
, sizeof (nswdev
)) !=
fprintf (stderr
, "%s: didn't read all of nswdev\n",
if (kvm_read (nl
[VM_DMMAX
].n_value
, &dmmax
, sizeof (dmmax
)) !=
fprintf (stderr
, "%s: didn't read all of dmmax\n",
if ((swdevt
= malloc (sizeof (struct swdevt
) * nswdev
)) == NULL
||
(by_device
= calloc (sizeof (*by_device
), nswdev
)) == NULL
) {
if (kvm_read (nl
[VM_SWDEVT
].n_value
, swdevt
,
sizeof (struct swdevt
) * nswdev
) !=
sizeof (struct swdevt
) * nswdev
) {
fprintf (stderr
, "%s: didn't read all of swdevt\n",
if (kvm_read (nl
[0].n_value
, &swapmap
, sizeof (struct rlist
*)) !=
sizeof (struct rlist
*)) {
fprintf (stderr
, "%s: didn't read all of swapmap\n",
/* Traverse the list of free swap space... */
int top
, bottom
, next_block
;
if (kvm_read ((long) swapmap
, &head
, sizeof (struct rlist
)) !=
sizeof (struct rlist
)) {
fprintf (stderr
, "%s: didn't read all of head\n",
total_free
+= top
- bottom
+ 1;
* Swap space is split up among the configured disk.
* The first dmmax blocks of swap space some from the
* first disk, the next dmmax blocks from the next,
* and so on. The list of free space joins adjacent
* free blocks, ignoring device boundries. If we want
* to keep track of this information per device, we'll
* just have to extract it ourselves.
while (top
/ dmmax
!= bottom
/ dmmax
) {
next_block
= ((bottom
+ dmmax
) / dmmax
);
by_device
[(bottom
/ dmmax
) % nswdev
] +=
next_block
* dmmax
- bottom
;
bottom
= next_block
* dmmax
;
by_device
[(bottom
/ dmmax
) % nswdev
] +=
header
= getbsize("swapinfo", &headerlen
, &blocksize
);
printf ("%-10s %10s %10s %10s %10s\n",
"Device", header
, "Used", "Available", "Capacity");
for (total_avail
= total_partitions
= i
= 0; i
< nswdev
; i
++) {
printf ("/dev/%-5s %10d ",
devname (swdevt
[i
].sw_dev
, S_IFBLK
),
swdevt
[i
].sw_nblks
/ (blocksize
/512));
* Don't report statistics for partitions which have not
* yet been activated via swapon(8).
if (!swdevt
[i
].sw_freed
) {
printf (" *** not available for swapping ***\n");
total_avail
+= swdevt
[i
].sw_nblks
;
printf ("%10d %10d %7.0f%%\n",
(swdevt
[i
].sw_nblks
- by_device
[i
]) / (blocksize
/512),
by_device
[i
] / (blocksize
/512),
(double) (swdevt
[i
].sw_nblks
-
(double) swdevt
[i
].sw_nblks
* 100.0);
* If only one partition has been set up via swapon(8), we don't
* need to bother with totals.
if (total_partitions
> 1)
printf ("%-10s %10d %10d %10d %7.0f%%\n", "Total",
total_avail
/ (blocksize
/512),
(total_avail
- total_free
) / (blocksize
/512),
total_free
/ (blocksize
/512),
(double) (total_avail
- total_free
) /
(double) total_avail
* 100.0);
(void)fprintf(stderr
, "usage: swapinfo [-k]\n");