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 <nfs/nfs4.h> 17 #include <nfs/nfs4_db_impl.h> 18 #include <limits.h> 19 20 #include "rfs4.h" 21 #include "common.h" 22 23 /* 24 * rfs4_db dcmd implementation 25 */ 26 27 int 28 rfs4_db_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 29 { 30 uintptr_t glbls; 31 uintptr_t zonep; 32 rfs4_database_t rfs4_db; 33 nfs_globals_t nfsglbls; 34 struct nfs4_srv nfs4srv; 35 36 if (argc > 0) 37 return (DCMD_USAGE); 38 39 40 if ((flags & DCMD_ADDRSPEC) != 0) { 41 zonep = addr; 42 } else { 43 if (mdb_readsym(&zonep, sizeof (uintptr_t), 44 "global_zone") == -1) { 45 mdb_warn("Failed to find global_zone"); 46 return (DCMD_ERR); 47 } 48 } 49 50 if (zoned_get_nfs_globals(zonep, &glbls) != DCMD_OK) { 51 mdb_warn("failed to get zoned specific NFS globals"); 52 return (DCMD_ERR); 53 } 54 55 if (mdb_vread(&nfsglbls, sizeof (nfs_globals_t), glbls) == -1) { 56 mdb_warn("can't read zone globals"); 57 return (DCMD_ERR); 58 } 59 60 if (mdb_vread(&nfs4srv, sizeof (struct nfs4_srv), 61 (uintptr_t)nfsglbls.nfs4_srv) == -1) { 62 mdb_warn("can't read NFS4 server structure"); 63 return (DCMD_ERR); 64 } 65 66 if (mdb_vread(&rfs4_db, sizeof (rfs4_database_t), 67 (uintptr_t)nfs4srv.nfs4_server_state) == -1) { 68 mdb_warn("can't read NFS4 server state"); 69 return (DCMD_ERR); 70 } 71 72 if (mdb_pwalk_dcmd("rfs4_db_tbl", "rfs4_tbl", 0, NULL, 73 (uintptr_t)rfs4_db.db_tables) == -1) { 74 mdb_warn("failed to walk tables"); 75 return (DCMD_ERR); 76 } 77 78 return (DCMD_OK); 79 } 80 81 /* 82 * rfs4_tbl dcmd implementation 83 */ 84 85 int 86 rfs4_tbl_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 87 { 88 rfs4_table_t tbl; 89 char name[14]; 90 uint_t opt_v = FALSE; 91 uint_t opt_w = FALSE; 92 93 if ((flags & DCMD_ADDRSPEC) == 0) { 94 mdb_printf("requires address of rfs4_table_t\n"); 95 return (DCMD_USAGE); 96 } 97 98 if (mdb_getopts(argc, argv, 99 'v', MDB_OPT_SETBITS, TRUE, &opt_v, 100 'w', MDB_OPT_SETBITS, TRUE, &opt_w, NULL) != argc) 101 return (DCMD_USAGE); 102 103 if (opt_w) { 104 mdb_arg_t arg; 105 mdb_arg_t *argp = NULL; 106 int n = 0; 107 108 if (opt_v) { 109 arg.a_type = MDB_TYPE_STRING; 110 arg.a_un.a_str = "-v"; 111 argp = &arg; 112 n = 1; 113 } 114 115 /* Walk through all tables */ 116 if (mdb_pwalk_dcmd("rfs4_db_tbl", "rfs4_tbl", n, argp, addr) 117 == -1) { 118 mdb_warn("failed to walk tables\n"); 119 return (DCMD_ERR); 120 } 121 return (DCMD_OK); 122 } 123 124 if (mdb_vread(&tbl, sizeof (tbl), addr) == -1) { 125 mdb_warn("can't read rfs4_table_t"); 126 return (DCMD_ERR); 127 } 128 129 if (!opt_v && DCMD_HDRSPEC(flags)) { 130 const size_t ptrsize = mdb_snprintf(NULL, 0, "%?p"); 131 size_t sz = ptrsize + 1 + sizeof (name) + 8 + 5 - 7; 132 size_t i; 133 134 mdb_printf("%<b>"); 135 for (i = 0; i < (sz + 1) / 2; i++) 136 mdb_printf("-"); 137 mdb_printf(" Table "); 138 for (i = 0; i < sz - (sz + 1) / 2; i++) 139 mdb_printf("-"); 140 141 mdb_printf(" Bkt "); 142 143 sz = ptrsize + 5 + 5 - 9; 144 145 for (i = 0; i < (sz + 1) / 2; i++) 146 mdb_printf("-"); 147 mdb_printf(" Indices "); 148 for (i = 0; i < sz - (sz + 1) / 2; i++) 149 mdb_printf("-"); 150 mdb_printf("%</b>\n"); 151 152 mdb_printf("%<b>%<u>%-?s %-*s%-8s Cnt %</u> %<u>Cnt %</u> " 153 "%<u>%-?s Cnt Max %</u>%</b>\n", "Address", sizeof (name), 154 "Name", "Flags", "Pointer"); 155 } 156 157 if (mdb_readstr(name, sizeof (name), (uintptr_t)tbl.dbt_name) == -1) { 158 mdb_warn("can't read dbt_name"); 159 return (DCMD_ERR); 160 } 161 mdb_printf("%?p %-*s%08x %04u %04u %?p %04u %04u\n", addr, 162 sizeof (name), name, tbl.dbt_debug, tbl.dbt_count, tbl.dbt_len, 163 tbl.dbt_indices, tbl.dbt_idxcnt, tbl.dbt_maxcnt); 164 165 if (opt_v) { 166 mdb_inc_indent(8); 167 mdb_printf("db = %p\n", tbl.dbt_db); 168 mdb_printf("t_lock = %s\n", 169 common_rwlock(tbl.dbt_t_lock)); 170 mdb_printf("lock = %s\n", 171 common_mutex(tbl.dbt_lock)); 172 mdb_printf("id_space = %p\n", tbl.dbt_id_space); 173 mdb_printf("min_cache_time = %lu\n", tbl.dbt_min_cache_time); 174 mdb_printf("max_cache_time = %lu\n", tbl.dbt_max_cache_time); 175 mdb_printf("usize = %u\n", tbl.dbt_usize); 176 mdb_printf("maxentries = %u\n", tbl.dbt_maxentries); 177 mdb_printf("len = %u\n", tbl.dbt_len); 178 mdb_printf("count = %u\n", tbl.dbt_count); 179 mdb_printf("idxcnt = %u\n", tbl.dbt_idxcnt); 180 mdb_printf("maxcnt = %u\n", tbl.dbt_maxcnt); 181 mdb_printf("ccnt = %u\n", tbl.dbt_ccnt); 182 mdb_printf("indices = %p\n", tbl.dbt_indices); 183 mdb_printf("create = %a\n", tbl.dbt_create); 184 mdb_printf("destroy = %a\n", tbl.dbt_destroy); 185 mdb_printf("expiry = %a\n", tbl.dbt_expiry); 186 mdb_printf("mem_cache = %p\n", tbl.dbt_mem_cache); 187 mdb_printf("debug = %08x\n", tbl.dbt_debug); 188 mdb_printf("reaper_shutdown = %s\n\n", 189 tbl.dbt_reaper_shutdown ? "TRUE" : "FALSE"); 190 mdb_dec_indent(8); 191 } 192 193 return (DCMD_OK); 194 } 195 196 void 197 rfs4_tbl_help(void) 198 { 199 mdb_printf( 200 "-v display more details about the table\n" 201 "-w walks along all tables in the list\n" 202 "\n" 203 "The following two commands are equivalent:\n" 204 " ::rfs4_tbl -w\n" 205 " ::walk rfs4_db_tbl|::rfs4_tbl\n"); 206 } 207 208 /* 209 * rfs4_tbl dcmd implementation 210 */ 211 212 int 213 rfs4_idx_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 214 { 215 rfs4_index_t idx; 216 char name[19]; 217 uint_t opt_w = FALSE; 218 219 if ((flags & DCMD_ADDRSPEC) == 0) { 220 mdb_printf("requires address of rfs4_index_t\n"); 221 return (DCMD_USAGE); 222 } 223 224 if (mdb_getopts(argc, argv, 225 'w', MDB_OPT_SETBITS, TRUE, &opt_w, NULL) != argc) 226 return (DCMD_USAGE); 227 228 if (opt_w) { 229 /* Walk through all tables */ 230 if (mdb_pwalk_dcmd("rfs4_db_idx", "rfs4_idx", 0, NULL, addr) 231 == -1) { 232 mdb_warn("failed to walk indices"); 233 return (DCMD_ERR); 234 } 235 return (DCMD_OK); 236 } 237 238 if (mdb_vread(&idx, sizeof (idx), addr) == -1) { 239 mdb_warn("can't read rfs4_index_t"); 240 return (DCMD_ERR); 241 } 242 243 if (DCMD_HDRSPEC(flags)) 244 mdb_printf("%<b>%<u>%-?s %-*sCreat Tndx %-?s%</u>%</b>\n", 245 "Address", sizeof (name), "Name", "Buckets"); 246 247 if (mdb_readstr(name, sizeof (name), (uintptr_t)idx.dbi_keyname) 248 == -1) { 249 mdb_warn("can't read dbi_keyname"); 250 return (DCMD_ERR); 251 } 252 253 mdb_printf("%?p %-*s%-5s %04u %?p\n", addr, sizeof (name), name, 254 idx.dbi_createable ? "TRUE" : "FALSE", idx.dbi_tblidx, 255 idx.dbi_buckets); 256 257 return (DCMD_OK); 258 } 259 260 void 261 rfs4_idx_help(void) 262 { 263 mdb_printf( 264 "-w walks along all indices in the list\n" 265 "\n" 266 "The following two commands are equivalent:\n" 267 " ::rfs4_idx -w\n" 268 " ::walk rfs4_db_idx|::rfs4_idx\n"); 269 } 270 271 /* 272 * rfs4_bkt dcmd implementation 273 */ 274 275 static int 276 rfs4_print_bkt_cb(uintptr_t addr, const void *data, void *cb_data) 277 { 278 const rfs4_bucket_t *bkt = data; 279 rfs4_link_t *lp; 280 rfs4_link_t rl; 281 282 for (lp = bkt->dbk_head; lp; lp = rl.next) { 283 rfs4_dbe_t dbe; 284 285 if (mdb_vread(&rl, sizeof (rl), (uintptr_t)lp) == -1) { 286 mdb_warn("can't read rfs4_link_t"); 287 return (WALK_ERR); 288 } 289 290 if (mdb_vread(&dbe, sizeof (dbe), (uintptr_t)rl.entry) == -1) { 291 mdb_warn("can't read rfs4_dbe_t"); 292 return (WALK_ERR); 293 } 294 295 mdb_inc_indent(4); 296 mdb_printf( 297 "DBE { Address=%p data->%p refcnt=%u skipsearch=%u\n" 298 " invalid=%u time_rele=%Y\n}\n", rl.entry, dbe.dbe_data, 299 dbe.dbe_refcnt, dbe.dbe_skipsearch, dbe.dbe_invalid, 300 dbe.dbe_time_rele); 301 mdb_dec_indent(4); 302 } 303 304 return (WALK_NEXT); 305 } 306 307 int 308 rfs4_bkt_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 309 { 310 if (argc > 0) 311 return (DCMD_USAGE); 312 313 if ((flags & DCMD_ADDRSPEC) == 0) { 314 mdb_printf("requires address of rfs4_index_t\n"); 315 return (DCMD_USAGE); 316 } 317 318 if (mdb_pwalk("rfs4_db_bkt", rfs4_print_bkt_cb, NULL, addr) == -1) { 319 mdb_warn("bucket walking failed"); 320 return (DCMD_ERR); 321 } 322 323 return (DCMD_OK); 324 } 325 326 /* 327 * rfs4_oo dcmd implementation 328 */ 329 330 static int 331 rfs4_print_oo(uintptr_t addr, uintptr_t client) 332 { 333 rfs4_openowner_t oo; 334 uint8_t *owner_val; 335 uint_t i; 336 337 if (mdb_vread(&oo, sizeof (oo), addr) == -1) { 338 mdb_warn("can't read rfs4_openowner_t"); 339 return (DCMD_ERR); 340 } 341 342 if (client && (client != (uintptr_t)oo.ro_client)) 343 return (DCMD_OK); 344 345 owner_val = mdb_alloc(oo.ro_owner.owner_len, UM_SLEEP | UM_GC); 346 if (mdb_vread(owner_val, oo.ro_owner.owner_len, 347 (uintptr_t)oo.ro_owner.owner_val) == -1) { 348 mdb_warn("can't read owner_val"); 349 return (DCMD_ERR); 350 } 351 352 mdb_printf("%?p %?p %?p %10u %16llx ", addr, oo.ro_dbe, oo.ro_client, 353 oo.ro_open_seqid, oo.ro_owner.clientid); 354 for (i = 0; i < oo.ro_owner.owner_len; i++) 355 mdb_printf("%02x", owner_val[i]); 356 mdb_printf("\n"); 357 358 return (DCMD_OK); 359 } 360 361 static int 362 rfs4_print_oo_cb(uintptr_t addr, const void *data, void *cb_data) 363 { 364 if (mdb_vread(&addr, sizeof (addr), addr + OFFSETOF(rfs4_dbe_t, 365 dbe_data)) == -1) { 366 mdb_warn("failed to read dbe_data"); 367 return (WALK_ERR); 368 } 369 370 return (rfs4_print_oo(addr, (uintptr_t)cb_data) == DCMD_OK 371 ? WALK_NEXT : WALK_ERR); 372 } 373 374 static void 375 print_oo_hdr(void) 376 { 377 mdb_printf("%<b>%<u>%-?s %-?s %-?s %10s %16s %-16s%</u>%</b>\n", 378 "Address", "Dbe", "Client", "OpenSeqID", "clientid", 379 "owner"); 380 } 381 382 int 383 rfs4_oo_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 384 { 385 if (argc > 0) 386 return (DCMD_USAGE); 387 388 if (DCMD_HDRSPEC(flags)) 389 print_oo_hdr(); 390 391 if (flags & DCMD_ADDRSPEC) 392 return (rfs4_print_oo(addr, 0)); 393 394 if (mdb_walk("OpenOwner_entry_cache", rfs4_print_oo_cb, NULL) == -1) { 395 mdb_warn("walking of %s failed", "OpenOwner_entry_cache"); 396 return (DCMD_ERR); 397 } 398 399 return (DCMD_OK); 400 } 401 402 /* 403 * rfs4_osid dcmd implementation 404 */ 405 406 static void 407 print_stateid(const stateid_t *st) 408 { 409 const char *s; 410 411 mdb_printf("chgseq=%u boottime=%x pid=%i\n", st->bits.chgseq, 412 st->bits.boottime, st->bits.pid); 413 414 switch ((stateid_type_t)st->bits.type) { 415 case OPENID: 416 s = "OpenID"; 417 break; 418 case LOCKID: 419 s = "LockID"; 420 break; 421 case DELEGID: 422 s = "DelegID"; 423 break; 424 default: 425 s = "<undefined>"; 426 break; 427 } 428 mdb_printf("type=%s ident=%x\n", s, st->bits.ident); 429 } 430 431 static int 432 rfs4_print_osid(uintptr_t addr, uint_t opt_v) 433 { 434 rfs4_state_t osid; 435 size_t i; 436 const char *s; 437 438 if (mdb_vread(&osid, sizeof (osid), addr) == -1) { 439 mdb_warn("can't read rfs4_state_t"); 440 return (DCMD_ERR); 441 } 442 443 mdb_printf("%?p %?p %?p %?p ", addr, osid.rs_dbe, osid.rs_owner, 444 osid.rs_finfo); 445 for (i = 0; i < sizeof (stateid4); i++) 446 mdb_printf("%02x", ((uint8_t *)&osid.rs_stateid)[i]); 447 mdb_printf("\n"); 448 449 if (!opt_v) 450 return (DCMD_OK); 451 452 mdb_inc_indent(8); 453 454 print_stateid(&osid.rs_stateid); 455 456 switch (osid.rs_share_access) { 457 case 0: 458 s = "none"; 459 break; 460 case OPEN4_SHARE_ACCESS_READ: 461 s = "read"; 462 break; 463 case OPEN4_SHARE_ACCESS_WRITE: 464 s = "write"; 465 break; 466 case OPEN4_SHARE_ACCESS_BOTH: 467 s = "read-write"; 468 break; 469 default: 470 s = "<invalid>"; 471 break; 472 } 473 mdb_printf("share_access: %s", s); 474 475 switch (osid.rs_share_deny) { 476 case OPEN4_SHARE_DENY_NONE: 477 s = "none"; 478 break; 479 case OPEN4_SHARE_DENY_READ: 480 s = "read"; 481 break; 482 case OPEN4_SHARE_DENY_WRITE: 483 s = "write"; 484 break; 485 case OPEN4_SHARE_DENY_BOTH: 486 s = "read-write"; 487 break; 488 default: 489 s = "<invalid>"; 490 break; 491 } 492 mdb_printf(" share_deny: %s file is: %s\n", s, 493 osid.rs_closed ? "CLOSED" : "OPEN"); 494 495 mdb_dec_indent(8); 496 497 return (DCMD_OK); 498 } 499 500 static int 501 rfs4_print_osid_cb(uintptr_t addr, const void *data, void *cb_data) 502 { 503 /* addr = ((rfs4_dbe_t *)addr)->dbe_data */ 504 if (mdb_vread(&addr, sizeof (addr), addr + OFFSETOF(rfs4_dbe_t, 505 dbe_data)) == -1) { 506 mdb_warn("failed to read dbe_data"); 507 return (WALK_ERR); 508 } 509 510 return (rfs4_print_osid(addr, *(uint_t *)cb_data) == DCMD_OK 511 ? WALK_NEXT : WALK_ERR); 512 } 513 514 int 515 rfs4_osid_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 516 { 517 uint_t opt_v = FALSE; 518 519 if (mdb_getopts(argc, argv, 520 'v', MDB_OPT_SETBITS, TRUE, &opt_v, NULL) != argc) 521 return (DCMD_USAGE); 522 523 if (DCMD_HDRSPEC(flags)) 524 mdb_printf("%<b>%<u>%-?s %-?s %-?s %-?s %-*s%</u>%</b>\n", 525 "Address", "Dbe", "Owner", "finfo", 2 * sizeof (stateid4), 526 "StateID"); 527 528 if (flags & DCMD_ADDRSPEC) 529 return (rfs4_print_osid(addr, opt_v)); 530 531 if (mdb_walk("OpenStateID_entry_cache", rfs4_print_osid_cb, &opt_v) 532 == -1) { 533 mdb_warn("walking of %s failed", "OpenStateID_entry_cache"); 534 return (DCMD_ERR); 535 } 536 537 return (DCMD_OK); 538 } 539 540 /* 541 * rfs4_file dcmd implementation 542 */ 543 544 static void 545 print_time(time_t t) 546 { 547 if (t == 0) 548 mdb_printf("0"); 549 else 550 mdb_printf("%Y", t); 551 } 552 553 static int 554 rfs4_print_file(uintptr_t addr, uint_t opt_v) 555 { 556 rfs4_file_t f; 557 uint8_t *nfs_fh4_val; 558 uint_t i; 559 uintptr_t vp; 560 char *s; 561 const rfs4_dinfo_t *di; 562 563 if (mdb_vread(&f, sizeof (f), addr) == -1) { 564 mdb_warn("can't read rfs4_file_t"); 565 return (DCMD_ERR); 566 } 567 568 nfs_fh4_val = mdb_alloc(f.rf_filehandle.nfs_fh4_len, UM_SLEEP | UM_GC); 569 if (mdb_vread(nfs_fh4_val, f.rf_filehandle.nfs_fh4_len, 570 (uintptr_t)f.rf_filehandle.nfs_fh4_val) == -1) { 571 mdb_warn("can't read nfs_fh4_val"); 572 return (DCMD_ERR); 573 } 574 575 mdb_printf("%?p %?p %?p ", addr, f.rf_dbe, f.rf_vp); 576 for (i = 0; i < f.rf_filehandle.nfs_fh4_len; i++) 577 mdb_printf("%02x", nfs_fh4_val[i]); 578 mdb_printf("\n"); 579 580 if (!opt_v) 581 return (DCMD_OK); 582 583 /* vp = f.rf_vp->v_path */ 584 if (mdb_vread(&vp, sizeof (vp), (uintptr_t)f.rf_vp 585 + OFFSETOF(vnode_t, v_path)) == -1) { 586 mdb_warn("can't read vnode_t"); 587 return (DCMD_ERR); 588 } 589 590 s = mdb_alloc(PATH_MAX, UM_SLEEP | UM_GC); 591 if (mdb_readstr(s, PATH_MAX, vp) == -1) { 592 mdb_warn("can't read v_path"); 593 return (DCMD_ERR); 594 } 595 596 mdb_inc_indent(8); 597 598 mdb_printf("path=%s\n", s); 599 600 di = &f.rf_dinfo; 601 switch (di->rd_dtype) { 602 case OPEN_DELEGATE_NONE: 603 s = "None"; 604 break; 605 case OPEN_DELEGATE_READ: 606 s = "Read"; 607 break; 608 case OPEN_DELEGATE_WRITE: 609 s = "Write"; 610 break; 611 default: 612 s = "?????"; 613 break; 614 } 615 mdb_printf("dtype=%-5s rdgrants=%u wrgrants=%u recall_cnt=%i " 616 "ever_recalled=%s\n", s, di->rd_rdgrants, di->rd_wrgrants, 617 di->rd_recall_count, (di->rd_ever_recalled == TRUE) ? "True" 618 : "False"); 619 620 mdb_printf("Time: "); 621 mdb_inc_indent(6); 622 623 mdb_printf("returned="); 624 print_time(di->rd_time_returned); 625 mdb_printf(" recalled="); 626 print_time(di->rd_time_recalled); 627 mdb_printf("\nlastgrant="); 628 print_time(di->rd_time_lastgrant); 629 mdb_printf(" lastwrite="); 630 print_time(di->rd_time_lastwrite); 631 mdb_printf("\nrm_delayed="); 632 print_time(di->rd_time_rm_delayed); 633 mdb_printf("\n"); 634 635 mdb_dec_indent(14); 636 637 return (DCMD_OK); 638 } 639 640 static int 641 rfs4_print_file_cb(uintptr_t addr, const void *data, void *cb_data) 642 { 643 /* addr = ((rfs4_dbe_t *)addr)->dbe_data */ 644 if (mdb_vread(&addr, sizeof (addr), addr + OFFSETOF(rfs4_dbe_t, 645 dbe_data)) == -1) { 646 mdb_warn("failed to read dbe_data"); 647 return (WALK_ERR); 648 } 649 650 return (rfs4_print_file(addr, *(uint_t *)cb_data) == DCMD_OK 651 ? WALK_NEXT : WALK_ERR); 652 } 653 654 int 655 rfs4_file_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 656 { 657 uint_t opt_v = FALSE; 658 659 if (mdb_getopts(argc, argv, 660 'v', MDB_OPT_SETBITS, TRUE, &opt_v, NULL) != argc) 661 return (DCMD_USAGE); 662 663 if (DCMD_HDRSPEC(flags)) 664 mdb_printf("%<b>%<u>%-?s %-?s %-?s %-32s%</u>%</b>\n", 665 "Address", "Dbe", "Vnode", "Filehandle"); 666 667 if (flags & DCMD_ADDRSPEC) 668 return (rfs4_print_file(addr, opt_v)); 669 670 if (mdb_walk("File_entry_cache", rfs4_print_file_cb, &opt_v) == -1) { 671 mdb_warn("walking of %s failed", "File_entry_cache"); 672 return (DCMD_ERR); 673 } 674 675 return (DCMD_OK); 676 } 677 678 /* 679 * rfs4_deleg dcmd implementation 680 */ 681 682 static int 683 rfs4_print_deleg(uintptr_t addr, uint_t opt_v, uintptr_t client) 684 { 685 rfs4_deleg_state_t ds; 686 size_t i; 687 uintptr_t pa; 688 char *s; 689 690 if (mdb_vread(&ds, sizeof (ds), addr) == -1) { 691 mdb_warn("can't read rfs4_deleg_state_t"); 692 return (DCMD_ERR); 693 } 694 695 if (client && (client != (uintptr_t)ds.rds_client)) 696 return (DCMD_OK); 697 698 mdb_printf("%?p %?p ", addr, ds.rds_dbe); 699 for (i = 0; i < sizeof (stateid4); i++) 700 mdb_printf("%02x", ((uint8_t *)&ds.rds_delegid)[i]); 701 mdb_printf(" %?p %?p\n", ds.rds_finfo, ds.rds_client); 702 703 if (!opt_v) 704 return (DCMD_OK); 705 706 /* pa = ds.rds_finfo->rf_vp */ 707 if (mdb_vread(&pa, sizeof (pa), (uintptr_t)ds.rds_finfo 708 + OFFSETOF(rfs4_file_t, rf_vp)) == -1) { 709 mdb_warn("can't read rf_vp"); 710 return (DCMD_ERR); 711 } 712 /* pa = ((vnode_t *)pa)->v_path */ 713 if (mdb_vread(&pa, sizeof (pa), pa + OFFSETOF(vnode_t, v_path)) == -1) { 714 mdb_warn("can't read rf_vp"); 715 return (DCMD_ERR); 716 } 717 718 s = mdb_alloc(PATH_MAX, UM_SLEEP | UM_GC); 719 if (mdb_readstr(s, PATH_MAX, pa) == -1) { 720 mdb_warn("can't read v_path"); 721 return (DCMD_ERR); 722 } 723 724 mdb_inc_indent(8); 725 mdb_printf("Time: "); 726 mdb_inc_indent(6); 727 728 mdb_printf("granted="); 729 print_time(ds.rds_time_granted); 730 mdb_printf(" recalled="); 731 print_time(ds.rds_time_recalled); 732 mdb_printf(" revoked="); 733 print_time(ds.rds_time_revoked); 734 735 mdb_dec_indent(6); 736 mdb_printf("\npath=%s\n", s); 737 mdb_dec_indent(8); 738 739 return (DCMD_OK); 740 } 741 742 static int 743 rfs4_print_deleg_cb(uintptr_t addr, const void *data, void *cb_data) 744 { 745 /* addr = ((rfs4_dbe_t *)addr)->dbe_data */ 746 if (mdb_vread(&addr, sizeof (addr), addr + OFFSETOF(rfs4_dbe_t, 747 dbe_data)) == -1) { 748 mdb_warn("failed to read dbe_data"); 749 return (WALK_ERR); 750 } 751 752 return (rfs4_print_deleg(addr, *(uint_t *)cb_data, 753 0) == DCMD_OK ? WALK_NEXT : WALK_ERR); 754 } 755 756 static void 757 print_deleg_hdr(void) 758 { 759 mdb_printf("%<b>%<u>%-?s %-?s %-*s %-?s %-?s%</u>%</b>\n", 760 "Address", "Dbe", 2 * sizeof (stateid4), "StateID", 761 "File Info", "Client"); 762 } 763 764 int 765 rfs4_deleg_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 766 { 767 uint_t opt_v = FALSE; 768 769 if (mdb_getopts(argc, argv, 770 'v', MDB_OPT_SETBITS, TRUE, &opt_v, NULL) != argc) 771 return (DCMD_USAGE); 772 773 if (DCMD_HDRSPEC(flags)) 774 print_deleg_hdr(); 775 776 if (flags & DCMD_ADDRSPEC) 777 return (rfs4_print_deleg(addr, opt_v, 0)); 778 779 if (mdb_walk("DelegStateID_entry_cache", rfs4_print_deleg_cb, &opt_v) 780 == -1) { 781 mdb_warn("walking of %s failed", "DelegStateID_entry_cache"); 782 return (DCMD_ERR); 783 } 784 785 return (DCMD_OK); 786 } 787 788 /* 789 * rfs4_lo dcmd implementation 790 */ 791 792 static int 793 rfs4_print_lo(uintptr_t addr, uintptr_t client) 794 { 795 rfs4_lockowner_t lo; 796 uint8_t *owner_val; 797 uint_t i; 798 799 if (mdb_vread(&lo, sizeof (lo), addr) == -1) { 800 mdb_warn("can't read rfs4_lockowner_t"); 801 return (DCMD_ERR); 802 } 803 804 if (client && (client != (uintptr_t)lo.rl_client)) 805 return (DCMD_OK); 806 807 owner_val = mdb_alloc(lo.rl_owner.owner_len, UM_SLEEP | UM_GC); 808 if (mdb_vread(owner_val, lo.rl_owner.owner_len, 809 (uintptr_t)lo.rl_owner.owner_val) == -1) { 810 mdb_warn("can't read owner_val"); 811 return (DCMD_ERR); 812 } 813 814 mdb_printf("%?p %?p %?p %10i %16llx ", addr, lo.rl_dbe, lo.rl_client, 815 lo.rl_pid, lo.rl_owner.clientid); 816 for (i = 0; i < lo.rl_owner.owner_len; i++) 817 mdb_printf("%02x", owner_val[i]); 818 mdb_printf("\n"); 819 820 return (DCMD_OK); 821 } 822 823 static int 824 rfs4_print_lo_cb(uintptr_t addr, const void *data, void *cb_data) 825 { 826 if (mdb_vread(&addr, sizeof (addr), addr + OFFSETOF(rfs4_dbe_t, 827 dbe_data)) == -1) { 828 mdb_warn("failed to read dbe_data"); 829 return (WALK_ERR); 830 } 831 832 return (rfs4_print_lo(addr, (uintptr_t)cb_data) == DCMD_OK 833 ? WALK_NEXT : WALK_ERR); 834 } 835 836 static void 837 print_lo_hdr(void) 838 { 839 mdb_printf("%<b>%<u>%-?s %-?s %-?s %10s %16s %-16s%</u>%</b>\n", 840 "Address", "Dbe", "Client", "Pid", "clientid", "owner"); 841 } 842 843 int 844 rfs4_lo_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 845 { 846 if (argc > 0) 847 return (DCMD_USAGE); 848 849 if (DCMD_HDRSPEC(flags)) 850 print_lo_hdr(); 851 852 if (flags & DCMD_ADDRSPEC) 853 return (rfs4_print_lo(addr, 0)); 854 855 if (mdb_walk("Lockowner_entry_cache", rfs4_print_lo_cb, NULL) == -1) { 856 mdb_warn("walking of %s failed", "Lockowner_entry_cache"); 857 return (DCMD_ERR); 858 } 859 860 return (DCMD_OK); 861 } 862 863 /* 864 * rfs4_lsid dcmd implementation 865 */ 866 867 static int 868 rfs4_print_lsid(uintptr_t addr, uint_t opt_v) 869 { 870 rfs4_lo_state_t lsid; 871 size_t i; 872 873 if (mdb_vread(&lsid, sizeof (lsid), addr) == -1) { 874 mdb_warn("can't read rfs4_lo_state_t"); 875 return (DCMD_ERR); 876 } 877 878 mdb_printf("%?p %?p %?p %10u ", addr, lsid.rls_dbe, lsid.rls_locker, 879 lsid.rls_seqid); 880 for (i = 0; i < sizeof (stateid4); i++) 881 mdb_printf("%02x", ((uint8_t *)&lsid.rls_lockid)[i]); 882 mdb_printf("\n"); 883 884 if (!opt_v) 885 return (DCMD_OK); 886 887 mdb_inc_indent(8); 888 print_stateid(&lsid.rls_lockid); 889 mdb_dec_indent(8); 890 891 return (DCMD_OK); 892 } 893 894 static int 895 rfs4_print_lsid_cb(uintptr_t addr, const void *data, void *cb_data) 896 { 897 if (mdb_vread(&addr, sizeof (addr), addr + OFFSETOF(rfs4_dbe_t, 898 dbe_data)) == -1) { 899 mdb_warn("failed to read dbe_data"); 900 return (WALK_ERR); 901 } 902 903 return (rfs4_print_lsid(addr, *(uint_t *)cb_data) == DCMD_OK 904 ? WALK_NEXT : WALK_ERR); 905 } 906 907 int 908 rfs4_lsid_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 909 { 910 uint_t opt_v = FALSE; 911 912 if (mdb_getopts(argc, argv, 913 'v', MDB_OPT_SETBITS, TRUE, &opt_v, NULL) != argc) 914 return (DCMD_USAGE); 915 916 if (DCMD_HDRSPEC(flags)) 917 mdb_printf("%<b>%<u>%-?s %-?s %-?s %10s %-*s%</u>%</b>\n", 918 "Address", "Dbe", "Locker", "SeqID", 2 * sizeof (stateid4), 919 "Lockid"); 920 921 if (flags & DCMD_ADDRSPEC) 922 return (rfs4_print_lsid(addr, opt_v)); 923 924 if (mdb_walk("LockStateID_entry_cache", rfs4_print_lsid_cb, &opt_v) 925 == -1) { 926 mdb_warn("walking of %s failed", "LockStateID_entry_cache"); 927 return (DCMD_ERR); 928 } 929 930 return (DCMD_OK); 931 } 932 933 /* 934 * rfs4_client dcmd implementation 935 */ 936 937 static int 938 rfs4_print_client(uintptr_t addr) 939 { 940 rfs4_client_t cl; 941 942 if (mdb_vread(&cl, sizeof (cl), addr) == -1) { 943 mdb_warn("can't read rfs4_client_t"); 944 return (DCMD_ERR); 945 } 946 947 mdb_printf("%?p %?p %-16llx %-16llx %-5s %-5s %?p %-20Y\n", addr, 948 cl.rc_dbe, cl.rc_clientid, cl.rc_confirm_verf, 949 cl.rc_need_confirm ? "True" : "False", 950 cl.rc_unlksys_completed ? "True" : "False", cl.rc_cp_confirmed, 951 cl.rc_last_access); 952 953 return (DCMD_OK); 954 } 955 956 static int 957 rfs4_client_deleg_cb(uintptr_t addr, const void *data, void *cb_data) 958 { 959 /* addr = ((rfs4_dbe_t *)addr)->dbe_data */ 960 if (mdb_vread(&addr, sizeof (addr), addr + OFFSETOF(rfs4_dbe_t, 961 dbe_data)) == -1) { 962 mdb_warn("failed to read dbe_data"); 963 return (WALK_ERR); 964 } 965 966 return (rfs4_print_deleg(addr, FALSE, (uintptr_t)cb_data) == DCMD_OK 967 ? WALK_NEXT : WALK_ERR); 968 } 969 970 static int 971 rfs4_print_client_cb(uintptr_t addr, const void *data, void *cb_data) 972 { 973 clientid4 clid; 974 975 /* addr = ((rfs4_dbe_t *)addr)->dbe_data */ 976 if (mdb_vread(&addr, sizeof (addr), addr + OFFSETOF(rfs4_dbe_t, 977 dbe_data)) == -1) { 978 mdb_warn("failed to read dbe_data"); 979 return (WALK_ERR); 980 } 981 982 /* if no clid specified then print all clients */ 983 if (!cb_data) 984 return (rfs4_print_client(addr) == DCMD_OK ? WALK_NEXT 985 : WALK_ERR); 986 987 /* clid = ((rfs4_client_t *)addr)->rc_clientid */ 988 if (mdb_vread(&clid, sizeof (clid), addr + OFFSETOF(rfs4_client_t, 989 rc_clientid)) == -1) { 990 mdb_warn("can't read rc_clientid"); 991 return (WALK_ERR); 992 } 993 994 /* clid does not match, do not print the client */ 995 if (clid != *(clientid4 *)cb_data) 996 return (WALK_NEXT); 997 998 if (rfs4_print_client(addr) != DCMD_OK) 999 return (WALK_ERR); 1000 1001 mdb_printf("\n"); 1002 print_oo_hdr(); 1003 if (mdb_walk("OpenOwner_entry_cache", rfs4_print_oo_cb, (void *)addr) 1004 == -1) { 1005 mdb_warn("walking of %s failed", "OpenOwner_entry_cache"); 1006 return (WALK_ERR); 1007 } 1008 1009 mdb_printf("\n"); 1010 print_lo_hdr(); 1011 if (mdb_walk("Lockowner_entry_cache", rfs4_print_lo_cb, (void *)addr) 1012 == -1) { 1013 mdb_warn("walking of %s failed", "Lockowner_entry_cache"); 1014 return (WALK_ERR); 1015 } 1016 1017 mdb_printf("\n"); 1018 print_deleg_hdr(); 1019 if (mdb_walk("DelegStateID_entry_cache", rfs4_client_deleg_cb, 1020 (void *)addr) == -1) { 1021 mdb_warn("walking of %s failed", "DelegStateID_entry_cache"); 1022 return (WALK_ERR); 1023 } 1024 1025 return (WALK_DONE); 1026 } 1027 1028 int 1029 rfs4_client_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 1030 { 1031 clientid4 clid; 1032 1033 if (mdb_getopts(argc, argv, 1034 'c', MDB_OPT_UINT64, &clid, NULL) != argc) 1035 return (DCMD_USAGE); 1036 1037 if (DCMD_HDRSPEC(flags)) 1038 mdb_printf("%<b>%<u>%-?s %-?s %-16s %-16s NCnfm unlnk %-?s " 1039 "%-20s%</u>%</b>\n", "Address", "dbe", "clientid", 1040 "confirm_verf", "cp_confirmed", "Last Access"); 1041 1042 if ((argc == 0) && (flags & DCMD_ADDRSPEC)) 1043 return (rfs4_print_client(addr)); 1044 1045 if (mdb_walk("Client_entry_cache", rfs4_print_client_cb, (argc > 0) 1046 ? &clid : NULL) == -1) { 1047 mdb_warn("walking of %s failed", "Client_entry_cache"); 1048 return (DCMD_ERR); 1049 } 1050 1051 return (DCMD_OK); 1052 } 1053 1054 void 1055 rfs4_client_help(void) 1056 { 1057 mdb_printf( 1058 "-c print all NFSv4 server state entries referencing\n" 1059 " the <clientid> client. In this case the supplied\n" 1060 " address is ignored\n"); 1061 } 1062 1063 /* 1064 * rfs4_db_tbl walker implementation 1065 */ 1066 1067 int 1068 rfs4_db_tbl_walk_init(mdb_walk_state_t *wsp) 1069 { 1070 if (wsp->walk_addr == 0) { 1071 mdb_warn("db tbl global walk not supported"); 1072 return (WALK_ERR); 1073 } 1074 1075 return (WALK_NEXT); 1076 } 1077 1078 int 1079 rfs4_db_tbl_walk_step(mdb_walk_state_t *wsp) 1080 { 1081 rfs4_table_t tbl; 1082 uintptr_t addr = wsp->walk_addr; 1083 1084 if (addr == 0) 1085 return (WALK_DONE); 1086 1087 if (mdb_vread(&tbl, sizeof (tbl), addr) == -1) { 1088 mdb_warn("can't read rfs4_table_t"); 1089 return (WALK_ERR); 1090 } 1091 1092 wsp->walk_addr = (uintptr_t)tbl.dbt_tnext; 1093 return (wsp->walk_callback(addr, &tbl, wsp->walk_cbdata)); 1094 } 1095 1096 /* 1097 * rfs4_db_idx walker implementation 1098 */ 1099 1100 int 1101 rfs4_db_idx_walk_init(mdb_walk_state_t *wsp) 1102 { 1103 if (wsp->walk_addr == 0) { 1104 mdb_warn("db idx global walk not supported"); 1105 return (WALK_ERR); 1106 } 1107 1108 return (WALK_NEXT); 1109 } 1110 1111 int 1112 rfs4_db_idx_walk_step(mdb_walk_state_t *wsp) 1113 { 1114 rfs4_index_t idx; 1115 uintptr_t addr = wsp->walk_addr; 1116 1117 if (addr == 0) 1118 return (WALK_DONE); 1119 1120 if (mdb_vread(&idx, sizeof (idx), addr) == -1) { 1121 mdb_warn("can't read rfs4_index_t"); 1122 return (WALK_ERR); 1123 } 1124 1125 wsp->walk_addr = (uintptr_t)idx.dbi_inext; 1126 return (wsp->walk_callback(addr, &idx, wsp->walk_cbdata)); 1127 } 1128 /* 1129 * rfs4_db_bkt walker implementation 1130 */ 1131 1132 int 1133 rfs4_db_bkt_walk_init(mdb_walk_state_t *wsp) 1134 { 1135 rfs4_index_t idx; 1136 uint32_t dbt_len; 1137 1138 if (wsp->walk_addr == 0) { 1139 mdb_warn("db bkt global walk not supported"); 1140 return (WALK_ERR); 1141 } 1142 1143 if (mdb_vread(&idx, sizeof (idx), wsp->walk_addr) == -1) { 1144 mdb_warn("can't read rfs4_index_t"); 1145 return (WALK_ERR); 1146 } 1147 1148 /* dbt_len = idx.dbi_table->dbt_len */ 1149 if (mdb_vread(&dbt_len, sizeof (dbt_len), (uintptr_t)idx.dbi_table 1150 + OFFSETOF(rfs4_table_t, dbt_len)) == -1) { 1151 mdb_warn("can't read dbt_len"); 1152 return (WALK_ERR); 1153 } 1154 1155 wsp->walk_data = mdb_alloc(sizeof (dbt_len), UM_SLEEP); 1156 *(uint32_t *)wsp->walk_data = dbt_len; 1157 wsp->walk_addr = (uintptr_t)idx.dbi_buckets; 1158 1159 return (WALK_NEXT); 1160 } 1161 1162 int 1163 rfs4_db_bkt_walk_step(mdb_walk_state_t *wsp) 1164 { 1165 rfs4_bucket_t bkt; 1166 uintptr_t addr = wsp->walk_addr; 1167 1168 if (*(uint32_t *)wsp->walk_data == 0) 1169 return (WALK_DONE); 1170 1171 if (mdb_vread(&bkt, sizeof (bkt), addr) == -1) { 1172 mdb_warn("can't read rfs4_bucket_t"); 1173 return (WALK_ERR); 1174 } 1175 1176 (*(uint32_t *)wsp->walk_data)--; 1177 wsp->walk_addr = (uintptr_t)((rfs4_bucket_t *)addr + 1); 1178 1179 return (wsp->walk_callback(addr, &bkt, wsp->walk_cbdata)); 1180 } 1181 1182 void 1183 rfs4_db_bkt_walk_fini(mdb_walk_state_t *wsp) 1184 { 1185 mdb_free(wsp->walk_data, sizeof (uint32_t)); 1186 } 1187