1288306Smr/*-
2368931Smr * Copyright (c) 2014 - 2017, 2019 Yoshihiro Ota
3288306Smr *
4288306Smr * Redistribution and use in source and binary forms, with or without
5288306Smr * modification, are permitted provided that the following conditions
6288306Smr * are met:
7288306Smr * 1. Redistributions of source code must retain the above copyright
8288306Smr *    notice, this list of conditions and the following disclaimer.
9288306Smr * 2. Redistributions in binary form must reproduce the above copyright
10288306Smr *    notice, this list of conditions and the following disclaimer in the
11288306Smr *    documentation and/or other materials provided with the distribution.
12288306Smr * 4. Neither the name of the University nor the names of its contributors
13288306Smr *    may be used to endorse or promote products derived from this software
14288306Smr *    without specific prior written permission.
15288306Smr *
16288306Smr * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
17288306Smr * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18288306Smr * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19288306Smr * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
20288306Smr * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21288306Smr * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22288306Smr * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23288306Smr * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24288306Smr * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25288306Smr * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26288306Smr * SUCH DAMAGE.
27288306Smr */
28288306Smr
29288306Smr#include <sys/cdefs.h>
30288306Smr__FBSDID("$FreeBSD: stable/11/usr.bin/systat/zarc.c 368931 2021-01-05 20:02:55Z mr $");
31288306Smr
32288306Smr#include <sys/types.h>
33288306Smr#include <sys/sysctl.h>
34288306Smr
35368931Smr#include <inttypes.h>
36288306Smr#include <string.h>
37368931Smr#include <err.h>
38368931Smr#include <libutil.h>
39288306Smr
40288306Smr#include "systat.h"
41288306Smr#include "extern.h"
42368931Smr#include "devs.h"
43288306Smr
44368931Smrstruct zfield {
45288306Smr	uint64_t arcstats;
46288306Smr	uint64_t arcstats_demand_data;
47288306Smr	uint64_t arcstats_demand_metadata;
48288306Smr	uint64_t arcstats_prefetch_data;
49288306Smr	uint64_t arcstats_prefetch_metadata;
50288306Smr	uint64_t zfetchstats;
51288306Smr	uint64_t arcstats_l2;
52288306Smr	uint64_t vdev_cache_stats;
53288306Smr};
54288306Smr
55288306Smrstatic struct zarcstats {
56288306Smr	struct zfield hits;
57288306Smr	struct zfield misses;
58288306Smr} curstat, initstat, oldstat;
59288306Smr
60368931Smrstruct zarcrates {
61368931Smr	struct zfield current;
62368931Smr	struct zfield total;
63368931Smr};
64368931Smr
65288306Smrstatic void
66288306Smrgetinfo(struct zarcstats *ls);
67288306Smr
68288306SmrWINDOW *
69288306Smropenzarc(void)
70288306Smr{
71368931Smr
72368931Smr	return (subwin(stdscr, LINES - 3 - 1, 0, MAINWIN_ROW, 0));
73288306Smr}
74288306Smr
75288306Smrvoid
76288306Smrclosezarc(WINDOW *w)
77288306Smr{
78368931Smr
79288306Smr	if (w == NULL)
80288306Smr		return;
81288306Smr	wclear(w);
82288306Smr	wrefresh(w);
83288306Smr	delwin(w);
84288306Smr}
85288306Smr
86288306Smrvoid
87288306Smrlabelzarc(void)
88288306Smr{
89368931Smr	int row = 1;
90368931Smr
91288306Smr	wmove(wnd, 0, 0); wclrtoeol(wnd);
92368931Smr	mvwprintw(wnd, 0, 31+1, "%4.4s %6.6s %6.6s | Total %4.4s %6.6s %6.6s",
93368931Smr		"Rate", "Hits", "Misses", "Rate", "Hits", "Misses");
94368931Smr#define L(str) mvwprintw(wnd, row++, 5, \
95368931Smr		"%-26.26s:   %%               |          %%", #str)
96368931Smr	L(arcstats);
97368931Smr	L(arcstats.demand_data);
98368931Smr	L(arcstats.demand_metadata);
99368931Smr	L(arcstats.prefetch_data);
100368931Smr	L(arcstats.prefetch_metadata);
101368931Smr	L(zfetchstats);
102368931Smr	L(arcstats.l2);
103368931Smr	L(vdev_cache_stats);
104288306Smr#undef L
105368931Smr	dslabel(12, 0, 18);
106288306Smr}
107288306Smr
108368931Smrstatic int
109368931Smrcalc_rate(uint64_t hits, uint64_t misses)
110288306Smr{
111368931Smr    if(hits)
112368931Smr	return 100 * hits / (hits + misses);
113288306Smr    else
114288306Smr	return 0;
115288306Smr}
116288306Smr
117288306Smrstatic void
118368931Smrdomode(struct zarcstats *delta, struct zarcrates *rate)
119288306Smr{
120288306Smr#define DO(stat) \
121288306Smr	delta->hits.stat = (curstat.hits.stat - oldstat.hits.stat); \
122288306Smr	delta->misses.stat = (curstat.misses.stat - oldstat.misses.stat); \
123368931Smr	rate->current.stat = calc_rate(delta->hits.stat, delta->misses.stat); \
124368931Smr	rate->total.stat = calc_rate(curstat.hits.stat, curstat.misses.stat)
125288306Smr	DO(arcstats);
126288306Smr	DO(arcstats_demand_data);
127288306Smr	DO(arcstats_demand_metadata);
128288306Smr	DO(arcstats_prefetch_data);
129288306Smr	DO(arcstats_prefetch_metadata);
130288306Smr	DO(zfetchstats);
131288306Smr	DO(arcstats_l2);
132288306Smr	DO(vdev_cache_stats);
133288306Smr	DO(arcstats);
134288306Smr	DO(arcstats_demand_data);
135288306Smr	DO(arcstats_demand_metadata);
136288306Smr	DO(arcstats_prefetch_data);
137288306Smr	DO(arcstats_prefetch_metadata);
138288306Smr	DO(zfetchstats);
139288306Smr	DO(arcstats_l2);
140288306Smr	DO(vdev_cache_stats);
141288306Smr#undef DO
142288306Smr}
143288306Smr
144288306Smrvoid
145288306Smrshowzarc(void)
146288306Smr{
147368931Smr	int row = 1;
148368931Smr	struct zarcstats delta = {};
149368931Smr	struct zarcrates rate = {};
150288306Smr
151288306Smr	domode(&delta, &rate);
152288306Smr
153368931Smr#define DO(stat, col, width) \
154368931Smr	sysputuint64(wnd, row, col, width, stat, HN_DIVISOR_1000)
155368931Smr#define	RATES(stat) mvwprintw(wnd, row, 31+1, "%3"PRIu64, rate.current.stat);\
156368931Smr	mvwprintw(wnd, row, 31+1+5+7+7+8, "%3"PRIu64, rate.total.stat)
157368931Smr#define	HITS(stat) DO(delta.hits.stat, 31+1+5, 6); \
158368931Smr	DO(curstat.hits.stat, 31+1+5+7+7+8+5, 6)
159368931Smr#define	MISSES(stat) DO(delta.misses.stat, 31+1+5+7, 6); \
160368931Smr	DO(curstat.misses.stat, 31+1+5+7+7+8+5+7, 6)
161368931Smr#define	E(stat) RATES(stat); HITS(stat); MISSES(stat); ++row
162368931Smr	E(arcstats);
163368931Smr	E(arcstats_demand_data);
164368931Smr	E(arcstats_demand_metadata);
165368931Smr	E(arcstats_prefetch_data);
166368931Smr	E(arcstats_prefetch_metadata);
167368931Smr	E(zfetchstats);
168368931Smr	E(arcstats_l2);
169368931Smr	E(vdev_cache_stats);
170288306Smr#undef DO
171288306Smr#undef E
172368931Smr#undef MISSES
173368931Smr#undef HITS
174368931Smr#undef RATES
175368931Smr	dsshow(12, 0, 18, &cur_dev, &last_dev);
176288306Smr}
177288306Smr
178288306Smrint
179288306Smrinitzarc(void)
180288306Smr{
181368931Smr	dsinit(12);
182288306Smr	getinfo(&initstat);
183288306Smr	curstat = oldstat = initstat;
184368931Smr
185288306Smr	return 1;
186288306Smr}
187288306Smr
188288306Smrvoid
189288306Smrresetzarc(void)
190288306Smr{
191368931Smr
192288306Smr	initzarc();
193288306Smr}
194288306Smr
195288306Smrstatic void
196288306Smrgetinfo(struct zarcstats *ls)
197288306Smr{
198368931Smr	struct devinfo *tmp_dinfo;
199368931Smr
200368931Smr	tmp_dinfo = last_dev.dinfo;
201368931Smr	last_dev.dinfo = cur_dev.dinfo;
202368931Smr	cur_dev.dinfo = tmp_dinfo;
203368931Smr
204368931Smr	last_dev.snap_time = cur_dev.snap_time;
205368931Smr	dsgetinfo(&cur_dev);
206368931Smr
207368931Smr	size_t size = sizeof(ls->hits.arcstats);
208368931Smr	if (sysctlbyname("kstat.zfs.misc.arcstats.hits",
209368931Smr		&ls->hits.arcstats, &size, NULL, 0) != 0)
210288306Smr		return;
211288306Smr	GETSYSCTL("kstat.zfs.misc.arcstats.misses",
212288306Smr		ls->misses.arcstats);
213288306Smr	GETSYSCTL("kstat.zfs.misc.arcstats.demand_data_hits",
214288306Smr		ls->hits.arcstats_demand_data);
215288306Smr	GETSYSCTL("kstat.zfs.misc.arcstats.demand_data_misses",
216288306Smr		ls->misses.arcstats_demand_data);
217288306Smr	GETSYSCTL("kstat.zfs.misc.arcstats.demand_metadata_hits",
218288306Smr		ls->hits.arcstats_demand_metadata);
219288306Smr	GETSYSCTL("kstat.zfs.misc.arcstats.demand_metadata_misses",
220288306Smr		ls->misses.arcstats_demand_metadata);
221288306Smr	GETSYSCTL("kstat.zfs.misc.arcstats.prefetch_data_hits",
222288306Smr		ls->hits.arcstats_prefetch_data);
223288306Smr	GETSYSCTL("kstat.zfs.misc.arcstats.prefetch_data_misses",
224288306Smr		ls->misses.arcstats_prefetch_data);
225288306Smr	GETSYSCTL("kstat.zfs.misc.arcstats.prefetch_metadata_hits",
226288306Smr		ls->hits.arcstats_prefetch_metadata);
227288306Smr	GETSYSCTL("kstat.zfs.misc.arcstats.prefetch_metadata_misses",
228288306Smr		ls->misses.arcstats_prefetch_metadata);
229288306Smr	GETSYSCTL("kstat.zfs.misc.zfetchstats.hits",
230288306Smr		ls->hits.zfetchstats);
231288306Smr	GETSYSCTL("kstat.zfs.misc.zfetchstats.misses",
232288306Smr		ls->misses.zfetchstats);
233288306Smr	GETSYSCTL("kstat.zfs.misc.arcstats.l2_hits",
234288306Smr		ls->hits.arcstats_l2);
235288306Smr	GETSYSCTL("kstat.zfs.misc.arcstats.l2_misses",
236288306Smr		ls->misses.arcstats_l2);
237288306Smr	GETSYSCTL("kstat.zfs.misc.vdev_cache_stats.hits",
238288306Smr		ls->hits.vdev_cache_stats);
239288306Smr	GETSYSCTL("kstat.zfs.misc.vdev_cache_stats.misses",
240288306Smr		ls->misses.vdev_cache_stats);
241288306Smr}
242288306Smr
243288306Smrvoid
244288306Smrfetchzarc(void)
245288306Smr{
246368931Smr
247288306Smr	oldstat = curstat;
248288306Smr	getinfo(&curstat);
249288306Smr}
250