usr.sbin/pstat/pstat.c
/*
 * swapmode is based on a program called swapinfo written
 * by Kevin Lahey <kml@rokkaku.atl.ga.us>.
 */
swapmode is based on a program called swapinfo written
by Kevin Lahey .
swapmode is based on a program called swapinfo written by Kevin Lahey .
void
swapmode()
{
	char *header, *p;
	int hlen, nswap, nswdev, dmmax, nswapmap, niswap, niswdev;
	int s, e, div, i, l, avail, nfree, npfree, used;
	struct swdevt *sw;
	long blocksize, *perdev;
	struct map *swapmap, *kswapmap;
	struct mapent *mp;
	KGET(VM_NSWAP, nswap);
	KGET(VM_NSWDEV, nswdev);
	KGET(VM_DMMAX, dmmax);
	KGET(VM_NSWAPMAP, nswapmap);
	KGET(VM_SWAPMAP, kswapmap);	
	if ((sw = malloc(nswdev * sizeof(*sw))) == NULL ||
	    (perdev = malloc(nswdev * sizeof(*perdev))) == NULL ||
	    (mp = malloc(nswapmap * sizeof(*mp))) == NULL)
		err(1, "malloc");
	KGET1(VM_SWDEVT, sw, nswdev * sizeof(*sw), "swdevt");
	KGET2((long)kswapmap, mp, nswapmap * sizeof(*mp), "swapmap");
	if (nl[VM_NISWAP].n_value != 0) {
		KGET(VM_NISWAP, niswap);
		KGET(VM_NISWDEV, niswdev);
	} else {
		niswap = nswap;
		niswdev = nswdev;
	}
	swapmap = (struct map *)mp;
	if (nswapmap != swapmap->m_limit - (struct mapent *)kswapmap)
		errx(1, "panic: nswapmap goof");
	nfree = 0;
	memset(perdev, 0, nswdev * sizeof(*perdev));
	for (mp++; mp->m_addr != 0; mp++) {
		s = mp->m_addr;			
		e = mp->m_addr + mp->m_size;	
		nfree += mp->m_size;
		i = -1;
		while (s < e) {		
			int bound = roundup(s+1, dmmax);
			if (bound > e)
				bound = e;
			if (bound <= niswap) {
				if (i == -1)
					i = (s / dmmax) % niswdev;
				perdev[i] += bound - s;
				if (++i >= niswdev)
					i = 0;
			} else {
				if (i < niswdev) {
					i = niswdev;
					l = niswap + sw[i].sw_nblks;
				}
				while (s >= l) {
					if (i == nswdev-1)
						break;
					l += sw[++i].sw_nblks;
				}
				perdev[i] += bound - s;
			}
			s = bound;
		}
	}
	header = getbsize(&hlen, &blocksize);
	if (!totalflag)
		(void)printf("%-11s %*s %8s %8s %8s  %s\n",
		    "Device", hlen, header,
		    "Used", "Avail", "Capacity", "Type");
	div = blocksize / 512;
	avail = npfree = 0;
	for (i = 0; i < nswdev; i++) {
		int xsize, xfree;
		if (!totalflag) {
			p = devname(sw[i].sw_dev, S_IFBLK);
			(void)printf("/dev/%-6s %*d ", p == NULL ? "??" : p,
			    hlen, sw[i].sw_nblks / div);
		}
		if (!(sw[i].sw_flags & SW_FREED)) {
			if (totalflag)
				continue;
			(void)printf(" *** not available for swapping ***\n");
			continue;
		}
		xsize = sw[i].sw_nblks;
		xfree = perdev[i];
		used = xsize - xfree;
		npfree++;
		avail += xsize;
		if (totalflag)
			continue;
		(void)printf("%8d %8d %5.0f%%    %s\n", 
		    used / div, xfree / div,
		    (double)used / (double)xsize * 100.0,
		    (sw[i].sw_flags & SW_SEQUENTIAL) ?
			     "Sequential" : "Interleaved");
	}
	used = avail - nfree;
	if (totalflag) {
		(void)printf("%dM/%dM swap space\n", used / 2048, avail / 2048);
		return;
	}
	if (npfree > 1) {
		(void)printf("%-11s %*d %8d %8d %5.0f%%\n",
		    "Total", hlen, avail / div, used / div, nfree / div,
		    (double)used / (double)avail * 100.0);
	}
}
void swapmode ( ) { char * header , * p ; int hlen , nswap , nswdev , dmmax , nswapmap , niswap , niswdev ; int s , e , div , i , l , avail , nfree , npfree , used ; struct swdevt * sw ; long blocksize , * perdev ; struct map * swapmap , * kswapmap ; struct mapent * mp ; KGET ( VM_NSWAP , nswap ) ; KGET ( VM_NSWDEV , nswdev ) ; KGET ( VM_DMMAX , dmmax ) ; KGET ( VM_NSWAPMAP , nswapmap ) ; KGET ( VM_SWAPMAP , kswapmap ) ; if ( ( sw = malloc ( nswdev * sizeof ( * sw ) ) ) == NULL || ( perdev = malloc ( nswdev * sizeof ( * perdev ) ) ) == NULL || ( mp = malloc ( nswapmap * sizeof ( * mp ) ) ) == NULL ) err ( 1 , " " ) ; KGET1 ( VM_SWDEVT , sw , nswdev * sizeof ( * sw ) , " " ) ; KGET2 ( ( long ) kswapmap , mp , nswapmap * sizeof ( * mp ) , " " ) ; if ( nl [ VM_NISWAP ] . n_value != 0 ) { KGET ( VM_NISWAP , niswap ) ; KGET ( VM_NISWDEV , niswdev ) ; } else { niswap = nswap ; niswdev = nswdev ; } swapmap = ( struct map * ) mp ; if ( nswapmap != swapmap -> m_limit - ( struct mapent * ) kswapmap ) errx ( 1 , " " ) ; nfree = 0 ; memset ( perdev , 0 , nswdev * sizeof ( * perdev ) ) ; for ( mp ++ ; mp -> m_addr != 0 ; mp ++ ) { s = mp -> m_addr ; e = mp -> m_addr + mp -> m_size ; nfree += mp -> m_size ; i = -1 ; while ( s < e ) { int bound = roundup ( s + 1 , dmmax ) ; if ( bound > e ) bound = e ; if ( bound <= niswap ) { if ( i == -1 ) i = ( s / dmmax ) % niswdev ; perdev [ i ] += bound - s ; if ( ++ i >= niswdev ) i = 0 ; } else { if ( i < niswdev ) { i = niswdev ; l = niswap + sw [ i ] . sw_nblks ; } while ( s >= l ) { if ( i == nswdev - 1 ) break ; l += sw [ ++ i ] . sw_nblks ; } perdev [ i ] += bound - s ; } s = bound ; } } header = getbsize ( & hlen , & blocksize ) ; if ( ! totalflag ) ( void ) printf ( " \n " , " " , hlen , header , " " , " " , " " , " " ) ; div = blocksize / 512 ; avail = npfree = 0 ; for ( i = 0 ; i < nswdev ; i ++ ) { int xsize , xfree ; if ( ! totalflag ) { p = devname ( sw [ i ] . sw_dev , S_IFBLK ) ; ( void ) printf ( " " , p == NULL ? " " : p , hlen , sw [ i ] . sw_nblks / div ) ; } if ( ! ( sw [ i ] . sw_flags & SW_FREED ) ) { if ( totalflag ) continue ; ( void ) printf ( " \n " ) ; continue ; } xsize = sw [ i ] . sw_nblks ; xfree = perdev [ i ] ; used = xsize - xfree ; npfree ++ ; avail += xsize ; if ( totalflag ) continue ; ( void ) printf ( " \n " , used / div , xfree / div , ( double ) used / ( double ) xsize * 100.0 , ( sw [ i ] . sw_flags & SW_SEQUENTIAL ) ? " " : " " ) ; } used = avail - nfree ; if ( totalflag ) { ( void ) printf ( " \n " , used / 2048 , avail / 2048 ) ; return ; } if ( npfree > 1 ) { ( void ) printf ( " \n " , " " , hlen , avail / div , used / div , nfree / div , ( double ) used / ( double ) avail * 100.0 ) ; } }
swapmode is based on a program called swapinfo written
 by Kevin Lahey <kml@rokkaku.atl.ga.us>.
