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
nfs_print_io_stat(uintptr_t kstat_addr)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
walk_count_cb(uintptr_t addr,const void * data,void * cb_data)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 *
nfs4_op_str(nfs_opnum4 op)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 *
nfs4_recov_str(nfs4_recov_t action)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 *
nfs4_stat_str(nfsstat4 stat)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 *
nfs4_tag_str(nfs4_tag_type_t tt)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
nfs_print_mntinfo_cb(uintptr_t addr,const void * data,void * cb_data)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
nfs_mntinfo_dcmd(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)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
nfs_mntinfo_help(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
nfs_servinfo_dcmd(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)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
nfs_servinfo_help(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
nfs4_mntinfo_dcmd(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)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
nfs4_mntinfo_help(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
nfs4_servinfo_dcmd(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)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
nfs4_servinfo_help(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
nfs4_server_info_dcmd(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)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
nfs4_server_info_help(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
mimsg_print_event(const nfs4_debug_msg_t * msg)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
mimsg_print_fact(const nfs4_debug_msg_t * msg)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
print_mimsg_cb(uintptr_t addr,const void * data,void * cb_data)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
nfs4_mimsg_dcmd(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)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
nfs4_mimsg_help(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
print_nfs4_fname(uintptr_t addr)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
nfs4_fname_dcmd(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)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
nfs4_oo_cb(uintptr_t addr,const void * data,void * varg)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
nfs4_foo_dcmd(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)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
nfs4_oob_dcmd(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)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
nfs4_openstream_print(uintptr_t addr,void * buf,int * opts)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
nfs4_openstreams_cb(uintptr_t addr,void * private,int * opts)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
nfs4_os_dcmd(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)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
nfs4_svnode_dcmd(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)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
nfs_rtable_common_init(mdb_walk_state_t * wsp,const char * tabname,const char * sizename)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
nfs_rtable_walk_init(mdb_walk_state_t * wsp)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
nfs_rtable4_walk_init(mdb_walk_state_t * wsp)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
nfs_vfs_walk_init(mdb_walk_state_t * wsp)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
nfs_vfs_walk_step(mdb_walk_state_t * wsp)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
nfs_vfs_walk_fini(mdb_walk_state_t * wsp)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
nfs_mnt_walk_init(mdb_walk_state_t * wsp)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
nfs_mnt_walk_step(mdb_walk_state_t * wsp)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
nfs_mnt_walk_fini(mdb_walk_state_t * wsp)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
nfs4_mnt_walk_init(mdb_walk_state_t * wsp)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
nfs4_mnt_walk_step(mdb_walk_state_t * wsp)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
nfs4_mnt_walk_fini(mdb_walk_state_t * wsp)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
nfs_serv_walk_init(mdb_walk_state_t * wsp)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
nfs_serv_walk_step(mdb_walk_state_t * wsp)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
nfs4_serv_walk_init(mdb_walk_state_t * wsp)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
nfs4_serv_walk_step(mdb_walk_state_t * wsp)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
nfs4_svnode_walk_init(mdb_walk_state_t * wsp)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
nfs4_svnode_walk_step(mdb_walk_state_t * wsp)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
nfs4_server_walk_init(mdb_walk_state_t * wsp)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
nfs4_server_walk_step(mdb_walk_state_t * wsp)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
nfs_async_walk_init(mdb_walk_state_t * wsp)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
nfs_async_walk_step(mdb_walk_state_t * wsp)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
nfs4_async_walk_init(mdb_walk_state_t * wsp)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
nfs4_async_walk_step(mdb_walk_state_t * wsp)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
nfs_acache_rnode_walk_init(mdb_walk_state_t * wsp)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
nfs_acache_rnode_walk_step(mdb_walk_state_t * wsp)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
nfs_acache_walk_init(mdb_walk_state_t * wsp)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
nfs_acache_walk_fini(mdb_walk_state_t * wsp)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
nfs_acache4_rnode_walk_init(mdb_walk_state_t * wsp)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
nfs_acache4_rnode_walk_step(mdb_walk_state_t * wsp)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
nfs_acache4_walk_init(mdb_walk_state_t * wsp)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
nfs_acache4_walk_fini(mdb_walk_state_t * wsp)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