/* $OpenBSD: nfs.c,v 1.10 2024/05/18 09:02:34 jsg Exp $ */ /* * Copyright (c) 2009 Jasper Lievisse Adriaanse * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * */ #include #include #include #include #include #include #include #include #include #include #include #include #include "systat.h" int select_client(void); int select_server(void); int read_nfs(void); void print_client(void); void print_server(void); struct nfsstats nfsstats; int num_client = 0; int num_server = 0; field_def fields_nfs[] = { /* Client */ {"RPC COUNTS", 10, 12, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0}, {"", 12, 14, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0}, {"RPC INFO", 14, 12, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0}, {"", 12, 14, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0}, {"CACHE INFO", 10, 12, 1, FLD_ALIGN_LEFT, -1, 0, 0, 0}, {"", 12, 14, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0}, /* Server */ {"RPC COUNTS", 10, 12, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0}, {"", 12, 14, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0}, {"CACHE STATS", 14, 12, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0}, {"", 12, 14, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0}, {"WRITES", 10, 12, 1, FLD_ALIGN_LEFT, -1, 0, 0, 0}, {"", 10, 12, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0}, }; /* _V suffixed fields indicate a value column. */ /* Client */ #define FLD_NFS_C_RPC_COUNTS FIELD_ADDR(fields_nfs,0) #define FLD_NFS_C_RPC_COUNTS_V FIELD_ADDR(fields_nfs,1) #define FLD_NFS_C_RPC_INFO FIELD_ADDR(fields_nfs,2) #define FLD_NFS_C_RPC_INFO_V FIELD_ADDR(fields_nfs,3) #define FLD_NFS_C_CACHE_INFO FIELD_ADDR(fields_nfs,4) #define FLD_NFS_C_CACHE_V FIELD_ADDR(fields_nfs,5) /* Server */ #define FLD_NFS_S_RPC_COUNTS FIELD_ADDR(fields_nfs,6) #define FLD_NFS_S_RPC_COUNTS_V FIELD_ADDR(fields_nfs,7) #define FLD_NFS_S_CACHE_STATS FIELD_ADDR(fields_nfs,8) #define FLD_NFS_S_CACHE_STATS_V FIELD_ADDR(fields_nfs,9) #define FLD_NFS_S_WRITES FIELD_ADDR(fields_nfs,10) #define FLD_NFS_S_WRITES_V FIELD_ADDR(fields_nfs,11) /* Define views */ field_def *view_nfs_0[] = { FLD_NFS_C_RPC_COUNTS, FLD_NFS_C_RPC_COUNTS_V, FLD_NFS_C_RPC_INFO, FLD_NFS_C_RPC_INFO_V, FLD_NFS_C_CACHE_INFO, FLD_NFS_C_CACHE_V ,NULL }; field_def *view_nfs_1[] = { FLD_NFS_S_RPC_COUNTS, FLD_NFS_S_RPC_COUNTS_V, FLD_NFS_S_CACHE_STATS, FLD_NFS_S_CACHE_STATS_V, FLD_NFS_S_WRITES, FLD_NFS_S_WRITES_V, NULL }; /* Define view managers */ struct view_manager nfs_client_mgr = { "Client", select_client, read_nfs, NULL, print_header, print_client, keyboard_callback, NULL, NULL }; struct view_manager nfs_server_mgr = { "Server", select_server, read_nfs, NULL, print_header, print_server, keyboard_callback, NULL, NULL }; field_view views_nfs[] = { {view_nfs_0, "nfsclient", '8', &nfs_client_mgr}, {view_nfs_1, "nfsserver", '9', &nfs_server_mgr}, {NULL, NULL, 0, NULL} }; int select_client(void) { num_disp = num_client; return(0); } int select_server(void) { num_disp = num_server; return(0); } int initnfs(void) { field_view *v; for (v = views_nfs; v->name != NULL; v++) add_view(v); read_nfs(); return(0); } /* * We get all the information in one go and don't care about * server or client fields (those will be '0' if not applicable). */ int read_nfs(void) { struct nfsstats *p = &nfsstats; int mib[3]; size_t len = sizeof(*p); mib[0] = CTL_VFS; mib[1] = 2; /* NETDEV */ mib[2] = NFS_NFSSTATS; if (sysctl(mib, 3, p, &len, NULL, 0) == -1) return(-1); else return(0); } /* * As we want a view with multiple columns, mixed with labels and values, * we can't use the regular dance and have to use our own (looong) dance * to build the layout. */ void print_client(void) { print_fld_str(FLD_NFS_C_RPC_COUNTS, "Getattr"); print_fld_ssize(FLD_NFS_C_RPC_COUNTS_V, nfsstats.rpccnt[NFSPROC_GETATTR]); print_fld_str(FLD_NFS_C_RPC_INFO, "TimedOut"); print_fld_ssize(FLD_NFS_C_RPC_INFO_V, nfsstats.rpctimeouts); print_fld_str(FLD_NFS_C_CACHE_INFO, "Attr Hits "); print_fld_ssize(FLD_NFS_C_CACHE_V, nfsstats.attrcache_hits); end_line(); print_fld_str(FLD_NFS_C_RPC_COUNTS, "Setattr"); print_fld_ssize(FLD_NFS_C_RPC_COUNTS_V, nfsstats.rpccnt[NFSPROC_SETATTR]); print_fld_str(FLD_NFS_C_RPC_INFO, "Invalid"); print_fld_ssize(FLD_NFS_C_RPC_INFO_V, nfsstats.rpcinvalid); print_fld_str(FLD_NFS_C_CACHE_INFO, "Attr Misses"); print_fld_ssize(FLD_NFS_C_CACHE_V, nfsstats.attrcache_misses); end_line(); print_fld_str(FLD_NFS_C_RPC_COUNTS, "Lookup"); print_fld_ssize(FLD_NFS_C_RPC_COUNTS_V, nfsstats.rpccnt[NFSPROC_LOOKUP]); print_fld_str(FLD_NFS_C_RPC_INFO, "X Replies"); print_fld_ssize(FLD_NFS_C_RPC_INFO_V, nfsstats.rpcunexpected); print_fld_str(FLD_NFS_C_CACHE_INFO, "Lkup Hits "); print_fld_ssize(FLD_NFS_C_CACHE_V, nfsstats.lookupcache_hits); end_line(); print_fld_str(FLD_NFS_C_RPC_COUNTS, "Readlink"); print_fld_ssize(FLD_NFS_C_RPC_COUNTS_V, nfsstats.rpccnt[NFSPROC_READLINK]); print_fld_str(FLD_NFS_C_RPC_INFO, "Retries"); print_fld_ssize(FLD_NFS_C_RPC_INFO_V, nfsstats.rpcretries); print_fld_str(FLD_NFS_C_CACHE_INFO, "Lkup Misses "); print_fld_ssize(FLD_NFS_C_CACHE_V, nfsstats.lookupcache_misses); end_line(); print_fld_str(FLD_NFS_C_RPC_COUNTS, "Read"); print_fld_ssize(FLD_NFS_C_RPC_COUNTS_V, nfsstats.rpccnt[NFSPROC_READ]); print_fld_str(FLD_NFS_C_RPC_INFO, "Requests"); print_fld_ssize(FLD_NFS_C_RPC_INFO_V, nfsstats.rpcrequests); print_fld_str(FLD_NFS_C_CACHE_INFO, "BioR Hits "); print_fld_ssize(FLD_NFS_C_CACHE_V, nfsstats.biocache_reads-nfsstats.read_bios); end_line(); print_fld_str(FLD_NFS_C_RPC_COUNTS, "Write"); print_fld_ssize(FLD_NFS_C_RPC_COUNTS_V, nfsstats.rpccnt[NFSPROC_WRITE]); print_fld_str(FLD_NFS_C_RPC_INFO, "FrcSync"); print_fld_ssize(FLD_NFS_C_RPC_INFO_V, nfsstats.forcedsync); print_fld_str(FLD_NFS_C_CACHE_INFO, "BioR Misses"); print_fld_ssize(FLD_NFS_C_CACHE_V, nfsstats.read_bios); end_line(); print_fld_str(FLD_NFS_C_RPC_COUNTS, "Create"); print_fld_ssize(FLD_NFS_C_RPC_COUNTS_V, nfsstats.rpccnt[NFSPROC_CREATE]); print_fld_str(FLD_NFS_C_CACHE_INFO, "BioW Hits "); print_fld_ssize(FLD_NFS_C_CACHE_V, nfsstats.biocache_writes-nfsstats.write_bios); end_line(); print_fld_str(FLD_NFS_C_RPC_COUNTS, "Remove"); print_fld_ssize(FLD_NFS_C_RPC_COUNTS_V, nfsstats.rpccnt[NFSPROC_REMOVE]); print_fld_str(FLD_NFS_C_CACHE_INFO, "BioW Misses"); print_fld_ssize(FLD_NFS_C_CACHE_V, nfsstats.write_bios); end_line(); print_fld_str(FLD_NFS_C_RPC_COUNTS, "Rename"); print_fld_ssize(FLD_NFS_C_RPC_COUNTS_V, nfsstats.rpccnt[NFSPROC_RENAME]); print_fld_str(FLD_NFS_C_CACHE_INFO, "BioRL Hits "); print_fld_ssize(FLD_NFS_C_CACHE_V, nfsstats.biocache_readlinks-nfsstats.readlink_bios); end_line(); print_fld_str(FLD_NFS_C_RPC_COUNTS, "Link"); print_fld_ssize(FLD_NFS_C_RPC_COUNTS_V, nfsstats.rpccnt[NFSPROC_LINK]); print_fld_str(FLD_NFS_C_CACHE_INFO, "BioRL Misses"); print_fld_ssize(FLD_NFS_C_CACHE_V, nfsstats.readlink_bios); end_line(); print_fld_str(FLD_NFS_C_RPC_COUNTS, "Symlink"); print_fld_ssize(FLD_NFS_C_RPC_COUNTS_V, nfsstats.rpccnt[NFSPROC_SYMLINK]); print_fld_str(FLD_NFS_C_CACHE_INFO, "BioD Hits "); print_fld_ssize(FLD_NFS_C_CACHE_V, nfsstats.biocache_readdirs-nfsstats.readdir_bios); end_line(); print_fld_str(FLD_NFS_C_RPC_COUNTS, "Mkdir"); print_fld_ssize(FLD_NFS_C_RPC_COUNTS_V, nfsstats.rpccnt[NFSPROC_MKDIR]); print_fld_str(FLD_NFS_C_CACHE_INFO, "BioD Misses"); print_fld_ssize(FLD_NFS_C_CACHE_V, nfsstats.readdir_bios); end_line(); print_fld_str(FLD_NFS_C_RPC_COUNTS, "Rmdir"); print_fld_ssize(FLD_NFS_C_RPC_COUNTS_V, nfsstats.rpccnt[NFSPROC_RMDIR]); print_fld_str(FLD_NFS_C_CACHE_INFO, "DirE Hits "); print_fld_ssize(FLD_NFS_C_CACHE_V, nfsstats.direofcache_hits); end_line(); print_fld_str(FLD_NFS_C_RPC_COUNTS, "Readdir"); print_fld_ssize(FLD_NFS_C_RPC_COUNTS_V, nfsstats.rpccnt[NFSPROC_READDIR]); print_fld_str(FLD_NFS_C_CACHE_INFO, "DirE Misses"); print_fld_ssize(FLD_NFS_C_CACHE_V, nfsstats.direofcache_misses); end_line(); print_fld_str(FLD_NFS_C_RPC_COUNTS, "RdirPlus"); print_fld_ssize(FLD_NFS_C_RPC_COUNTS_V, nfsstats.rpccnt[NFSPROC_READDIRPLUS]); end_line(); print_fld_str(FLD_NFS_C_RPC_COUNTS, "Access"); print_fld_ssize(FLD_NFS_C_RPC_COUNTS_V, nfsstats.rpccnt[NFSPROC_ACCESS]); end_line(); print_fld_str(FLD_NFS_C_RPC_COUNTS, "Mknod"); print_fld_ssize(FLD_NFS_C_RPC_COUNTS_V, nfsstats.rpccnt[NFSPROC_MKNOD]); end_line(); print_fld_str(FLD_NFS_C_RPC_COUNTS, "Fsstat"); print_fld_ssize(FLD_NFS_C_RPC_COUNTS_V, nfsstats.rpccnt[NFSPROC_FSSTAT]); end_line(); print_fld_str(FLD_NFS_C_RPC_COUNTS, "Fsinfo"); print_fld_ssize(FLD_NFS_C_RPC_COUNTS_V, nfsstats.rpccnt[NFSPROC_FSINFO]); end_line(); print_fld_str(FLD_NFS_C_RPC_COUNTS, "PathConf"); print_fld_ssize(FLD_NFS_C_RPC_COUNTS_V, nfsstats.rpccnt[NFSPROC_PATHCONF]); end_line(); print_fld_str(FLD_NFS_C_RPC_COUNTS, "Commit"); print_fld_ssize(FLD_NFS_C_RPC_COUNTS_V, nfsstats.rpccnt[NFSPROC_COMMIT]); end_line(); } void print_server(void) { print_fld_str(FLD_NFS_S_RPC_COUNTS, "Getattr"); print_fld_ssize(FLD_NFS_S_RPC_COUNTS_V, nfsstats.srvrpccnt[NFSPROC_GETATTR]); print_fld_str(FLD_NFS_S_CACHE_STATS, "Inprog"); print_fld_ssize(FLD_NFS_S_CACHE_STATS_V, nfsstats.srvcache_inproghits); print_fld_str(FLD_NFS_S_WRITES, "WriteOps"); print_fld_ssize(FLD_NFS_S_WRITES_V, nfsstats.srvvop_writes); end_line(); print_fld_str(FLD_NFS_S_RPC_COUNTS, "Setattr"); print_fld_ssize(FLD_NFS_S_RPC_COUNTS_V, nfsstats.srvrpccnt[NFSPROC_SETATTR]); print_fld_str(FLD_NFS_S_CACHE_STATS, "Idem"); print_fld_ssize(FLD_NFS_S_CACHE_STATS_V, nfsstats.srvcache_idemdonehits); print_fld_str(FLD_NFS_S_WRITES, "WriteRPC"); print_fld_ssize(FLD_NFS_S_WRITES_V, nfsstats.srvrpccnt[NFSPROC_WRITE]); end_line(); print_fld_str(FLD_NFS_S_RPC_COUNTS, "Lookup"); print_fld_ssize(FLD_NFS_S_RPC_COUNTS_V, nfsstats.srvrpccnt[NFSPROC_LOOKUP]); print_fld_str(FLD_NFS_S_CACHE_STATS, "Non-idem"); print_fld_ssize(FLD_NFS_S_CACHE_STATS_V, nfsstats.srvcache_nonidemdonehits); print_fld_str(FLD_NFS_S_WRITES, "Opsaved"); print_fld_ssize(FLD_NFS_S_WRITES_V, nfsstats.srvrpccnt[NFSPROC_WRITE] - nfsstats.srvvop_writes); end_line(); print_fld_str(FLD_NFS_S_RPC_COUNTS, "Readlink"); print_fld_ssize(FLD_NFS_S_RPC_COUNTS_V, nfsstats.srvrpccnt[NFSPROC_READLINK]); print_fld_str(FLD_NFS_S_CACHE_STATS, "Misses"); print_fld_ssize(FLD_NFS_S_CACHE_STATS_V, nfsstats.srvcache_misses); end_line(); print_fld_str(FLD_NFS_S_RPC_COUNTS, "Read"); print_fld_ssize(FLD_NFS_S_RPC_COUNTS_V, nfsstats.srvrpccnt[NFSPROC_READ]); end_line(); print_fld_str(FLD_NFS_S_RPC_COUNTS, "Write"); print_fld_ssize(FLD_NFS_S_RPC_COUNTS_V, nfsstats.srvrpccnt[NFSPROC_WRITE]); end_line(); print_fld_str(FLD_NFS_S_RPC_COUNTS, "Create"); print_fld_ssize(FLD_NFS_S_RPC_COUNTS_V, nfsstats.srvrpccnt[NFSPROC_CREATE]); end_line(); print_fld_str(FLD_NFS_S_RPC_COUNTS, "Remove"); print_fld_ssize(FLD_NFS_S_RPC_COUNTS_V, nfsstats.srvrpccnt[NFSPROC_REMOVE]); end_line(); print_fld_str(FLD_NFS_S_RPC_COUNTS, "Rename"); print_fld_ssize(FLD_NFS_S_RPC_COUNTS_V, nfsstats.srvrpccnt[NFSPROC_RENAME]); end_line(); print_fld_str(FLD_NFS_S_RPC_COUNTS, "Link"); print_fld_ssize(FLD_NFS_S_RPC_COUNTS_V, nfsstats.srvrpccnt[NFSPROC_LINK]); end_line(); print_fld_str(FLD_NFS_S_RPC_COUNTS, "Symlink"); print_fld_ssize(FLD_NFS_S_RPC_COUNTS_V, nfsstats.srvrpccnt[NFSPROC_SYMLINK]); end_line(); print_fld_str(FLD_NFS_S_RPC_COUNTS, "Mkdir"); print_fld_ssize(FLD_NFS_S_RPC_COUNTS_V, nfsstats.srvrpccnt[NFSPROC_MKDIR]); end_line(); print_fld_str(FLD_NFS_S_RPC_COUNTS, "Rmdir"); print_fld_ssize(FLD_NFS_S_RPC_COUNTS_V, nfsstats.srvrpccnt[NFSPROC_RMDIR]); end_line(); print_fld_str(FLD_NFS_S_RPC_COUNTS, "Readdir"); print_fld_ssize(FLD_NFS_S_RPC_COUNTS_V, nfsstats.srvrpccnt[NFSPROC_READDIR]); end_line(); print_fld_str(FLD_NFS_S_RPC_COUNTS, "RdirPlus"); print_fld_ssize(FLD_NFS_S_RPC_COUNTS_V, nfsstats.srvrpccnt[NFSPROC_READDIRPLUS]); end_line(); print_fld_str(FLD_NFS_S_RPC_COUNTS, "Access"); print_fld_ssize(FLD_NFS_S_RPC_COUNTS_V, nfsstats.srvrpccnt[NFSPROC_ACCESS]); end_line(); print_fld_str(FLD_NFS_S_RPC_COUNTS, "Mknod"); print_fld_ssize(FLD_NFS_S_RPC_COUNTS_V, nfsstats.srvrpccnt[NFSPROC_MKNOD]); end_line(); print_fld_str(FLD_NFS_S_RPC_COUNTS, "Fsstat"); print_fld_ssize(FLD_NFS_S_RPC_COUNTS_V, nfsstats.srvrpccnt[NFSPROC_FSSTAT]); end_line(); print_fld_str(FLD_NFS_S_RPC_COUNTS, "Fsinfo"); print_fld_ssize(FLD_NFS_S_RPC_COUNTS_V, nfsstats.srvrpccnt[NFSPROC_FSINFO]); end_line(); print_fld_str(FLD_NFS_S_RPC_COUNTS, "PathConf"); print_fld_ssize(FLD_NFS_S_RPC_COUNTS_V, nfsstats.srvrpccnt[NFSPROC_PATHCONF]); end_line(); print_fld_str(FLD_NFS_S_RPC_COUNTS, "Commit"); print_fld_ssize(FLD_NFS_S_RPC_COUNTS_V, nfsstats.srvrpccnt[NFSPROC_COMMIT]); end_line(); /* This creates an empty space on screen to separate the two blocks */ print_fld_str(FLD_NFS_S_RPC_COUNTS, ""); end_line(); print_fld_str(FLD_NFS_S_RPC_COUNTS, "Ret-Failed"); print_fld_ssize(FLD_NFS_S_RPC_COUNTS_V, nfsstats.srvrpc_errs); print_fld_str(FLD_NFS_S_CACHE_STATS, "Faults"); print_fld_ssize(FLD_NFS_S_CACHE_STATS_V, nfsstats.srv_errs); end_line(); }