1 0 stevel /* 2 0 stevel * CDDL HEADER START 3 0 stevel * 4 0 stevel * The contents of this file are subject to the terms of the 5 3406 th199096 * Common Development and Distribution License (the "License"). 6 3406 th199096 * You may not use this file except in compliance with the License. 7 0 stevel * 8 0 stevel * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 0 stevel * or http://www.opensolaris.org/os/licensing. 10 0 stevel * See the License for the specific language governing permissions 11 0 stevel * and limitations under the License. 12 0 stevel * 13 0 stevel * When distributing Covered Code, include this CDDL HEADER in each 14 0 stevel * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 0 stevel * If applicable, add the following below this CDDL HEADER, with the 16 0 stevel * fields enclosed by brackets "[]" replaced with your own identifying 17 0 stevel * information: Portions Copyright [yyyy] [name of copyright owner] 18 0 stevel * 19 0 stevel * CDDL HEADER END 20 0 stevel */ 21 3406 th199096 22 0 stevel /* LINTLIBRARY */ 23 0 stevel /* PROTOLIB1 */ 24 0 stevel 25 0 stevel /* 26 10265 Krishnendu * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 27 0 stevel * Use is subject to license terms. 28 0 stevel */ 29 0 stevel 30 0 stevel /* 31 0 stevel * nfsstat: Network File System statistics 32 0 stevel * 33 0 stevel */ 34 0 stevel 35 0 stevel #include <stdio.h> 36 0 stevel #include <stdlib.h> 37 0 stevel #include <unistd.h> 38 0 stevel #include <stdarg.h> 39 0 stevel #include <string.h> 40 0 stevel #include <errno.h> 41 0 stevel #include <fcntl.h> 42 0 stevel #include <kvm.h> 43 0 stevel #include <kstat.h> 44 0 stevel #include <sys/param.h> 45 0 stevel #include <sys/types.h> 46 0 stevel #include <sys/t_lock.h> 47 0 stevel #include <sys/tiuser.h> 48 0 stevel #include <sys/statvfs.h> 49 0 stevel #include <sys/mntent.h> 50 0 stevel #include <sys/mnttab.h> 51 0 stevel #include <sys/sysmacros.h> 52 0 stevel #include <sys/mkdev.h> 53 0 stevel #include <rpc/types.h> 54 0 stevel #include <rpc/xdr.h> 55 0 stevel #include <rpc/auth.h> 56 0 stevel #include <rpc/clnt.h> 57 0 stevel #include <nfs/nfs.h> 58 0 stevel #include <nfs/nfs_clnt.h> 59 0 stevel #include <nfs/nfs_sec.h> 60 0 stevel #include <inttypes.h> 61 0 stevel #include <signal.h> 62 0 stevel #include <time.h> 63 0 stevel #include <sys/time.h> 64 0 stevel #include <strings.h> 65 0 stevel #include <ctype.h> 66 10265 Krishnendu #include <locale.h> 67 0 stevel 68 10265 Krishnendu #include "statcommon.h" 69 0 stevel 70 0 stevel static kstat_ctl_t *kc = NULL; /* libkstat cookie */ 71 0 stevel static kstat_t *rpc_clts_client_kstat, *rpc_clts_server_kstat; 72 0 stevel static kstat_t *rpc_cots_client_kstat, *rpc_cots_server_kstat; 73 0 stevel static kstat_t *rpc_rdma_client_kstat, *rpc_rdma_server_kstat; 74 0 stevel static kstat_t *nfs_client_kstat, *nfs_server_v2_kstat, *nfs_server_v3_kstat; 75 0 stevel static kstat_t *nfs4_client_kstat, *nfs_server_v4_kstat; 76 0 stevel static kstat_t *rfsproccnt_v2_kstat, *rfsproccnt_v3_kstat, *rfsproccnt_v4_kstat; 77 0 stevel static kstat_t *rfsreqcnt_v2_kstat, *rfsreqcnt_v3_kstat, *rfsreqcnt_v4_kstat; 78 0 stevel static kstat_t *aclproccnt_v2_kstat, *aclproccnt_v3_kstat; 79 0 stevel static kstat_t *aclreqcnt_v2_kstat, *aclreqcnt_v3_kstat; 80 0 stevel static kstat_t *ksum_kstat; 81 0 stevel 82 0 stevel static void handle_sig(int); 83 0 stevel static int getstats_rpc(void); 84 0 stevel static int getstats_nfs(void); 85 0 stevel static int getstats_rfsproc(int); 86 0 stevel static int getstats_rfsreq(int); 87 0 stevel static int getstats_aclproc(void); 88 0 stevel static int getstats_aclreq(void); 89 0 stevel static void putstats(void); 90 0 stevel static void setup(void); 91 0 stevel static void cr_print(int); 92 0 stevel static void sr_print(int); 93 0 stevel static void cn_print(int, int); 94 0 stevel static void sn_print(int, int); 95 0 stevel static void ca_print(int, int); 96 0 stevel static void sa_print(int, int); 97 0 stevel static void req_print(kstat_t *, kstat_t *, int, int, int); 98 0 stevel static void req_print_v4(kstat_t *, kstat_t *, int, int); 99 0 stevel static void stat_print(const char *, kstat_t *, kstat_t *, int, int); 100 10265 Krishnendu static void nfsstat_kstat_sum(kstat_t *, kstat_t *, kstat_t *); 101 0 stevel static void stats_timer(int); 102 0 stevel static void safe_zalloc(void **, uint_t, int); 103 0 stevel static int safe_strtoi(char const *, char *); 104 0 stevel 105 0 stevel 106 10265 Krishnendu static void nfsstat_kstat_copy(kstat_t *, kstat_t *, int); 107 0 stevel static kid_t safe_kstat_read(kstat_ctl_t *, kstat_t *, void *); 108 0 stevel static kid_t safe_kstat_write(kstat_ctl_t *, kstat_t *, void *); 109 0 stevel 110 0 stevel static void usage(void); 111 0 stevel static void mi_print(void); 112 0 stevel static int ignore(char *); 113 0 stevel static int interval; /* interval between stats */ 114 0 stevel static int count; /* number of iterations the stat is printed */ 115 0 stevel #define MAX_COLUMNS 80 116 0 stevel #define MAX_PATHS 50 /* max paths that can be taken by -m */ 117 0 stevel 118 5302 th199096 /* 119 5302 th199096 * MI4_MIRRORMOUNT is canonically defined in nfs4_clnt.h, but we cannot 120 5302 th199096 * include that file here. 121 5302 th199096 */ 122 5302 th199096 #define MI4_MIRRORMOUNT 0x4000 123 5302 th199096 #define NFS_V4 4 124 5302 th199096 125 0 stevel static int req_width(kstat_t *, int); 126 0 stevel static int stat_width(kstat_t *, int); 127 0 stevel static char *path [MAX_PATHS] = {NULL}; /* array to store the multiple paths */ 128 0 stevel 129 0 stevel /* 130 0 stevel * Struct holds the previous kstat values so 131 0 stevel * we can compute deltas when using the -i flag 132 0 stevel */ 133 0 stevel typedef struct old_kstat 134 0 stevel { 135 0 stevel kstat_t kst; 136 0 stevel int tot; 137 0 stevel } old_kstat_t; 138 0 stevel 139 0 stevel static old_kstat_t old_rpc_clts_client_kstat, old_rpc_clts_server_kstat; 140 0 stevel static old_kstat_t old_rpc_cots_client_kstat, old_rpc_cots_server_kstat; 141 0 stevel static old_kstat_t old_rpc_rdma_client_kstat, old_rpc_rdma_server_kstat; 142 0 stevel static old_kstat_t old_nfs_client_kstat, old_nfs_server_v2_kstat; 143 0 stevel static old_kstat_t old_nfs_server_v3_kstat, old_ksum_kstat; 144 0 stevel static old_kstat_t old_nfs4_client_kstat, old_nfs_server_v4_kstat; 145 0 stevel static old_kstat_t old_rfsproccnt_v2_kstat, old_rfsproccnt_v3_kstat; 146 0 stevel static old_kstat_t old_rfsproccnt_v4_kstat, old_rfsreqcnt_v2_kstat; 147 0 stevel static old_kstat_t old_rfsreqcnt_v3_kstat, old_rfsreqcnt_v4_kstat; 148 0 stevel static old_kstat_t old_aclproccnt_v2_kstat, old_aclproccnt_v3_kstat; 149 0 stevel static old_kstat_t old_aclreqcnt_v2_kstat, old_aclreqcnt_v3_kstat; 150 0 stevel 151 10265 Krishnendu static uint_t timestamp_fmt = NODATE; 152 0 stevel 153 10265 Krishnendu #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */ 154 10265 Krishnendu #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it isn't */ 155 10265 Krishnendu #endif 156 0 stevel 157 249 jwahlig int 158 0 stevel main(int argc, char *argv[]) 159 0 stevel { 160 0 stevel int c, go_forever, j; 161 0 stevel int cflag = 0; /* client stats */ 162 0 stevel int sflag = 0; /* server stats */ 163 0 stevel int nflag = 0; /* nfs stats */ 164 0 stevel int rflag = 0; /* rpc stats */ 165 0 stevel int mflag = 0; /* mount table stats */ 166 0 stevel int aflag = 0; /* print acl statistics */ 167 0 stevel int vflag = 0; /* version specified, 0 specifies all */ 168 0 stevel int zflag = 0; /* zero stats after printing */ 169 0 stevel char *split_line = "*******************************************" 170 5302 th199096 "*************************************"; 171 0 stevel 172 0 stevel interval = 0; 173 0 stevel count = 0; 174 0 stevel go_forever = 0; 175 0 stevel 176 10265 Krishnendu (void) setlocale(LC_ALL, ""); 177 10265 Krishnendu (void) textdomain(TEXT_DOMAIN); 178 10265 Krishnendu 179 10265 Krishnendu while ((c = getopt(argc, argv, "cnrsmzav:T:")) != EOF) { 180 0 stevel switch (c) { 181 0 stevel case 'c': 182 0 stevel cflag++; 183 0 stevel break; 184 0 stevel case 'n': 185 0 stevel nflag++; 186 0 stevel break; 187 0 stevel case 'r': 188 0 stevel rflag++; 189 0 stevel break; 190 0 stevel case 's': 191 0 stevel sflag++; 192 0 stevel break; 193 0 stevel case 'm': 194 0 stevel mflag++; 195 0 stevel break; 196 0 stevel case 'z': 197 0 stevel if (geteuid()) 198 0 stevel fail(0, "Must be root for z flag\n"); 199 0 stevel zflag++; 200 0 stevel break; 201 0 stevel case 'a': 202 0 stevel aflag++; 203 0 stevel break; 204 0 stevel case 'v': 205 0 stevel vflag = atoi(optarg); 206 0 stevel if ((vflag < 2) || (vflag > 4)) 207 0 stevel fail(0, "Invalid version number\n"); 208 10265 Krishnendu break; 209 10265 Krishnendu case 'T': 210 10265 Krishnendu if (optarg) { 211 10265 Krishnendu if (*optarg == 'u') 212 10265 Krishnendu timestamp_fmt = UDATE; 213 10265 Krishnendu else if (*optarg == 'd') 214 10265 Krishnendu timestamp_fmt = DDATE; 215 10265 Krishnendu else 216 10265 Krishnendu usage(); 217 10265 Krishnendu } else { 218 10265 Krishnendu usage(); 219 10265 Krishnendu } 220 0 stevel break; 221 0 stevel case '?': 222 0 stevel default: 223 0 stevel usage(); 224 0 stevel } 225 0 stevel } 226 0 stevel 227 0 stevel if (((argc - optind) > 0) && !mflag) { 228 0 stevel 229 0 stevel interval = safe_strtoi(argv[optind], "invalid interval"); 230 0 stevel if (interval < 1) 231 0 stevel fail(0, "invalid interval\n"); 232 0 stevel optind++; 233 0 stevel 234 0 stevel if ((argc - optind) > 0) { 235 0 stevel count = safe_strtoi(argv[optind], "invalid count"); 236 0 stevel if ((count <= 0) || (count == NULL)) 237 0 stevel fail(0, "invalid count\n"); 238 0 stevel } 239 0 stevel optind++; 240 0 stevel 241 0 stevel if ((argc - optind) > 0) 242 0 stevel usage(); 243 0 stevel 244 0 stevel /* 245 0 stevel * no count number was set, so we will loop infinitely 246 0 stevel * at interval specified 247 0 stevel */ 248 0 stevel if (!count) 249 0 stevel go_forever = 1; 250 0 stevel stats_timer(interval); 251 0 stevel } else if (mflag) { 252 0 stevel 253 0 stevel if (cflag || rflag || sflag || zflag || nflag || aflag || vflag) 254 5302 th199096 fail(0, 255 5302 th199096 "The -m flag may not be used with any other flags"); 256 0 stevel 257 0 stevel for (j = 0; (argc - optind > 0) && (j < (MAX_PATHS - 1)); j++) { 258 0 stevel path[j] = argv[optind]; 259 0 stevel if (*path[j] != '/') 260 0 stevel fail(0, "Please fully qualify your pathname " 261 0 stevel "with a leading '/'"); 262 0 stevel optind++; 263 0 stevel } 264 0 stevel path[j] = NULL; 265 0 stevel if (argc - optind > 0) 266 0 stevel fprintf(stderr, "Only the first 50 paths " 267 5302 th199096 "will be searched for\n"); 268 0 stevel } 269 0 stevel 270 0 stevel setup(); 271 0 stevel 272 0 stevel do { 273 0 stevel if (mflag) { 274 0 stevel mi_print(); 275 0 stevel } else { 276 10265 Krishnendu if (timestamp_fmt != NODATE) 277 10265 Krishnendu print_timestamp(timestamp_fmt); 278 0 stevel 279 0 stevel if (sflag && 280 0 stevel (rpc_clts_server_kstat == NULL || 281 0 stevel nfs_server_v4_kstat == NULL)) { 282 0 stevel fprintf(stderr, 283 0 stevel "nfsstat: kernel is not configured with " 284 0 stevel "the server nfs and rpc code.\n"); 285 0 stevel } 286 0 stevel 287 0 stevel /* if s and nothing else, all 3 prints are called */ 288 0 stevel if (sflag || (!sflag && !cflag)) { 289 0 stevel if (rflag || (!rflag && !nflag && !aflag)) 290 0 stevel sr_print(zflag); 291 0 stevel if (nflag || (!rflag && !nflag && !aflag)) 292 0 stevel sn_print(zflag, vflag); 293 0 stevel if (aflag || (!rflag && !nflag && !aflag)) 294 0 stevel sa_print(zflag, vflag); 295 0 stevel } 296 0 stevel if (cflag && 297 0 stevel (rpc_clts_client_kstat == NULL || 298 0 stevel nfs_client_kstat == NULL)) { 299 0 stevel fprintf(stderr, 300 5302 th199096 "nfsstat: kernel is not configured with" 301 5302 th199096 " the client nfs and rpc code.\n"); 302 0 stevel } 303 0 stevel if (cflag || (!sflag && !cflag)) { 304 0 stevel if (rflag || (!rflag && !nflag && !aflag)) 305 0 stevel cr_print(zflag); 306 0 stevel if (nflag || (!rflag && !nflag && !aflag)) 307 0 stevel cn_print(zflag, vflag); 308 0 stevel if (aflag || (!rflag && !nflag && !aflag)) 309 0 stevel ca_print(zflag, vflag); 310 0 stevel } 311 0 stevel } 312 0 stevel 313 0 stevel if (zflag) 314 0 stevel putstats(); 315 0 stevel if (interval) 316 0 stevel printf("%s\n", split_line); 317 0 stevel 318 0 stevel if (interval > 0) 319 0 stevel (void) pause(); 320 0 stevel } while ((--count > 0) || go_forever); 321 0 stevel 322 0 stevel kstat_close(kc); 323 0 stevel free(ksum_kstat); 324 0 stevel return (0); 325 0 stevel } 326 0 stevel 327 0 stevel 328 0 stevel static int 329 0 stevel getstats_rpc(void) 330 0 stevel { 331 0 stevel int field_width = 0; 332 0 stevel 333 0 stevel if (rpc_clts_client_kstat != NULL) { 334 0 stevel safe_kstat_read(kc, rpc_clts_client_kstat, NULL); 335 0 stevel field_width = stat_width(rpc_clts_client_kstat, field_width); 336 0 stevel } 337 0 stevel 338 0 stevel if (rpc_cots_client_kstat != NULL) { 339 0 stevel safe_kstat_read(kc, rpc_cots_client_kstat, NULL); 340 0 stevel field_width = stat_width(rpc_cots_client_kstat, field_width); 341 0 stevel } 342 0 stevel 343 0 stevel if (rpc_rdma_client_kstat != NULL) { 344 0 stevel safe_kstat_read(kc, rpc_rdma_client_kstat, NULL); 345 0 stevel field_width = stat_width(rpc_rdma_client_kstat, field_width); 346 0 stevel } 347 0 stevel 348 0 stevel if (rpc_clts_server_kstat != NULL) { 349 0 stevel safe_kstat_read(kc, rpc_clts_server_kstat, NULL); 350 0 stevel field_width = stat_width(rpc_clts_server_kstat, field_width); 351 0 stevel } 352 0 stevel if (rpc_cots_server_kstat != NULL) { 353 0 stevel safe_kstat_read(kc, rpc_cots_server_kstat, NULL); 354 0 stevel field_width = stat_width(rpc_cots_server_kstat, field_width); 355 0 stevel } 356 0 stevel if (rpc_rdma_server_kstat != NULL) { 357 0 stevel safe_kstat_read(kc, rpc_rdma_server_kstat, NULL); 358 0 stevel field_width = stat_width(rpc_rdma_server_kstat, field_width); 359 0 stevel } 360 0 stevel return (field_width); 361 0 stevel } 362 0 stevel 363 0 stevel static int 364 0 stevel getstats_nfs(void) 365 0 stevel { 366 0 stevel int field_width = 0; 367 0 stevel 368 0 stevel if (nfs_client_kstat != NULL) { 369 0 stevel safe_kstat_read(kc, nfs_client_kstat, NULL); 370 0 stevel field_width = stat_width(nfs_client_kstat, field_width); 371 0 stevel } 372 0 stevel if (nfs4_client_kstat != NULL) { 373 0 stevel safe_kstat_read(kc, nfs4_client_kstat, NULL); 374 0 stevel field_width = stat_width(nfs4_client_kstat, field_width); 375 0 stevel } 376 0 stevel if (nfs_server_v2_kstat != NULL) { 377 0 stevel safe_kstat_read(kc, nfs_server_v2_kstat, NULL); 378 0 stevel field_width = stat_width(nfs_server_v2_kstat, field_width); 379 0 stevel } 380 0 stevel if (nfs_server_v3_kstat != NULL) { 381 0 stevel safe_kstat_read(kc, nfs_server_v3_kstat, NULL); 382 0 stevel field_width = stat_width(nfs_server_v3_kstat, field_width); 383 0 stevel } 384 0 stevel if (nfs_server_v4_kstat != NULL) { 385 0 stevel safe_kstat_read(kc, nfs_server_v4_kstat, NULL); 386 0 stevel field_width = stat_width(nfs_server_v4_kstat, field_width); 387 0 stevel } 388 0 stevel return (field_width); 389 0 stevel } 390 0 stevel 391 0 stevel static int 392 0 stevel getstats_rfsproc(int ver) 393 0 stevel { 394 0 stevel int field_width = 0; 395 0 stevel 396 0 stevel if ((ver == 2) && (rfsproccnt_v2_kstat != NULL)) { 397 0 stevel safe_kstat_read(kc, rfsproccnt_v2_kstat, NULL); 398 0 stevel field_width = req_width(rfsproccnt_v2_kstat, field_width); 399 0 stevel } 400 0 stevel if ((ver == 3) && (rfsproccnt_v3_kstat != NULL)) { 401 0 stevel safe_kstat_read(kc, rfsproccnt_v3_kstat, NULL); 402 0 stevel field_width = req_width(rfsproccnt_v3_kstat, field_width); 403 0 stevel } 404 0 stevel if ((ver == 4) && (rfsproccnt_v4_kstat != NULL)) { 405 0 stevel safe_kstat_read(kc, rfsproccnt_v4_kstat, NULL); 406 0 stevel field_width = req_width(rfsproccnt_v4_kstat, field_width); 407 0 stevel } 408 0 stevel return (field_width); 409 0 stevel } 410 0 stevel 411 0 stevel static int 412 0 stevel getstats_rfsreq(int ver) 413 0 stevel { 414 0 stevel int field_width = 0; 415 0 stevel if ((ver == 2) && (rfsreqcnt_v2_kstat != NULL)) { 416 0 stevel safe_kstat_read(kc, rfsreqcnt_v2_kstat, NULL); 417 0 stevel field_width = req_width(rfsreqcnt_v2_kstat, field_width); 418 0 stevel } 419 0 stevel if ((ver == 3) && (rfsreqcnt_v3_kstat != NULL)) { 420 0 stevel safe_kstat_read(kc, rfsreqcnt_v3_kstat, NULL); 421 0 stevel field_width = req_width(rfsreqcnt_v3_kstat, field_width); 422 0 stevel } 423 0 stevel if ((ver == 4) && (rfsreqcnt_v4_kstat != NULL)) { 424 0 stevel safe_kstat_read(kc, rfsreqcnt_v4_kstat, NULL); 425 0 stevel field_width = req_width(rfsreqcnt_v4_kstat, field_width); 426 0 stevel } 427 0 stevel return (field_width); 428 0 stevel } 429 0 stevel 430 0 stevel static int 431 0 stevel getstats_aclproc(void) 432 0 stevel { 433 0 stevel int field_width = 0; 434 0 stevel if (aclproccnt_v2_kstat != NULL) { 435 0 stevel safe_kstat_read(kc, aclproccnt_v2_kstat, NULL); 436 0 stevel field_width = req_width(aclproccnt_v2_kstat, field_width); 437 0 stevel } 438 0 stevel if (aclproccnt_v3_kstat != NULL) { 439 0 stevel safe_kstat_read(kc, aclproccnt_v3_kstat, NULL); 440 0 stevel field_width = req_width(aclproccnt_v3_kstat, field_width); 441 0 stevel } 442 0 stevel return (field_width); 443 0 stevel } 444 0 stevel 445 0 stevel static int 446 0 stevel getstats_aclreq(void) 447 0 stevel { 448 0 stevel int field_width = 0; 449 0 stevel if (aclreqcnt_v2_kstat != NULL) { 450 0 stevel safe_kstat_read(kc, aclreqcnt_v2_kstat, NULL); 451 0 stevel field_width = req_width(aclreqcnt_v2_kstat, field_width); 452 0 stevel } 453 0 stevel if (aclreqcnt_v3_kstat != NULL) { 454 0 stevel safe_kstat_read(kc, aclreqcnt_v3_kstat, NULL); 455 0 stevel field_width = req_width(aclreqcnt_v3_kstat, field_width); 456 0 stevel } 457 0 stevel return (field_width); 458 0 stevel } 459 0 stevel 460 0 stevel static void 461 0 stevel putstats(void) 462 0 stevel { 463 0 stevel if (rpc_clts_client_kstat != NULL) 464 0 stevel safe_kstat_write(kc, rpc_clts_client_kstat, NULL); 465 0 stevel if (rpc_cots_client_kstat != NULL) 466 0 stevel safe_kstat_write(kc, rpc_cots_client_kstat, NULL); 467 0 stevel if (rpc_rdma_client_kstat != NULL) 468 0 stevel safe_kstat_write(kc, rpc_rdma_client_kstat, NULL); 469 0 stevel if (nfs_client_kstat != NULL) 470 0 stevel safe_kstat_write(kc, nfs_client_kstat, NULL); 471 0 stevel if (nfs4_client_kstat != NULL) 472 0 stevel safe_kstat_write(kc, nfs4_client_kstat, NULL); 473 0 stevel if (rpc_clts_server_kstat != NULL) 474 0 stevel safe_kstat_write(kc, rpc_clts_server_kstat, NULL); 475 0 stevel if (rpc_cots_server_kstat != NULL) 476 0 stevel safe_kstat_write(kc, rpc_cots_server_kstat, NULL); 477 0 stevel if (rpc_rdma_server_kstat != NULL) 478 0 stevel safe_kstat_write(kc, rpc_rdma_server_kstat, NULL); 479 0 stevel if (nfs_server_v2_kstat != NULL) 480 0 stevel safe_kstat_write(kc, nfs_server_v2_kstat, NULL); 481 0 stevel if (nfs_server_v3_kstat != NULL) 482 0 stevel safe_kstat_write(kc, nfs_server_v3_kstat, NULL); 483 0 stevel if (nfs_server_v4_kstat != NULL) 484 0 stevel safe_kstat_write(kc, nfs_server_v4_kstat, NULL); 485 0 stevel if (rfsproccnt_v2_kstat != NULL) 486 0 stevel safe_kstat_write(kc, rfsproccnt_v2_kstat, NULL); 487 0 stevel if (rfsproccnt_v3_kstat != NULL) 488 0 stevel safe_kstat_write(kc, rfsproccnt_v3_kstat, NULL); 489 0 stevel if (rfsproccnt_v4_kstat != NULL) 490 0 stevel safe_kstat_write(kc, rfsproccnt_v4_kstat, NULL); 491 0 stevel if (rfsreqcnt_v2_kstat != NULL) 492 0 stevel safe_kstat_write(kc, rfsreqcnt_v2_kstat, NULL); 493 0 stevel if (rfsreqcnt_v3_kstat != NULL) 494 0 stevel safe_kstat_write(kc, rfsreqcnt_v3_kstat, NULL); 495 0 stevel if (rfsreqcnt_v4_kstat != NULL) 496 0 stevel safe_kstat_write(kc, rfsreqcnt_v4_kstat, NULL); 497 0 stevel if (aclproccnt_v2_kstat != NULL) 498 0 stevel safe_kstat_write(kc, aclproccnt_v2_kstat, NULL); 499 0 stevel if (aclproccnt_v3_kstat != NULL) 500 0 stevel safe_kstat_write(kc, aclproccnt_v3_kstat, NULL); 501 0 stevel if (aclreqcnt_v2_kstat != NULL) 502 0 stevel safe_kstat_write(kc, aclreqcnt_v2_kstat, NULL); 503 0 stevel if (aclreqcnt_v3_kstat != NULL) 504 0 stevel safe_kstat_write(kc, aclreqcnt_v3_kstat, NULL); 505 0 stevel } 506 0 stevel 507 0 stevel static void 508 0 stevel setup(void) 509 0 stevel { 510 0 stevel if ((kc = kstat_open()) == NULL) 511 0 stevel fail(1, "kstat_open(): can't open /dev/kstat"); 512 0 stevel 513 10429 Marcel /* alloc space for our temporary kstat */ 514 10429 Marcel safe_zalloc((void **)&ksum_kstat, sizeof (kstat_t), 0); 515 0 stevel rpc_clts_client_kstat = kstat_lookup(kc, "unix", 0, "rpc_clts_client"); 516 0 stevel rpc_clts_server_kstat = kstat_lookup(kc, "unix", 0, "rpc_clts_server"); 517 0 stevel rpc_cots_client_kstat = kstat_lookup(kc, "unix", 0, "rpc_cots_client"); 518 0 stevel rpc_cots_server_kstat = kstat_lookup(kc, "unix", 0, "rpc_cots_server"); 519 0 stevel rpc_rdma_client_kstat = kstat_lookup(kc, "unix", 0, "rpc_rdma_client"); 520 0 stevel rpc_rdma_server_kstat = kstat_lookup(kc, "unix", 0, "rpc_rdma_server"); 521 0 stevel nfs_client_kstat = kstat_lookup(kc, "nfs", 0, "nfs_client"); 522 0 stevel nfs4_client_kstat = kstat_lookup(kc, "nfs", 0, "nfs4_client"); 523 0 stevel nfs_server_v2_kstat = kstat_lookup(kc, "nfs", 2, "nfs_server"); 524 0 stevel nfs_server_v3_kstat = kstat_lookup(kc, "nfs", 3, "nfs_server"); 525 0 stevel nfs_server_v4_kstat = kstat_lookup(kc, "nfs", 4, "nfs_server"); 526 0 stevel rfsproccnt_v2_kstat = kstat_lookup(kc, "nfs", 0, "rfsproccnt_v2"); 527 0 stevel rfsproccnt_v3_kstat = kstat_lookup(kc, "nfs", 0, "rfsproccnt_v3"); 528 0 stevel rfsproccnt_v4_kstat = kstat_lookup(kc, "nfs", 0, "rfsproccnt_v4"); 529 0 stevel rfsreqcnt_v2_kstat = kstat_lookup(kc, "nfs", 0, "rfsreqcnt_v2"); 530 0 stevel rfsreqcnt_v3_kstat = kstat_lookup(kc, "nfs", 0, "rfsreqcnt_v3"); 531 0 stevel rfsreqcnt_v4_kstat = kstat_lookup(kc, "nfs", 0, "rfsreqcnt_v4"); 532 0 stevel aclproccnt_v2_kstat = kstat_lookup(kc, "nfs_acl", 0, "aclproccnt_v2"); 533 0 stevel aclproccnt_v3_kstat = kstat_lookup(kc, "nfs_acl", 0, "aclproccnt_v3"); 534 0 stevel aclreqcnt_v2_kstat = kstat_lookup(kc, "nfs_acl", 0, "aclreqcnt_v2"); 535 0 stevel aclreqcnt_v3_kstat = kstat_lookup(kc, "nfs_acl", 0, "aclreqcnt_v3"); 536 0 stevel if (rpc_clts_client_kstat == NULL && rpc_cots_server_kstat == NULL && 537 0 stevel rfsproccnt_v2_kstat == NULL && rfsreqcnt_v3_kstat == NULL) 538 0 stevel fail(0, "Multiple kstat lookups failed." 539 3406 th199096 "Your kernel module may not be loaded\n"); 540 0 stevel } 541 0 stevel 542 0 stevel static int 543 0 stevel req_width(kstat_t *req, int field_width) 544 0 stevel { 545 0 stevel int i, nreq, per, len; 546 0 stevel char fixlen[128]; 547 0 stevel kstat_named_t *knp; 548 0 stevel uint64_t tot; 549 0 stevel 550 0 stevel tot = 0; 551 0 stevel knp = KSTAT_NAMED_PTR(req); 552 0 stevel for (i = 0; i < req->ks_ndata; i++) 553 0 stevel tot += knp[i].value.ui64; 554 0 stevel 555 0 stevel knp = kstat_data_lookup(req, "null"); 556 0 stevel nreq = req->ks_ndata - (knp - KSTAT_NAMED_PTR(req)); 557 0 stevel 558 0 stevel for (i = 0; i < nreq; i++) { 559 0 stevel len = strlen(knp[i].name) + 1; 560 0 stevel if (field_width < len) 561 0 stevel field_width = len; 562 0 stevel if (tot) 563 0 stevel per = (int)(knp[i].value.ui64 * 100 / tot); 564 0 stevel else 565 0 stevel per = 0; 566 0 stevel (void) sprintf(fixlen, "%" PRIu64 " %d%%", 567 5302 th199096 knp[i].value.ui64, per); 568 0 stevel len = strlen(fixlen) + 1; 569 0 stevel if (field_width < len) 570 0 stevel field_width = len; 571 0 stevel } 572 0 stevel return (field_width); 573 0 stevel } 574 0 stevel 575 0 stevel static int 576 0 stevel stat_width(kstat_t *req, int field_width) 577 0 stevel { 578 0 stevel int i, nreq, len; 579 0 stevel char fixlen[128]; 580 0 stevel kstat_named_t *knp; 581 0 stevel 582 0 stevel knp = KSTAT_NAMED_PTR(req); 583 0 stevel nreq = req->ks_ndata; 584 0 stevel 585 0 stevel for (i = 0; i < nreq; i++) { 586 0 stevel len = strlen(knp[i].name) + 1; 587 0 stevel if (field_width < len) 588 0 stevel field_width = len; 589 0 stevel (void) sprintf(fixlen, "%" PRIu64, knp[i].value.ui64); 590 0 stevel len = strlen(fixlen) + 1; 591 0 stevel if (field_width < len) 592 0 stevel field_width = len; 593 0 stevel } 594 0 stevel return (field_width); 595 0 stevel } 596 0 stevel 597 0 stevel static void 598 0 stevel cr_print(int zflag) 599 0 stevel { 600 0 stevel int field_width; 601 0 stevel 602 0 stevel field_width = getstats_rpc(); 603 3406 th199096 if (field_width == 0) 604 3406 th199096 return; 605 3406 th199096 606 0 stevel stat_print("\nClient rpc:\nConnection oriented:", 607 5302 th199096 rpc_cots_client_kstat, 608 5302 th199096 &old_rpc_cots_client_kstat.kst, field_width, zflag); 609 0 stevel stat_print("Connectionless:", rpc_clts_client_kstat, 610 5302 th199096 &old_rpc_clts_client_kstat.kst, field_width, zflag); 611 0 stevel stat_print("RDMA based:", rpc_rdma_client_kstat, 612 5302 th199096 &old_rpc_rdma_client_kstat.kst, field_width, zflag); 613 0 stevel } 614 0 stevel 615 0 stevel static void 616 0 stevel sr_print(int zflag) 617 0 stevel { 618 0 stevel int field_width; 619 0 stevel 620 0 stevel field_width = getstats_rpc(); 621 3406 th199096 if (field_width == 0) 622 3406 th199096 return; 623 3406 th199096 624 0 stevel stat_print("\nServer rpc:\nConnection oriented:", rpc_cots_server_kstat, 625 5302 th199096 &old_rpc_cots_server_kstat.kst, field_width, zflag); 626 0 stevel stat_print("Connectionless:", rpc_clts_server_kstat, 627 5302 th199096 &old_rpc_clts_server_kstat.kst, field_width, zflag); 628 0 stevel stat_print("RDMA based:", rpc_rdma_server_kstat, 629 5302 th199096 &old_rpc_rdma_server_kstat.kst, field_width, zflag); 630 0 stevel } 631 0 stevel 632 0 stevel static void 633 0 stevel cn_print(int zflag, int vflag) 634 0 stevel { 635 0 stevel int field_width; 636 0 stevel 637 0 stevel field_width = getstats_nfs(); 638 3406 th199096 if (field_width == 0) 639 3406 th199096 return; 640 0 stevel 641 0 stevel if (vflag == 0) { 642 10265 Krishnendu nfsstat_kstat_sum(nfs_client_kstat, nfs4_client_kstat, 643 10265 Krishnendu ksum_kstat); 644 0 stevel stat_print("\nClient nfs:", ksum_kstat, &old_ksum_kstat.kst, 645 5302 th199096 field_width, zflag); 646 0 stevel } 647 0 stevel 648 0 stevel if (vflag == 2 || vflag == 3) { 649 0 stevel stat_print("\nClient nfs:", nfs_client_kstat, 650 5302 th199096 &old_nfs_client_kstat.kst, field_width, zflag); 651 0 stevel } 652 0 stevel 653 0 stevel if (vflag == 4) { 654 0 stevel stat_print("\nClient nfs:", nfs4_client_kstat, 655 5302 th199096 &old_nfs4_client_kstat.kst, field_width, zflag); 656 0 stevel } 657 0 stevel 658 0 stevel if (vflag == 2 || vflag == 0) { 659 0 stevel field_width = getstats_rfsreq(2); 660 0 stevel req_print(rfsreqcnt_v2_kstat, &old_rfsreqcnt_v2_kstat.kst, 661 5302 th199096 2, field_width, zflag); 662 0 stevel } 663 0 stevel 664 0 stevel if (vflag == 3 || vflag == 0) { 665 0 stevel field_width = getstats_rfsreq(3); 666 0 stevel req_print(rfsreqcnt_v3_kstat, &old_rfsreqcnt_v3_kstat.kst, 3, 667 5302 th199096 field_width, zflag); 668 0 stevel } 669 0 stevel 670 0 stevel if (vflag == 4 || vflag == 0) { 671 0 stevel field_width = getstats_rfsreq(4); 672 0 stevel req_print_v4(rfsreqcnt_v4_kstat, &old_rfsreqcnt_v4_kstat.kst, 673 5302 th199096 field_width, zflag); 674 0 stevel } 675 0 stevel } 676 0 stevel 677 0 stevel static void 678 0 stevel sn_print(int zflag, int vflag) 679 0 stevel { 680 0 stevel int field_width; 681 0 stevel 682 0 stevel field_width = getstats_nfs(); 683 3406 th199096 if (field_width == 0) 684 3406 th199096 return; 685 3406 th199096 686 0 stevel if (vflag == 2 || vflag == 0) { 687 0 stevel stat_print("\nServer NFSv2:", nfs_server_v2_kstat, 688 5302 th199096 &old_nfs_server_v2_kstat.kst, field_width, zflag); 689 0 stevel } 690 0 stevel 691 0 stevel if (vflag == 3 || vflag == 0) { 692 0 stevel stat_print("\nServer NFSv3:", nfs_server_v3_kstat, 693 5302 th199096 &old_nfs_server_v3_kstat.kst, field_width, zflag); 694 0 stevel } 695 0 stevel 696 0 stevel if (vflag == 4 || vflag == 0) { 697 0 stevel stat_print("\nServer NFSv4:", nfs_server_v4_kstat, 698 5302 th199096 &old_nfs_server_v4_kstat.kst, field_width, zflag); 699 0 stevel } 700 0 stevel 701 0 stevel if (vflag == 2 || vflag == 0) { 702 0 stevel field_width = getstats_rfsproc(2); 703 0 stevel req_print(rfsproccnt_v2_kstat, &old_rfsproccnt_v2_kstat.kst, 704 5302 th199096 2, field_width, zflag); 705 0 stevel } 706 0 stevel 707 0 stevel if (vflag == 3 || vflag == 0) { 708 0 stevel field_width = getstats_rfsproc(3); 709 0 stevel req_print(rfsproccnt_v3_kstat, &old_rfsproccnt_v3_kstat.kst, 710 5302 th199096 3, field_width, zflag); 711 0 stevel } 712 0 stevel 713 0 stevel if (vflag == 4 || vflag == 0) { 714 0 stevel field_width = getstats_rfsproc(4); 715 0 stevel req_print_v4(rfsproccnt_v4_kstat, &old_rfsproccnt_v4_kstat.kst, 716 5302 th199096 field_width, zflag); 717 0 stevel } 718 0 stevel } 719 0 stevel 720 0 stevel static void 721 0 stevel ca_print(int zflag, int vflag) 722 0 stevel { 723 0 stevel int field_width; 724 0 stevel 725 0 stevel field_width = getstats_aclreq(); 726 3406 th199096 if (field_width == 0) 727 3406 th199096 return; 728 3406 th199096 729 0 stevel printf("\nClient nfs_acl:\n"); 730 0 stevel 731 0 stevel if (vflag == 2 || vflag == 0) { 732 0 stevel req_print(aclreqcnt_v2_kstat, &old_aclreqcnt_v2_kstat.kst, 2, 733 5302 th199096 field_width, zflag); 734 0 stevel } 735 0 stevel 736 0 stevel if (vflag == 3 || vflag == 0) { 737 0 stevel req_print(aclreqcnt_v3_kstat, &old_aclreqcnt_v3_kstat.kst, 738 5302 th199096 3, field_width, zflag); 739 0 stevel } 740 0 stevel } 741 0 stevel 742 0 stevel static void 743 0 stevel sa_print(int zflag, int vflag) 744 0 stevel { 745 0 stevel int field_width; 746 0 stevel 747 0 stevel field_width = getstats_aclproc(); 748 3406 th199096 if (field_width == 0) 749 3406 th199096 return; 750 0 stevel 751 0 stevel printf("\nServer nfs_acl:\n"); 752 0 stevel 753 0 stevel if (vflag == 2 || vflag == 0) { 754 0 stevel req_print(aclproccnt_v2_kstat, &old_aclproccnt_v2_kstat.kst, 755 5302 th199096 2, field_width, zflag); 756 0 stevel } 757 0 stevel 758 0 stevel if (vflag == 3 || vflag == 0) { 759 0 stevel req_print(aclproccnt_v3_kstat, &old_aclproccnt_v3_kstat.kst, 760 5302 th199096 3, field_width, zflag); 761 0 stevel } 762 0 stevel } 763 0 stevel 764 0 stevel #define MIN(a, b) ((a) < (b) ? (a) : (b)) 765 0 stevel 766 0 stevel static void 767 0 stevel req_print(kstat_t *req, kstat_t *req_old, int ver, int field_width, 768 5302 th199096 int zflag) 769 0 stevel { 770 0 stevel int i, j, nreq, per, ncolumns; 771 0 stevel uint64_t tot, old_tot; 772 0 stevel char fixlen[128]; 773 0 stevel kstat_named_t *knp; 774 0 stevel kstat_named_t *kptr; 775 0 stevel kstat_named_t *knp_old; 776 0 stevel 777 0 stevel if (req == NULL) 778 0 stevel return; 779 0 stevel 780 3406 th199096 if (field_width == 0) 781 3406 th199096 return; 782 3406 th199096 783 0 stevel ncolumns = (MAX_COLUMNS -1)/field_width; 784 0 stevel knp = kstat_data_lookup(req, "null"); 785 0 stevel knp_old = KSTAT_NAMED_PTR(req_old); 786 0 stevel 787 0 stevel kptr = KSTAT_NAMED_PTR(req); 788 0 stevel nreq = req->ks_ndata - (knp - KSTAT_NAMED_PTR(req)); 789 0 stevel 790 0 stevel tot = 0; 791 0 stevel old_tot = 0; 792 0 stevel 793 0 stevel if (knp_old == NULL) { 794 0 stevel old_tot = 0; 795 0 stevel } 796 0 stevel 797 0 stevel for (i = 0; i < req->ks_ndata; i++) 798 0 stevel tot += kptr[i].value.ui64; 799 0 stevel 800 0 stevel if (interval && knp_old != NULL) { 801 0 stevel for (i = 0; i < req_old->ks_ndata; i++) 802 0 stevel old_tot += knp_old[i].value.ui64; 803 0 stevel tot -= old_tot; 804 0 stevel } 805 0 stevel 806 0 stevel printf("Version %d: (%" PRIu64 " calls)\n", ver, tot); 807 0 stevel 808 0 stevel for (i = 0; i < nreq; i += ncolumns) { 809 0 stevel for (j = i; j < MIN(i + ncolumns, nreq); j++) { 810 0 stevel printf("%-*s", field_width, knp[j].name); 811 0 stevel } 812 0 stevel printf("\n"); 813 0 stevel for (j = i; j < MIN(i + ncolumns, nreq); j++) { 814 0 stevel if (tot && interval && knp_old != NULL) 815 0 stevel per = (int)((knp[j].value.ui64 - 816 0 stevel knp_old[j].value.ui64) * 100 / tot); 817 0 stevel else if (tot) 818 0 stevel per = (int)(knp[j].value.ui64 * 100 / tot); 819 0 stevel else 820 0 stevel per = 0; 821 0 stevel (void) sprintf(fixlen, "%" PRIu64 " %d%% ", 822 5302 th199096 ((interval && knp_old != NULL) ? 823 5302 th199096 (knp[j].value.ui64 - knp_old[j].value.ui64) 824 5302 th199096 : knp[j].value.ui64), per); 825 0 stevel printf("%-*s", field_width, fixlen); 826 0 stevel } 827 0 stevel printf("\n"); 828 0 stevel } 829 5998 gt29601 if (zflag) { 830 5998 gt29601 for (i = 0; i < req->ks_ndata; i++) 831 5998 gt29601 knp[i].value.ui64 = 0; 832 5998 gt29601 } 833 5998 gt29601 if (knp_old != NULL) 834 10265 Krishnendu nfsstat_kstat_copy(req, req_old, 1); 835 5998 gt29601 else 836 10265 Krishnendu nfsstat_kstat_copy(req, req_old, 0); 837 0 stevel } 838 0 stevel 839 0 stevel /* 840 0 stevel * Separate version of the req_print() to deal with V4 and its use of 841 0 stevel * procedures and operations. It looks odd to have the counts for 842 0 stevel * both of those lumped into the same set of statistics so this 843 0 stevel * function (copy of req_print() does the separation and titles). 844 0 stevel */ 845 0 stevel 846 0 stevel #define COUNT 2 847 0 stevel 848 0 stevel static void 849 0 stevel req_print_v4(kstat_t *req, kstat_t *req_old, int field_width, int zflag) 850 0 stevel { 851 0 stevel int i, j, nreq, per, ncolumns; 852 0 stevel uint64_t tot, tot_ops, old_tot, old_tot_ops; 853 0 stevel char fixlen[128]; 854 0 stevel kstat_named_t *kptr; 855 0 stevel kstat_named_t *knp; 856 0 stevel kstat_named_t *kptr_old; 857 0 stevel 858 0 stevel if (req == NULL) 859 3406 th199096 return; 860 3406 th199096 861 3406 th199096 if (field_width == 0) 862 0 stevel return; 863 0 stevel 864 0 stevel ncolumns = (MAX_COLUMNS)/field_width; 865 0 stevel kptr = KSTAT_NAMED_PTR(req); 866 0 stevel kptr_old = KSTAT_NAMED_PTR(req_old); 867 0 stevel 868 0 stevel if (kptr_old == NULL) { 869 0 stevel old_tot_ops = 0; 870 0 stevel old_tot = 0; 871 0 stevel } else { 872 0 stevel old_tot = kptr_old[0].value.ui64 + kptr_old[1].value.ui64; 873 0 stevel for (i = 2, old_tot_ops = 0; i < req_old->ks_ndata; i++) 874 0 stevel old_tot_ops += kptr_old[i].value.ui64; 875 0 stevel } 876 0 stevel 877 0 stevel /* Count the number of operations sent */ 878 0 stevel for (i = 2, tot_ops = 0; i < req->ks_ndata; i++) 879 0 stevel tot_ops += kptr[i].value.ui64; 880 0 stevel /* For v4 NULL/COMPOUND are the only procedures */ 881 0 stevel tot = kptr[0].value.ui64 + kptr[1].value.ui64; 882 0 stevel 883 0 stevel if (interval) { 884 0 stevel tot -= old_tot; 885 0 stevel tot_ops -= old_tot_ops; 886 0 stevel } 887 0 stevel 888 0 stevel printf("Version 4: (%" PRIu64 " calls)\n", tot); 889 0 stevel 890 0 stevel knp = kstat_data_lookup(req, "null"); 891 0 stevel nreq = req->ks_ndata - (knp - KSTAT_NAMED_PTR(req)); 892 0 stevel 893 0 stevel for (i = 0; i < COUNT; i += ncolumns) { 894 0 stevel for (j = i; j < MIN(i + ncolumns, 2); j++) { 895 0 stevel printf("%-*s", field_width, knp[j].name); 896 0 stevel } 897 0 stevel printf("\n"); 898 0 stevel for (j = i; j < MIN(i + ncolumns, 2); j++) { 899 0 stevel if (tot && interval && kptr_old != NULL) 900 0 stevel per = (int)((knp[j].value.ui64 - 901 0 stevel kptr_old[j].value.ui64) * 100 / tot); 902 0 stevel else if (tot) 903 0 stevel per = (int)(knp[j].value.ui64 * 100 / tot); 904 0 stevel else 905 0 stevel per = 0; 906 0 stevel (void) sprintf(fixlen, "%" PRIu64 " %d%% ", 907 5302 th199096 ((interval && kptr_old != NULL) ? 908 5302 th199096 (knp[j].value.ui64 - kptr_old[j].value.ui64) 909 5302 th199096 : knp[j].value.ui64), per); 910 0 stevel printf("%-*s", field_width, fixlen); 911 0 stevel } 912 0 stevel printf("\n"); 913 0 stevel } 914 0 stevel 915 0 stevel printf("Version 4: (%" PRIu64 " operations)\n", tot_ops); 916 0 stevel for (i = 2; i < nreq; i += ncolumns) { 917 0 stevel for (j = i; j < MIN(i + ncolumns, nreq); j++) { 918 0 stevel printf("%-*s", field_width, knp[j].name); 919 0 stevel } 920 0 stevel printf("\n"); 921 0 stevel for (j = i; j < MIN(i + ncolumns, nreq); j++) { 922 0 stevel if (tot_ops && interval && kptr_old != NULL) 923 0 stevel per = (int)((knp[j].value.ui64 - 924 0 stevel kptr_old[j].value.ui64) * 100 / tot_ops); 925 0 stevel else if (tot_ops) 926 0 stevel per = (int)(knp[j].value.ui64 * 100 / tot_ops); 927 0 stevel else 928 0 stevel per = 0; 929 0 stevel (void) sprintf(fixlen, "%" PRIu64 " %d%% ", 930 5302 th199096 ((interval && kptr_old != NULL) ? 931 5302 th199096 (knp[j].value.ui64 - kptr_old[j].value.ui64) 932 5302 th199096 : knp[j].value.ui64), per); 933 0 stevel printf("%-*s", field_width, fixlen); 934 0 stevel } 935 0 stevel printf("\n"); 936 0 stevel } 937 0 stevel if (zflag) { 938 0 stevel for (i = 0; i < req->ks_ndata; i++) 939 0 stevel kptr[i].value.ui64 = 0; 940 0 stevel } 941 0 stevel if (kptr_old != NULL) 942 10265 Krishnendu nfsstat_kstat_copy(req, req_old, 1); 943 0 stevel else 944 10265 Krishnendu nfsstat_kstat_copy(req, req_old, 0); 945 0 stevel } 946 0 stevel 947 0 stevel static void 948 0 stevel stat_print(const char *title_string, kstat_t *req, kstat_t *req_old, 949 5302 th199096 int field_width, int zflag) 950 0 stevel { 951 0 stevel int i, j, nreq, ncolumns; 952 0 stevel char fixlen[128]; 953 0 stevel kstat_named_t *knp; 954 0 stevel kstat_named_t *knp_old; 955 0 stevel 956 0 stevel if (req == NULL) 957 0 stevel return; 958 0 stevel 959 3406 th199096 if (field_width == 0) 960 3406 th199096 return; 961 3406 th199096 962 0 stevel printf("%s\n", title_string); 963 0 stevel ncolumns = (MAX_COLUMNS -1)/field_width; 964 0 stevel 965 0 stevel /* MEANS knp = (kstat_named_t *)req->ks_data */ 966 0 stevel knp = KSTAT_NAMED_PTR(req); 967 0 stevel nreq = req->ks_ndata; 968 0 stevel knp_old = KSTAT_NAMED_PTR(req_old); 969 0 stevel 970 0 stevel for (i = 0; i < nreq; i += ncolumns) { 971 0 stevel /* prints out the titles of the columns */ 972 0 stevel for (j = i; j < MIN(i + ncolumns, nreq); j++) { 973 0 stevel printf("%-*s", field_width, knp[j].name); 974 0 stevel } 975 0 stevel printf("\n"); 976 0 stevel /* prints out the stat numbers */ 977 0 stevel for (j = i; j < MIN(i + ncolumns, nreq); j++) { 978 0 stevel (void) sprintf(fixlen, "%" PRIu64 " ", 979 5302 th199096 (interval && knp_old != NULL) ? 980 5302 th199096 (knp[j].value.ui64 - knp_old[j].value.ui64) 981 5302 th199096 : knp[j].value.ui64); 982 0 stevel printf("%-*s", field_width, fixlen); 983 0 stevel } 984 0 stevel printf("\n"); 985 0 stevel 986 0 stevel } 987 0 stevel if (zflag) { 988 0 stevel for (i = 0; i < req->ks_ndata; i++) 989 0 stevel knp[i].value.ui64 = 0; 990 0 stevel } 991 0 stevel 992 0 stevel if (knp_old != NULL) 993 10265 Krishnendu nfsstat_kstat_copy(req, req_old, 1); 994 0 stevel else 995 10265 Krishnendu nfsstat_kstat_copy(req, req_old, 0); 996 0 stevel } 997 3406 th199096 998 0 stevel static void 999 10265 Krishnendu nfsstat_kstat_sum(kstat_t *kstat1, kstat_t *kstat2, kstat_t *sum) 1000 0 stevel { 1001 0 stevel int i; 1002 0 stevel kstat_named_t *knp1, *knp2, *knpsum; 1003 0 stevel if (kstat1 == NULL || kstat2 == NULL) 1004 0 stevel return; 1005 0 stevel 1006 0 stevel knp1 = KSTAT_NAMED_PTR(kstat1); 1007 0 stevel knp2 = KSTAT_NAMED_PTR(kstat2); 1008 0 stevel if (sum->ks_data == NULL) 1009 10265 Krishnendu nfsstat_kstat_copy(kstat1, sum, 0); 1010 0 stevel knpsum = KSTAT_NAMED_PTR(sum); 1011 0 stevel 1012 0 stevel for (i = 0; i < (kstat1->ks_ndata); i++) 1013 0 stevel knpsum[i].value.ui64 = knp1[i].value.ui64 + knp2[i].value.ui64; 1014 0 stevel } 1015 0 stevel 1016 0 stevel /* 1017 0 stevel * my_dir and my_path could be pointers 1018 0 stevel */ 1019 0 stevel struct myrec { 1020 0 stevel ulong_t my_fsid; 1021 0 stevel char my_dir[MAXPATHLEN]; 1022 0 stevel char *my_path; 1023 0 stevel char *ig_path; 1024 0 stevel struct myrec *next; 1025 0 stevel }; 1026 0 stevel 1027 0 stevel /* 1028 0 stevel * Print the mount table info 1029 0 stevel */ 1030 0 stevel static void 1031 0 stevel mi_print(void) 1032 0 stevel { 1033 0 stevel FILE *mt; 1034 0 stevel struct extmnttab m; 1035 0 stevel struct myrec *list, *mrp, *pmrp; 1036 0 stevel char *flavor; 1037 0 stevel int ignored = 0; 1038 0 stevel seconfig_t nfs_sec; 1039 0 stevel kstat_t *ksp; 1040 0 stevel struct mntinfo_kstat mik; 1041 0 stevel int transport_flag = 0; 1042 0 stevel int path_count; 1043 0 stevel int found; 1044 0 stevel char *timer_name[] = { 1045 0 stevel "Lookups", 1046 0 stevel "Reads", 1047 0 stevel "Writes", 1048 0 stevel "All" 1049 0 stevel }; 1050 0 stevel 1051 0 stevel mt = fopen(MNTTAB, "r"); 1052 0 stevel if (mt == NULL) { 1053 0 stevel perror(MNTTAB); 1054 0 stevel exit(0); 1055 0 stevel } 1056 0 stevel 1057 0 stevel list = NULL; 1058 0 stevel resetmnttab(mt); 1059 0 stevel 1060 0 stevel while (getextmntent(mt, &m, sizeof (struct extmnttab)) == 0) { 1061 0 stevel /* ignore non "nfs" and save the "ignore" entries */ 1062 0 stevel if (strcmp(m.mnt_fstype, MNTTYPE_NFS) != 0) 1063 0 stevel continue; 1064 0 stevel /* 1065 0 stevel * Check to see here if user gave a path(s) to 1066 0 stevel * only show the mount point they wanted 1067 0 stevel * Iterate through the list of paths the user gave and see 1068 5302 th199096 * if any of them match our current nfs mount 1069 0 stevel */ 1070 0 stevel if (path[0] != NULL) { 1071 0 stevel found = 0; 1072 0 stevel for (path_count = 0; path[path_count] != NULL; 1073 0 stevel path_count++) { 1074 0 stevel if (strcmp(path[path_count], m.mnt_mountp) 1075 0 stevel == 0) { 1076 0 stevel found = 1; 1077 0 stevel break; 1078 0 stevel } 1079 0 stevel } 1080 0 stevel if (!found) 1081 0 stevel continue; 1082 0 stevel } 1083 0 stevel 1084 0 stevel if ((mrp = malloc(sizeof (struct myrec))) == 0) { 1085 0 stevel fprintf(stderr, "nfsstat: not enough memory\n"); 1086 0 stevel exit(1); 1087 0 stevel } 1088 0 stevel mrp->my_fsid = makedev(m.mnt_major, m.mnt_minor); 1089 0 stevel if (ignore(m.mnt_mntopts)) { 1090 0 stevel /* 1091 0 stevel * ignored entries cannot be ignored for this 1092 0 stevel * option. We have to display the info for this 1093 0 stevel * nfs mount. The ignore is an indication 1094 0 stevel * that the actual mount point is different and 1095 0 stevel * something is in between the nfs mount. 1096 0 stevel * So save the mount point now 1097 0 stevel */ 1098 0 stevel if ((mrp->ig_path = malloc( 1099 5302 th199096 strlen(m.mnt_mountp) + 1)) == 0) { 1100 0 stevel fprintf(stderr, "nfsstat: not enough memory\n"); 1101 0 stevel exit(1); 1102 0 stevel } 1103 0 stevel (void) strcpy(mrp->ig_path, m.mnt_mountp); 1104 0 stevel ignored++; 1105 0 stevel } else { 1106 0 stevel mrp->ig_path = 0; 1107 0 stevel (void) strcpy(mrp->my_dir, m.mnt_mountp); 1108 0 stevel } 1109 0 stevel if ((mrp->my_path = strdup(m.mnt_special)) == NULL) { 1110 0 stevel fprintf(stderr, "nfsstat: not enough memory\n"); 1111 0 stevel exit(1); 1112 0 stevel } 1113 0 stevel mrp->next = list; 1114 0 stevel list = mrp; 1115 0 stevel } 1116 0 stevel 1117 0 stevel /* 1118 0 stevel * If something got ignored, go to the beginning of the mnttab 1119 0 stevel * and look for the cachefs entries since they are the one 1120 0 stevel * causing this. The mount point saved for the ignored entries 1121 0 stevel * is matched against the special to get the actual mount point. 1122 0 stevel * We are interested in the acutal mount point so that the output 1123 0 stevel * look nice too. 1124 0 stevel */ 1125 0 stevel if (ignored) { 1126 0 stevel rewind(mt); 1127 0 stevel resetmnttab(mt); 1128 0 stevel while (getextmntent(mt, &m, sizeof (struct extmnttab)) == 0) { 1129 0 stevel 1130 0 stevel /* ignore non "cachefs" */ 1131 0 stevel if (strcmp(m.mnt_fstype, MNTTYPE_CACHEFS) != 0) 1132 0 stevel continue; 1133 0 stevel 1134 0 stevel for (mrp = list; mrp; mrp = mrp->next) { 1135 0 stevel if (mrp->ig_path == 0) 1136 0 stevel continue; 1137 0 stevel if (strcmp(mrp->ig_path, m.mnt_special) == 0) { 1138 0 stevel mrp->ig_path = 0; 1139 0 stevel (void) strcpy(mrp->my_dir, 1140 5302 th199096 m.mnt_mountp); 1141 0 stevel } 1142 0 stevel } 1143 0 stevel } 1144 0 stevel /* 1145 0 stevel * Now ignored entries which do not have 1146 0 stevel * the my_dir initialized are really ignored; This never 1147 0 stevel * happens unless the mnttab is corrupted. 1148 0 stevel */ 1149 0 stevel for (pmrp = 0, mrp = list; mrp; mrp = mrp->next) { 1150 0 stevel if (mrp->ig_path == 0) 1151 0 stevel pmrp = mrp; 1152 0 stevel else if (pmrp) 1153 0 stevel pmrp->next = mrp->next; 1154 0 stevel else 1155 0 stevel list = mrp->next; 1156 0 stevel } 1157 0 stevel } 1158 0 stevel 1159 0 stevel (void) fclose(mt); 1160 0 stevel 1161 0 stevel 1162 0 stevel for (ksp = kc->kc_chain; ksp; ksp = ksp->ks_next) { 1163 0 stevel int i; 1164 0 stevel 1165 0 stevel if (ksp->ks_type != KSTAT_TYPE_RAW) 1166 0 stevel continue; 1167 0 stevel if (strcmp(ksp->ks_module, "nfs") != 0) 1168 0 stevel continue; 1169 0 stevel if (strcmp(ksp->ks_name, "mntinfo") != 0) 1170 0 stevel continue; 1171 0 stevel 1172 0 stevel for (mrp = list; mrp; mrp = mrp->next) { 1173 0 stevel if ((mrp->my_fsid & MAXMIN) == ksp->ks_instance) 1174 0 stevel break; 1175 0 stevel } 1176 0 stevel if (mrp == 0) 1177 0 stevel continue; 1178 0 stevel 1179 0 stevel if (safe_kstat_read(kc, ksp, &mik) == -1) 1180 0 stevel continue; 1181 0 stevel 1182 0 stevel printf("%s from %s\n", mrp->my_dir, mrp->my_path); 1183 0 stevel 1184 0 stevel /* 1185 0 stevel * for printing rdma transport and provider string. 1186 0 stevel * This way we avoid modifying the kernel mntinfo_kstat 1187 0 stevel * struct for protofmly. 1188 0 stevel */ 1189 0 stevel if (strcmp(mik.mik_proto, "ibtf") == 0) { 1190 0 stevel printf(" Flags: vers=%u,proto=rdma", 1191 0 stevel mik.mik_vers); 1192 0 stevel transport_flag = 1; 1193 0 stevel } else { 1194 0 stevel printf(" Flags: vers=%u,proto=%s", 1195 0 stevel mik.mik_vers, mik.mik_proto); 1196 0 stevel transport_flag = 0; 1197 0 stevel } 1198 0 stevel 1199 0 stevel /* 1200 0 stevel * get the secmode name from /etc/nfssec.conf. 1201 0 stevel */ 1202 0 stevel if (!nfs_getseconfig_bynumber(mik.mik_secmod, &nfs_sec)) { 1203 0 stevel flavor = nfs_sec.sc_name; 1204 0 stevel } else 1205 0 stevel flavor = NULL; 1206 0 stevel 1207 0 stevel if (flavor != NULL) 1208 0 stevel printf(",sec=%s", flavor); 1209 0 stevel else 1210 0 stevel printf(",sec#=%d", mik.mik_secmod); 1211 0 stevel 1212 0 stevel printf(",%s", (mik.mik_flags & MI_HARD) ? "hard" : "soft"); 1213 0 stevel if (mik.mik_flags & MI_PRINTED) 1214 0 stevel printf(",printed"); 1215 0 stevel printf(",%s", (mik.mik_flags & MI_INT) ? "intr" : "nointr"); 1216 0 stevel if (mik.mik_flags & MI_DOWN) 1217 0 stevel printf(",down"); 1218 0 stevel if (mik.mik_flags & MI_NOAC) 1219 0 stevel printf(",noac"); 1220 0 stevel if (mik.mik_flags & MI_NOCTO) 1221 0 stevel printf(",nocto"); 1222 0 stevel if (mik.mik_flags & MI_DYNAMIC) 1223 0 stevel printf(",dynamic"); 1224 0 stevel if (mik.mik_flags & MI_LLOCK) 1225 0 stevel printf(",llock"); 1226 0 stevel if (mik.mik_flags & MI_GRPID) 1227 0 stevel printf(",grpid"); 1228 0 stevel if (mik.mik_flags & MI_RPCTIMESYNC) 1229 0 stevel printf(",rpctimesync"); 1230 0 stevel if (mik.mik_flags & MI_LINK) 1231 0 stevel printf(",link"); 1232 0 stevel if (mik.mik_flags & MI_SYMLINK) 1233 0 stevel printf(",symlink"); 1234 5897 th199096 if (mik.mik_vers < NFS_V4 && mik.mik_flags & MI_READDIRONLY) 1235 0 stevel printf(",readdironly"); 1236 0 stevel if (mik.mik_flags & MI_ACL) 1237 0 stevel printf(",acl"); 1238 10924 Marcel if (mik.mik_flags & MI_DIRECTIO) 1239 10924 Marcel printf(",forcedirectio"); 1240 0 stevel 1241 5302 th199096 if (mik.mik_vers >= NFS_V4) { 1242 5302 th199096 if (mik.mik_flags & MI4_MIRRORMOUNT) 1243 5302 th199096 printf(",mirrormount"); 1244 5302 th199096 } 1245 5302 th199096 1246 0 stevel printf(",rsize=%d,wsize=%d,retrans=%d,timeo=%d", 1247 5302 th199096 mik.mik_curread, mik.mik_curwrite, mik.mik_retrans, 1248 5302 th199096 mik.mik_timeo); 1249 0 stevel printf("\n"); 1250 0 stevel printf(" Attr cache: acregmin=%d,acregmax=%d" 1251 5302 th199096 ",acdirmin=%d,acdirmax=%d\n", mik.mik_acregmin, 1252 5302 th199096 mik.mik_acregmax, mik.mik_acdirmin, mik.mik_acdirmax); 1253 0 stevel 1254 0 stevel if (transport_flag) { 1255 0 stevel printf(" Transport: proto=rdma, plugin=%s\n", 1256 0 stevel mik.mik_proto); 1257 0 stevel } 1258 0 stevel 1259 0 stevel #define srtt_to_ms(x) x, (x * 2 + x / 2) 1260 0 stevel #define dev_to_ms(x) x, (x * 5) 1261 0 stevel 1262 0 stevel for (i = 0; i < NFS_CALLTYPES + 1; i++) { 1263 0 stevel int j; 1264 0 stevel 1265 0 stevel j = (i == NFS_CALLTYPES ? i - 1 : i); 1266 0 stevel if (mik.mik_timers[j].srtt || 1267 0 stevel mik.mik_timers[j].rtxcur) { 1268 5302 th199096 printf(" %s: srtt=%d (%dms), " 1269 5302 th199096 "dev=%d (%dms), cur=%u (%ums)\n", 1270 5302 th199096 timer_name[i], 1271 5302 th199096 srtt_to_ms(mik.mik_timers[i].srtt), 1272 5302 th199096 dev_to_ms(mik.mik_timers[i].deviate), 1273 5302 th199096 mik.mik_timers[i].rtxcur, 1274 5302 th199096 mik.mik_timers[i].rtxcur * 20); 1275 0 stevel } 1276 0 stevel } 1277 0 stevel 1278 0 stevel if (strchr(mrp->my_path, ',')) 1279 0 stevel printf( 1280 0 stevel " Failover: noresponse=%d,failover=%d," 1281 0 stevel "remap=%d,currserver=%s\n", 1282 0 stevel mik.mik_noresponse, mik.mik_failover, 1283 0 stevel mik.mik_remap, mik.mik_curserver); 1284 0 stevel printf("\n"); 1285 0 stevel } 1286 0 stevel } 1287 0 stevel 1288 0 stevel static char *mntopts[] = { MNTOPT_IGNORE, MNTOPT_DEV, NULL }; 1289 0 stevel #define IGNORE 0 1290 0 stevel #define DEV 1 1291 0 stevel 1292 0 stevel /* 1293 0 stevel * Return 1 if "ignore" appears in the options string 1294 0 stevel */ 1295 0 stevel static int 1296 0 stevel ignore(char *opts) 1297 0 stevel { 1298 0 stevel char *value; 1299 0 stevel char *s; 1300 0 stevel 1301 0 stevel if (opts == NULL) 1302 0 stevel return (0); 1303 0 stevel s = strdup(opts); 1304 0 stevel if (s == NULL) 1305 0 stevel return (0); 1306 0 stevel opts = s; 1307 0 stevel 1308 0 stevel while (*opts != '\0') { 1309 0 stevel if (getsubopt(&opts, mntopts, &value) == IGNORE) { 1310 0 stevel free(s); 1311 0 stevel return (1); 1312 0 stevel } 1313 0 stevel } 1314 0 stevel 1315 0 stevel free(s); 1316 0 stevel return (0); 1317 0 stevel } 1318 0 stevel 1319 0 stevel void 1320 0 stevel usage(void) 1321 0 stevel { 1322 0 stevel fprintf(stderr, "Usage: nfsstat [-cnrsza [-v version] " 1323 10265 Krishnendu "[-T d|u] [interval [count]]\n"); 1324 0 stevel fprintf(stderr, "Usage: nfsstat -m [pathname..]\n"); 1325 0 stevel exit(1); 1326 0 stevel } 1327 0 stevel 1328 10265 Krishnendu void 1329 0 stevel fail(int do_perror, char *message, ...) 1330 0 stevel { 1331 0 stevel va_list args; 1332 0 stevel 1333 0 stevel va_start(args, message); 1334 0 stevel fprintf(stderr, "nfsstat: "); 1335 0 stevel vfprintf(stderr, message, args); 1336 0 stevel va_end(args); 1337 0 stevel if (do_perror) 1338 0 stevel fprintf(stderr, ": %s", strerror(errno)); 1339 0 stevel fprintf(stderr, "\n"); 1340 0 stevel exit(1); 1341 0 stevel } 1342 0 stevel 1343 0 stevel kid_t 1344 0 stevel safe_kstat_read(kstat_ctl_t *kc, kstat_t *ksp, void *data) 1345 0 stevel { 1346 0 stevel kid_t kstat_chain_id = kstat_read(kc, ksp, data); 1347 0 stevel 1348 0 stevel if (kstat_chain_id == -1) 1349 0 stevel fail(1, "kstat_read(%x, '%s') failed", kc, ksp->ks_name); 1350 0 stevel return (kstat_chain_id); 1351 0 stevel } 1352 0 stevel 1353 0 stevel kid_t 1354 0 stevel safe_kstat_write(kstat_ctl_t *kc, kstat_t *ksp, void *data) 1355 0 stevel { 1356 0 stevel kid_t kstat_chain_id = 0; 1357 0 stevel 1358 0 stevel if (ksp->ks_data != NULL) { 1359 0 stevel kstat_chain_id = kstat_write(kc, ksp, data); 1360 0 stevel 1361 0 stevel if (kstat_chain_id == -1) 1362 0 stevel fail(1, "kstat_write(%x, '%s') failed", kc, 1363 0 stevel ksp->ks_name); 1364 0 stevel } 1365 0 stevel return (kstat_chain_id); 1366 0 stevel } 1367 0 stevel 1368 0 stevel void 1369 0 stevel stats_timer(int interval) 1370 0 stevel { 1371 0 stevel timer_t t_id; 1372 0 stevel itimerspec_t time_struct; 1373 0 stevel struct sigevent sig_struct; 1374 0 stevel struct sigaction act; 1375 0 stevel 1376 0 stevel bzero(&sig_struct, sizeof (struct sigevent)); 1377 0 stevel bzero(&act, sizeof (struct sigaction)); 1378 0 stevel 1379 0 stevel /* Create timer */ 1380 0 stevel sig_struct.sigev_notify = SIGEV_SIGNAL; 1381 0 stevel sig_struct.sigev_signo = SIGUSR1; 1382 0 stevel sig_struct.sigev_value.sival_int = 0; 1383 0 stevel 1384 0 stevel if (timer_create(CLOCK_REALTIME, &sig_struct, &t_id) != 0) { 1385 0 stevel fail(1, "Timer creation failed"); 1386 0 stevel } 1387 0 stevel 1388 0 stevel act.sa_handler = handle_sig; 1389 0 stevel 1390 0 stevel if (sigaction(SIGUSR1, &act, NULL) != 0) { 1391 0 stevel fail(1, "Could not set up signal handler"); 1392 0 stevel } 1393 0 stevel 1394 0 stevel time_struct.it_value.tv_sec = interval; 1395 0 stevel time_struct.it_value.tv_nsec = 0; 1396 0 stevel time_struct.it_interval.tv_sec = interval; 1397 0 stevel time_struct.it_interval.tv_nsec = 0; 1398 0 stevel 1399 0 stevel /* Arm timer */ 1400 0 stevel if ((timer_settime(t_id, 0, &time_struct, NULL)) != 0) { 1401 0 stevel fail(1, "Setting timer failed"); 1402 0 stevel } 1403 0 stevel } 1404 0 stevel 1405 0 stevel void 1406 0 stevel handle_sig(int x) 1407 0 stevel { 1408 0 stevel } 1409 0 stevel 1410 0 stevel static void 1411 10265 Krishnendu nfsstat_kstat_copy(kstat_t *src, kstat_t *dst, int fr) 1412 0 stevel { 1413 0 stevel 1414 0 stevel if (fr) 1415 0 stevel free(dst->ks_data); 1416 0 stevel 1417 0 stevel *dst = *src; 1418 0 stevel 1419 0 stevel if (src->ks_data != NULL) { 1420 0 stevel safe_zalloc(&dst->ks_data, src->ks_data_size, 0); 1421 0 stevel (void) memcpy(dst->ks_data, src->ks_data, src->ks_data_size); 1422 0 stevel } else { 1423 0 stevel dst->ks_data = NULL; 1424 0 stevel dst->ks_data_size = 0; 1425 0 stevel } 1426 0 stevel } 1427 0 stevel 1428 0 stevel /* 1429 10429 Marcel * "Safe" allocators - if we return we're guaranteed to have the desired space 1430 10429 Marcel * allocated and zero-filled. We exit via fail if we can't get the space. 1431 0 stevel */ 1432 0 stevel void 1433 0 stevel safe_zalloc(void **ptr, uint_t size, int free_first) 1434 0 stevel { 1435 10429 Marcel if (ptr == NULL) 1436 0 stevel fail(1, "invalid pointer"); 1437 0 stevel if (free_first && *ptr != NULL) 1438 0 stevel free(*ptr); 1439 0 stevel if ((*ptr = (void *)malloc(size)) == NULL) 1440 0 stevel fail(1, "malloc failed"); 1441 0 stevel (void) memset(*ptr, 0, size); 1442 0 stevel } 1443 0 stevel 1444 0 stevel static int 1445 0 stevel safe_strtoi(char const *val, char *errmsg) 1446 0 stevel { 1447 0 stevel char *end; 1448 0 stevel long tmp; 1449 0 stevel errno = 0; 1450 0 stevel tmp = strtol(val, &end, 10); 1451 0 stevel if (*end != '\0' || errno) 1452 0 stevel fail(0, "%s %s", errmsg, val); 1453 0 stevel return ((int)tmp); 1454 0 stevel } 1455