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