1/* $OpenBSD: nfs.c,v 1.10 2024/05/18 09:02:34 jsg Exp $ */ 2 3/* 4 * Copyright (c) 2009 Jasper Lievisse Adriaanse <jasper@openbsd.org> 5 * 6 * Permission to use, copy, modify, and distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 * 18 */ 19 20#include <sys/types.h> 21#include <sys/mount.h> 22#include <sys/signal.h> 23#include <sys/sysctl.h> 24#include <nfs/rpcv2.h> 25#include <nfs/nfsproto.h> 26#include <nfs/nfs.h> 27 28#include <err.h> 29#include <errno.h> 30#include <stdio.h> 31#include <stdlib.h> 32#include <string.h> 33 34#include "systat.h" 35 36int select_client(void); 37int select_server(void); 38int read_nfs(void); 39void print_client(void); 40void print_server(void); 41 42struct nfsstats nfsstats; 43int num_client = 0; 44int num_server = 0; 45 46field_def fields_nfs[] = { 47 /* Client */ 48 {"RPC COUNTS", 10, 12, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0}, 49 {"", 12, 14, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0}, 50 {"RPC INFO", 14, 12, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0}, 51 {"", 12, 14, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0}, 52 {"CACHE INFO", 10, 12, 1, FLD_ALIGN_LEFT, -1, 0, 0, 0}, 53 {"", 12, 14, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0}, 54 55 /* Server */ 56 {"RPC COUNTS", 10, 12, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0}, 57 {"", 12, 14, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0}, 58 {"CACHE STATS", 14, 12, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0}, 59 {"", 12, 14, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0}, 60 {"WRITES", 10, 12, 1, FLD_ALIGN_LEFT, -1, 0, 0, 0}, 61 {"", 10, 12, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0}, 62}; 63 64/* _V suffixed fields indicate a value column. */ 65/* Client */ 66#define FLD_NFS_C_RPC_COUNTS FIELD_ADDR(fields_nfs,0) 67#define FLD_NFS_C_RPC_COUNTS_V FIELD_ADDR(fields_nfs,1) 68#define FLD_NFS_C_RPC_INFO FIELD_ADDR(fields_nfs,2) 69#define FLD_NFS_C_RPC_INFO_V FIELD_ADDR(fields_nfs,3) 70#define FLD_NFS_C_CACHE_INFO FIELD_ADDR(fields_nfs,4) 71#define FLD_NFS_C_CACHE_V FIELD_ADDR(fields_nfs,5) 72 73/* Server */ 74#define FLD_NFS_S_RPC_COUNTS FIELD_ADDR(fields_nfs,6) 75#define FLD_NFS_S_RPC_COUNTS_V FIELD_ADDR(fields_nfs,7) 76#define FLD_NFS_S_CACHE_STATS FIELD_ADDR(fields_nfs,8) 77#define FLD_NFS_S_CACHE_STATS_V FIELD_ADDR(fields_nfs,9) 78#define FLD_NFS_S_WRITES FIELD_ADDR(fields_nfs,10) 79#define FLD_NFS_S_WRITES_V FIELD_ADDR(fields_nfs,11) 80 81/* Define views */ 82field_def *view_nfs_0[] = { 83 FLD_NFS_C_RPC_COUNTS, FLD_NFS_C_RPC_COUNTS_V, FLD_NFS_C_RPC_INFO, 84 FLD_NFS_C_RPC_INFO_V, FLD_NFS_C_CACHE_INFO, FLD_NFS_C_CACHE_V ,NULL 85}; 86 87field_def *view_nfs_1[] = { 88 FLD_NFS_S_RPC_COUNTS, FLD_NFS_S_RPC_COUNTS_V, FLD_NFS_S_CACHE_STATS, 89 FLD_NFS_S_CACHE_STATS_V, FLD_NFS_S_WRITES, FLD_NFS_S_WRITES_V, NULL 90}; 91 92/* Define view managers */ 93struct view_manager nfs_client_mgr = { 94 "Client", select_client, read_nfs, NULL, print_header, 95 print_client, keyboard_callback, NULL, NULL 96}; 97 98struct view_manager nfs_server_mgr = { 99 "Server", select_server, read_nfs, NULL, print_header, 100 print_server, keyboard_callback, NULL, NULL 101}; 102 103field_view views_nfs[] = { 104 {view_nfs_0, "nfsclient", '8', &nfs_client_mgr}, 105 {view_nfs_1, "nfsserver", '9', &nfs_server_mgr}, 106 {NULL, NULL, 0, NULL} 107}; 108 109int 110select_client(void) 111{ 112 num_disp = num_client; 113 return(0); 114} 115 116int 117select_server(void) 118{ 119 num_disp = num_server; 120 return(0); 121} 122 123int 124initnfs(void) 125{ 126 field_view *v; 127 128 for (v = views_nfs; v->name != NULL; v++) 129 add_view(v); 130 131 read_nfs(); 132 133 return(0); 134} 135 136/* 137 * We get all the information in one go and don't care about 138 * server or client fields (those will be '0' if not applicable). 139 */ 140int 141read_nfs(void) 142{ 143 struct nfsstats *p = &nfsstats; 144 int mib[3]; 145 size_t len = sizeof(*p); 146 147 mib[0] = CTL_VFS; 148 mib[1] = 2; /* NETDEV */ 149 mib[2] = NFS_NFSSTATS; 150 151 if (sysctl(mib, 3, p, &len, NULL, 0) == -1) 152 return(-1); 153 else 154 return(0); 155} 156 157 158/* 159 * As we want a view with multiple columns, mixed with labels and values, 160 * we can't use the regular dance and have to use our own (looong) dance 161 * to build the layout. 162 */ 163void 164print_client(void) 165{ 166 print_fld_str(FLD_NFS_C_RPC_COUNTS, "Getattr"); 167 print_fld_ssize(FLD_NFS_C_RPC_COUNTS_V, 168 nfsstats.rpccnt[NFSPROC_GETATTR]); 169 print_fld_str(FLD_NFS_C_RPC_INFO, "TimedOut"); 170 print_fld_ssize(FLD_NFS_C_RPC_INFO_V, nfsstats.rpctimeouts); 171 print_fld_str(FLD_NFS_C_CACHE_INFO, "Attr Hits "); 172 print_fld_ssize(FLD_NFS_C_CACHE_V, nfsstats.attrcache_hits); 173 end_line(); 174 175 print_fld_str(FLD_NFS_C_RPC_COUNTS, "Setattr"); 176 print_fld_ssize(FLD_NFS_C_RPC_COUNTS_V, 177 nfsstats.rpccnt[NFSPROC_SETATTR]); 178 print_fld_str(FLD_NFS_C_RPC_INFO, "Invalid"); 179 print_fld_ssize(FLD_NFS_C_RPC_INFO_V, nfsstats.rpcinvalid); 180 print_fld_str(FLD_NFS_C_CACHE_INFO, "Attr Misses"); 181 print_fld_ssize(FLD_NFS_C_CACHE_V, nfsstats.attrcache_misses); 182 end_line(); 183 184 print_fld_str(FLD_NFS_C_RPC_COUNTS, "Lookup"); 185 print_fld_ssize(FLD_NFS_C_RPC_COUNTS_V, 186 nfsstats.rpccnt[NFSPROC_LOOKUP]); 187 print_fld_str(FLD_NFS_C_RPC_INFO, "X Replies"); 188 print_fld_ssize(FLD_NFS_C_RPC_INFO_V, nfsstats.rpcunexpected); 189 print_fld_str(FLD_NFS_C_CACHE_INFO, "Lkup Hits "); 190 print_fld_ssize(FLD_NFS_C_CACHE_V, nfsstats.lookupcache_hits); 191 end_line(); 192 193 print_fld_str(FLD_NFS_C_RPC_COUNTS, "Readlink"); 194 print_fld_ssize(FLD_NFS_C_RPC_COUNTS_V, 195 nfsstats.rpccnt[NFSPROC_READLINK]); 196 print_fld_str(FLD_NFS_C_RPC_INFO, "Retries"); 197 print_fld_ssize(FLD_NFS_C_RPC_INFO_V, nfsstats.rpcretries); 198 print_fld_str(FLD_NFS_C_CACHE_INFO, "Lkup Misses "); 199 print_fld_ssize(FLD_NFS_C_CACHE_V, nfsstats.lookupcache_misses); 200 end_line(); 201 202 print_fld_str(FLD_NFS_C_RPC_COUNTS, "Read"); 203 print_fld_ssize(FLD_NFS_C_RPC_COUNTS_V, 204 nfsstats.rpccnt[NFSPROC_READ]); 205 print_fld_str(FLD_NFS_C_RPC_INFO, "Requests"); 206 print_fld_ssize(FLD_NFS_C_RPC_INFO_V, nfsstats.rpcrequests); 207 print_fld_str(FLD_NFS_C_CACHE_INFO, "BioR Hits "); 208 print_fld_ssize(FLD_NFS_C_CACHE_V, 209 nfsstats.biocache_reads-nfsstats.read_bios); 210 end_line(); 211 212 print_fld_str(FLD_NFS_C_RPC_COUNTS, "Write"); 213 print_fld_ssize(FLD_NFS_C_RPC_COUNTS_V, nfsstats.rpccnt[NFSPROC_WRITE]); 214 print_fld_str(FLD_NFS_C_RPC_INFO, "FrcSync"); 215 print_fld_ssize(FLD_NFS_C_RPC_INFO_V, nfsstats.forcedsync); 216 print_fld_str(FLD_NFS_C_CACHE_INFO, "BioR Misses"); 217 print_fld_ssize(FLD_NFS_C_CACHE_V, nfsstats.read_bios); 218 end_line(); 219 220 print_fld_str(FLD_NFS_C_RPC_COUNTS, "Create"); 221 print_fld_ssize(FLD_NFS_C_RPC_COUNTS_V, 222 nfsstats.rpccnt[NFSPROC_CREATE]); 223 print_fld_str(FLD_NFS_C_CACHE_INFO, "BioW Hits "); 224 print_fld_ssize(FLD_NFS_C_CACHE_V, 225 nfsstats.biocache_writes-nfsstats.write_bios); 226 end_line(); 227 228 print_fld_str(FLD_NFS_C_RPC_COUNTS, "Remove"); 229 print_fld_ssize(FLD_NFS_C_RPC_COUNTS_V, 230 nfsstats.rpccnt[NFSPROC_REMOVE]); 231 print_fld_str(FLD_NFS_C_CACHE_INFO, "BioW Misses"); 232 print_fld_ssize(FLD_NFS_C_CACHE_V, nfsstats.write_bios); 233 end_line(); 234 235 print_fld_str(FLD_NFS_C_RPC_COUNTS, "Rename"); 236 print_fld_ssize(FLD_NFS_C_RPC_COUNTS_V, 237 nfsstats.rpccnt[NFSPROC_RENAME]); 238 print_fld_str(FLD_NFS_C_CACHE_INFO, "BioRL Hits "); 239 print_fld_ssize(FLD_NFS_C_CACHE_V, 240 nfsstats.biocache_readlinks-nfsstats.readlink_bios); 241 end_line(); 242 243 print_fld_str(FLD_NFS_C_RPC_COUNTS, "Link"); 244 print_fld_ssize(FLD_NFS_C_RPC_COUNTS_V, nfsstats.rpccnt[NFSPROC_LINK]); 245 print_fld_str(FLD_NFS_C_CACHE_INFO, "BioRL Misses"); 246 print_fld_ssize(FLD_NFS_C_CACHE_V, nfsstats.readlink_bios); 247 end_line(); 248 249 print_fld_str(FLD_NFS_C_RPC_COUNTS, "Symlink"); 250 print_fld_ssize(FLD_NFS_C_RPC_COUNTS_V, 251 nfsstats.rpccnt[NFSPROC_SYMLINK]); 252 print_fld_str(FLD_NFS_C_CACHE_INFO, "BioD Hits "); 253 print_fld_ssize(FLD_NFS_C_CACHE_V, 254 nfsstats.biocache_readdirs-nfsstats.readdir_bios); 255 end_line(); 256 257 print_fld_str(FLD_NFS_C_RPC_COUNTS, "Mkdir"); 258 print_fld_ssize(FLD_NFS_C_RPC_COUNTS_V, nfsstats.rpccnt[NFSPROC_MKDIR]); 259 print_fld_str(FLD_NFS_C_CACHE_INFO, "BioD Misses"); 260 print_fld_ssize(FLD_NFS_C_CACHE_V, nfsstats.readdir_bios); 261 end_line(); 262 263 print_fld_str(FLD_NFS_C_RPC_COUNTS, "Rmdir"); 264 print_fld_ssize(FLD_NFS_C_RPC_COUNTS_V, nfsstats.rpccnt[NFSPROC_RMDIR]); 265 print_fld_str(FLD_NFS_C_CACHE_INFO, "DirE Hits "); 266 print_fld_ssize(FLD_NFS_C_CACHE_V, nfsstats.direofcache_hits); 267 end_line(); 268 269 print_fld_str(FLD_NFS_C_RPC_COUNTS, "Readdir"); 270 print_fld_ssize(FLD_NFS_C_RPC_COUNTS_V, 271 nfsstats.rpccnt[NFSPROC_READDIR]); 272 print_fld_str(FLD_NFS_C_CACHE_INFO, "DirE Misses"); 273 print_fld_ssize(FLD_NFS_C_CACHE_V, nfsstats.direofcache_misses); 274 end_line(); 275 276 print_fld_str(FLD_NFS_C_RPC_COUNTS, "RdirPlus"); 277 print_fld_ssize(FLD_NFS_C_RPC_COUNTS_V, 278 nfsstats.rpccnt[NFSPROC_READDIRPLUS]); 279 end_line(); 280 281 print_fld_str(FLD_NFS_C_RPC_COUNTS, "Access"); 282 print_fld_ssize(FLD_NFS_C_RPC_COUNTS_V, 283 nfsstats.rpccnt[NFSPROC_ACCESS]); 284 end_line(); 285 286 print_fld_str(FLD_NFS_C_RPC_COUNTS, "Mknod"); 287 print_fld_ssize(FLD_NFS_C_RPC_COUNTS_V, nfsstats.rpccnt[NFSPROC_MKNOD]); 288 end_line(); 289 290 print_fld_str(FLD_NFS_C_RPC_COUNTS, "Fsstat"); 291 print_fld_ssize(FLD_NFS_C_RPC_COUNTS_V, 292 nfsstats.rpccnt[NFSPROC_FSSTAT]); 293 end_line(); 294 295 print_fld_str(FLD_NFS_C_RPC_COUNTS, "Fsinfo"); 296 print_fld_ssize(FLD_NFS_C_RPC_COUNTS_V, 297 nfsstats.rpccnt[NFSPROC_FSINFO]); 298 end_line(); 299 300 print_fld_str(FLD_NFS_C_RPC_COUNTS, "PathConf"); 301 print_fld_ssize(FLD_NFS_C_RPC_COUNTS_V, 302 nfsstats.rpccnt[NFSPROC_PATHCONF]); 303 end_line(); 304 305 print_fld_str(FLD_NFS_C_RPC_COUNTS, "Commit"); 306 print_fld_ssize(FLD_NFS_C_RPC_COUNTS_V, 307 nfsstats.rpccnt[NFSPROC_COMMIT]); 308 end_line(); 309} 310 311void 312print_server(void) 313{ 314 print_fld_str(FLD_NFS_S_RPC_COUNTS, "Getattr"); 315 print_fld_ssize(FLD_NFS_S_RPC_COUNTS_V, 316 nfsstats.srvrpccnt[NFSPROC_GETATTR]); 317 print_fld_str(FLD_NFS_S_CACHE_STATS, "Inprog"); 318 print_fld_ssize(FLD_NFS_S_CACHE_STATS_V, nfsstats.srvcache_inproghits); 319 print_fld_str(FLD_NFS_S_WRITES, "WriteOps"); 320 print_fld_ssize(FLD_NFS_S_WRITES_V, nfsstats.srvvop_writes); 321 end_line(); 322 323 print_fld_str(FLD_NFS_S_RPC_COUNTS, "Setattr"); 324 print_fld_ssize(FLD_NFS_S_RPC_COUNTS_V, 325 nfsstats.srvrpccnt[NFSPROC_SETATTR]); 326 print_fld_str(FLD_NFS_S_CACHE_STATS, "Idem"); 327 print_fld_ssize(FLD_NFS_S_CACHE_STATS_V, 328 nfsstats.srvcache_idemdonehits); 329 print_fld_str(FLD_NFS_S_WRITES, "WriteRPC"); 330 print_fld_ssize(FLD_NFS_S_WRITES_V, nfsstats.srvrpccnt[NFSPROC_WRITE]); 331 end_line(); 332 333 print_fld_str(FLD_NFS_S_RPC_COUNTS, "Lookup"); 334 print_fld_ssize(FLD_NFS_S_RPC_COUNTS_V, 335 nfsstats.srvrpccnt[NFSPROC_LOOKUP]); 336 print_fld_str(FLD_NFS_S_CACHE_STATS, "Non-idem"); 337 print_fld_ssize(FLD_NFS_S_CACHE_STATS_V, 338 nfsstats.srvcache_nonidemdonehits); 339 print_fld_str(FLD_NFS_S_WRITES, "Opsaved"); 340 print_fld_ssize(FLD_NFS_S_WRITES_V, 341 nfsstats.srvrpccnt[NFSPROC_WRITE] - nfsstats.srvvop_writes); 342 end_line(); 343 344 print_fld_str(FLD_NFS_S_RPC_COUNTS, "Readlink"); 345 print_fld_ssize(FLD_NFS_S_RPC_COUNTS_V, 346 nfsstats.srvrpccnt[NFSPROC_READLINK]); 347 print_fld_str(FLD_NFS_S_CACHE_STATS, "Misses"); 348 print_fld_ssize(FLD_NFS_S_CACHE_STATS_V, nfsstats.srvcache_misses); 349 end_line(); 350 351 print_fld_str(FLD_NFS_S_RPC_COUNTS, "Read"); 352 print_fld_ssize(FLD_NFS_S_RPC_COUNTS_V, 353 nfsstats.srvrpccnt[NFSPROC_READ]); 354 end_line(); 355 356 print_fld_str(FLD_NFS_S_RPC_COUNTS, "Write"); 357 print_fld_ssize(FLD_NFS_S_RPC_COUNTS_V, 358 nfsstats.srvrpccnt[NFSPROC_WRITE]); 359 end_line(); 360 361 print_fld_str(FLD_NFS_S_RPC_COUNTS, "Create"); 362 print_fld_ssize(FLD_NFS_S_RPC_COUNTS_V, 363 nfsstats.srvrpccnt[NFSPROC_CREATE]); 364 end_line(); 365 366 print_fld_str(FLD_NFS_S_RPC_COUNTS, "Remove"); 367 print_fld_ssize(FLD_NFS_S_RPC_COUNTS_V, 368 nfsstats.srvrpccnt[NFSPROC_REMOVE]); 369 end_line(); 370 371 print_fld_str(FLD_NFS_S_RPC_COUNTS, "Rename"); 372 print_fld_ssize(FLD_NFS_S_RPC_COUNTS_V, 373 nfsstats.srvrpccnt[NFSPROC_RENAME]); 374 end_line(); 375 376 print_fld_str(FLD_NFS_S_RPC_COUNTS, "Link"); 377 print_fld_ssize(FLD_NFS_S_RPC_COUNTS_V, 378 nfsstats.srvrpccnt[NFSPROC_LINK]); 379 end_line(); 380 381 print_fld_str(FLD_NFS_S_RPC_COUNTS, "Symlink"); 382 print_fld_ssize(FLD_NFS_S_RPC_COUNTS_V, 383 nfsstats.srvrpccnt[NFSPROC_SYMLINK]); 384 end_line(); 385 386 print_fld_str(FLD_NFS_S_RPC_COUNTS, "Mkdir"); 387 print_fld_ssize(FLD_NFS_S_RPC_COUNTS_V, 388 nfsstats.srvrpccnt[NFSPROC_MKDIR]); 389 end_line(); 390 391 print_fld_str(FLD_NFS_S_RPC_COUNTS, "Rmdir"); 392 print_fld_ssize(FLD_NFS_S_RPC_COUNTS_V, 393 nfsstats.srvrpccnt[NFSPROC_RMDIR]); 394 end_line(); 395 396 print_fld_str(FLD_NFS_S_RPC_COUNTS, "Readdir"); 397 print_fld_ssize(FLD_NFS_S_RPC_COUNTS_V, 398 nfsstats.srvrpccnt[NFSPROC_READDIR]); 399 end_line(); 400 401 print_fld_str(FLD_NFS_S_RPC_COUNTS, "RdirPlus"); 402 print_fld_ssize(FLD_NFS_S_RPC_COUNTS_V, 403 nfsstats.srvrpccnt[NFSPROC_READDIRPLUS]); 404 end_line(); 405 406 print_fld_str(FLD_NFS_S_RPC_COUNTS, "Access"); 407 print_fld_ssize(FLD_NFS_S_RPC_COUNTS_V, 408 nfsstats.srvrpccnt[NFSPROC_ACCESS]); 409 end_line(); 410 411 print_fld_str(FLD_NFS_S_RPC_COUNTS, "Mknod"); 412 print_fld_ssize(FLD_NFS_S_RPC_COUNTS_V, 413 nfsstats.srvrpccnt[NFSPROC_MKNOD]); 414 end_line(); 415 416 print_fld_str(FLD_NFS_S_RPC_COUNTS, "Fsstat"); 417 print_fld_ssize(FLD_NFS_S_RPC_COUNTS_V, 418 nfsstats.srvrpccnt[NFSPROC_FSSTAT]); 419 end_line(); 420 421 print_fld_str(FLD_NFS_S_RPC_COUNTS, "Fsinfo"); 422 print_fld_ssize(FLD_NFS_S_RPC_COUNTS_V, 423 nfsstats.srvrpccnt[NFSPROC_FSINFO]); 424 end_line(); 425 426 print_fld_str(FLD_NFS_S_RPC_COUNTS, "PathConf"); 427 print_fld_ssize(FLD_NFS_S_RPC_COUNTS_V, 428 nfsstats.srvrpccnt[NFSPROC_PATHCONF]); 429 end_line(); 430 431 print_fld_str(FLD_NFS_S_RPC_COUNTS, "Commit"); 432 print_fld_ssize(FLD_NFS_S_RPC_COUNTS_V, 433 nfsstats.srvrpccnt[NFSPROC_COMMIT]); 434 end_line(); 435 436 /* This creates an empty space on screen to separate the two blocks */ 437 print_fld_str(FLD_NFS_S_RPC_COUNTS, ""); 438 end_line(); 439 440 print_fld_str(FLD_NFS_S_RPC_COUNTS, "Ret-Failed"); 441 print_fld_ssize(FLD_NFS_S_RPC_COUNTS_V, nfsstats.srvrpc_errs); 442 print_fld_str(FLD_NFS_S_CACHE_STATS, "Faults"); 443 print_fld_ssize(FLD_NFS_S_CACHE_STATS_V, nfsstats.srv_errs); 444 end_line(); 445} 446