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 * 65 openzarc(void) 66 { 67 68 return (subwin(stdscr, LINES - 3 - 1, 0, MAINWIN_ROW, 0)); 69 } 70 71 void 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 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 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 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 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 171 initzarc(void) 172 { 173 dsinit(12); 174 getinfo(&initstat); 175 curstat = oldstat = initstat; 176 177 return 1; 178 } 179 180 void 181 resetzarc(void) 182 { 183 184 initzarc(); 185 } 186 187 static void 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 232 fetchzarc(void) 233 { 234 235 oldstat = curstat; 236 getinfo(&curstat); 237 } 238