1 /* 2 * This file and its contents are supplied under the terms of the 3 * Common Development and Distribution License ("CDDL"), version 1.0. 4 * You may only use this file in accordance with the terms of version 5 * 1.0 of the CDDL. 6 * 7 * A full copy of the text of the CDDL should have accompanied this 8 * source. A copy of the CDDL is also available via the Internet at 9 * http://www.illumos.org/license/CDDL. 10 */ 11 /* 12 * Copyright 2021 Tintri by DDN, Inc. All rights reserved. 13 */ 14 15 #include <sys/mdb_modapi.h> 16 #include <sys/list.h> 17 #include <nfs/rnode.h> 18 #include <nfs/rnode4.h> 19 #include <nfs/nfs_clnt.h> 20 #include <nfs/nfs4_clnt.h> 21 #include <mdb/mdb_ks.h> 22 #include <mdb/mdb_ctf.h> 23 24 #include "nfs_clnt.h" 25 #include "common.h" 26 27 /* 28 * Common functions 29 */ 30 31 static void 32 nfs_print_io_stat(uintptr_t kstat_addr) 33 { 34 kstat_t kstat; 35 kstat_io_t kstat_io; 36 37 mdb_printf("IO statistics for this mount:\n"); 38 mdb_inc_indent(2); 39 40 if (mdb_vread(&kstat, sizeof (kstat), kstat_addr) == -1 || 41 mdb_vread(&kstat_io, sizeof (kstat_io), 42 (uintptr_t)KSTAT_IO_PTR(&kstat)) == -1) { 43 mdb_printf("No. of bytes read: %9s\n", "??"); 44 mdb_printf("No. of read operations: %9s\n", "??"); 45 mdb_printf("No. of bytes written: %9s\n", "??"); 46 mdb_printf("No. of write operations: %9s\n", "??"); 47 } else { 48 mdb_printf("No. of bytes read: %9llu\n", kstat_io.nread); 49 mdb_printf("No. of read operations: %9lu\n", kstat_io.reads); 50 mdb_printf("No. of bytes written: %9llu\n", 51 kstat_io.nwritten); 52 mdb_printf("No. of write operations: %9lu\n", kstat_io.writes); 53 } 54 55 mdb_dec_indent(2); 56 } 57 58 static int 59 walk_count_cb(uintptr_t addr, const void *data, void *cb_data) 60 { 61 (*(size_t *)cb_data)++; 62 return (WALK_NEXT); 63 } 64 65 #define TBL_ENTRY(e) {#e, e} 66 67 static const struct { 68 const char *str; 69 nfs_opnum4 op; 70 } nfs4_op_tbl[] = { 71 TBL_ENTRY(OP_ACCESS), 72 TBL_ENTRY(OP_CLOSE), 73 TBL_ENTRY(OP_COMMIT), 74 TBL_ENTRY(OP_CREATE), 75 TBL_ENTRY(OP_DELEGPURGE), 76 TBL_ENTRY(OP_DELEGRETURN), 77 TBL_ENTRY(OP_GETATTR), 78 TBL_ENTRY(OP_GETFH), 79 TBL_ENTRY(OP_LINK), 80 TBL_ENTRY(OP_LOCK), 81 TBL_ENTRY(OP_LOCKT), 82 TBL_ENTRY(OP_LOCKU), 83 TBL_ENTRY(OP_LOOKUP), 84 TBL_ENTRY(OP_LOOKUPP), 85 TBL_ENTRY(OP_NVERIFY), 86 TBL_ENTRY(OP_OPEN), 87 TBL_ENTRY(OP_OPENATTR), 88 TBL_ENTRY(OP_OPEN_CONFIRM), 89 TBL_ENTRY(OP_OPEN_DOWNGRADE), 90 TBL_ENTRY(OP_PUTFH), 91 TBL_ENTRY(OP_PUTPUBFH), 92 TBL_ENTRY(OP_PUTROOTFH), 93 TBL_ENTRY(OP_READ), 94 TBL_ENTRY(OP_READDIR), 95 TBL_ENTRY(OP_READLINK), 96 TBL_ENTRY(OP_REMOVE), 97 TBL_ENTRY(OP_RENAME), 98 TBL_ENTRY(OP_RENEW), 99 TBL_ENTRY(OP_RESTOREFH), 100 TBL_ENTRY(OP_SAVEFH), 101 TBL_ENTRY(OP_SECINFO), 102 TBL_ENTRY(OP_SETATTR), 103 TBL_ENTRY(OP_SETCLIENTID), 104 TBL_ENTRY(OP_SETCLIENTID_CONFIRM), 105 TBL_ENTRY(OP_VERIFY), 106 TBL_ENTRY(OP_WRITE), 107 TBL_ENTRY(OP_RELEASE_LOCKOWNER), 108 TBL_ENTRY(OP_ILLEGAL), 109 TBL_ENTRY(OP_CCREATE), 110 TBL_ENTRY(OP_CLINK), 111 TBL_ENTRY(OP_CLOOKUP), 112 TBL_ENTRY(OP_COPEN), 113 TBL_ENTRY(OP_CPUTFH), 114 TBL_ENTRY(OP_CREMOVE), 115 TBL_ENTRY(OP_CRENAME), 116 TBL_ENTRY(OP_CSECINFO), 117 {NULL} 118 }; 119 120 static const char * 121 nfs4_op_str(nfs_opnum4 op) 122 { 123 int i; 124 125 for (i = 0; nfs4_op_tbl[i].str != NULL; i++) 126 if (nfs4_op_tbl[i].op == op) 127 return (nfs4_op_tbl[i].str); 128 129 return ("??"); 130 } 131 132 static const struct { 133 const char *str; 134 nfs4_recov_t action; 135 } nfs4_recov_tbl[] = { 136 TBL_ENTRY(NR_UNUSED), 137 TBL_ENTRY(NR_CLIENTID), 138 TBL_ENTRY(NR_OPENFILES), 139 TBL_ENTRY(NR_FHEXPIRED), 140 TBL_ENTRY(NR_FAILOVER), 141 TBL_ENTRY(NR_WRONGSEC), 142 TBL_ENTRY(NR_EXPIRED), 143 TBL_ENTRY(NR_BAD_STATEID), 144 TBL_ENTRY(NR_BADHANDLE), 145 TBL_ENTRY(NR_BAD_SEQID), 146 TBL_ENTRY(NR_OLDSTATEID), 147 TBL_ENTRY(NR_GRACE), 148 TBL_ENTRY(NR_DELAY), 149 TBL_ENTRY(NR_LOST_LOCK), 150 TBL_ENTRY(NR_LOST_STATE_RQST), 151 TBL_ENTRY(NR_STALE), 152 TBL_ENTRY(NR_MOVED), 153 {NULL} 154 }; 155 156 static const char * 157 nfs4_recov_str(nfs4_recov_t action) 158 { 159 int i; 160 161 for (i = 0; nfs4_recov_tbl[i].str != NULL; i++) 162 if (nfs4_recov_tbl[i].action == action) 163 return (nfs4_recov_tbl[i].str); 164 165 return ("??"); 166 } 167 168 static const struct { 169 const char *str; 170 nfsstat4 stat; 171 } nfs4_stat_tbl[] = { 172 TBL_ENTRY(NFS4_OK), 173 TBL_ENTRY(NFS4ERR_PERM), 174 TBL_ENTRY(NFS4ERR_NOENT), 175 TBL_ENTRY(NFS4ERR_IO), 176 TBL_ENTRY(NFS4ERR_NXIO), 177 TBL_ENTRY(NFS4ERR_ACCESS), 178 TBL_ENTRY(NFS4ERR_EXIST), 179 TBL_ENTRY(NFS4ERR_XDEV), 180 TBL_ENTRY(NFS4ERR_NOTDIR), 181 TBL_ENTRY(NFS4ERR_ISDIR), 182 TBL_ENTRY(NFS4ERR_INVAL), 183 TBL_ENTRY(NFS4ERR_FBIG), 184 TBL_ENTRY(NFS4ERR_NOSPC), 185 TBL_ENTRY(NFS4ERR_ROFS), 186 TBL_ENTRY(NFS4ERR_MLINK), 187 TBL_ENTRY(NFS4ERR_NAMETOOLONG), 188 TBL_ENTRY(NFS4ERR_NOTEMPTY), 189 TBL_ENTRY(NFS4ERR_DQUOT), 190 TBL_ENTRY(NFS4ERR_STALE), 191 TBL_ENTRY(NFS4ERR_BADHANDLE), 192 TBL_ENTRY(NFS4ERR_BAD_COOKIE), 193 TBL_ENTRY(NFS4ERR_NOTSUPP), 194 TBL_ENTRY(NFS4ERR_TOOSMALL), 195 TBL_ENTRY(NFS4ERR_SERVERFAULT), 196 TBL_ENTRY(NFS4ERR_BADTYPE), 197 TBL_ENTRY(NFS4ERR_DELAY), 198 TBL_ENTRY(NFS4ERR_SAME), 199 TBL_ENTRY(NFS4ERR_DENIED), 200 TBL_ENTRY(NFS4ERR_EXPIRED), 201 TBL_ENTRY(NFS4ERR_LOCKED), 202 TBL_ENTRY(NFS4ERR_GRACE), 203 TBL_ENTRY(NFS4ERR_FHEXPIRED), 204 TBL_ENTRY(NFS4ERR_SHARE_DENIED), 205 TBL_ENTRY(NFS4ERR_WRONGSEC), 206 TBL_ENTRY(NFS4ERR_CLID_INUSE), 207 TBL_ENTRY(NFS4ERR_RESOURCE), 208 TBL_ENTRY(NFS4ERR_MOVED), 209 TBL_ENTRY(NFS4ERR_NOFILEHANDLE), 210 TBL_ENTRY(NFS4ERR_MINOR_VERS_MISMATCH), 211 TBL_ENTRY(NFS4ERR_STALE_CLIENTID), 212 TBL_ENTRY(NFS4ERR_STALE_STATEID), 213 TBL_ENTRY(NFS4ERR_OLD_STATEID), 214 TBL_ENTRY(NFS4ERR_BAD_STATEID), 215 TBL_ENTRY(NFS4ERR_BAD_SEQID), 216 TBL_ENTRY(NFS4ERR_NOT_SAME), 217 TBL_ENTRY(NFS4ERR_LOCK_RANGE), 218 TBL_ENTRY(NFS4ERR_SYMLINK), 219 TBL_ENTRY(NFS4ERR_RESTOREFH), 220 TBL_ENTRY(NFS4ERR_LEASE_MOVED), 221 TBL_ENTRY(NFS4ERR_ATTRNOTSUPP), 222 TBL_ENTRY(NFS4ERR_NO_GRACE), 223 TBL_ENTRY(NFS4ERR_RECLAIM_BAD), 224 TBL_ENTRY(NFS4ERR_RECLAIM_CONFLICT), 225 TBL_ENTRY(NFS4ERR_BADXDR), 226 TBL_ENTRY(NFS4ERR_LOCKS_HELD), 227 TBL_ENTRY(NFS4ERR_OPENMODE), 228 TBL_ENTRY(NFS4ERR_BADOWNER), 229 TBL_ENTRY(NFS4ERR_BADCHAR), 230 TBL_ENTRY(NFS4ERR_BADNAME), 231 TBL_ENTRY(NFS4ERR_BAD_RANGE), 232 TBL_ENTRY(NFS4ERR_LOCK_NOTSUPP), 233 TBL_ENTRY(NFS4ERR_OP_ILLEGAL), 234 TBL_ENTRY(NFS4ERR_DEADLOCK), 235 TBL_ENTRY(NFS4ERR_FILE_OPEN), 236 TBL_ENTRY(NFS4ERR_ADMIN_REVOKED), 237 TBL_ENTRY(NFS4ERR_CB_PATH_DOWN), 238 {NULL} 239 }; 240 241 static const char * 242 nfs4_stat_str(nfsstat4 stat) 243 { 244 int i; 245 246 for (i = 0; nfs4_stat_tbl[i].str != NULL; i++) 247 if (nfs4_stat_tbl[i].stat == stat) 248 return (nfs4_stat_tbl[i].str); 249 250 return ("??"); 251 } 252 253 static const struct { 254 const char *str; 255 nfs4_tag_type_t tt; 256 } nfs4_tag_tbl[] = { 257 {"", TAG_NONE}, 258 {"access", TAG_ACCESS}, 259 {"close", TAG_CLOSE}, 260 {"lost close", TAG_CLOSE_LOST}, 261 {"undo close", TAG_CLOSE_UNDO}, 262 {"commit", TAG_COMMIT}, 263 {"delegreturn", TAG_DELEGRETURN}, 264 {"fsinfo", TAG_FSINFO}, 265 {"get symlink text", TAG_GET_SYMLINK}, 266 {"getattr", TAG_GETATTR}, 267 {"getattr fslocation", TAG_GETATTR_FSLOCATION}, 268 {"inactive", TAG_INACTIVE}, 269 {"link", TAG_LINK}, 270 {"lock", TAG_LOCK}, 271 {"reclaim lock", TAG_LOCK_RECLAIM}, 272 {"resend lock", TAG_LOCK_RESEND}, 273 {"reinstate lock", TAG_LOCK_REINSTATE}, 274 {"unknown lock", TAG_LOCK_UNKNOWN}, 275 {"lock test", TAG_LOCKT}, 276 {"unlock", TAG_LOCKU}, 277 {"resend locku", TAG_LOCKU_RESEND}, 278 {"reinstate unlock", TAG_LOCKU_REINSTATE}, 279 {"lookup", TAG_LOOKUP}, 280 {"lookup parent", TAG_LOOKUP_PARENT}, 281 {"lookup valid", TAG_LOOKUP_VALID}, 282 {"lookup valid parent", TAG_LOOKUP_VPARENT}, 283 {"mkdir", TAG_MKDIR}, 284 {"mknod", TAG_MKNOD}, 285 {"mount", TAG_MOUNT}, 286 {"open", TAG_OPEN}, 287 {"open confirm", TAG_OPEN_CONFIRM}, 288 {"lost open confirm", TAG_OPEN_CONFIRM_LOST}, 289 {"open downgrade", TAG_OPEN_DG}, 290 {"lost open downgrade", TAG_OPEN_DG_LOST}, 291 {"lost open", TAG_OPEN_LOST}, 292 {"openattr", TAG_OPENATTR}, 293 {"pathconf", TAG_PATHCONF}, 294 {"putrootfh", TAG_PUTROOTFH}, 295 {"read", TAG_READ}, 296 {"readahead", TAG_READAHEAD}, 297 {"readdir", TAG_READDIR}, 298 {"readlink", TAG_READLINK}, 299 {"relock", TAG_RELOCK}, 300 {"remap lookup", TAG_REMAP_LOOKUP}, 301 {"remap lookup attr dir", TAG_REMAP_LOOKUP_AD}, 302 {"remap lookup named attrs", TAG_REMAP_LOOKUP_NA}, 303 {"remap mount", TAG_REMAP_MOUNT}, 304 {"rmdir", TAG_RMDIR}, 305 {"remove", TAG_REMOVE}, 306 {"rename", TAG_RENAME}, 307 {"rename volatile fh", TAG_RENAME_VFH}, 308 {"renew", TAG_RENEW}, 309 {"reopen", TAG_REOPEN}, 310 {"lost reopen", TAG_REOPEN_LOST}, 311 {"secinfo", TAG_SECINFO}, 312 {"setattr", TAG_SETATTR}, 313 {"setclientid", TAG_SETCLIENTID}, 314 {"setclientid_confirm", TAG_SETCLIENTID_CF}, 315 {"symlink", TAG_SYMLINK}, 316 {"write", TAG_WRITE}, 317 {NULL, 0} 318 }; 319 320 static const char * 321 nfs4_tag_str(nfs4_tag_type_t tt) 322 { 323 int i; 324 325 for (i = 0; nfs4_tag_tbl[i].str != NULL; i++) 326 if (nfs4_tag_tbl[i].tt == tt) 327 return (nfs4_tag_tbl[i].str); 328 329 return ("??"); 330 } 331 332 /* 333 * nfs_mntinfo dcmd implementation 334 */ 335 336 static const mdb_bitmask_t nfs_mi_flags[] = { 337 {"MI_HARD", MI_HARD, MI_HARD}, 338 {"MI_PRINTED", MI_PRINTED, MI_PRINTED}, 339 {"MI_INT", MI_INT, MI_INT}, 340 {"MI_DOWN", MI_DOWN, MI_DOWN}, 341 {"MI_NOAC", MI_NOAC, MI_NOAC}, 342 {"MI_NOCTO", MI_NOCTO, MI_NOCTO}, 343 {"MI_DYNAMIC", MI_DYNAMIC, MI_DYNAMIC}, 344 {"MI_LLOCK", MI_LLOCK, MI_LLOCK}, 345 {"MI_GRPID", MI_GRPID, MI_GRPID}, 346 {"MI_RPCTIMESYNC", MI_RPCTIMESYNC, MI_RPCTIMESYNC}, 347 {"MI_LINK", MI_LINK, MI_LINK}, 348 {"MI_SYMLINK", MI_SYMLINK, MI_SYMLINK}, 349 {"MI_READDIRONLY", MI_READDIRONLY, MI_READDIRONLY}, 350 {"MI_ACL", MI_ACL, MI_ACL}, 351 {"MI_BINDINPROG", MI_BINDINPROG, MI_BINDINPROG}, 352 {"MI_LOOPBACK", MI_LOOPBACK, MI_LOOPBACK}, 353 {"MI_SEMISOFT", MI_SEMISOFT, MI_SEMISOFT}, 354 {"MI_NOPRINT", MI_NOPRINT, MI_NOPRINT}, 355 {"MI_DIRECTIO", MI_DIRECTIO, MI_DIRECTIO}, 356 {"MI_EXTATTR", MI_EXTATTR, MI_EXTATTR}, 357 {"MI_ASYNC_MGR_STOP", MI_ASYNC_MGR_STOP, MI_ASYNC_MGR_STOP}, 358 {"MI_DEAD", MI_DEAD, MI_DEAD}, 359 {NULL, 0, 0} 360 }; 361 362 static int 363 nfs_print_mntinfo_cb(uintptr_t addr, const void *data, void *cb_data) 364 { 365 const mntinfo_t *mi = data; 366 uintptr_t nfs3_ops; 367 vfs_t vfs; 368 char buf[MAXPATHLEN]; 369 uint_t opt_v = *(uint_t *)cb_data; 370 int i; 371 372 if (mdb_readvar(&nfs3_ops, "nfs3_vfsops") == -1) { 373 mdb_warn("failed to read %s", "nfs3_vfsops"); 374 return (WALK_ERR); 375 } 376 377 if (mdb_vread(&vfs, sizeof (vfs), (uintptr_t)mi->mi_vfsp) == -1) { 378 mdb_warn("failed to read vfs_t at %p", mi->mi_vfsp); 379 return (WALK_ERR); 380 } 381 382 mdb_printf("NFS Version: %d\n", 383 nfs3_ops == (uintptr_t)vfs.vfs_op ? 3 : 2); 384 mdb_inc_indent(2); 385 386 mdb_printf("mi_flags: %b\n", mi->mi_flags, nfs_mi_flags); 387 if (mdb_read_refstr((uintptr_t)vfs.vfs_mntpt, buf, 388 sizeof (buf)) == -1) 389 strcpy(buf, "??"); 390 mdb_printf("mount point: %s\n", buf); 391 if (mdb_read_refstr((uintptr_t)vfs.vfs_resource, buf, 392 sizeof (buf)) == -1) 393 strcpy(buf, "??"); 394 mdb_printf("mount from: %s\n", buf); 395 396 mdb_dec_indent(2); 397 mdb_printf("\n"); 398 399 if (!opt_v) 400 return (WALK_NEXT); 401 402 mdb_inc_indent(2); 403 404 mdb_printf("mi_zone = %p\n", mi->mi_zone); 405 mdb_printf("mi_curread = %i, mi_curwrite = %i, mi_retrans = %i, " 406 "mi_timeo = %i\n", mi->mi_curread, mi->mi_curwrite, mi->mi_retrans, 407 mi->mi_timeo); 408 mdb_printf("mi_acregmin = %lu, mi_acregmax = %lu, mi_acdirmin = %lu, " 409 "mi_acdirmax = %lu\n", mi->mi_acregmin, mi->mi_acregmax, 410 mi->mi_acdirmin, mi->mi_acdirmax); 411 412 mdb_printf("\nServer list: %p\n", mi->mi_servers); 413 mdb_inc_indent(2); 414 if (mdb_pwalk_dcmd("nfs_serv", "nfs_servinfo", 0, NULL, 415 (uintptr_t)mi->mi_servers) == -1) 416 mdb_printf("??\n"); 417 mdb_dec_indent(2); 418 419 mdb_printf("Current Server: %p ", mi->mi_curr_serv); 420 if (mdb_call_dcmd("nfs_servinfo", (uintptr_t)mi->mi_curr_serv, 421 DCMD_ADDRSPEC, 0, NULL) == -1) 422 mdb_printf("??\n"); 423 424 mdb_printf( 425 "\nTotal: Server Non-responses = %u, Server Failovers = %u\n", 426 mi->mi_noresponse, mi->mi_failover); 427 428 if (mi->mi_io_kstats != NULL) 429 nfs_print_io_stat((uintptr_t)mi->mi_io_kstats); 430 431 mdb_printf("\nAsync Request queue:\n"); 432 mdb_inc_indent(2); 433 mdb_printf("max threads = %u, active threads = %u\n", 434 mi->mi_max_threads, mi->mi_threads[NFS_ASYNC_QUEUE]); 435 mdb_printf("Async reserved page operation only active threads = %u\n", 436 mi->mi_threads[NFS_ASYNC_PGOPS_QUEUE]); 437 mdb_printf("number requests queued:\n"); 438 for (i = 0; i < NFS_ASYNC_TYPES; i++) { 439 const char *opname; 440 size_t count = 0; 441 442 switch (i) { 443 case NFS_PUTAPAGE: 444 opname = "PUTAPAGE"; 445 break; 446 case NFS_PAGEIO: 447 opname = "PAGEIO"; 448 break; 449 case NFS_COMMIT: 450 opname = "COMMIT"; 451 break; 452 case NFS_READ_AHEAD: 453 opname = "READ_AHEAD"; 454 break; 455 case NFS_READDIR: 456 opname = "READDIR"; 457 break; 458 case NFS_INACTIVE: 459 opname = "INACTIVE"; 460 break; 461 default: 462 opname = "??"; 463 break; 464 } 465 466 if (mi->mi_async_reqs[i] == NULL || mdb_pwalk("nfs_async", 467 walk_count_cb, &count, (uintptr_t)mi->mi_async_reqs[i]) 468 == -1) 469 mdb_printf("\t%s = ??", opname); 470 else 471 mdb_printf("\t%s = %llu", opname, count); 472 } 473 mdb_printf("\n"); 474 mdb_dec_indent(2); 475 476 if (mi->mi_printftime) 477 mdb_printf("\nLast error report time = %Y\n", 478 mi->mi_printftime); 479 480 mdb_dec_indent(2); 481 mdb_printf("\n"); 482 483 return (WALK_NEXT); 484 } 485 486 int 487 nfs_mntinfo_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 488 { 489 mntinfo_t mi; 490 uint_t opt_v = FALSE; 491 492 if (mdb_getopts(argc, argv, 493 'v', MDB_OPT_SETBITS, TRUE, &opt_v, NULL) != argc) 494 return (DCMD_USAGE); 495 496 if ((flags & DCMD_ADDRSPEC) == 0) { 497 if (mdb_walk("nfs_mnt", nfs_print_mntinfo_cb, &opt_v) == -1) { 498 mdb_warn("failed to walk nfs_mnt"); 499 return (DCMD_ERR); 500 } 501 return (DCMD_OK); 502 } 503 504 if (mdb_vread(&mi, sizeof (mi), addr) == -1) { 505 mdb_warn("failed to read mntinfo_t"); 506 return (DCMD_ERR); 507 } 508 509 return (nfs_print_mntinfo_cb(addr, &mi, &opt_v) == WALK_ERR ? DCMD_ERR 510 : DCMD_OK); 511 } 512 513 void 514 nfs_mntinfo_help(void) 515 { 516 mdb_printf("-v verbose information\n"); 517 } 518 519 /* 520 * nfs_servinfo dcmd implementation 521 */ 522 523 int 524 nfs_servinfo_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 525 { 526 servinfo_t si; 527 uint_t opt_v = FALSE; 528 const char *addr_str; 529 struct knetconfig knconf; 530 char *hostname; 531 int i; 532 533 if ((flags & DCMD_ADDRSPEC) == 0) { 534 mdb_printf("requires address of servinfo_t\n"); 535 return (DCMD_USAGE); 536 } 537 538 if (mdb_getopts(argc, argv, 539 'v', MDB_OPT_SETBITS, TRUE, &opt_v, NULL) != argc) 540 return (DCMD_USAGE); 541 542 if (mdb_vread(&si, sizeof (si), addr) == -1) { 543 mdb_warn("can't read servinfo_t"); 544 return (DCMD_ERR); 545 } 546 547 addr_str = common_netbuf_str(&si.sv_addr); 548 549 if (!opt_v) { 550 mdb_printf("%s\n", addr_str); 551 return (DCMD_OK); 552 } 553 554 mdb_printf("secdata ptr = %p\n", si.sv_secdata); 555 556 mdb_printf("address = "); 557 if (mdb_vread(&knconf, sizeof (knconf), 558 (uintptr_t)si.sv_knconf) == -1) { 559 mdb_printf("?\?/?\?/??"); 560 } else { 561 char knc_str[KNC_STRSIZE]; 562 563 mdb_printf("%u", knconf.knc_semantics); 564 565 if (mdb_readstr(knc_str, sizeof (knc_str), 566 (uintptr_t)knconf.knc_protofmly) == -1) 567 mdb_printf("/??"); 568 else 569 mdb_printf("/%s", knc_str); 570 571 if (mdb_readstr(knc_str, sizeof (knc_str), 572 (uintptr_t)knconf.knc_proto) == -1) 573 mdb_printf("/??"); 574 else 575 mdb_printf("/%s", knc_str); 576 } 577 mdb_printf("/%s\n", addr_str); 578 579 if (si.sv_hostnamelen <= 0 || (hostname = mdb_alloc(si.sv_hostnamelen, 580 UM_NOSLEEP | UM_GC)) == NULL || mdb_readstr(hostname, 581 si.sv_hostnamelen, (uintptr_t)si.sv_hostname) == -1) 582 mdb_printf("hostname = ??\n"); 583 else 584 mdb_printf("hostname = %s\n", hostname); 585 586 mdb_printf("filehandle = "); 587 if (si.sv_fhandle.fh_len >= 0 && 588 si.sv_fhandle.fh_len <= NFS_FHANDLE_LEN) 589 for (i = 0; i < si.sv_fhandle.fh_len; i++) 590 mdb_printf("%02x", 591 (unsigned char)si.sv_fhandle.fh_buf[i]); 592 else 593 mdb_printf("??"); 594 mdb_printf("\n\n"); 595 596 return (DCMD_OK); 597 } 598 599 void 600 nfs_servinfo_help(void) 601 { 602 mdb_printf("-v verbose information\n"); 603 } 604 605 /* 606 * nfs4_mntinfo dcmd implementation 607 */ 608 609 static const mdb_bitmask_t nfs_mi4_flags[] = { 610 {"MI4_HARD", MI4_HARD, MI4_HARD}, 611 {"MI4_PRINTED", MI4_PRINTED, MI4_PRINTED}, 612 {"MI4_INT", MI4_INT, MI4_INT}, 613 {"MI4_DOWN", MI4_DOWN, MI4_DOWN}, 614 {"MI4_NOAC", MI4_NOAC, MI4_NOAC}, 615 {"MI4_NOCTO", MI4_NOCTO, MI4_NOCTO}, 616 {"MI4_LLOCK", MI4_LLOCK, MI4_LLOCK}, 617 {"MI4_GRPID", MI4_GRPID, MI4_GRPID}, 618 {"MI4_SHUTDOWN", MI4_SHUTDOWN, MI4_SHUTDOWN}, 619 {"MI4_LINK", MI4_LINK, MI4_LINK}, 620 {"MI4_SYMLINK", MI4_SYMLINK, MI4_SYMLINK}, 621 {"MI4_EPHEMERAL_RECURSED", MI4_EPHEMERAL_RECURSED, 622 MI4_EPHEMERAL_RECURSED}, 623 {"MI4_ACL", MI4_ACL, MI4_ACL}, 624 {"MI4_MIRRORMOUNT", MI4_MIRRORMOUNT, MI4_MIRRORMOUNT}, 625 {"MI4_REFERRAL", MI4_REFERRAL, MI4_REFERRAL}, 626 {"MI4_EPHEMERAL", MI4_EPHEMERAL, MI4_EPHEMERAL}, 627 {"MI4_NOPRINT", MI4_NOPRINT, MI4_NOPRINT}, 628 {"MI4_DIRECTIO", MI4_DIRECTIO, MI4_DIRECTIO}, 629 {"MI4_RECOV_ACTIV", MI4_RECOV_ACTIV, MI4_RECOV_ACTIV}, 630 {"MI4_REMOVE_ON_LAST_CLOSE", MI4_REMOVE_ON_LAST_CLOSE, 631 MI4_REMOVE_ON_LAST_CLOSE}, 632 {"MI4_RECOV_FAIL", MI4_RECOV_FAIL, MI4_RECOV_FAIL}, 633 {"MI4_PUBLIC", MI4_PUBLIC, MI4_PUBLIC}, 634 {"MI4_MOUNTING", MI4_MOUNTING, MI4_MOUNTING}, 635 {"MI4_POSIX_LOCK", MI4_POSIX_LOCK, MI4_POSIX_LOCK}, 636 {"MI4_LOCK_DEBUG", MI4_LOCK_DEBUG, MI4_LOCK_DEBUG}, 637 {"MI4_DEAD", MI4_DEAD, MI4_DEAD}, 638 {"MI4_INACTIVE_IDLE", MI4_INACTIVE_IDLE, MI4_INACTIVE_IDLE}, 639 {"MI4_BADOWNER_DEBUG", MI4_BADOWNER_DEBUG, MI4_BADOWNER_DEBUG}, 640 {"MI4_ASYNC_MGR_STOP", MI4_ASYNC_MGR_STOP, MI4_ASYNC_MGR_STOP}, 641 {"MI4_TIMEDOUT", MI4_TIMEDOUT, MI4_TIMEDOUT}, 642 {NULL, 0, 0} 643 }; 644 645 static const mdb_bitmask_t nfs_mi4_recovflags[] = { 646 {"MI4R_NEED_CLIENTID", MI4R_NEED_CLIENTID, MI4R_NEED_CLIENTID}, 647 {"MI4R_REOPEN_FILES", MI4R_REOPEN_FILES, MI4R_REOPEN_FILES}, 648 {"MI4R_NEED_SECINFO", MI4R_NEED_SECINFO, MI4R_NEED_SECINFO}, 649 {"MI4R_NEED_NEW_SERVER", MI4R_NEED_NEW_SERVER, MI4R_NEED_NEW_SERVER}, 650 {"MI4R_REMAP_FILES", MI4R_REMAP_FILES, MI4R_REMAP_FILES}, 651 {"MI4R_SRV_REBOOT", MI4R_SRV_REBOOT, MI4R_SRV_REBOOT}, 652 {"MI4R_LOST_STATE", MI4R_LOST_STATE, MI4R_LOST_STATE}, 653 {"MI4R_BAD_SEQID", MI4R_BAD_SEQID, MI4R_BAD_SEQID}, 654 {"MI4R_MOVED", MI4R_MOVED, MI4R_MOVED}, 655 {NULL, 0, 0} 656 }; 657 658 int 659 nfs4_mntinfo_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 660 { 661 mntinfo4_t mi; 662 vfs_t vfs; 663 char buf[MAXPATHLEN]; 664 uint_t opt_m = FALSE; 665 uint_t opt_v = FALSE; 666 667 if ((flags & DCMD_ADDRSPEC) == 0) { 668 if (mdb_walk_dcmd("nfs4_mnt", "nfs4_mntinfo", argc, 669 argv) == -1) { 670 mdb_warn("failed to walk nfs4_mnt"); 671 return (DCMD_ERR); 672 } 673 return (DCMD_OK); 674 } 675 676 if (mdb_getopts(argc, argv, 677 'm', MDB_OPT_SETBITS, TRUE, &opt_m, 678 'v', MDB_OPT_SETBITS, TRUE, &opt_v, NULL) != argc) 679 return (DCMD_USAGE); 680 681 if (mdb_vread(&mi, sizeof (mi), addr) == -1) { 682 mdb_warn("failed to read mntinfo4_t at %p", addr); 683 return (DCMD_ERR); 684 } 685 686 if (mdb_vread(&vfs, sizeof (vfs), (uintptr_t)mi.mi_vfsp) == -1) { 687 mdb_warn("failed to read vfs_t at %p", mi.mi_vfsp); 688 return (DCMD_ERR); 689 } 690 691 mdb_printf("+--------------------------------------+\n"); 692 mdb_printf(" mntinfo4_t: 0x%p\n", addr); 693 mdb_printf(" NFS Version: 4\n"); 694 mdb_printf(" mi_flags: %b\n", mi.mi_flags, nfs_mi4_flags); 695 mdb_printf(" mi_error: %u\n", mi.mi_error); 696 mdb_printf(" mi_open_files: %i\n", mi.mi_open_files); 697 mdb_printf(" mi_msg_count: %i\n", mi.mi_msg_count); 698 mdb_printf(" mi_recovflags: %b\n", mi.mi_recovflags, 699 nfs_mi4_recovflags); 700 mdb_printf("mi_recovthread: 0x%p\n", mi.mi_recovthread); 701 mdb_printf("mi_in_recovery: %i\n", mi.mi_in_recovery); 702 703 if (mdb_read_refstr((uintptr_t)vfs.vfs_mntpt, buf, 704 sizeof (buf)) == -1) 705 strcpy(buf, "??"); 706 mdb_printf(" mount point: %s\n", buf); 707 if (mdb_read_refstr((uintptr_t)vfs.vfs_resource, buf, 708 sizeof (buf)) == -1) 709 strcpy(buf, "??"); 710 mdb_printf(" mount from: %s\n", buf); 711 712 if (opt_v) { 713 int i; 714 715 mdb_printf("\n"); 716 mdb_inc_indent(2); 717 718 mdb_printf("mi_zone = %p\n", mi.mi_zone); 719 mdb_printf("mi_curread = %i, mi_curwrite = %i, " 720 "mi_retrans = %i, mi_timeo = %i\n", mi.mi_curread, 721 mi.mi_curwrite, mi.mi_retrans, mi.mi_timeo); 722 mdb_printf("mi_acregmin = %lu, mi_acregmax = %lu, " 723 "mi_acdirmin = %lu, mi_acdirmax = %lu\n", mi.mi_acregmin, 724 mi.mi_acregmax, mi.mi_acdirmin, mi.mi_acdirmax); 725 726 mdb_printf("\nServer list: %p\n", mi.mi_servers); 727 mdb_inc_indent(2); 728 if (mdb_pwalk_dcmd("nfs4_serv", "nfs4_servinfo", 0, NULL, 729 (uintptr_t)mi.mi_servers) == -1) 730 mdb_printf("??\n"); 731 mdb_dec_indent(2); 732 733 mdb_printf("Current Server: %p ", mi.mi_curr_serv); 734 if (mdb_call_dcmd("nfs4_servinfo", (uintptr_t)mi.mi_curr_serv, 735 DCMD_ADDRSPEC, 0, NULL) == -1) 736 mdb_printf("??\n"); 737 738 mdb_printf("\nTotal: Server Non-responses = %u, " 739 "Server Failovers = %u\n", mi.mi_noresponse, 740 mi.mi_failover); 741 742 if (mi.mi_io_kstats != NULL) 743 nfs_print_io_stat((uintptr_t)mi.mi_io_kstats); 744 745 mdb_printf("\nAsync Request queue:\n"); 746 mdb_inc_indent(2); 747 mdb_printf("max threads = %u, active threads = %u\n", 748 mi.mi_max_threads, mi.mi_threads[NFS4_ASYNC_QUEUE]); 749 mdb_printf("Async reserved page operation only active " 750 "threads = %u\n", mi.mi_threads[NFS4_ASYNC_PGOPS_QUEUE]); 751 mdb_printf("number requests queued:\n"); 752 for (i = 0; i < NFS4_ASYNC_TYPES; i++) { 753 const char *opname; 754 size_t count = 0; 755 756 switch (i) { 757 case NFS4_PUTAPAGE: 758 opname = "PUTAPAGE"; 759 break; 760 case NFS4_PAGEIO: 761 opname = "PAGEIO"; 762 break; 763 case NFS4_COMMIT: 764 opname = "COMMIT"; 765 break; 766 case NFS4_READ_AHEAD: 767 opname = "READ_AHEAD"; 768 break; 769 case NFS4_READDIR: 770 opname = "READDIR"; 771 break; 772 case NFS4_INACTIVE: 773 opname = "INACTIVE"; 774 break; 775 default: 776 opname = "??"; 777 break; 778 } 779 780 if (mi.mi_async_reqs[i] != NULL && 781 mdb_pwalk("nfs4_async", walk_count_cb, &count, 782 (uintptr_t)mi.mi_async_reqs[i]) == -1) 783 mdb_printf("\t%s = ??", opname); 784 else 785 mdb_printf("\t%s = %llu", opname, count); 786 } 787 mdb_printf("\n"); 788 mdb_dec_indent(2); 789 790 mdb_dec_indent(2); 791 } 792 793 return (DCMD_OK); 794 } 795 796 void 797 nfs4_mntinfo_help(void) 798 { 799 mdb_printf("<mntinfo4>::nfs4_mntinfo -> gives mntinfo4_t information\n" 800 " ::nfs4_mntinfo -> walks thru all NFSv4 mntinfo4_t\n" 801 "Each of these formats also takes the following argument\n" 802 " -v -> Verbose output\n"); 803 } 804 805 /* 806 * nfs4_servinfo dcmd implementation 807 */ 808 809 int 810 nfs4_servinfo_dcmd(uintptr_t addr, uint_t flags, int argc, 811 const mdb_arg_t *argv) 812 { 813 servinfo4_t si; 814 uint_t opt_v = FALSE; 815 const char *addr_str; 816 struct knetconfig knconf; 817 char *hostname; 818 int i; 819 820 if ((flags & DCMD_ADDRSPEC) == 0) { 821 mdb_printf("requires address of servinfo4_t\n"); 822 return (DCMD_USAGE); 823 } 824 825 if (mdb_getopts(argc, argv, 826 'v', MDB_OPT_SETBITS, TRUE, &opt_v, NULL) != argc) 827 return (DCMD_USAGE); 828 829 if (mdb_vread(&si, sizeof (si), addr) == -1) { 830 mdb_warn("can't read servinfo_t"); 831 return (DCMD_ERR); 832 } 833 834 addr_str = common_netbuf_str(&si.sv_addr); 835 836 if (!opt_v) { 837 mdb_printf("%s\n", addr_str); 838 return (DCMD_OK); 839 } 840 841 mdb_printf("secdata ptr = %p\n", si.sv_secdata); 842 843 mdb_printf("address = "); 844 if (mdb_vread(&knconf, sizeof (knconf), 845 (uintptr_t)si.sv_knconf) == -1) { 846 mdb_printf("?\?/?\?/??"); 847 } else { 848 char knc_str[KNC_STRSIZE]; 849 850 mdb_printf("%u", knconf.knc_semantics); 851 852 if (mdb_readstr(knc_str, sizeof (knc_str), 853 (uintptr_t)knconf.knc_protofmly) == -1) 854 mdb_printf("/??"); 855 else 856 mdb_printf("/%s", knc_str); 857 858 if (mdb_readstr(knc_str, sizeof (knc_str), 859 (uintptr_t)knconf.knc_proto) == -1) 860 mdb_printf("/??"); 861 else 862 mdb_printf("/%s", knc_str); 863 } 864 mdb_printf("/%s\n", addr_str); 865 866 if (si.sv_hostnamelen <= 0 || (hostname = mdb_alloc(si.sv_hostnamelen, 867 UM_NOSLEEP | UM_GC)) == NULL || mdb_readstr(hostname, 868 si.sv_hostnamelen, (uintptr_t)si.sv_hostname) == -1) 869 mdb_printf("hostname = ??\n"); 870 else 871 mdb_printf("hostname = %s\n", hostname); 872 873 mdb_printf("server filehandle = "); 874 if (si.sv_fhandle.fh_len >= 0 && si.sv_fhandle.fh_len <= NFS4_FHSIZE) 875 for (i = 0; i < si.sv_fhandle.fh_len; i++) 876 mdb_printf("%02x", 877 (unsigned char)si.sv_fhandle.fh_buf[i]); 878 else 879 mdb_printf("??"); 880 881 mdb_printf("\nparent dir filehandle = "); 882 if (si.sv_pfhandle.fh_len >= 0 && si.sv_pfhandle.fh_len <= NFS4_FHSIZE) 883 for (i = 0; i < si.sv_pfhandle.fh_len; i++) 884 mdb_printf("%02x", 885 (unsigned char)si.sv_pfhandle.fh_buf[i]); 886 else 887 mdb_printf("??"); 888 mdb_printf("\n\n"); 889 890 return (DCMD_OK); 891 } 892 893 void 894 nfs4_servinfo_help(void) 895 { 896 mdb_printf("-v verbose information\n"); 897 } 898 899 /* 900 * nfs4_server_info dcmd implementation 901 */ 902 903 static const mdb_bitmask_t nfs4_si_flags[] = { 904 {"N4S_CLIENTID_SET", N4S_CLIENTID_SET, N4S_CLIENTID_SET}, 905 {"N4S_CLIENTID_PEND", N4S_CLIENTID_PEND, N4S_CLIENTID_PEND}, 906 {"N4S_CB_PINGED", N4S_CB_PINGED, N4S_CB_PINGED}, 907 {"N4S_CB_WAITER", N4S_CB_WAITER, N4S_CB_WAITER}, 908 {"N4S_INSERTED", N4S_INSERTED, N4S_INSERTED}, 909 {"N4S_BADOWNER_DEBUG", N4S_BADOWNER_DEBUG, N4S_BADOWNER_DEBUG}, 910 {NULL, 0, 0} 911 }; 912 913 int 914 nfs4_server_info_dcmd(uintptr_t addr, uint_t flags, int argc, 915 const mdb_arg_t *argv) 916 { 917 nfs4_server_t srv; 918 char *id_val; 919 uint_t opt_c = FALSE; 920 uint_t opt_s = FALSE; 921 922 if ((flags & DCMD_ADDRSPEC) == 0) { 923 if (mdb_walk_dcmd("nfs4_server", "nfs4_server_info", argc, argv) 924 == -1) { 925 mdb_warn("nfs4_server walker failed"); 926 return (DCMD_ERR); 927 } 928 return (DCMD_OK); 929 } 930 931 if (mdb_getopts(argc, argv, 932 'c', MDB_OPT_SETBITS, TRUE, &opt_c, 933 's', MDB_OPT_SETBITS, TRUE, &opt_s, NULL) != argc) 934 return (DCMD_USAGE); 935 936 if (mdb_vread(&srv, sizeof (srv), addr) == -1) { 937 mdb_warn("failed to read nfs4_server_t at %p", addr); 938 return (DCMD_ERR); 939 } 940 941 if (srv.saddr.len == 0) 942 return (DCMD_OK); 943 944 mdb_printf("Address: %p Zone: %i Server: %s\n", addr, srv.zoneid, 945 common_netbuf_str(&srv.saddr)); 946 mdb_printf("Program: %x Flags: %b\n", srv.s_program, srv.s_flags, 947 nfs4_si_flags); 948 mdb_printf("Client ID: %#llx", srv.clientid); 949 if (opt_s) { 950 struct { 951 uint32_t start_time; 952 uint32_t c_id; 953 } *impl_id = (void *)&srv.clientid; 954 mdb_printf(" (srvrboot: %Y, c_id: %u)", impl_id->start_time, 955 impl_id->c_id); 956 } 957 958 mdb_printf("\nCLIDtoSend: [verifier: %llx", srv.clidtosend.verifier); 959 if (opt_c) { 960 struct { 961 uint32_t sec; 962 uint32_t subsec; 963 } *curtime = (void *)&srv.clidtosend.verifier; 964 mdb_printf(" (%Y + %u nsec)", curtime->sec, curtime->subsec); 965 } 966 967 mdb_printf(", client identifier: "); 968 id_val = mdb_alloc(srv.clidtosend.id_len, UM_NOSLEEP | UM_GC); 969 if (id_val != NULL && mdb_vread(id_val, srv.clidtosend.id_len, 970 (uintptr_t)srv.clidtosend.id_val) == srv.clidtosend.id_len) { 971 uint_t i; 972 973 if (opt_c) { 974 size_t l; 975 struct netbuf nb; 976 977 l = strlen(id_val) + 1; 978 nb.len = nb.maxlen = srv.clidtosend.id_len - l; 979 nb.buf = srv.clidtosend.id_val + l; 980 mdb_printf("(%s/%s) ", id_val, common_netbuf_str(&nb)); 981 } 982 983 for (i = 0; i < srv.clidtosend.id_len; i++) 984 mdb_printf("%02x", (unsigned char)id_val[i]); 985 } else { 986 mdb_printf("??"); 987 } 988 mdb_printf(" ]\n"); 989 990 mdb_printf("mntinfo4 list: %p\n", srv.mntinfo4_list); 991 mdb_printf("Deleg list: %p ::walk list\n", addr + 992 OFFSETOF(nfs4_server_t, s_deleg_list)); 993 mdb_printf("Lease Valid: "); 994 switch (srv.lease_valid) { 995 case NFS4_LEASE_INVALID: 996 mdb_printf("INVALID\n"); 997 break; 998 case NFS4_LEASE_VALID: 999 mdb_printf("VALID\n"); 1000 break; 1001 case NFS4_LEASE_UNINITIALIZED: 1002 mdb_printf("UNINIT\n"); 1003 break; 1004 case NFS4_LEASE_NOT_STARTED: 1005 mdb_printf("NOT_STARTED\n"); 1006 break; 1007 default: 1008 mdb_printf("??\n"); 1009 break; 1010 } 1011 1012 mdb_printf("Lease Time: %i sec\n", srv.s_lease_time); 1013 mdb_printf("Last renewal: %Y\n", srv.last_renewal_time); 1014 mdb_printf("Propgn Delay: %li sec : %li nsec\n", 1015 srv.propagation_delay.tv_sec, srv.propagation_delay.tv_nsec); 1016 mdb_printf("Credential: %p\n\n", srv.s_cred); 1017 1018 return (DCMD_OK); 1019 } 1020 1021 void 1022 nfs4_server_info_help(void) 1023 { 1024 mdb_printf( 1025 "-c assumes client is an illumos NFSv4 Client\n" 1026 "-s assumes server is an illumos NFSv4 Server\n" 1027 "\n" 1028 "The -c option enables the dcmd to decode the client generated\n" 1029 "structure CLIDtoSend that is normally opaque to the server.\n" 1030 "The -s option enables the dcmd to decode the server generated\n" 1031 "structure Client ID that is normally opaque to the client.\n"); 1032 } 1033 1034 /* 1035 * nfs4_mimsg dcmd implementation 1036 */ 1037 1038 static const struct { 1039 const char *str; 1040 nfs4_event_type_t et; 1041 } nfs4_event_type_tbl[] = { 1042 TBL_ENTRY(RE_BAD_SEQID), 1043 TBL_ENTRY(RE_BADHANDLE), 1044 TBL_ENTRY(RE_CLIENTID), 1045 TBL_ENTRY(RE_DEAD_FILE), 1046 TBL_ENTRY(RE_END), 1047 TBL_ENTRY(RE_FAIL_RELOCK), 1048 TBL_ENTRY(RE_FAIL_REMAP_LEN), 1049 TBL_ENTRY(RE_FAIL_REMAP_OP), 1050 TBL_ENTRY(RE_FAILOVER), 1051 TBL_ENTRY(RE_FILE_DIFF), 1052 TBL_ENTRY(RE_LOST_STATE), 1053 TBL_ENTRY(RE_OPENS_CHANGED), 1054 TBL_ENTRY(RE_SIGLOST), 1055 TBL_ENTRY(RE_SIGLOST_NO_DUMP), 1056 TBL_ENTRY(RE_START), 1057 TBL_ENTRY(RE_UNEXPECTED_ACTION), 1058 TBL_ENTRY(RE_UNEXPECTED_ERRNO), 1059 TBL_ENTRY(RE_UNEXPECTED_STATUS), 1060 TBL_ENTRY(RE_WRONGSEC), 1061 TBL_ENTRY(RE_LOST_STATE_BAD_OP), 1062 TBL_ENTRY(RE_REFERRAL), 1063 {NULL} 1064 }; 1065 1066 static const struct { 1067 const char *str; 1068 nfs4_fact_type_t ft; 1069 } nfs4_fact_type_tbl[] = { 1070 TBL_ENTRY(RF_BADOWNER), 1071 TBL_ENTRY(RF_ERR), 1072 TBL_ENTRY(RF_RENEW_EXPIRED), 1073 TBL_ENTRY(RF_SRV_NOT_RESPOND), 1074 TBL_ENTRY(RF_SRV_OK), 1075 TBL_ENTRY(RF_SRVS_NOT_RESPOND), 1076 TBL_ENTRY(RF_SRVS_OK), 1077 TBL_ENTRY(RF_DELMAP_CB_ERR), 1078 TBL_ENTRY(RF_SENDQ_FULL), 1079 {NULL} 1080 }; 1081 1082 static void 1083 mimsg_print_event(const nfs4_debug_msg_t *msg) 1084 { 1085 const nfs4_revent_t *ep = &msg->rmsg_u.msg_event; 1086 char msg_srv[MAXPATHLEN]; 1087 char msg_mntpt[MAXPATHLEN]; 1088 char char1[MAXPATHLEN]; 1089 char *char1p = char1; 1090 char char2[MAXPATHLEN]; 1091 char *char2p = char2; 1092 1093 if (mdb_readstr(msg_srv, sizeof (msg_srv), 1094 (uintptr_t)msg->msg_srv) == -1) 1095 strcpy(msg_srv, "??"); 1096 1097 if (mdb_readstr(msg_mntpt, sizeof (msg_mntpt), 1098 (uintptr_t)msg->msg_mntpt) == -1) 1099 strcpy(msg_mntpt, "??"); 1100 1101 if (ep->re_char1 != NULL) { 1102 if (mdb_readstr(char1, sizeof (char1), 1103 (uintptr_t)ep->re_char1) == -1) 1104 strcpy(char1, "??"); 1105 } else { 1106 char1[0] = '\0'; 1107 char1p = NULL; 1108 } 1109 1110 if (ep->re_char2 != NULL) { 1111 if (mdb_readstr(char2, sizeof (char2), 1112 (uintptr_t)ep->re_char2) == -1) 1113 strcpy(char2, "??"); 1114 } else { 1115 char2[0] = '\0'; 1116 char2p = NULL; 1117 } 1118 1119 switch (ep->re_type) { 1120 case RE_BAD_SEQID: 1121 mdb_printf("Operation %s for file %s (rnode_pt 0x%p), pid %d " 1122 "using seqid %u got %s on server %s. Last good seqid was " 1123 "%u for operation %s.", nfs4_tag_str(ep->re_tag1), char1p, 1124 ep->re_rp1, ep->re_pid, ep->re_seqid1, 1125 nfs4_stat_str(ep->re_stat4), msg_srv, ep->re_seqid2, 1126 nfs4_tag_str(ep->re_tag2)); 1127 break; 1128 case RE_BADHANDLE: 1129 if (ep->re_char1 != NULL) { 1130 mdb_printf("server %s said filehandle was invalid for " 1131 "file: %s (rnode_pt %p) on mount %s", msg_srv, 1132 char1, ep->re_rp1, msg_mntpt); 1133 } else { 1134 mdb_printf("server %s said filehandle was invalid for " 1135 "file: (rnode_pt %p) on mount %s", msg_srv, 1136 ep->re_rp1, msg_mntpt); 1137 } 1138 break; 1139 case RE_CLIENTID: 1140 mdb_printf("Can't recover clientid on mi 0x%p due to error %u " 1141 "(%s), for server %s. Marking file system as unusable.", 1142 ep->re_mi, ep->re_uint, nfs4_stat_str(ep->re_stat4), 1143 msg_srv); 1144 break; 1145 case RE_DEAD_FILE: 1146 mdb_printf("File %s (rnode_pt %p) on server %s could not be " 1147 "recovered and was closed. %s %s.", char1p, ep->re_rp1, 1148 msg_srv, char2, 1149 ep->re_stat4 ? nfs4_stat_str(ep->re_stat4) : ""); 1150 break; 1151 case RE_END: 1152 mdb_printf("Recovery done for mount %s (0x%p) on server %s, " 1153 "rnode_pt1 %s (0x%p), rnode_pt2 %s (0x%p)", msg_mntpt, 1154 ep->re_mi, msg_srv, char1p, ep->re_rp1, char2p, ep->re_rp2); 1155 break; 1156 case RE_FAIL_RELOCK: 1157 mdb_printf("Couldn't reclaim lock for pid %d for file %s " 1158 "(rnode_pt %p) on (server %s): error %u", ep->re_pid, 1159 char1p, ep->re_rp1, msg_srv, 1160 ep->re_uint ? ep->re_uint : ep->re_stat4); 1161 break; 1162 case RE_FAIL_REMAP_LEN: 1163 mdb_printf("remap_lookup: server %s returned bad fhandle " 1164 "length (%u)", msg_srv, ep->re_uint); 1165 break; 1166 case RE_FAIL_REMAP_OP: 1167 mdb_printf("remap_lookup: didn't get expected OP_GETFH for " 1168 "server %s", msg_srv); 1169 break; 1170 case RE_FAILOVER: 1171 if (ep->re_char1) 1172 mdb_printf("Failing over from %s to %s", msg_srv, 1173 char1p); 1174 else 1175 mdb_printf("Failing over: selecting original server %s", 1176 msg_srv); 1177 break; 1178 case RE_FILE_DIFF: 1179 mdb_printf("Replicas %s and %s: file %s(%p) not same", 1180 msg_srv, msg_mntpt, ep->re_char1, (void *)ep->re_rp1); 1181 break; 1182 case RE_LOST_STATE: 1183 /* 1184 * if char1 is null you should use ::nfs4_fname for re_rp1 1185 */ 1186 mdb_printf("client has a lost %s request for rnode_pt1 %s " 1187 "(0x%p), rnode_pt2 %s (0x%p) on fs %s, server %s.", 1188 nfs4_op_str(ep->re_uint), char1p, ep->re_rp1, char2p, 1189 ep->re_rp2, msg_mntpt, msg_srv); 1190 break; 1191 case RE_OPENS_CHANGED: 1192 mdb_printf("Recovery: number of open files changed " 1193 "for mount %s (0x%p) (old %d, new %d) on server %s\n", 1194 msg_mntpt, (void *)ep->re_mi, ep->re_uint, ep->re_pid, 1195 msg_srv); 1196 break; 1197 case RE_SIGLOST: 1198 case RE_SIGLOST_NO_DUMP: 1199 mdb_printf("Process %d lost its locks on file %s (rnode_pt %p) " 1200 "due to a NFS error (%u) on server %s", ep->re_pid, char1p, 1201 ep->re_rp1, ep->re_uint ? ep->re_uint : ep->re_stat4, 1202 msg_srv); 1203 break; 1204 case RE_START: 1205 mdb_printf("Starting recovery for mount %s (0x%p, flags %#x) " 1206 "on server %s, rnode_pt1 %s (0x%p), rnode_pt2 %s (0x%p)", 1207 msg_mntpt, ep->re_mi, ep->re_uint, msg_srv, char1p, 1208 ep->re_rp1, char2p, ep->re_rp2); 1209 break; 1210 case RE_UNEXPECTED_ACTION: 1211 mdb_printf("Recovery, unexpected action (%d) on server %s\n", 1212 ep->re_uint, msg_srv); 1213 break; 1214 case RE_UNEXPECTED_ERRNO: 1215 mdb_printf("Recovery, unexpected errno (%d) on server %s\n", 1216 ep->re_uint, msg_srv); 1217 break; 1218 case RE_UNEXPECTED_STATUS: 1219 mdb_printf("Recovery, unexpected NFS status code (%s) " 1220 "on server %s\n", 1221 nfs4_stat_str(ep->re_stat4), msg_srv); 1222 break; 1223 case RE_WRONGSEC: 1224 mdb_printf("Recovery, can't recover from NFS4ERR_WRONGSEC." 1225 " error %d for mount %s server %s: rnode_pt1 %s (0x%p)" 1226 " rnode_pt2 %s (0x%p)", ep->re_uint, msg_mntpt, msg_srv, 1227 ep->re_char1, (void *)ep->re_rp1, ep->re_char2, 1228 (void *)ep->re_rp2); 1229 break; 1230 case RE_LOST_STATE_BAD_OP: 1231 mdb_printf("NFS lost state with unrecognized op (%d)." 1232 " fs %s, server %s, pid %d, file %s (rnode_pt: 0x%p), " 1233 "dir %s (0x%p)", ep->re_uint, msg_mntpt, msg_srv, 1234 ep->re_pid, ep->re_char1, (void *)ep->re_rp1, 1235 ep->re_char2, (void *)ep->re_rp2); 1236 break; 1237 case RE_REFERRAL: 1238 if (ep->re_char1) 1239 mdb_printf("Referal, Server: %s on Mntpt: %s" 1240 "being referred from %s to %s", msg_srv, 1241 msg_mntpt, msg_srv, ep->re_char1); 1242 else 1243 mdb_printf("Referal, Server: %s on Mntpt: %s" 1244 "NFS4: being referred from %s to unknown server", 1245 msg_srv, msg_mntpt, msg->msg_srv); 1246 break; 1247 default: 1248 mdb_printf("illegal event %d", ep->re_type); 1249 break; 1250 } 1251 } 1252 1253 static void 1254 mimsg_print_fact(const nfs4_debug_msg_t *msg) 1255 { 1256 const nfs4_rfact_t *fp = &msg->rmsg_u.msg_fact; 1257 char msg_srv[MAXPATHLEN]; 1258 char file[MAXPATHLEN]; 1259 1260 if (mdb_readstr(msg_srv, sizeof (msg_srv), 1261 (uintptr_t)msg->msg_srv) == -1) 1262 strcpy(msg_srv, "??"); 1263 1264 switch (fp->rf_type) { 1265 case RF_BADOWNER: 1266 mdb_printf("NFSMAPID_DOMAIN does not match server: %s's " 1267 "domain.", msg_srv); 1268 break; 1269 case RF_ERR: 1270 mdb_printf("Op %s got error ", nfs4_op_str(fp->rf_op)); 1271 if (fp->rf_error) 1272 mdb_printf("%d", fp->rf_error); 1273 else 1274 mdb_printf("%s", nfs4_stat_str(fp->rf_stat4)); 1275 mdb_printf(" causing recovery action %s.", 1276 nfs4_recov_str(fp->rf_action)); 1277 if (fp->rf_reboot) 1278 mdb_printf(" Client also suspects server rebooted"); 1279 break; 1280 case RF_RENEW_EXPIRED: 1281 mdb_printf("Client's lease expired on server %s.", msg_srv); 1282 break; 1283 case RF_SRV_NOT_RESPOND: 1284 mdb_printf("Server %s not responding, still trying", msg_srv); 1285 break; 1286 case RF_SRV_OK: 1287 mdb_printf("Server %s ok", msg_srv); 1288 break; 1289 case RF_SRVS_NOT_RESPOND: 1290 mdb_printf("Servers %s not responding, still trying", msg_srv); 1291 break; 1292 case RF_SRVS_OK: 1293 mdb_printf("Servers %s ok", msg_srv); 1294 break; 1295 case RF_DELMAP_CB_ERR: 1296 if (mdb_readstr(file, sizeof (file), 1297 (uintptr_t)fp->rf_char1) == -1) 1298 strcpy(file, "??"); 1299 mdb_printf("Op %s got error %s when executing delmap on file " 1300 "%s (rnode_pt 0x%p).", nfs4_op_str(fp->rf_op), 1301 nfs4_stat_str(fp->rf_stat4), file, fp->rf_rp1); 1302 break; 1303 case RF_SENDQ_FULL: 1304 mdb_printf("Send queue to NFS server %s is full; still trying", 1305 msg_srv); 1306 break; 1307 default: 1308 mdb_printf("??"); 1309 break; 1310 } 1311 } 1312 1313 static int 1314 print_mimsg_cb(uintptr_t addr, const void *data, void *cb_data) 1315 { 1316 nfs4_debug_msg_t msg; 1317 uint_t opt_s = *(uint_t *)cb_data; 1318 1319 if (mdb_vread(&msg, sizeof (msg), addr) == -1) { 1320 mdb_warn("failed to read nfs4_debug_msg_t at %p", addr); 1321 return (WALK_ERR); 1322 } 1323 1324 if (opt_s) { 1325 const char *msg_type = "??"; 1326 const char *ef_type = "??"; 1327 int i; 1328 1329 switch (msg.msg_type) { 1330 case RM_EVENT: 1331 msg_type = "event"; 1332 for (i = 0; nfs4_event_type_tbl[i].str != NULL; i++) 1333 if (nfs4_event_type_tbl[i].et == 1334 msg.rmsg_u.msg_event.re_type) { 1335 ef_type = nfs4_event_type_tbl[i].str; 1336 break; 1337 } 1338 break; 1339 case RM_FACT: 1340 msg_type = "fact"; 1341 for (i = 0; nfs4_fact_type_tbl[i].str != NULL; i++) 1342 if (nfs4_fact_type_tbl[i].ft == 1343 msg.rmsg_u.msg_fact.rf_type) { 1344 ef_type = nfs4_fact_type_tbl[i].str; 1345 break; 1346 } 1347 break; 1348 } 1349 1350 mdb_printf("%Y: %s %s\n", msg.msg_time.tv_sec, msg_type, 1351 ef_type); 1352 1353 return (WALK_NEXT); 1354 } 1355 1356 mdb_printf("[NFS4]%Y: ", msg.msg_time.tv_sec); 1357 switch (msg.msg_type) { 1358 case RM_EVENT: 1359 mimsg_print_event(&msg); 1360 break; 1361 case RM_FACT: 1362 mimsg_print_fact(&msg); 1363 break; 1364 default: 1365 mdb_printf("??"); 1366 break; 1367 } 1368 mdb_printf("\n"); 1369 1370 return (WALK_NEXT); 1371 } 1372 1373 int 1374 nfs4_mimsg_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 1375 { 1376 uint_t opt_s = FALSE; 1377 1378 if ((flags & DCMD_ADDRSPEC) == 0) { 1379 mdb_printf("requires address of mi_msg_list\n"); 1380 return (DCMD_USAGE); 1381 } 1382 1383 if (mdb_getopts(argc, argv, 1384 's', MDB_OPT_SETBITS, TRUE, &opt_s, NULL) != argc) 1385 return (DCMD_USAGE); 1386 1387 if (mdb_pwalk("list", print_mimsg_cb, &opt_s, addr) == -1) { 1388 mdb_warn("failed to walk mi_msg_list list"); 1389 return (DCMD_ERR); 1390 } 1391 1392 return (DCMD_OK); 1393 } 1394 1395 void 1396 nfs4_mimsg_help(void) 1397 { 1398 mdb_printf( 1399 "-c assumes client is an illumos NFSv4 Client\n" 1400 "-s assumes server is an illumos NFSv4 Server\n" 1401 "\n" 1402 "The -c option enables the dcmd to decode the client generated\n" 1403 "structure CLIDtoSend that is normally opaque to the server.\n" 1404 "The -s option enables the dcmd to decode the server generated\n" 1405 "structure Client ID that is normally opaque to the client.\n"); 1406 } 1407 1408 /* 1409 * nfs4_fname dcmd implementation 1410 */ 1411 1412 static void 1413 print_nfs4_fname(uintptr_t addr) 1414 { 1415 char path[MAXPATHLEN]; 1416 char *p = path + sizeof (path) - 1; 1417 1418 *p = '\0'; 1419 while (addr != 0) { 1420 nfs4_fname_t fn; 1421 char name[MAXNAMELEN]; 1422 1423 if (mdb_vread(&fn, sizeof (fn), addr) == -1 || 1424 fn.fn_len >= sizeof (name) || fn.fn_len < 0 || 1425 p - fn.fn_len - 1 < path || mdb_readstr(name, sizeof (name), 1426 (uintptr_t)fn.fn_name) != fn.fn_len) { 1427 mdb_printf("??"); 1428 break; 1429 } 1430 1431 bcopy(name, p -= fn.fn_len, fn.fn_len); 1432 1433 if ((addr = (uintptr_t)fn.fn_parent) != 0) 1434 *--p = '/'; 1435 } 1436 mdb_printf("%s", p); 1437 } 1438 1439 int 1440 nfs4_fname_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 1441 { 1442 if ((flags & DCMD_ADDRSPEC) == 0) { 1443 mdb_printf("requires address of nfs4_fname_t \n"); 1444 return (DCMD_USAGE); 1445 } 1446 1447 if (argc != 0) 1448 return (DCMD_USAGE); 1449 1450 print_nfs4_fname(addr); 1451 mdb_printf("\n"); 1452 1453 return (DCMD_OK); 1454 } 1455 1456 /* 1457 * Open Owner commands and walkers 1458 */ 1459 int 1460 nfs4_oo_cb(uintptr_t addr, const void *data, void *varg) 1461 { 1462 nfs4_open_owner_t oop; 1463 1464 if (mdb_vread(&oop, sizeof (nfs4_open_owner_t), addr) == -1) { 1465 mdb_warn("failed to read nfs4_open_onwer at %p", addr); 1466 return (WALK_ERR); 1467 } 1468 mdb_printf("%p %p %d %d %s %s\n", addr, oop.oo_cred, 1469 oop.oo_ref_count, oop.oo_seqid, 1470 oop.oo_just_created ? "True" : "False", 1471 oop.oo_seqid_inuse ? "True" : "False"); 1472 1473 return (WALK_NEXT); 1474 } 1475 1476 /* 1477 * nfs4_foo dcmd implementation 1478 */ 1479 int 1480 nfs4_foo_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 1481 { 1482 int foo_off; 1483 uintptr_t list_addr; 1484 1485 mntinfo4_t mi; 1486 foo_off = offsetof(mntinfo4_t, mi_foo_list); 1487 1488 if ((flags & DCMD_ADDRSPEC) == 0) { 1489 mdb_printf("requires address of mntinfo4_t\n"); 1490 return (DCMD_USAGE); 1491 } 1492 1493 if (argc != 0) 1494 return (DCMD_USAGE); 1495 1496 if (mdb_vread(&mi, sizeof (mntinfo4_t), addr) == -1) { 1497 mdb_warn("Failed to read mntinfo at %p", addr); 1498 return (DCMD_ERR); 1499 } 1500 1501 list_addr = addr + foo_off; 1502 1503 mdb_printf("mntinfo4: %p, mi_foo_num=%d, mi_foo_max=%d \n", 1504 addr, mi.mi_foo_num, mi.mi_foo_max); 1505 mdb_printf("Address Cred RefCnt SeqID "); 1506 mdb_printf("JustCre SeqInUse BadSeqid\n"); 1507 1508 if (mdb_pwalk("list", nfs4_oo_cb, NULL, list_addr) == -1) { 1509 mdb_warn("failed to walk 'nfs4_foo'"); 1510 return (DCMD_ERR); 1511 } 1512 return (DCMD_OK); 1513 } 1514 1515 /* 1516 * nfs4_oob_dcmd dcmd 1517 */ 1518 int 1519 nfs4_oob_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 1520 { 1521 int oo_off; 1522 uintptr_t list_addr; 1523 uintptr_t list_inst; 1524 int i; 1525 1526 1527 if ((flags & DCMD_ADDRSPEC) == 0) { 1528 mdb_printf("requires address of mntinfo4_t\n"); 1529 return (DCMD_USAGE); 1530 } 1531 1532 if (argc != 0) 1533 return (DCMD_USAGE); 1534 1535 oo_off = offsetof(mntinfo4_t, mi_oo_list); 1536 list_addr = addr + oo_off; 1537 1538 mdb_printf("Address Cred RefCnt SeqID "); 1539 mdb_printf("JustCre SeqInUse BadSeqid\n"); 1540 1541 for (i = 0; i < NFS4_NUM_OO_BUCKETS; i++) { 1542 list_inst = list_addr + (sizeof (nfs4_oo_hash_bucket_t) * i); 1543 1544 if (mdb_pwalk("list", nfs4_oo_cb, NULL, list_inst) == -1) { 1545 mdb_warn("failed to walk 'nfs4_oob'"); 1546 return (DCMD_ERR); 1547 } 1548 } 1549 1550 return (DCMD_OK); 1551 } 1552 1553 /* 1554 * print out open stream entry 1555 */ 1556 int 1557 nfs4_openstream_print(uintptr_t addr, void *buf, int *opts) 1558 { 1559 nfs4_open_stream_t os; 1560 1561 if (mdb_vread(&os, sizeof (nfs4_open_stream_t), addr) == -1) { 1562 mdb_warn("Failed to read open stream at %p", addr); 1563 return (DCMD_ERR); 1564 } 1565 1566 mdb_printf("%p\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t" 1567 "%d\t%d\t%d\n", addr, os.os_ref_count, os.os_share_acc_read, 1568 os.os_share_acc_write, os.os_mmap_read, os.os_mmap_write, 1569 os.os_share_deny_none, os.os_share_deny_read, 1570 os.os_share_deny_write, os.os_open_ref_count, os.os_dc_openacc, 1571 os.os_mapcnt); 1572 1573 if (opts && *opts & TRUE) { 1574 mdb_printf(" "); 1575 if (os.os_valid) 1576 mdb_printf("os_valid "); 1577 if (os.os_delegation) 1578 mdb_printf("os_delegation "); 1579 if (os.os_final_close) 1580 mdb_printf("os_final_close "); 1581 if (os.os_pending_close) 1582 mdb_printf("os_pending_close "); 1583 if (os.os_failed_reopen) 1584 mdb_printf("os_failed_reopen "); 1585 if (os.os_force_close) 1586 mdb_printf("os_force_close "); 1587 mdb_printf("os_orig_oo_name: %s\n", 1588 (uchar_t *)&os.os_orig_oo_name); 1589 } 1590 return (DCMD_OK); 1591 } 1592 1593 /* 1594 * nfs4_svnode dcmd implementation 1595 */ 1596 int 1597 nfs4_openstreams_cb(uintptr_t addr, void *private, int *opts) 1598 { 1599 mdb_ctf_id_t ctfid; 1600 ulong_t offset; 1601 uintptr_t os_list_ptr; 1602 1603 /* 1604 * Walk the rnode4 ptr's r_open_streams list. 1605 */ 1606 if ((mdb_ctf_lookup_by_name("rnode4_t", &ctfid) == 0) && 1607 (mdb_ctf_offsetof(ctfid, "r_open_streams", &offset) == 0) && 1608 (offset % (sizeof (uintptr_t) * NBBY) == 0)) { 1609 offset /= NBBY; 1610 } else { 1611 offset = offsetof(rnode4_t, r_open_streams); 1612 } 1613 1614 os_list_ptr = addr + offset; 1615 1616 if (mdb_pwalk("list", (mdb_walk_cb_t)nfs4_openstream_print, opts, 1617 os_list_ptr) == -1) { 1618 mdb_warn("Failed to walk r_open_streams"); 1619 return (DCMD_ERR); 1620 } 1621 return (DCMD_OK); 1622 } 1623 1624 /* 1625 * nfs4_os_dcmd list open streams 1626 */ 1627 int 1628 nfs4_os_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 1629 { 1630 int opts = 0; 1631 1632 if (mdb_getopts(argc, argv, 'v', MDB_OPT_SETBITS, TRUE, &opts, 1633 NULL) != argc) { 1634 return (DCMD_USAGE); 1635 } 1636 1637 mdb_printf(" ref\t| os_share | os_mmap | " 1638 "os_share_deny | open | deleg |\t|\n"); 1639 1640 mdb_printf("%<u>%-?s %-s|%s %s|%s %s|%s %s %s|" 1641 "%s |%s |%s |%</u>\n", "Address", "count", "acc_read", 1642 "acc_write", "read", "write", "none", "read", "write", "count", 1643 "access", "mapcnt"); 1644 1645 /* 1646 * Walk the rnode4 cache if no address is specified 1647 */ 1648 if (!(flags & DCMD_ADDRSPEC)) { 1649 if (mdb_walk("nfs_rtable4", (mdb_walk_cb_t)nfs4_openstreams_cb, 1650 &opts) == -1) { 1651 mdb_warn("unable to walk nfs_rtable4"); 1652 return (DCMD_ERR); 1653 } 1654 return (DCMD_OK); 1655 } 1656 return (nfs4_openstreams_cb(addr, NULL, &opts)); 1657 } 1658 1659 1660 int 1661 nfs4_svnode_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 1662 { 1663 svnode_t sn; 1664 1665 if ((flags & DCMD_ADDRSPEC) == 0) { 1666 mdb_printf("requires address of svnode_t\n"); 1667 return (DCMD_USAGE); 1668 } 1669 1670 if (argc != 0) 1671 return (DCMD_USAGE); 1672 1673 if (mdb_vread(&sn, sizeof (sn), addr) == -1) { 1674 mdb_warn("can't read svnode_t at %p", addr); 1675 return (DCMD_ERR); 1676 } 1677 1678 if (DCMD_HDRSPEC(flags)) 1679 mdb_printf("%<b>%<u>%-?s %-?s %-20s%</u>%</b>\n", "SVNODE", 1680 "VNODE", "PATH"); 1681 1682 mdb_printf("%-?p %-?p ", addr, sn.sv_r_vnode); 1683 print_nfs4_fname((uintptr_t)sn.sv_name); 1684 mdb_printf("\n"); 1685 1686 return (DCMD_OK); 1687 } 1688 1689 /* 1690 * nfs_rtable walker implementation 1691 */ 1692 1693 hash_table_walk_arg_t nfs_rtable_arg = { 1694 0, /* will be set in the init */ 1695 0, /* will be set in the init */ 1696 sizeof (rhashq_t), 1697 "r_hashf", 1698 OFFSETOF(rhashq_t, r_hashf), 1699 "rnode_t", 1700 sizeof (rnode_t), 1701 OFFSETOF(struct rnode, r_hashf) 1702 }; 1703 1704 static int 1705 nfs_rtable_common_init(mdb_walk_state_t *wsp, const char *tabname, 1706 const char *sizename) 1707 { 1708 hash_table_walk_arg_t *arg = wsp->walk_arg; 1709 int rtsize; 1710 uintptr_t rtaddr; 1711 1712 if (mdb_readsym(&rtsize, sizeof (rtsize), sizename) == -1) { 1713 mdb_warn("failed to get %s", sizename); 1714 return (WALK_ERR); 1715 } 1716 1717 if (rtsize < 0) { 1718 mdb_warn("%s is negative: %d", sizename, rtsize); 1719 return (WALK_ERR); 1720 } 1721 1722 if (mdb_readsym(&rtaddr, sizeof (rtaddr), tabname) == -1) { 1723 mdb_warn("failed to get %s", tabname); 1724 return (WALK_ERR); 1725 } 1726 1727 arg->array_addr = rtaddr; 1728 arg->array_len = rtsize; 1729 1730 return (hash_table_walk_init(wsp)); 1731 } 1732 1733 int 1734 nfs_rtable_walk_init(mdb_walk_state_t *wsp) 1735 { 1736 if (wsp->walk_addr != 0) { 1737 mdb_warn("nfs_rtable supports only global walks"); 1738 return (WALK_ERR); 1739 } 1740 1741 return (nfs_rtable_common_init(wsp, "rtable", "rtablesize")); 1742 } 1743 1744 /* 1745 * nfs_rtable4 walker implementation 1746 */ 1747 1748 hash_table_walk_arg_t nfs_rtable4_arg = { 1749 0, /* will be set in the init */ 1750 0, /* will be set in the init */ 1751 sizeof (r4hashq_t), 1752 "r_hashf", 1753 OFFSETOF(r4hashq_t, r_hashf), 1754 "rnode4_t", 1755 sizeof (rnode4_t), 1756 OFFSETOF(struct rnode4, r_hashf) 1757 }; 1758 1759 int 1760 nfs_rtable4_walk_init(mdb_walk_state_t *wsp) 1761 { 1762 if (wsp->walk_addr != 0) { 1763 mdb_warn("nfs_rtable4 supports only global walks"); 1764 return (WALK_ERR); 1765 } 1766 1767 return (nfs_rtable_common_init(wsp, "rtable4", "rtable4size")); 1768 } 1769 1770 /* 1771 * nfs_vfs walker implementation 1772 */ 1773 1774 typedef struct nfs_vfs_walk { 1775 uintptr_t nfs2_ops; 1776 uintptr_t nfs3_ops; 1777 uintptr_t nfs4_ops; 1778 void *data; /* walker specific data */ 1779 } nfs_vfs_walk_t; 1780 1781 int 1782 nfs_vfs_walk_init(mdb_walk_state_t *wsp) 1783 { 1784 nfs_vfs_walk_t data; 1785 nfs_vfs_walk_t *datap; 1786 1787 if (mdb_readvar(&data.nfs2_ops, "nfs_vfsops") == -1) { 1788 mdb_warn("failed to read %s", "nfs_vfsops"); 1789 return (WALK_ERR); 1790 } 1791 1792 if (mdb_readvar(&data.nfs3_ops, "nfs3_vfsops") == -1) { 1793 mdb_warn("failed to read %s", "nfs3_vfsops"); 1794 return (WALK_ERR); 1795 } 1796 1797 if (mdb_readvar(&data.nfs4_ops, "nfs4_vfsops") == -1) { 1798 mdb_warn("failed to read %s", "nfs4_vfsops"); 1799 return (WALK_ERR); 1800 } 1801 1802 if (mdb_layered_walk("genunix`vfs", wsp) == -1) { 1803 mdb_warn("failed to walk vfs"); 1804 return (WALK_ERR); 1805 } 1806 1807 datap = mdb_alloc(sizeof (data), UM_SLEEP); 1808 *datap = data; 1809 wsp->walk_data = datap; 1810 1811 return (WALK_NEXT); 1812 } 1813 1814 int 1815 nfs_vfs_walk_step(mdb_walk_state_t *wsp) 1816 { 1817 nfs_vfs_walk_t *data = (nfs_vfs_walk_t *)wsp->walk_data; 1818 vfs_t *vfs = (vfs_t *)wsp->walk_layer; 1819 1820 if (data->nfs2_ops != (uintptr_t)vfs->vfs_op && 1821 data->nfs3_ops != (uintptr_t)vfs->vfs_op && 1822 data->nfs4_ops != (uintptr_t)vfs->vfs_op) 1823 return (WALK_NEXT); 1824 1825 return (wsp->walk_callback(wsp->walk_addr, wsp->walk_layer, 1826 wsp->walk_cbdata)); 1827 } 1828 1829 void 1830 nfs_vfs_walk_fini(mdb_walk_state_t *wsp) 1831 { 1832 mdb_free(wsp->walk_data, sizeof (nfs_vfs_walk_t)); 1833 } 1834 1835 /* 1836 * nfs_mnt walker implementation 1837 */ 1838 1839 int 1840 nfs_mnt_walk_init(mdb_walk_state_t *wsp) 1841 { 1842 int status; 1843 nfs_vfs_walk_t *data; 1844 1845 status = nfs_vfs_walk_init(wsp); 1846 if (status != WALK_NEXT) 1847 return (status); 1848 1849 data = wsp->walk_data; 1850 data->data = mdb_alloc(sizeof (mntinfo_t), UM_SLEEP); 1851 1852 return (WALK_NEXT); 1853 } 1854 1855 int 1856 nfs_mnt_walk_step(mdb_walk_state_t *wsp) 1857 { 1858 nfs_vfs_walk_t *data = (nfs_vfs_walk_t *)wsp->walk_data; 1859 vfs_t *vfs = (vfs_t *)wsp->walk_layer; 1860 1861 if (data->nfs2_ops != (uintptr_t)vfs->vfs_op && 1862 data->nfs3_ops != (uintptr_t)vfs->vfs_op) 1863 return (WALK_NEXT); 1864 1865 if (mdb_vread(data->data, sizeof (mntinfo_t), (uintptr_t)VFTOMI(vfs)) 1866 == -1) { 1867 mdb_warn("can't read mntinfo"); 1868 return (WALK_ERR); 1869 } 1870 1871 return (wsp->walk_callback((uintptr_t)VFTOMI(vfs), data->data, 1872 wsp->walk_cbdata)); 1873 } 1874 1875 void 1876 nfs_mnt_walk_fini(mdb_walk_state_t *wsp) 1877 { 1878 nfs_vfs_walk_t *data = (nfs_vfs_walk_t *)wsp->walk_data; 1879 1880 mdb_free(data->data, sizeof (mntinfo_t)); 1881 nfs_vfs_walk_fini(wsp); 1882 } 1883 1884 /* 1885 * nfs4_mnt walker implementation 1886 */ 1887 1888 int 1889 nfs4_mnt_walk_init(mdb_walk_state_t *wsp) 1890 { 1891 int status; 1892 nfs_vfs_walk_t *data; 1893 1894 status = nfs_vfs_walk_init(wsp); 1895 if (status != WALK_NEXT) 1896 return (status); 1897 1898 data = wsp->walk_data; 1899 data->data = mdb_alloc(sizeof (mntinfo4_t), UM_SLEEP); 1900 1901 return (WALK_NEXT); 1902 } 1903 1904 int 1905 nfs4_mnt_walk_step(mdb_walk_state_t *wsp) 1906 { 1907 nfs_vfs_walk_t *data = (nfs_vfs_walk_t *)wsp->walk_data; 1908 vfs_t *vfs = (vfs_t *)wsp->walk_layer; 1909 1910 if (data->nfs4_ops != (uintptr_t)vfs->vfs_op) 1911 return (WALK_NEXT); 1912 1913 if (mdb_vread(data->data, sizeof (mntinfo4_t), (uintptr_t)VFTOMI4(vfs)) 1914 == -1) { 1915 mdb_warn("can't read mntinfo4"); 1916 return (WALK_ERR); 1917 } 1918 1919 return (wsp->walk_callback((uintptr_t)VFTOMI4(vfs), data->data, 1920 wsp->walk_cbdata)); 1921 } 1922 1923 void 1924 nfs4_mnt_walk_fini(mdb_walk_state_t *wsp) 1925 { 1926 nfs_vfs_walk_t *data = (nfs_vfs_walk_t *)wsp->walk_data; 1927 1928 mdb_free(data->data, sizeof (mntinfo4_t)); 1929 nfs_vfs_walk_fini(wsp); 1930 } 1931 1932 /* 1933 * nfs_serv walker implementation 1934 */ 1935 1936 int 1937 nfs_serv_walk_init(mdb_walk_state_t *wsp) 1938 { 1939 if (wsp->walk_addr == 0) { 1940 mdb_warn("global walk not supported"); 1941 return (WALK_ERR); 1942 } 1943 1944 return (WALK_NEXT); 1945 } 1946 1947 int 1948 nfs_serv_walk_step(mdb_walk_state_t *wsp) 1949 { 1950 servinfo_t si; 1951 uintptr_t addr = wsp->walk_addr; 1952 1953 if (addr == 0) 1954 return (WALK_DONE); 1955 1956 if (mdb_vread(&si, sizeof (si), addr) == -1) { 1957 mdb_warn("can't read servinfo_t"); 1958 return (WALK_ERR); 1959 } 1960 1961 wsp->walk_addr = (uintptr_t)si.sv_next; 1962 return (wsp->walk_callback(addr, &si, wsp->walk_cbdata)); 1963 } 1964 1965 /* 1966 * nfs4_serv walker implementation 1967 */ 1968 1969 int 1970 nfs4_serv_walk_init(mdb_walk_state_t *wsp) 1971 { 1972 if (wsp->walk_addr == 0) { 1973 mdb_warn("global walk not supported"); 1974 return (WALK_ERR); 1975 } 1976 1977 return (WALK_NEXT); 1978 } 1979 1980 int 1981 nfs4_serv_walk_step(mdb_walk_state_t *wsp) 1982 { 1983 servinfo4_t si; 1984 uintptr_t addr = wsp->walk_addr; 1985 1986 if (addr == 0) 1987 return (WALK_DONE); 1988 1989 if (mdb_vread(&si, sizeof (si), addr) == -1) { 1990 mdb_warn("can't read servinfo4_t"); 1991 return (WALK_ERR); 1992 } 1993 1994 wsp->walk_addr = (uintptr_t)si.sv_next; 1995 return (wsp->walk_callback(addr, &si, wsp->walk_cbdata)); 1996 } 1997 1998 /* 1999 * nfs4_svnode walker implementation 2000 */ 2001 2002 int 2003 nfs4_svnode_walk_init(mdb_walk_state_t *wsp) 2004 { 2005 if (wsp->walk_addr == 0) { 2006 mdb_warn("global walk not supported"); 2007 return (WALK_ERR); 2008 } 2009 2010 wsp->walk_data = (void *)wsp->walk_addr; 2011 2012 return (WALK_NEXT); 2013 } 2014 2015 int 2016 nfs4_svnode_walk_step(mdb_walk_state_t *wsp) 2017 { 2018 svnode_t sn; 2019 uintptr_t addr = wsp->walk_addr; 2020 int status; 2021 2022 if (mdb_vread(&sn, sizeof (sn), addr) == -1) { 2023 mdb_warn("can't read svnode_t"); 2024 return (WALK_ERR); 2025 } 2026 2027 wsp->walk_addr = (uintptr_t)sn.sv_forw; 2028 2029 status = wsp->walk_callback(addr, &sn, wsp->walk_cbdata); 2030 if (status != WALK_NEXT) 2031 return (status); 2032 2033 return (((void *)wsp->walk_addr == wsp->walk_data) ? WALK_DONE 2034 : WALK_NEXT); 2035 } 2036 2037 /* 2038 * nfs4_server walker implementation 2039 */ 2040 2041 int 2042 nfs4_server_walk_init(mdb_walk_state_t *wsp) 2043 { 2044 if (wsp->walk_addr == 0) { 2045 GElf_Sym sym; 2046 2047 if (mdb_lookup_by_name("nfs4_server_lst", &sym) == -1) { 2048 mdb_warn("failed to find 'nfs4_server_lst'"); 2049 return (WALK_ERR); 2050 } 2051 2052 wsp->walk_addr = sym.st_value; 2053 } 2054 2055 wsp->walk_data = (void *)wsp->walk_addr; 2056 2057 return (WALK_NEXT); 2058 } 2059 2060 int 2061 nfs4_server_walk_step(mdb_walk_state_t *wsp) 2062 { 2063 nfs4_server_t srv; 2064 uintptr_t addr = wsp->walk_addr; 2065 int status; 2066 2067 if (mdb_vread(&srv, sizeof (srv), addr) == -1) { 2068 mdb_warn("can't read nfs4_server_t"); 2069 return (WALK_ERR); 2070 } 2071 2072 wsp->walk_addr = (uintptr_t)srv.forw; 2073 2074 status = wsp->walk_callback(addr, &srv, wsp->walk_cbdata); 2075 if (status != WALK_NEXT) 2076 return (status); 2077 2078 return (((void *)wsp->walk_addr == wsp->walk_data) ? WALK_DONE 2079 : WALK_NEXT); 2080 } 2081 2082 /* 2083 * nfs_async walker implementation 2084 */ 2085 2086 int 2087 nfs_async_walk_init(mdb_walk_state_t *wsp) 2088 { 2089 if (wsp->walk_addr == 0) { 2090 mdb_warn("global walk not supported"); 2091 return (WALK_ERR); 2092 } 2093 2094 return (WALK_NEXT); 2095 } 2096 2097 int 2098 nfs_async_walk_step(mdb_walk_state_t *wsp) 2099 { 2100 struct nfs_async_reqs areq; 2101 uintptr_t addr = wsp->walk_addr; 2102 2103 if (addr == 0) 2104 return (WALK_DONE); 2105 2106 if (mdb_vread(&areq, sizeof (areq), addr) == -1) { 2107 mdb_warn("can't read struct nfs_async_reqs"); 2108 return (WALK_ERR); 2109 } 2110 2111 wsp->walk_addr = (uintptr_t)areq.a_next; 2112 2113 return (wsp->walk_callback(addr, &areq, wsp->walk_cbdata)); 2114 } 2115 2116 /* 2117 * nfs4_async walker implementation 2118 */ 2119 2120 int 2121 nfs4_async_walk_init(mdb_walk_state_t *wsp) 2122 { 2123 if (wsp->walk_addr == 0) { 2124 mdb_warn("global walk not supported"); 2125 return (WALK_ERR); 2126 } 2127 2128 return (WALK_NEXT); 2129 } 2130 2131 int 2132 nfs4_async_walk_step(mdb_walk_state_t *wsp) 2133 { 2134 struct nfs4_async_reqs areq; 2135 uintptr_t addr = wsp->walk_addr; 2136 2137 if (addr == 0) 2138 return (WALK_DONE); 2139 2140 if (mdb_vread(&areq, sizeof (areq), addr) == -1) { 2141 mdb_warn("can't read struct nfs4_async_reqs"); 2142 return (WALK_ERR); 2143 } 2144 2145 wsp->walk_addr = (uintptr_t)areq.a_next; 2146 2147 return (wsp->walk_callback(addr, &areq, wsp->walk_cbdata)); 2148 } 2149 2150 /* 2151 * nfs_acache_rnode walker implementation 2152 */ 2153 2154 int 2155 nfs_acache_rnode_walk_init(mdb_walk_state_t *wsp) 2156 { 2157 rnode_t rn; 2158 2159 if (wsp->walk_addr == 0) { 2160 mdb_warn("global walk not supported"); 2161 return (WALK_ERR); 2162 } 2163 2164 if (mdb_vread(&rn, sizeof (rn), wsp->walk_addr) == -1) { 2165 mdb_warn("can't read rnode_t at %p", wsp->walk_addr); 2166 return (WALK_ERR); 2167 } 2168 2169 wsp->walk_addr = (uintptr_t)rn.r_acache; 2170 2171 return (WALK_NEXT); 2172 } 2173 2174 int 2175 nfs_acache_rnode_walk_step(mdb_walk_state_t *wsp) 2176 { 2177 acache_t ac; 2178 uintptr_t addr = wsp->walk_addr; 2179 2180 if (addr == 0) 2181 return (WALK_DONE); 2182 2183 if (mdb_vread(&ac, sizeof (ac), addr) == -1) { 2184 mdb_warn("can't read acache_t at %p", addr); 2185 return (WALK_ERR); 2186 } 2187 2188 wsp->walk_addr = (uintptr_t)ac.list; 2189 2190 return (wsp->walk_callback(addr, &ac, wsp->walk_cbdata)); 2191 } 2192 2193 /* 2194 * nfs_acache walker implementation 2195 */ 2196 2197 static const hash_table_walk_arg_t nfs_acache_arg = { 2198 0, /* placeholder */ 2199 0, /* placeholder */ 2200 sizeof (acache_hash_t), 2201 "next", 2202 OFFSETOF(acache_hash_t, next), 2203 "acache_t", 2204 sizeof (acache_t), 2205 OFFSETOF(acache_t, next) 2206 }; 2207 2208 int 2209 nfs_acache_walk_init(mdb_walk_state_t *wsp) 2210 { 2211 hash_table_walk_arg_t *arg; 2212 int size; 2213 uintptr_t addr; 2214 int status; 2215 2216 if (wsp->walk_addr != 0) { 2217 mdb_warn("local walk not supported"); 2218 return (WALK_ERR); 2219 } 2220 2221 if (mdb_readsym(&size, sizeof (size), "acachesize") == -1) { 2222 mdb_warn("failed to get %s", "acachesize"); 2223 return (WALK_ERR); 2224 } 2225 2226 if (size < 0) { 2227 mdb_warn("%s is negative: %d", "acachesize", size); 2228 return (WALK_ERR); 2229 } 2230 2231 if (mdb_readsym(&addr, sizeof (addr), "acache") == -1) { 2232 mdb_warn("failed to get %s", "acache"); 2233 return (WALK_ERR); 2234 } 2235 2236 arg = mdb_alloc(sizeof (*arg), UM_SLEEP); 2237 bcopy(&nfs_acache_arg, arg, sizeof (*arg)); 2238 2239 arg->array_addr = addr; 2240 arg->array_len = size; 2241 2242 wsp->walk_arg = arg; 2243 2244 status = hash_table_walk_init(wsp); 2245 if (status != WALK_NEXT) 2246 mdb_free(wsp->walk_arg, sizeof (hash_table_walk_arg_t)); 2247 return (status); 2248 } 2249 2250 void 2251 nfs_acache_walk_fini(mdb_walk_state_t *wsp) 2252 { 2253 hash_table_walk_fini(wsp); 2254 mdb_free(wsp->walk_arg, sizeof (hash_table_walk_arg_t)); 2255 } 2256 2257 /* 2258 * nfs_acache4_rnode walker implementation 2259 */ 2260 2261 int 2262 nfs_acache4_rnode_walk_init(mdb_walk_state_t *wsp) 2263 { 2264 rnode4_t rn; 2265 2266 if (wsp->walk_addr == 0) { 2267 mdb_warn("global walk not supported"); 2268 return (WALK_ERR); 2269 } 2270 2271 if (mdb_vread(&rn, sizeof (rn), wsp->walk_addr) == -1) { 2272 mdb_warn("can't read rnode4_t at %p", wsp->walk_addr); 2273 return (WALK_ERR); 2274 } 2275 2276 wsp->walk_addr = (uintptr_t)rn.r_acache; 2277 2278 return (WALK_NEXT); 2279 } 2280 2281 int 2282 nfs_acache4_rnode_walk_step(mdb_walk_state_t *wsp) 2283 { 2284 acache4_t ac; 2285 uintptr_t addr = wsp->walk_addr; 2286 2287 if (addr == 0) 2288 return (WALK_DONE); 2289 2290 if (mdb_vread(&ac, sizeof (ac), addr) == -1) { 2291 mdb_warn("can't read acache4_t at %p", addr); 2292 return (WALK_ERR); 2293 } 2294 2295 wsp->walk_addr = (uintptr_t)ac.list; 2296 2297 return (wsp->walk_callback(addr, &ac, wsp->walk_cbdata)); 2298 } 2299 2300 /* 2301 * nfs_acache4 walker implementation 2302 */ 2303 2304 static const hash_table_walk_arg_t nfs_acache4_arg = { 2305 0, /* placeholder */ 2306 0, /* placeholder */ 2307 sizeof (acache4_hash_t), 2308 "next", 2309 OFFSETOF(acache4_hash_t, next), 2310 "acache4_t", 2311 sizeof (acache4_t), 2312 OFFSETOF(acache4_t, next) 2313 }; 2314 2315 int 2316 nfs_acache4_walk_init(mdb_walk_state_t *wsp) 2317 { 2318 hash_table_walk_arg_t *arg; 2319 int size; 2320 uintptr_t addr; 2321 int status; 2322 2323 if (wsp->walk_addr != 0) { 2324 mdb_warn("local walk not supported"); 2325 return (WALK_ERR); 2326 } 2327 2328 if (mdb_readsym(&size, sizeof (size), "acache4size") == -1) { 2329 mdb_warn("failed to get %s", "acache4size"); 2330 return (WALK_ERR); 2331 } 2332 2333 if (size < 0) { 2334 mdb_warn("%s is negative: %d\n", "acache4size", size); 2335 return (WALK_ERR); 2336 } 2337 2338 if (mdb_readsym(&addr, sizeof (addr), "acache4") == -1) { 2339 mdb_warn("failed to get %s", "acache4"); 2340 return (WALK_ERR); 2341 } 2342 2343 arg = mdb_alloc(sizeof (*arg), UM_SLEEP); 2344 bcopy(&nfs_acache4_arg, arg, sizeof (*arg)); 2345 2346 arg->array_addr = addr; 2347 arg->array_len = size; 2348 2349 wsp->walk_arg = arg; 2350 2351 status = hash_table_walk_init(wsp); 2352 if (status != WALK_NEXT) 2353 mdb_free(wsp->walk_arg, sizeof (hash_table_walk_arg_t)); 2354 return (status); 2355 } 2356 2357 void 2358 nfs_acache4_walk_fini(mdb_walk_state_t *wsp) 2359 { 2360 hash_table_walk_fini(wsp); 2361 mdb_free(wsp->walk_arg, sizeof (hash_table_walk_arg_t)); 2362 } 2363