1/*-
2 * SPDX-License-Identifier: BSD-2-Clause
3 *
4 * Copyright (c) 2014 - 2017, 2019 Yoshihiro Ota
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 */
27
28#include <sys/types.h>
29#include <sys/sysctl.h>
30
31#include <inttypes.h>
32#include <string.h>
33#include <err.h>
34#include <libutil.h>
35
36#include "systat.h"
37#include "extern.h"
38#include "devs.h"
39
40struct zfield {
41	uint64_t arcstats;
42	uint64_t arcstats_demand_data;
43	uint64_t arcstats_demand_metadata;
44	uint64_t arcstats_prefetch_data;
45	uint64_t arcstats_prefetch_metadata;
46	uint64_t zfetchstats;
47	uint64_t arcstats_l2;
48};
49
50static struct zarcstats {
51	struct zfield hits;
52	struct zfield misses;
53} curstat, initstat, oldstat;
54
55struct zarcrates {
56	struct zfield current;
57	struct zfield total;
58};
59
60static void
61getinfo(struct zarcstats *ls);
62
63WINDOW *
64openzarc(void)
65{
66
67	return (subwin(stdscr, LINES - 3 - 1, 0, MAINWIN_ROW, 0));
68}
69
70void
71closezarc(WINDOW *w)
72{
73
74	if (w == NULL)
75		return;
76	wclear(w);
77	wrefresh(w);
78	delwin(w);
79}
80
81void
82labelzarc(void)
83{
84	int row = 1;
85
86	wmove(wnd, 0, 0); wclrtoeol(wnd);
87	mvwprintw(wnd, 0, 31+1, "%4.4s %6.6s %6.6s | Total %4.4s %6.6s %6.6s",
88		"Rate", "Hits", "Misses", "Rate", "Hits", "Misses");
89#define L(str) mvwprintw(wnd, row++, 5, \
90		"%-26.26s:   %%               |          %%", #str)
91	L(arcstats);
92	L(arcstats.demand_data);
93	L(arcstats.demand_metadata);
94	L(arcstats.prefetch_data);
95	L(arcstats.prefetch_metadata);
96	L(zfetchstats);
97	L(arcstats.l2);
98#undef L
99	dslabel(12, 0, 18);
100}
101
102static int
103calc_rate(uint64_t hits, uint64_t misses)
104{
105    if(hits)
106	return 100 * hits / (hits + misses);
107    else
108	return 0;
109}
110
111static void
112domode(struct zarcstats *delta, struct zarcrates *rate)
113{
114#define DO(stat) \
115	delta->hits.stat = (curstat.hits.stat - oldstat.hits.stat); \
116	delta->misses.stat = (curstat.misses.stat - oldstat.misses.stat); \
117	rate->current.stat = calc_rate(delta->hits.stat, delta->misses.stat); \
118	rate->total.stat = calc_rate(curstat.hits.stat, curstat.misses.stat)
119	DO(arcstats);
120	DO(arcstats_demand_data);
121	DO(arcstats_demand_metadata);
122	DO(arcstats_prefetch_data);
123	DO(arcstats_prefetch_metadata);
124	DO(zfetchstats);
125	DO(arcstats_l2);
126	DO(arcstats);
127	DO(arcstats_demand_data);
128	DO(arcstats_demand_metadata);
129	DO(arcstats_prefetch_data);
130	DO(arcstats_prefetch_metadata);
131	DO(zfetchstats);
132	DO(arcstats_l2);
133#undef DO
134}
135
136void
137showzarc(void)
138{
139	int row = 1;
140	struct zarcstats delta = {};
141	struct zarcrates rate = {};
142
143	domode(&delta, &rate);
144
145#define DO(stat, col, width) \
146	sysputuint64(wnd, row, col, width, stat, HN_DIVISOR_1000)
147#define	RATES(stat) mvwprintw(wnd, row, 31+1, "%3"PRIu64, rate.current.stat);\
148	mvwprintw(wnd, row, 31+1+5+7+7+8, "%3"PRIu64, rate.total.stat)
149#define	HITS(stat) DO(delta.hits.stat, 31+1+5, 6); \
150	DO(curstat.hits.stat, 31+1+5+7+7+8+5, 6)
151#define	MISSES(stat) DO(delta.misses.stat, 31+1+5+7, 6); \
152	DO(curstat.misses.stat, 31+1+5+7+7+8+5+7, 6)
153#define	E(stat) RATES(stat); HITS(stat); MISSES(stat); ++row
154	E(arcstats);
155	E(arcstats_demand_data);
156	E(arcstats_demand_metadata);
157	E(arcstats_prefetch_data);
158	E(arcstats_prefetch_metadata);
159	E(zfetchstats);
160	E(arcstats_l2);
161#undef DO
162#undef E
163#undef MISSES
164#undef HITS
165#undef RATES
166	dsshow(12, 0, 18, &cur_dev, &last_dev);
167}
168
169int
170initzarc(void)
171{
172	dsinit(12);
173	getinfo(&initstat);
174	curstat = oldstat = initstat;
175
176	return 1;
177}
178
179void
180resetzarc(void)
181{
182
183	initzarc();
184}
185
186static void
187getinfo(struct zarcstats *ls)
188{
189	struct devinfo *tmp_dinfo;
190
191	tmp_dinfo = last_dev.dinfo;
192	last_dev.dinfo = cur_dev.dinfo;
193	cur_dev.dinfo = tmp_dinfo;
194
195	last_dev.snap_time = cur_dev.snap_time;
196	dsgetinfo(&cur_dev);
197
198	size_t size = sizeof(ls->hits.arcstats);
199	if (sysctlbyname("kstat.zfs.misc.arcstats.hits",
200		&ls->hits.arcstats, &size, NULL, 0) != 0)
201		return;
202	GETSYSCTL("kstat.zfs.misc.arcstats.misses",
203		ls->misses.arcstats);
204	GETSYSCTL("kstat.zfs.misc.arcstats.demand_data_hits",
205		ls->hits.arcstats_demand_data);
206	GETSYSCTL("kstat.zfs.misc.arcstats.demand_data_misses",
207		ls->misses.arcstats_demand_data);
208	GETSYSCTL("kstat.zfs.misc.arcstats.demand_metadata_hits",
209		ls->hits.arcstats_demand_metadata);
210	GETSYSCTL("kstat.zfs.misc.arcstats.demand_metadata_misses",
211		ls->misses.arcstats_demand_metadata);
212	GETSYSCTL("kstat.zfs.misc.arcstats.prefetch_data_hits",
213		ls->hits.arcstats_prefetch_data);
214	GETSYSCTL("kstat.zfs.misc.arcstats.prefetch_data_misses",
215		ls->misses.arcstats_prefetch_data);
216	GETSYSCTL("kstat.zfs.misc.arcstats.prefetch_metadata_hits",
217		ls->hits.arcstats_prefetch_metadata);
218	GETSYSCTL("kstat.zfs.misc.arcstats.prefetch_metadata_misses",
219		ls->misses.arcstats_prefetch_metadata);
220	GETSYSCTL("kstat.zfs.misc.zfetchstats.hits",
221		ls->hits.zfetchstats);
222	GETSYSCTL("kstat.zfs.misc.zfetchstats.misses",
223		ls->misses.zfetchstats);
224	GETSYSCTL("kstat.zfs.misc.arcstats.l2_hits",
225		ls->hits.arcstats_l2);
226	GETSYSCTL("kstat.zfs.misc.arcstats.l2_misses",
227		ls->misses.arcstats_l2);
228}
229
230void
231fetchzarc(void)
232{
233
234	oldstat = curstat;
235	getinfo(&curstat);
236}
237