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