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/cdefs.h>
29 #include <sys/types.h>
30 #include <sys/sysctl.h>
31
32 #include <inttypes.h>
33 #include <string.h>
34 #include <err.h>
35 #include <libutil.h>
36
37 #include "systat.h"
38 #include "extern.h"
39 #include "devs.h"
40
41 struct zfield {
42 uint64_t arcstats;
43 uint64_t arcstats_demand_data;
44 uint64_t arcstats_demand_metadata;
45 uint64_t arcstats_prefetch_data;
46 uint64_t arcstats_prefetch_metadata;
47 uint64_t zfetchstats;
48 uint64_t arcstats_l2;
49 };
50
51 static struct zarcstats {
52 struct zfield hits;
53 struct zfield misses;
54 } curstat, initstat, oldstat;
55
56 struct zarcrates {
57 struct zfield current;
58 struct zfield total;
59 };
60
61 static void
62 getinfo(struct zarcstats *ls);
63
64 WINDOW *
openzarc(void)65 openzarc(void)
66 {
67
68 return (subwin(stdscr, LINES - 3 - 1, 0, MAINWIN_ROW, 0));
69 }
70
71 void
closezarc(WINDOW * w)72 closezarc(WINDOW *w)
73 {
74
75 if (w == NULL)
76 return;
77 wclear(w);
78 wrefresh(w);
79 delwin(w);
80 }
81
82 void
labelzarc(void)83 labelzarc(void)
84 {
85 int row = 1;
86
87 wmove(wnd, 0, 0); wclrtoeol(wnd);
88 mvwprintw(wnd, 0, 31+1, "%4.4s %6.6s %6.6s | Total %4.4s %6.6s %6.6s",
89 "Rate", "Hits", "Misses", "Rate", "Hits", "Misses");
90 #define L(str) mvwprintw(wnd, row++, 5, \
91 "%-26.26s: %% | %%", #str)
92 L(arcstats);
93 L(arcstats.demand_data);
94 L(arcstats.demand_metadata);
95 L(arcstats.prefetch_data);
96 L(arcstats.prefetch_metadata);
97 L(zfetchstats);
98 L(arcstats.l2);
99 #undef L
100 dslabel(12, 0, 18);
101 }
102
103 static int
calc_rate(uint64_t hits,uint64_t misses)104 calc_rate(uint64_t hits, uint64_t misses)
105 {
106 if(hits)
107 return 100 * hits / (hits + misses);
108 else
109 return 0;
110 }
111
112 static void
domode(struct zarcstats * delta,struct zarcrates * rate)113 domode(struct zarcstats *delta, struct zarcrates *rate)
114 {
115 #define DO(stat) \
116 delta->hits.stat = (curstat.hits.stat - oldstat.hits.stat); \
117 delta->misses.stat = (curstat.misses.stat - oldstat.misses.stat); \
118 rate->current.stat = calc_rate(delta->hits.stat, delta->misses.stat); \
119 rate->total.stat = calc_rate(curstat.hits.stat, curstat.misses.stat)
120 DO(arcstats);
121 DO(arcstats_demand_data);
122 DO(arcstats_demand_metadata);
123 DO(arcstats_prefetch_data);
124 DO(arcstats_prefetch_metadata);
125 DO(zfetchstats);
126 DO(arcstats_l2);
127 DO(arcstats);
128 DO(arcstats_demand_data);
129 DO(arcstats_demand_metadata);
130 DO(arcstats_prefetch_data);
131 DO(arcstats_prefetch_metadata);
132 DO(zfetchstats);
133 DO(arcstats_l2);
134 #undef DO
135 }
136
137 void
showzarc(void)138 showzarc(void)
139 {
140 int row = 1;
141 struct zarcstats delta = {};
142 struct zarcrates rate = {};
143
144 domode(&delta, &rate);
145
146 #define DO(stat, col, width) \
147 sysputuint64(wnd, row, col, width, stat, HN_DIVISOR_1000)
148 #define RATES(stat) mvwprintw(wnd, row, 31+1, "%3"PRIu64, rate.current.stat);\
149 mvwprintw(wnd, row, 31+1+5+7+7+8, "%3"PRIu64, rate.total.stat)
150 #define HITS(stat) DO(delta.hits.stat, 31+1+5, 6); \
151 DO(curstat.hits.stat, 31+1+5+7+7+8+5, 6)
152 #define MISSES(stat) DO(delta.misses.stat, 31+1+5+7, 6); \
153 DO(curstat.misses.stat, 31+1+5+7+7+8+5+7, 6)
154 #define E(stat) RATES(stat); HITS(stat); MISSES(stat); ++row
155 E(arcstats);
156 E(arcstats_demand_data);
157 E(arcstats_demand_metadata);
158 E(arcstats_prefetch_data);
159 E(arcstats_prefetch_metadata);
160 E(zfetchstats);
161 E(arcstats_l2);
162 #undef DO
163 #undef E
164 #undef MISSES
165 #undef HITS
166 #undef RATES
167 dsshow(12, 0, 18, &cur_dev, &last_dev);
168 }
169
170 int
initzarc(void)171 initzarc(void)
172 {
173 dsinit(12);
174 getinfo(&initstat);
175 curstat = oldstat = initstat;
176
177 return 1;
178 }
179
180 void
resetzarc(void)181 resetzarc(void)
182 {
183
184 initzarc();
185 }
186
187 static void
getinfo(struct zarcstats * ls)188 getinfo(struct zarcstats *ls)
189 {
190 struct devinfo *tmp_dinfo;
191
192 tmp_dinfo = last_dev.dinfo;
193 last_dev.dinfo = cur_dev.dinfo;
194 cur_dev.dinfo = tmp_dinfo;
195
196 last_dev.snap_time = cur_dev.snap_time;
197 dsgetinfo(&cur_dev);
198
199 size_t size = sizeof(ls->hits.arcstats);
200 if (sysctlbyname("kstat.zfs.misc.arcstats.hits",
201 &ls->hits.arcstats, &size, NULL, 0) != 0)
202 return;
203 GETSYSCTL("kstat.zfs.misc.arcstats.misses",
204 ls->misses.arcstats);
205 GETSYSCTL("kstat.zfs.misc.arcstats.demand_data_hits",
206 ls->hits.arcstats_demand_data);
207 GETSYSCTL("kstat.zfs.misc.arcstats.demand_data_misses",
208 ls->misses.arcstats_demand_data);
209 GETSYSCTL("kstat.zfs.misc.arcstats.demand_metadata_hits",
210 ls->hits.arcstats_demand_metadata);
211 GETSYSCTL("kstat.zfs.misc.arcstats.demand_metadata_misses",
212 ls->misses.arcstats_demand_metadata);
213 GETSYSCTL("kstat.zfs.misc.arcstats.prefetch_data_hits",
214 ls->hits.arcstats_prefetch_data);
215 GETSYSCTL("kstat.zfs.misc.arcstats.prefetch_data_misses",
216 ls->misses.arcstats_prefetch_data);
217 GETSYSCTL("kstat.zfs.misc.arcstats.prefetch_metadata_hits",
218 ls->hits.arcstats_prefetch_metadata);
219 GETSYSCTL("kstat.zfs.misc.arcstats.prefetch_metadata_misses",
220 ls->misses.arcstats_prefetch_metadata);
221 GETSYSCTL("kstat.zfs.misc.zfetchstats.hits",
222 ls->hits.zfetchstats);
223 GETSYSCTL("kstat.zfs.misc.zfetchstats.misses",
224 ls->misses.zfetchstats);
225 GETSYSCTL("kstat.zfs.misc.arcstats.l2_hits",
226 ls->hits.arcstats_l2);
227 GETSYSCTL("kstat.zfs.misc.arcstats.l2_misses",
228 ls->misses.arcstats_l2);
229 }
230
231 void
fetchzarc(void)232 fetchzarc(void)
233 {
234
235 oldstat = curstat;
236 getinfo(&curstat);
237 }
238