xref: /freebsd/usr.bin/systat/zarc.c (revision 4d846d260e2b9a3d4d0a701462568268cbfe7a5b)
127aa4769SMichael Reifenberger /*-
2*4d846d26SWarner Losh  * SPDX-License-Identifier: BSD-2-Clause
39e16b953SKirk McKusick  *
44bde6353SMichael Reifenberger  * Copyright (c) 2014 - 2017, 2019 Yoshihiro Ota
527aa4769SMichael Reifenberger  *
627aa4769SMichael Reifenberger  * Redistribution and use in source and binary forms, with or without
727aa4769SMichael Reifenberger  * modification, are permitted provided that the following conditions
827aa4769SMichael Reifenberger  * are met:
927aa4769SMichael Reifenberger  * 1. Redistributions of source code must retain the above copyright
1027aa4769SMichael Reifenberger  *    notice, this list of conditions and the following disclaimer.
1127aa4769SMichael Reifenberger  * 2. Redistributions in binary form must reproduce the above copyright
1227aa4769SMichael Reifenberger  *    notice, this list of conditions and the following disclaimer in the
1327aa4769SMichael Reifenberger  *    documentation and/or other materials provided with the distribution.
1427aa4769SMichael Reifenberger  *
159e16b953SKirk McKusick  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1627aa4769SMichael Reifenberger  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1727aa4769SMichael Reifenberger  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
189e16b953SKirk McKusick  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1927aa4769SMichael Reifenberger  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2027aa4769SMichael Reifenberger  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2127aa4769SMichael Reifenberger  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2227aa4769SMichael Reifenberger  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2327aa4769SMichael Reifenberger  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2427aa4769SMichael Reifenberger  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2527aa4769SMichael Reifenberger  * SUCH DAMAGE.
2627aa4769SMichael Reifenberger  */
2727aa4769SMichael Reifenberger 
2827aa4769SMichael Reifenberger #include <sys/cdefs.h>
2927aa4769SMichael Reifenberger __FBSDID("$FreeBSD$");
3027aa4769SMichael Reifenberger 
3127aa4769SMichael Reifenberger #include <sys/types.h>
3227aa4769SMichael Reifenberger #include <sys/sysctl.h>
3327aa4769SMichael Reifenberger 
34970bdbf5SMichael Tuexen #include <inttypes.h>
3527aa4769SMichael Reifenberger #include <string.h>
3645518845SMichael Reifenberger #include <err.h>
374bde6353SMichael Reifenberger #include <libutil.h>
3827aa4769SMichael Reifenberger 
3927aa4769SMichael Reifenberger #include "systat.h"
4027aa4769SMichael Reifenberger #include "extern.h"
4145518845SMichael Reifenberger #include "devs.h"
4227aa4769SMichael Reifenberger 
4327aa4769SMichael Reifenberger struct zfield {
4427aa4769SMichael Reifenberger 	uint64_t arcstats;
4527aa4769SMichael Reifenberger 	uint64_t arcstats_demand_data;
4627aa4769SMichael Reifenberger 	uint64_t arcstats_demand_metadata;
4727aa4769SMichael Reifenberger 	uint64_t arcstats_prefetch_data;
4827aa4769SMichael Reifenberger 	uint64_t arcstats_prefetch_metadata;
4927aa4769SMichael Reifenberger 	uint64_t zfetchstats;
5027aa4769SMichael Reifenberger 	uint64_t arcstats_l2;
5127aa4769SMichael Reifenberger 	uint64_t vdev_cache_stats;
5227aa4769SMichael Reifenberger };
5327aa4769SMichael Reifenberger 
5427aa4769SMichael Reifenberger static struct zarcstats {
5527aa4769SMichael Reifenberger 	struct zfield hits;
5627aa4769SMichael Reifenberger 	struct zfield misses;
5727aa4769SMichael Reifenberger } curstat, initstat, oldstat;
5827aa4769SMichael Reifenberger 
594bde6353SMichael Reifenberger struct zarcrates {
604bde6353SMichael Reifenberger 	struct zfield current;
614bde6353SMichael Reifenberger 	struct zfield total;
624bde6353SMichael Reifenberger };
634bde6353SMichael Reifenberger 
6427aa4769SMichael Reifenberger static void
6527aa4769SMichael Reifenberger getinfo(struct zarcstats *ls);
6627aa4769SMichael Reifenberger 
6727aa4769SMichael Reifenberger WINDOW *
6827aa4769SMichael Reifenberger openzarc(void)
6927aa4769SMichael Reifenberger {
704bde6353SMichael Reifenberger 
7127aa4769SMichael Reifenberger 	return (subwin(stdscr, LINES - 3 - 1, 0, MAINWIN_ROW, 0));
7227aa4769SMichael Reifenberger }
7327aa4769SMichael Reifenberger 
7427aa4769SMichael Reifenberger void
7527aa4769SMichael Reifenberger closezarc(WINDOW *w)
7627aa4769SMichael Reifenberger {
774bde6353SMichael Reifenberger 
7827aa4769SMichael Reifenberger 	if (w == NULL)
7927aa4769SMichael Reifenberger 		return;
8027aa4769SMichael Reifenberger 	wclear(w);
8127aa4769SMichael Reifenberger 	wrefresh(w);
8227aa4769SMichael Reifenberger 	delwin(w);
8327aa4769SMichael Reifenberger }
8427aa4769SMichael Reifenberger 
8527aa4769SMichael Reifenberger void
8627aa4769SMichael Reifenberger labelzarc(void)
8727aa4769SMichael Reifenberger {
8845518845SMichael Reifenberger 	int row = 1;
894bde6353SMichael Reifenberger 
9027aa4769SMichael Reifenberger 	wmove(wnd, 0, 0); wclrtoeol(wnd);
914bde6353SMichael Reifenberger 	mvwprintw(wnd, 0, 31+1, "%4.4s %6.6s %6.6s | Total %4.4s %6.6s %6.6s",
924bde6353SMichael Reifenberger 		"Rate", "Hits", "Misses", "Rate", "Hits", "Misses");
934bde6353SMichael Reifenberger #define L(str) mvwprintw(wnd, row++, 5, \
944bde6353SMichael Reifenberger 		"%-26.26s:   %%               |          %%", #str)
9545518845SMichael Reifenberger 	L(arcstats);
9645518845SMichael Reifenberger 	L(arcstats.demand_data);
9745518845SMichael Reifenberger 	L(arcstats.demand_metadata);
9845518845SMichael Reifenberger 	L(arcstats.prefetch_data);
9945518845SMichael Reifenberger 	L(arcstats.prefetch_metadata);
10045518845SMichael Reifenberger 	L(zfetchstats);
10145518845SMichael Reifenberger 	L(arcstats.l2);
10245518845SMichael Reifenberger 	L(vdev_cache_stats);
10327aa4769SMichael Reifenberger #undef L
10445518845SMichael Reifenberger 	dslabel(12, 0, 18);
10527aa4769SMichael Reifenberger }
10627aa4769SMichael Reifenberger 
1074bde6353SMichael Reifenberger static int
1084bde6353SMichael Reifenberger calc_rate(uint64_t hits, uint64_t misses)
10927aa4769SMichael Reifenberger {
11027aa4769SMichael Reifenberger     if(hits)
11127aa4769SMichael Reifenberger 	return 100 * hits / (hits + misses);
11227aa4769SMichael Reifenberger     else
11327aa4769SMichael Reifenberger 	return 0;
11427aa4769SMichael Reifenberger }
11527aa4769SMichael Reifenberger 
11627aa4769SMichael Reifenberger static void
1174bde6353SMichael Reifenberger domode(struct zarcstats *delta, struct zarcrates *rate)
11827aa4769SMichael Reifenberger {
11927aa4769SMichael Reifenberger #define DO(stat) \
12027aa4769SMichael Reifenberger 	delta->hits.stat = (curstat.hits.stat - oldstat.hits.stat); \
12127aa4769SMichael Reifenberger 	delta->misses.stat = (curstat.misses.stat - oldstat.misses.stat); \
1224bde6353SMichael Reifenberger 	rate->current.stat = calc_rate(delta->hits.stat, delta->misses.stat); \
1234bde6353SMichael Reifenberger 	rate->total.stat = calc_rate(curstat.hits.stat, curstat.misses.stat)
12427aa4769SMichael Reifenberger 	DO(arcstats);
12527aa4769SMichael Reifenberger 	DO(arcstats_demand_data);
12627aa4769SMichael Reifenberger 	DO(arcstats_demand_metadata);
12727aa4769SMichael Reifenberger 	DO(arcstats_prefetch_data);
12827aa4769SMichael Reifenberger 	DO(arcstats_prefetch_metadata);
12927aa4769SMichael Reifenberger 	DO(zfetchstats);
13027aa4769SMichael Reifenberger 	DO(arcstats_l2);
13127aa4769SMichael Reifenberger 	DO(vdev_cache_stats);
13227aa4769SMichael Reifenberger 	DO(arcstats);
13327aa4769SMichael Reifenberger 	DO(arcstats_demand_data);
13427aa4769SMichael Reifenberger 	DO(arcstats_demand_metadata);
13527aa4769SMichael Reifenberger 	DO(arcstats_prefetch_data);
13627aa4769SMichael Reifenberger 	DO(arcstats_prefetch_metadata);
13727aa4769SMichael Reifenberger 	DO(zfetchstats);
13827aa4769SMichael Reifenberger 	DO(arcstats_l2);
13927aa4769SMichael Reifenberger 	DO(vdev_cache_stats);
14027aa4769SMichael Reifenberger #undef DO
14127aa4769SMichael Reifenberger }
14227aa4769SMichael Reifenberger 
14327aa4769SMichael Reifenberger void
14427aa4769SMichael Reifenberger showzarc(void)
14527aa4769SMichael Reifenberger {
14645518845SMichael Reifenberger 	int row = 1;
1474bde6353SMichael Reifenberger 	struct zarcstats delta = {};
1484bde6353SMichael Reifenberger 	struct zarcrates rate = {};
14927aa4769SMichael Reifenberger 
15027aa4769SMichael Reifenberger 	domode(&delta, &rate);
15127aa4769SMichael Reifenberger 
1524bde6353SMichael Reifenberger #define DO(stat, col, width) \
1534bde6353SMichael Reifenberger 	sysputuint64(wnd, row, col, width, stat, HN_DIVISOR_1000)
1544bde6353SMichael Reifenberger #define	RATES(stat) mvwprintw(wnd, row, 31+1, "%3"PRIu64, rate.current.stat);\
1554bde6353SMichael Reifenberger 	mvwprintw(wnd, row, 31+1+5+7+7+8, "%3"PRIu64, rate.total.stat)
1564bde6353SMichael Reifenberger #define	HITS(stat) DO(delta.hits.stat, 31+1+5, 6); \
1574bde6353SMichael Reifenberger 	DO(curstat.hits.stat, 31+1+5+7+7+8+5, 6)
1584bde6353SMichael Reifenberger #define	MISSES(stat) DO(delta.misses.stat, 31+1+5+7, 6); \
1594bde6353SMichael Reifenberger 	DO(curstat.misses.stat, 31+1+5+7+7+8+5+7, 6)
1604bde6353SMichael Reifenberger #define	E(stat) RATES(stat); HITS(stat); MISSES(stat); ++row
16145518845SMichael Reifenberger 	E(arcstats);
16245518845SMichael Reifenberger 	E(arcstats_demand_data);
16345518845SMichael Reifenberger 	E(arcstats_demand_metadata);
16445518845SMichael Reifenberger 	E(arcstats_prefetch_data);
16545518845SMichael Reifenberger 	E(arcstats_prefetch_metadata);
16645518845SMichael Reifenberger 	E(zfetchstats);
16745518845SMichael Reifenberger 	E(arcstats_l2);
16845518845SMichael Reifenberger 	E(vdev_cache_stats);
16927aa4769SMichael Reifenberger #undef DO
17027aa4769SMichael Reifenberger #undef E
1714bde6353SMichael Reifenberger #undef MISSES
1724bde6353SMichael Reifenberger #undef HITS
1734bde6353SMichael Reifenberger #undef RATES
17445518845SMichael Reifenberger 	dsshow(12, 0, 18, &cur_dev, &last_dev);
17527aa4769SMichael Reifenberger }
17627aa4769SMichael Reifenberger 
17727aa4769SMichael Reifenberger int
17827aa4769SMichael Reifenberger initzarc(void)
17927aa4769SMichael Reifenberger {
18045518845SMichael Reifenberger 	dsinit(12);
18127aa4769SMichael Reifenberger 	getinfo(&initstat);
18227aa4769SMichael Reifenberger 	curstat = oldstat = initstat;
18345518845SMichael Reifenberger 
18427aa4769SMichael Reifenberger 	return 1;
18527aa4769SMichael Reifenberger }
18627aa4769SMichael Reifenberger 
18727aa4769SMichael Reifenberger void
18827aa4769SMichael Reifenberger resetzarc(void)
18927aa4769SMichael Reifenberger {
1904bde6353SMichael Reifenberger 
19127aa4769SMichael Reifenberger 	initzarc();
19227aa4769SMichael Reifenberger }
19327aa4769SMichael Reifenberger 
19427aa4769SMichael Reifenberger static void
19527aa4769SMichael Reifenberger getinfo(struct zarcstats *ls)
19627aa4769SMichael Reifenberger {
19745518845SMichael Reifenberger 	struct devinfo *tmp_dinfo;
19845518845SMichael Reifenberger 
19945518845SMichael Reifenberger 	tmp_dinfo = last_dev.dinfo;
20045518845SMichael Reifenberger 	last_dev.dinfo = cur_dev.dinfo;
20145518845SMichael Reifenberger 	cur_dev.dinfo = tmp_dinfo;
20245518845SMichael Reifenberger 
20345518845SMichael Reifenberger 	last_dev.snap_time = cur_dev.snap_time;
20445518845SMichael Reifenberger 	dsgetinfo(&cur_dev);
20545518845SMichael Reifenberger 
20627aa4769SMichael Reifenberger 	size_t size = sizeof(ls->hits.arcstats);
20727aa4769SMichael Reifenberger 	if (sysctlbyname("kstat.zfs.misc.arcstats.hits",
20827aa4769SMichael Reifenberger 		&ls->hits.arcstats, &size, NULL, 0) != 0)
20927aa4769SMichael Reifenberger 		return;
21027aa4769SMichael Reifenberger 	GETSYSCTL("kstat.zfs.misc.arcstats.misses",
21127aa4769SMichael Reifenberger 		ls->misses.arcstats);
21227aa4769SMichael Reifenberger 	GETSYSCTL("kstat.zfs.misc.arcstats.demand_data_hits",
21327aa4769SMichael Reifenberger 		ls->hits.arcstats_demand_data);
21427aa4769SMichael Reifenberger 	GETSYSCTL("kstat.zfs.misc.arcstats.demand_data_misses",
21527aa4769SMichael Reifenberger 		ls->misses.arcstats_demand_data);
21627aa4769SMichael Reifenberger 	GETSYSCTL("kstat.zfs.misc.arcstats.demand_metadata_hits",
21727aa4769SMichael Reifenberger 		ls->hits.arcstats_demand_metadata);
21827aa4769SMichael Reifenberger 	GETSYSCTL("kstat.zfs.misc.arcstats.demand_metadata_misses",
21927aa4769SMichael Reifenberger 		ls->misses.arcstats_demand_metadata);
22027aa4769SMichael Reifenberger 	GETSYSCTL("kstat.zfs.misc.arcstats.prefetch_data_hits",
22127aa4769SMichael Reifenberger 		ls->hits.arcstats_prefetch_data);
22227aa4769SMichael Reifenberger 	GETSYSCTL("kstat.zfs.misc.arcstats.prefetch_data_misses",
22327aa4769SMichael Reifenberger 		ls->misses.arcstats_prefetch_data);
22427aa4769SMichael Reifenberger 	GETSYSCTL("kstat.zfs.misc.arcstats.prefetch_metadata_hits",
22527aa4769SMichael Reifenberger 		ls->hits.arcstats_prefetch_metadata);
22627aa4769SMichael Reifenberger 	GETSYSCTL("kstat.zfs.misc.arcstats.prefetch_metadata_misses",
22727aa4769SMichael Reifenberger 		ls->misses.arcstats_prefetch_metadata);
22827aa4769SMichael Reifenberger 	GETSYSCTL("kstat.zfs.misc.zfetchstats.hits",
22927aa4769SMichael Reifenberger 		ls->hits.zfetchstats);
23027aa4769SMichael Reifenberger 	GETSYSCTL("kstat.zfs.misc.zfetchstats.misses",
23127aa4769SMichael Reifenberger 		ls->misses.zfetchstats);
23227aa4769SMichael Reifenberger 	GETSYSCTL("kstat.zfs.misc.arcstats.l2_hits",
23327aa4769SMichael Reifenberger 		ls->hits.arcstats_l2);
23427aa4769SMichael Reifenberger 	GETSYSCTL("kstat.zfs.misc.arcstats.l2_misses",
23527aa4769SMichael Reifenberger 		ls->misses.arcstats_l2);
23627aa4769SMichael Reifenberger 	GETSYSCTL("kstat.zfs.misc.vdev_cache_stats.hits",
23727aa4769SMichael Reifenberger 		ls->hits.vdev_cache_stats);
23827aa4769SMichael Reifenberger 	GETSYSCTL("kstat.zfs.misc.vdev_cache_stats.misses",
23927aa4769SMichael Reifenberger 		ls->misses.vdev_cache_stats);
24027aa4769SMichael Reifenberger }
24127aa4769SMichael Reifenberger 
24227aa4769SMichael Reifenberger void
24327aa4769SMichael Reifenberger fetchzarc(void)
24427aa4769SMichael Reifenberger {
2454bde6353SMichael Reifenberger 
24627aa4769SMichael Reifenberger 	oldstat = curstat;
24727aa4769SMichael Reifenberger 	getinfo(&curstat);
24827aa4769SMichael Reifenberger }
249