swapmode is based on a program called swapinfo written by Kevin Lahey <kml@rokkaku . atl . ga . us > .
/* kernel `swapmap' is a pointer */ /* Supports sequential swap */ /* First entry in map is `struct map'; rest are mapent's. */ /* Count up swap space. */ /* start of swap region */ /* end of region */ /*
		 * Swap space is split up among the configured disks.
		 *
		 * For interleaved swap devices, the first dmmax blocks
		 * of swap space some from the first disk, the next dmmax
		 * blocks from the next, and so on up to niswap blocks.
		 *
		 * Sequential swap devices follow the interleaved devices
		 * (i.e. blocks starting at niswap) in the order in which
		 * they appear in the swdev table.  The size of each device
		 * will be a multiple of dmmax.
		 *
		 * 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.  We know that dmmax-sized chunks
		 * cannot span device boundaries (interleaved or sequential)
		 * so we loop over such chunks assigning them to devices.
		 */ /* XXX this is inefficient */ /* Interleaved swap chunk. */ /* Sequential swap chunk. */ /* XXX don't die on bogus blocks */ /*
		 * Don't report statistics for partitions which have not
		 * yet been activated via swapon(8).
		 */ /* 
	 * If only one partition has been set up via swapon(8), we don't
	 * need to bother with totals.
	 */