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 <mdb/mdb_types.h>
17 #include <sys/refstr.h>
18 #include <sys/kstat.h>
19 #include <sys/refstr_impl.h>
20 #include <nfs/nfs4_clnt.h>
21 #include <nfs/nfs_clnt.h>
22 #include <nfs/nfs4_db_impl.h>
23 #include <nfs/nfs4.h>
24 #include <nfs/rnode.h>
25 #include <nfs/rnode4.h>
26 #include <rpc/clnt.h>
27 #include <nfs/nfs4_idmap_impl.h>
28 #include <mdb/mdb_ks.h>
29
30 #include "svc.h"
31 #include "rfs4.h"
32 #include "nfssrv.h"
33 #include "idmap.h"
34 #include "nfs_clnt.h"
35
36 typedef struct nfs_rnode_cbdata {
37 int printed_hdr;
38 uintptr_t vfs_addr; /* for nfs_rnode4find */
39 } nfs_rnode_cbdata_t;
40
41 static const mdb_bitmask_t vfs_flags[] = {
42 { "VFS_RDONLY", VFS_RDONLY, VFS_RDONLY },
43 { "VFS_NOMNTTAB", VFS_NOMNTTAB, VFS_NOMNTTAB },
44 { "VFS_NOSETUID", VFS_NOSETUID, VFS_NOSETUID },
45 { "VFS_REMOUNT", VFS_REMOUNT, VFS_REMOUNT },
46 { "VFS_NOTRUNC", VFS_NOTRUNC, VFS_NOTRUNC },
47 { "VFS_PXFS", VFS_PXFS, VFS_PXFS },
48 { "VFS_NBMAND", VFS_NBMAND, VFS_NBMAND },
49 { "VFS_XATTR", VFS_XATTR, VFS_XATTR },
50 { "VFS_NOEXEC", VFS_NOEXEC, VFS_NOEXEC },
51 { "VFS_STATS", VFS_STATS, VFS_STATS },
52 { "VFS_XID", VFS_XID, VFS_XID },
53 { "VFS_UNLINKABLE", VFS_UNLINKABLE, VFS_UNLINKABLE },
54 { "VFS_UNMOUNTED", VFS_UNMOUNTED, VFS_UNMOUNTED },
55 { NULL, 0, 0 }
56 };
57
58 static const mdb_bitmask_t nfs_mi4_flags[] = {
59 { "MI4_HARD", MI4_HARD, MI4_HARD },
60 { "MI4_PRINTED", MI4_PRINTED, MI4_PRINTED },
61 { "MI4_INT", MI4_INT, MI4_INT },
62 { "MI4_DOWN", MI4_DOWN, MI4_DOWN },
63 { "MI4_NOAC", MI4_NOAC, MI4_NOAC },
64 { "MI4_NOCTO", MI4_NOCTO, MI4_NOCTO },
65 { "MI4_LLOCK", MI4_LLOCK, MI4_LLOCK },
66 { "MI4_GRPID", MI4_GRPID, MI4_GRPID },
67 { "MI4_SHUTDOWN", MI4_SHUTDOWN, MI4_SHUTDOWN },
68 { "MI4_LINK", MI4_LINK, MI4_LINK },
69 { "MI4_SYMLINK", MI4_SYMLINK, MI4_SYMLINK },
70 { "MI4_ACL", MI4_ACL, MI4_ACL },
71 { "MI4_REFERRAL", MI4_REFERRAL, MI4_REFERRAL },
72 { "MI4_NOPRINT", MI4_NOPRINT, MI4_NOPRINT },
73 { "MI4_DIRECTIO", MI4_DIRECTIO, MI4_DIRECTIO },
74 { "MI4_PUBLIC", MI4_PUBLIC, MI4_PUBLIC },
75 { "MI4_MOUNTING", MI4_MOUNTING, MI4_MOUNTING },
76 { "MI4_DEAD", MI4_DEAD, MI4_DEAD },
77 { "MI4_TIMEDOUT", MI4_TIMEDOUT, MI4_TIMEDOUT },
78 { "MI4_MIRRORMOUNT", MI4_MIRRORMOUNT, MI4_MIRRORMOUNT },
79 { "MI4_RECOV_ACTIV", MI4_RECOV_ACTIV, MI4_RECOV_ACTIV },
80 { "MI4_RECOV_FAIL", MI4_RECOV_FAIL, MI4_RECOV_FAIL },
81 { "MI4_POSIX_LOCK", MI4_POSIX_LOCK, MI4_POSIX_LOCK },
82 { "MI4_LOCK_DEBUG", MI4_LOCK_DEBUG, MI4_LOCK_DEBUG },
83 { "MI4_INACTIVE_IDLE", MI4_INACTIVE_IDLE, MI4_INACTIVE_IDLE },
84 { "MI4_BADOWNER_DEBUG", MI4_BADOWNER_DEBUG, MI4_BADOWNER_DEBUG },
85 { "MI4_ASYNC_MGR_STOP", MI4_ASYNC_MGR_STOP, MI4_ASYNC_MGR_STOP },
86 { "MI4_EPHEMERAL", MI4_EPHEMERAL, MI4_EPHEMERAL },
87 { "MI4_REMOVE_ON_LAST_CLOSE", MI4_REMOVE_ON_LAST_CLOSE,
88 MI4_REMOVE_ON_LAST_CLOSE },
89 { NULL, 0, 0 }
90 };
91
92 static const mdb_bitmask_t nfs_mi4_recover[] = {
93 { "MI4R_NEED_CLIENTID", MI4R_NEED_CLIENTID, MI4R_NEED_CLIENTID },
94 { "MI4R_REOPEN_FILES", MI4R_REOPEN_FILES, MI4R_REOPEN_FILES },
95 { "MI4R_NEED_SECINFO", MI4R_NEED_SECINFO, MI4R_NEED_SECINFO },
96 { "MI4R_REOPEN_FILES", MI4R_REOPEN_FILES, MI4R_REOPEN_FILES },
97 { "MI4R_SRV_REBOOT", MI4R_SRV_REBOOT, MI4R_SRV_REBOOT },
98 { "MI4R_LOST_STATE", MI4R_LOST_STATE, MI4R_LOST_STATE },
99 { "MI4R_BAD_SEQID", MI4R_BAD_SEQID, MI4R_BAD_SEQID },
100 { "MI4R_MOVED", MI4R_MOVED, MI4R_MOVED },
101 { "MI4R_NEED_NEW_SERVER", MI4R_NEED_NEW_SERVER, MI4R_NEED_NEW_SERVER },
102 { NULL, 0, 0 }
103 };
104
105 static const char *
nfs4_tag_str(int tag)106 nfs4_tag_str(int tag)
107 {
108 switch (tag) {
109 case TAG_NONE:
110 return ("TAG_NONE");
111 case TAG_ACCESS:
112 return ("TAG_ACCESS");
113 case TAG_CLOSE:
114 return ("TAG_CLOSE");
115 case TAG_CLOSE_LOST:
116 return ("TAG_CLOSE_LOST");
117 case TAG_CLOSE_UNDO:
118 return ("TAG_CLOSE_UNDO");
119 case TAG_COMMIT:
120 return ("TAG_COMMIT");
121 case TAG_DELEGRETURN:
122 return ("TAG_DELEGRETURN");
123 case TAG_FSINFO:
124 return ("TAG_FSINFO");
125 case TAG_GET_SYMLINK:
126 return ("TAG_GET_SYMLINK");
127 case TAG_GETATTR:
128 return ("TAG_GETATTR");
129 case TAG_GETATTR_FSLOCATION:
130 return ("TAG_GETATTR_FSLOCATION");
131 case TAG_INACTIVE:
132 return ("TAG_INACTIVE");
133 case TAG_LINK:
134 return ("TAG_LINK");
135 case TAG_LOCK:
136 return ("TAG_LOCK");
137 case TAG_LOCK_RECLAIM:
138 return ("TAG_LOCK_RECLAIM");
139 case TAG_LOCK_RESEND:
140 return ("TAG_LOCK_RESEND");
141 case TAG_LOCK_REINSTATE:
142 return ("TAG_LOCK_REINSTATE");
143 case TAG_LOCK_UNKNOWN:
144 return ("TAG_LOCK_UNKNOWN");
145 case TAG_LOCKT:
146 return ("TAG_LOCKT");
147 case TAG_LOCKU:
148 return ("TAG_LOCKU");
149 case TAG_LOCKU_RESEND:
150 return ("TAG_LOCKU_RESEND");
151 case TAG_LOCKU_REINSTATE:
152 return ("TAG_LOCKU_REINSTATE");
153 case TAG_LOOKUP:
154 return ("TAG_LOOKUP");
155 case TAG_LOOKUP_PARENT:
156 return ("TAG_LOOKUP_PARENT");
157 case TAG_LOOKUP_VALID:
158 return ("TAG_LOOKUP_VALID");
159 case TAG_LOOKUP_VPARENT:
160 return ("TAG_LOOKUP_VPARENT");
161 case TAG_MKDIR:
162 return ("TAG_MKDIR");
163 case TAG_MKNOD:
164 return ("TAG_MKNOD");
165 case TAG_MOUNT:
166 return ("TAG_MOUNT");
167 case TAG_OPEN:
168 return ("TAG_OPEN");
169 case TAG_OPEN_CONFIRM:
170 return ("TAG_OPEN_CONFIRM");
171 case TAG_OPEN_CONFIRM_LOST:
172 return ("TAG_OPEN_CONFIRM_LOST");
173 case TAG_OPEN_DG:
174 return ("TAG_OPEN_DG");
175 case TAG_OPEN_DG_LOST:
176 return ("TAG_OPEN_DG_LOST");
177 case TAG_OPEN_LOST:
178 return ("TAG_OPEN_LOST");
179 case TAG_OPENATTR:
180 return ("TAG_OPENATTR");
181 case TAG_PATHCONF:
182 return ("TAG_PATHCONF");
183 case TAG_PUTROOTFH:
184 return ("TAG_PUTROOTFH");
185 case TAG_READ:
186 return ("TAG_READ");
187 case TAG_READAHEAD:
188 return ("TAG_READAHEAD");
189 case TAG_READDIR:
190 return ("TAG_READDIR");
191 case TAG_READLINK:
192 return ("TAG_READLINK");
193 case TAG_RELOCK:
194 return ("TAG_RELOCK");
195 case TAG_REMAP_LOOKUP:
196 return ("TAG_REMAP_LOOKUP");
197 case TAG_REMAP_LOOKUP_AD:
198 return ("TAG_REMAP_LOOKUP_AD");
199 case TAG_REMAP_LOOKUP_NA:
200 return ("TAG_REMAP_LOOKUP_NA");
201 case TAG_REMAP_MOUNT:
202 return ("TAG_REMAP_MOUNT");
203 case TAG_RMDIR:
204 return ("TAG_RMDIR");
205 case TAG_REMOVE:
206 return ("TAG_REMOVE");
207 case TAG_RENAME:
208 return ("TAG_RENAME");
209 case TAG_RENAME_VFH:
210 return ("TAG_RENAME_VFH");
211 case TAG_RENEW:
212 return ("TAG_RENEW");
213 case TAG_REOPEN:
214 return ("TAG_REOPEN");
215 case TAG_REOPEN_LOST:
216 return ("TAG_REOPEN_LOST");
217 case TAG_SECINFO:
218 return ("TAG_SECINFO");
219 case TAG_SETATTR:
220 return ("TAG_SETATTR");
221 case TAG_SETCLIENTID:
222 return ("TAG_SETCLIENTID");
223 case TAG_SETCLIENTID_CF:
224 return ("TAG_SETCLIENTID_CF");
225 case TAG_SYMLINK:
226 return ("TAG_SYMLINK");
227 case TAG_WRITE:
228 return ("TAG_WRITE");
229 default:
230 return ("Undefined");
231 }
232 }
233
234 /*
235 * Return stringified NFS4 error.
236 * Note, it may return pointer to static buffer (in case of unknown error)
237 */
238 static const char *
nfs4_stat_str(nfsstat4 err)239 nfs4_stat_str(nfsstat4 err)
240 {
241 static char str[64];
242
243 switch (err) {
244 case NFS4_OK:
245 return ("NFS4_OK");
246 case NFS4ERR_PERM:
247 return ("NFS4ERR_PERM");
248 case NFS4ERR_NOENT:
249 return ("NFS4ERR_NOENT");
250 case NFS4ERR_IO:
251 return ("NFS4ERR_IO");
252 case NFS4ERR_NXIO:
253 return ("NFS4ERR_NXIO");
254 case NFS4ERR_ACCESS:
255 return ("NFS4ERR_ACCESS");
256 case NFS4ERR_EXIST:
257 return ("NFS4ERR_EXIST");
258 case NFS4ERR_XDEV:
259 return ("NFS4ERR_XDEV");
260 case NFS4ERR_NOTDIR:
261 return ("NFS4ERR_NOTDIR");
262 case NFS4ERR_ISDIR:
263 return ("NFS4ERR_ISDIR");
264 case NFS4ERR_INVAL:
265 return ("NFS4ERR_INVAL");
266 case NFS4ERR_FBIG:
267 return ("NFS4ERR_FBIG");
268 case NFS4ERR_NOSPC:
269 return ("NFS4ERR_NOSPC");
270 case NFS4ERR_ROFS:
271 return ("NFS4ERR_ROFS");
272 case NFS4ERR_MLINK:
273 return ("NFS4ERR_MLINK");
274 case NFS4ERR_NAMETOOLONG:
275 return ("NFS4ERR_NAMETOOLONG");
276 case NFS4ERR_NOTEMPTY:
277 return ("NFS4ERR_NOTEMPTY");
278 case NFS4ERR_DQUOT:
279 return ("NFS4ERR_DQUOT");
280 case NFS4ERR_STALE:
281 return ("NFS4ERR_STALE");
282 case NFS4ERR_BADHANDLE:
283 return ("NFS4ERR_BADHANDLE");
284 case NFS4ERR_BAD_COOKIE:
285 return ("NFS4ERR_BAD_COOKIE");
286 case NFS4ERR_NOTSUPP:
287 return ("NFS4ERR_NOTSUPP");
288 case NFS4ERR_TOOSMALL:
289 return ("NFS4ERR_TOOSMALL");
290 case NFS4ERR_SERVERFAULT:
291 return ("NFS4ERR_SERVERFAULT");
292 case NFS4ERR_BADTYPE:
293 return ("NFS4ERR_BADTYPE");
294 case NFS4ERR_DELAY:
295 return ("NFS4ERR_DELAY");
296 case NFS4ERR_SAME:
297 return ("NFS4ERR_SAME");
298 case NFS4ERR_DENIED:
299 return ("NFS4ERR_DENIED");
300 case NFS4ERR_EXPIRED:
301 return ("NFS4ERR_EXPIRED");
302 case NFS4ERR_LOCKED:
303 return ("NFS4ERR_LOCKED");
304 case NFS4ERR_GRACE:
305 return ("NFS4ERR_GRACE");
306 case NFS4ERR_FHEXPIRED:
307 return ("NFS4ERR_FHEXPIRED");
308 case NFS4ERR_SHARE_DENIED:
309 return ("NFS4ERR_SHARE_DENIED");
310 case NFS4ERR_WRONGSEC:
311 return ("NFS4ERR_WRONGSEC");
312 case NFS4ERR_CLID_INUSE:
313 return ("NFS4ERR_CLID_INUSE");
314 case NFS4ERR_RESOURCE:
315 return ("NFS4ERR_RESOURCE");
316 case NFS4ERR_MOVED:
317 return ("NFS4ERR_MOVED");
318 case NFS4ERR_NOFILEHANDLE:
319 return ("NFS4ERR_NOFILEHANDLE");
320 case NFS4ERR_MINOR_VERS_MISMATCH:
321 return ("NFS4ERR_MINOR_VERS_MISMATCH");
322 case NFS4ERR_STALE_CLIENTID:
323 return ("NFS4ERR_STALE_CLIENTID");
324 case NFS4ERR_STALE_STATEID:
325 return ("NFS4ERR_STALE_STATEID");
326 case NFS4ERR_OLD_STATEID:
327 return ("NFS4ERR_OLD_STATEID");
328 case NFS4ERR_BAD_STATEID:
329 return ("NFS4ERR_BAD_STATEID");
330 case NFS4ERR_BAD_SEQID:
331 return ("NFS4ERR_BAD_SEQID");
332 case NFS4ERR_NOT_SAME:
333 return ("NFS4ERR_NOT_SAME");
334 case NFS4ERR_LOCK_RANGE:
335 return ("NFS4ERR_LOCK_RANGE");
336 case NFS4ERR_SYMLINK:
337 return ("NFS4ERR_SYMLINK");
338 case NFS4ERR_RESTOREFH:
339 return ("NFS4ERR_RESTOREFH");
340 case NFS4ERR_LEASE_MOVED:
341 return ("NFS4ERR_LEASE_MOVED");
342 case NFS4ERR_ATTRNOTSUPP:
343 return ("NFS4ERR_ATTRNOTSUPP");
344 case NFS4ERR_NO_GRACE:
345 return ("NFS4ERR_NO_GRACE");
346 case NFS4ERR_RECLAIM_BAD:
347 return ("NFS4ERR_RECLAIM_BAD");
348 case NFS4ERR_RECLAIM_CONFLICT:
349 return ("NFS4ERR_RECLAIM_CONFLICT");
350 case NFS4ERR_BADXDR:
351 return ("NFS4ERR_BADXDR");
352 case NFS4ERR_LOCKS_HELD:
353 return ("NFS4ERR_LOCKS_HELD");
354 case NFS4ERR_OPENMODE:
355 return ("NFS4ERR_OPENMODE");
356 case NFS4ERR_BADOWNER:
357 return ("NFS4ERR_BADOWNER");
358 case NFS4ERR_BADCHAR:
359 return ("NFS4ERR_BADCHAR");
360 case NFS4ERR_BADNAME:
361 return ("NFS4ERR_BADNAME");
362 case NFS4ERR_BAD_RANGE:
363 return ("NFS4ERR_BAD_RANGE");
364 case NFS4ERR_LOCK_NOTSUPP:
365 return ("NFS4ERR_LOCK_NOTSUPP");
366 case NFS4ERR_OP_ILLEGAL:
367 return ("NFS4ERR_OP_ILLEGAL");
368 case NFS4ERR_DEADLOCK:
369 return ("NFS4ERR_DEADLOCK");
370 case NFS4ERR_FILE_OPEN:
371 return ("NFS4ERR_FILE_OPEN");
372 case NFS4ERR_ADMIN_REVOKED:
373 return ("NFS4ERR_ADMIN_REVOKED");
374 case NFS4ERR_CB_PATH_DOWN:
375 return ("NFS4ERR_CB_PATH_DOWN");
376 default:
377 mdb_snprintf(str, sizeof (str), "Unknown %d", err);
378 return (str);
379 }
380 }
381
382 static const char *
nfs4_op_str(uint_t op)383 nfs4_op_str(uint_t op)
384 {
385 switch (op) {
386 case OP_ACCESS:
387 return ("OP_ACCESS");
388 case OP_CLOSE:
389 return ("OP_CLOSE");
390 case OP_COMMIT:
391 return ("OP_COMMIT");
392 case OP_CREATE:
393 return ("OP_CREATE");
394 case OP_DELEGPURGE:
395 return ("OP_DELEGPURGE");
396 case OP_DELEGRETURN:
397 return ("OP_DELEGRETURN");
398 case OP_GETATTR:
399 return ("OP_GETATTR");
400 case OP_GETFH:
401 return ("OP_GETFH");
402 case OP_LINK:
403 return ("OP_LINK");
404 case OP_LOCK:
405 return ("OP_LOCK");
406 case OP_LOCKT:
407 return ("OP_LOCKT");
408 case OP_LOCKU:
409 return ("OP_LOCKU");
410 case OP_LOOKUP:
411 return ("OP_LOOKUP");
412 case OP_LOOKUPP:
413 return ("OP_LOOKUPP");
414 case OP_NVERIFY:
415 return ("OP_NVERIFY");
416 case OP_OPEN:
417 return ("OP_OPEN");
418 case OP_OPENATTR:
419 return ("OP_OPENATTR");
420 case OP_OPEN_CONFIRM:
421 return ("OP_OPEN_CONFIRM");
422 case OP_OPEN_DOWNGRADE:
423 return ("OP_OPEN_DOWNGRADE");
424 case OP_PUTFH:
425 return ("OP_PUTFH");
426 case OP_PUTPUBFH:
427 return ("OP_PUTPUBFH");
428 case OP_PUTROOTFH:
429 return ("OP_PUTROOTFH");
430 case OP_READ:
431 return ("OP_READ");
432 case OP_READDIR:
433 return ("OP_READDIR");
434 case OP_READLINK:
435 return ("OP_READLINK");
436 case OP_REMOVE:
437 return ("OP_REMOVE");
438 case OP_RENAME:
439 return ("OP_RENAME");
440 case OP_RENEW:
441 return ("OP_RENEW");
442 case OP_RESTOREFH:
443 return ("OP_RESTOREFH");
444 case OP_SAVEFH:
445 return ("OP_SAVEFH");
446 case OP_SECINFO:
447 return ("OP_SECINFO");
448 case OP_SETATTR:
449 return ("OP_SETATTR");
450 case OP_SETCLIENTID:
451 return ("OP_SETCLIENTID");
452 case OP_SETCLIENTID_CONFIRM:
453 return ("OP_SETCLIENTID_CONFIRM");
454 case OP_VERIFY:
455 return ("OP_VERIFY");
456 case OP_WRITE:
457 return ("OP_WRITE");
458 case OP_RELEASE_LOCKOWNER:
459 return ("OP_RELEASE_LOCKOWNER");
460 case OP_ILLEGAL:
461 return ("OP_ILLEGAL");
462 default:
463 return ("Unknown");
464 }
465 }
466
467 static const char *
nfs4_recov_str(uint_t act)468 nfs4_recov_str(uint_t act)
469 {
470 switch (act) {
471 case NR_UNUSED:
472 return ("NR_UNUSED");
473 case NR_STALE:
474 return ("NR_STALE");
475 case NR_FAILOVER:
476 return ("NR_FAILOVER");
477 case NR_CLIENTID:
478 return ("NR_CLIENTID");
479 case NR_OPENFILES:
480 return ("NR_OPENFILES");
481 case NR_WRONGSEC:
482 return ("NR_WRONGSEC");
483 case NR_EXPIRED:
484 return ("NR_EXPIRED");
485 case NR_BAD_STATEID:
486 return ("NR_BAD_STATEID");
487 case NR_FHEXPIRED:
488 return ("NR_FHEXPIRED");
489 case NR_BADHANDLE:
490 return ("NR_BADHANDLE");
491 case NR_BAD_SEQID:
492 return ("NR_BAD_SEQID");
493 case NR_OLDSTATEID:
494 return ("NR_OLDSTATEID");
495 case NR_GRACE:
496 return ("NR_GRACE");
497 case NR_DELAY:
498 return ("NR_DELAY");
499 case NR_LOST_LOCK:
500 return ("NR_LOST_LOCK");
501 case NR_LOST_STATE_RQST:
502 return ("NR_LOST_STATE_RQST");
503 case NR_MOVED:
504 return ("NR_MOVED");
505 default:
506 return ("Unknown");
507 }
508 }
509
510 static void
nfs_addr_by_conf(uintptr_t knconf,struct netbuf * addr,char * s,size_t nbytes)511 nfs_addr_by_conf(uintptr_t knconf, struct netbuf *addr,
512 char *s, size_t nbytes)
513 {
514 struct knetconfig conf;
515 char buf[16];
516
517 if (mdb_vread(&conf, sizeof (conf), knconf) == -1) {
518 mdb_warn("can't read sv_knconf");
519 return;
520 }
521
522 if (mdb_readstr(buf, sizeof (buf),
523 (uintptr_t)conf.knc_protofmly) == -1) {
524 mdb_warn("can't read knc_protofmly");
525 return;
526 }
527 /* Support only IPv4 addresses */
528 if (strcmp(NC_INET, buf) == 0) {
529 struct sockaddr_in *in;
530
531 in = mdb_alloc(addr->len + 1, UM_SLEEP | UM_GC);
532 if (mdb_vread(in, addr->len, (uintptr_t)addr->buf) == -1)
533 return;
534
535 mdb_nhconvert(&in->sin_port, &in->sin_port,
536 sizeof (in->sin_port));
537
538 (void) mdb_snprintf(s, nbytes, "%I:%d", in->sin_addr.s_addr,
539 in->sin_port);
540 }
541 }
542
543 /*
544 * Get IPv4 string address by servinfo4_t
545 *
546 * in case of error does not modify 's'
547 */
548 static void
nfs_addr_by_servinfo4(uintptr_t addr,char * s,size_t nbytes)549 nfs_addr_by_servinfo4(uintptr_t addr, char *s, size_t nbytes)
550 {
551 struct servinfo4 *si;
552
553 si = mdb_alloc(sizeof (*si), UM_SLEEP | UM_GC);
554 if (mdb_vread(si, sizeof (*si), addr) == -1) {
555 mdb_warn("can't read servinfo4");
556 return;
557 }
558
559 nfs_addr_by_conf((uintptr_t)si->sv_knconf, &si->sv_addr,
560 s, nbytes);
561 }
562
563
564 /*
565 * Get IPv4 string address by servinfo_t
566 *
567 * in case of error does not modify 's'
568 */
569 static void
nfs_addr_by_servinfo(uintptr_t addr,char * s,size_t nbytes)570 nfs_addr_by_servinfo(uintptr_t addr, char *s, size_t nbytes)
571 {
572 struct servinfo *si;
573
574 si = mdb_alloc(sizeof (*si), UM_SLEEP | UM_GC);
575 if (mdb_vread(si, sizeof (*si), addr) == -1) {
576 mdb_warn("can't read servinfo");
577 return;
578 }
579
580 nfs_addr_by_conf((uintptr_t)si->sv_knconf, &si->sv_addr,
581 s, nbytes);
582 }
583
584 static void
nfs_queue_show_event(const nfs4_debug_msg_t * msg)585 nfs_queue_show_event(const nfs4_debug_msg_t *msg)
586 {
587 const nfs4_revent_t *re;
588 time_t time;
589 char *re_char1 = "<unknown>", *re_char2 = "<unknown>";
590
591 re = &msg->rmsg_u.msg_event;
592 time = msg->msg_time.tv_sec;
593
594 if (re->re_char1 != NULL) {
595 char *s;
596
597 s = mdb_alloc(MAXPATHLEN, UM_SLEEP | UM_GC);
598 if (mdb_readstr(s, MAXPATHLEN, (uintptr_t)re->re_char1) != -1)
599 re_char1 = s;
600 else
601 mdb_warn("can't read re_char1");
602 }
603
604 if (re->re_char2 != NULL) {
605 char *s;
606
607 s = mdb_alloc(MAXPATHLEN, UM_SLEEP | UM_GC);
608
609 if (mdb_readstr(s, MAXPATHLEN, (uintptr_t)re->re_char2) != -1)
610 re_char2 = s;
611 else
612 mdb_warn("can't read re_char2");
613 }
614
615 switch (re->re_type) {
616 case RE_BAD_SEQID:
617 mdb_printf("[NFS4]%Y: Op %s for file %s rnode_pt %p\n"
618 "pid %d using seqid %d got %s. Last good seqid was %d "
619 "for operation %s\n",
620 time, nfs4_tag_str(re->re_tag1), re->re_char1, re->re_rp1,
621 re->re_pid, re->re_seqid1, nfs4_stat_str(re->re_stat4),
622 re->re_seqid2, nfs4_tag_str(re->re_tag2));
623 break;
624 case RE_BADHANDLE:
625 mdb_printf("[NFS4]%Y: server said filehandle was "
626 "invalid for file: %s rnode_pt 0x%p\n", time,
627 re_char1, re->re_rp1);
628 break;
629 case RE_CLIENTID:
630 mdb_printf("[NFS4]%Y: Can't recover clientid on mountpoint %s\n"
631 "mi %p due to error %d (%s). Marking file system "
632 "as unusable\n", time, msg->msg_mntpt,
633 re->re_mi, re->re_uint, nfs4_stat_str(re->re_stat4));
634 break;
635 case RE_DEAD_FILE:
636 mdb_printf("[NFS4]%Y: File: %s rnode_pt: %p was closed on NFS\n"
637 "recovery error [%s %s]\n", time, re_char1, re->re_rp1,
638 re_char2, nfs4_stat_str(re->re_stat4));
639 break;
640 case RE_END:
641 mdb_printf("[NFS4]%Y: NFS Recovery done for mi %p "
642 "rnode_pt1 %s (%p), rnode_pt2 %s (%p)\n", time, re->re_mi,
643 re_char1, re->re_rp1, re_char2, re->re_rp2);
644 break;
645
646 case RE_FAIL_RELOCK:
647 mdb_printf("[NFS4]%Y: Couldn't reclaim lock for pid %d for\n"
648 "file %s (rnode_pt %p) error %d\n", time, re->re_pid,
649 re_char1, re->re_rp1,
650 re->re_uint ? re->re_uint : re->re_stat4);
651 break;
652 case RE_FAIL_REMAP_LEN:
653 mdb_printf("[NFS4]%Y: remap_lookup: returned bad\n"
654 "fhandle length %d\n", time, re->re_uint);
655 break;
656 case RE_FAIL_REMAP_OP:
657 mdb_printf("[NFS4]%Y: remap_lookup: didn't get expected "
658 " OP_GETFH\n", time);
659 break;
660 case RE_FAILOVER:
661 mdb_printf("[NFS4]%Y: failing over to %s\n", time, re_char1);
662 break;
663
664 case RE_FILE_DIFF:
665 mdb_printf("[NFS4]%Y: File %s rnode_pt: %p was closed\n"
666 "and failed attempted failover since its is different\n"
667 "than the original file\n", time, re_char1, re->re_rp1);
668 break;
669
670 case RE_LOST_STATE:
671 mdb_printf("[NFS4]%Y: Lost %s request file %s\n"
672 "rnode_pt: %p, dir %s (%p)\n", time,
673 nfs4_op_str(re->re_uint), re_char1,
674 re->re_rp1, re_char2, re->re_rp2);
675 break;
676 case RE_OPENS_CHANGED:
677 mdb_printf("[NFS4]%Y: The number of open files to reopen\n"
678 "changed for mount %s mi %p old %d, new %d\n", time,
679 msg->msg_mntpt, re->re_mi, re->re_uint, re->re_pid);
680 break;
681 case RE_SIGLOST:
682 case RE_SIGLOST_NO_DUMP:
683 mdb_printf("[NFS4]%Y: Process %d lost its locks on file %s\n"
684 "rnode_pt: %p due to NFS recovery error (%d:%s)\n",
685 time, re->re_pid, re_char1,
686 re->re_rp1, re->re_uint, nfs4_stat_str(re->re_stat4));
687 break;
688 case RE_START:
689 mdb_printf("[NFS4]%Y: NFS Starting recovery for\n"
690 "mi %p mi_recovflags [0x%x] rnode_pt1 %s %p "
691 "rnode_pt2 %s %p\n", time,
692 re->re_mi, re->re_uint, re_char1, re->re_rp1,
693 re_char2, re->re_rp2);
694 break;
695 case RE_UNEXPECTED_ACTION:
696 mdb_printf("[NFS4]%Y: NFS recovery: unexpected action %s\n",
697 time, nfs4_recov_str(re->re_uint));
698 break;
699 case RE_UNEXPECTED_ERRNO:
700 mdb_printf("[NFS4]%Y: NFS recovery: unexpected errno %d\n",
701 time, re->re_uint);
702 break;
703 case RE_UNEXPECTED_STATUS:
704 mdb_printf("[NFS4]%Y: NFS recovery: unexpected status"
705 "code (%s)\n", time, nfs4_stat_str(re->re_stat4));
706 break;
707 case RE_WRONGSEC:
708 mdb_printf("[NFS4]%Y: NFS can't recover from NFS4ERR_WRONGSEC\n"
709 "error %d rnode_pt1 %s (%p) rnode_pt2 %s (0x%p)\n", time,
710 re->re_uint, re_char1, re->re_rp1, re_char2, re->re_rp2);
711 break;
712 case RE_LOST_STATE_BAD_OP:
713 mdb_printf("[NFS4]%Y: NFS lost state with unrecognized op %d\n"
714 "fs %s, pid %d, file %s (rnode_pt: %p) dir %s (%p)\n",
715 time, re->re_uint, msg->msg_mntpt, re->re_pid, re_char1,
716 re->re_rp1, re_char2, re->re_rp2);
717 break;
718 case RE_REFERRAL:
719 mdb_printf("[NFS4]%Y: being referred to %s\n",
720 time, re_char1);
721 break;
722 default:
723 mdb_printf("illegal event %d\n", re->re_type);
724 break;
725 }
726 }
727
728 static void
nfs_queue_show_fact(const nfs4_debug_msg_t * msg)729 nfs_queue_show_fact(const nfs4_debug_msg_t *msg)
730 {
731 time_t time;
732 const nfs4_rfact_t *rf;
733 char *rf_char1 = "<unknown>";
734
735 rf = &msg->rmsg_u.msg_fact;
736 time = msg->msg_time.tv_sec;
737
738 if (rf->rf_char1 != NULL) {
739 char *s;
740
741 s = mdb_alloc(MAXPATHLEN, UM_SLEEP | UM_GC);
742 if (mdb_readstr(s, MAXPATHLEN, (uintptr_t)rf->rf_char1) != -1)
743 rf_char1 = s;
744 else
745 mdb_warn("can't read rf_char1");
746 }
747
748 switch (rf->rf_type) {
749 case RF_ERR:
750 mdb_printf("[NFS4]%Y: NFS op %s got "
751 "error %s:%d causing recovery action %s.%s\n",
752 time, nfs4_op_str(rf->rf_op),
753 rf->rf_error ? "" : nfs4_stat_str(rf->rf_stat4),
754 rf->rf_error,
755 nfs4_recov_str(rf->rf_action),
756 rf->rf_reboot ?
757 " Client also suspects that the server rebooted,"
758 " or experienced a network partition." : "");
759 break;
760 case RF_RENEW_EXPIRED:
761 mdb_printf("[NFS4]%Y: NFS4 renew thread detected client's "
762 "lease has expired. Current open files/locks/IO may fail\n",
763 time);
764 break;
765 case RF_SRV_NOT_RESPOND:
766 mdb_printf("[NFS4]%Y: NFS server not responding;"
767 "still trying\n", time);
768 break;
769 case RF_SRV_OK:
770 mdb_printf("[NFS4]%Y: NFS server ok\n", time);
771 break;
772 case RF_SRVS_NOT_RESPOND:
773 mdb_printf("[NFS4]%Y: NFS servers not responding; "
774 "still trying\n", time);
775 break;
776 case RF_SRVS_OK:
777 mdb_printf("[NFS4]%Y: NFS servers ok\n", time);
778 break;
779 case RF_DELMAP_CB_ERR:
780 mdb_printf("[NFS4]%Y: NFS op %s got error %s when executing "
781 "delmap on file %s rnode_pt %p\n", time,
782 nfs4_op_str(rf->rf_op), nfs4_stat_str(rf->rf_stat4),
783 rf_char1, rf->rf_rp1);
784 break;
785 case RF_SENDQ_FULL:
786 mdb_printf("[NFS4]%Y: sending queue to NFS server is full; "
787 "still trying\n", time);
788 break;
789
790 default:
791 mdb_printf("queue_print_fact: illegal fact %d\n", rf->rf_type);
792 }
793 }
794
795 static int
nfs4_show_message(uintptr_t addr,const void * arg,void * data)796 nfs4_show_message(uintptr_t addr, const void *arg, void *data)
797 {
798 nfs4_debug_msg_t msg;
799 if (mdb_vread(&msg, sizeof (msg), addr) == -1) {
800 mdb_warn("failed to read nfs4_debug_msg_t at %p", addr);
801 return (WALK_ERR);
802 }
803
804 if (msg.msg_type == RM_EVENT)
805 nfs_queue_show_event(&msg);
806 else if (msg.msg_type == RM_FACT)
807 nfs_queue_show_fact(&msg);
808 else
809 mdb_printf("Wrong msg_type %d\n", msg.msg_type);
810 return (WALK_NEXT);
811 }
812
813 static void
nfs4_print_messages(uintptr_t head)814 nfs4_print_messages(uintptr_t head)
815 {
816 mdb_printf("-----------------------------\n");
817 mdb_printf("Messages queued:\n");
818 mdb_inc_indent(2);
819 mdb_pwalk("list", nfs4_show_message, NULL, (uintptr_t)head);
820 mdb_dec_indent(2);
821 mdb_printf("-----------------------------\n");
822 }
823
824
825 static void
nfs_print_mi4(uintptr_t miaddr,int verbose)826 nfs_print_mi4(uintptr_t miaddr, int verbose)
827 {
828 mntinfo4_t *mi;
829 char str[INET6_ADDRSTRLEN] = "";
830
831 mi = mdb_alloc(sizeof (*mi), UM_SLEEP | UM_GC);
832 if (mdb_vread(mi, sizeof (*mi), miaddr) == -1) {
833 mdb_warn("can't read mntinfo");
834 return;
835 }
836
837 mdb_printf("mntinfo4_t: %p\n", miaddr);
838 mdb_printf("NFS Version: 4\n");
839 mdb_printf("mi_flags: %b\n", mi->mi_flags, nfs_mi4_flags);
840 mdb_printf("mi_error: %x\n", mi->mi_error);
841 mdb_printf("mi_open_files: %d\n", mi->mi_open_files);
842 mdb_printf("mi_msg_count: %d\n", mi->mi_msg_count);
843 mdb_printf("mi_recovflags: %b\n", mi->mi_recovflags,
844 nfs_mi4_recover);
845 mdb_printf("mi_recovthread: %p\n", mi->mi_recovthread);
846 mdb_printf("mi_in_recovery: %d\n", mi->mi_in_recovery);
847
848 if (verbose == 0)
849 return;
850
851 mdb_printf("mi_zone: %p\n", mi->mi_zone);
852 mdb_printf("mi_curread: %d\n", mi->mi_curread);
853 mdb_printf("mi_curwrite: %d\n", mi->mi_curwrite);
854 mdb_printf("mi_retrans: %d\n", mi->mi_retrans);
855 mdb_printf("mi_timeo: %d\n", mi->mi_timeo);
856 mdb_printf("mi_acregmin: %llu\n", mi->mi_acregmin);
857 mdb_printf("mi_acregmax: %llu\n", mi->mi_acregmax);
858 mdb_printf("mi_acdirmin: %llu\n", mi->mi_acdirmin);
859 mdb_printf("mi_acdirmax: %llu\n", mi->mi_acdirmax);
860 mdb_printf("mi_count: %u\n", mi->mi_count);
861 mdb_printf("\nServer list: %p\n", mi->mi_servers);
862 nfs_addr_by_servinfo4((uintptr_t)mi->mi_curr_serv, str, sizeof (str));
863 mdb_printf("Curr Server: %p %s\n", mi->mi_curr_serv, str);
864 mdb_printf("Total:\n");
865 mdb_inc_indent(2);
866 mdb_printf("Server Non-responses: %u\n", mi->mi_noresponse);
867 mdb_printf("Server Failovers: %u\n\n", mi->mi_failover);
868 mdb_dec_indent(2);
869
870 mdb_printf("\nAsync Request queue:\n");
871 mdb_inc_indent(2);
872 mdb_printf("max threads: %u\n", mi->mi_max_threads);
873 mdb_printf("active threads: %u\n", mi->mi_threads[NFS_ASYNC_QUEUE]);
874 mdb_dec_indent(2);
875
876 nfs4_print_messages(miaddr + OFFSETOF(mntinfo4_t, mi_msg_list));
877 }
878
879 static void
nfs_print_mi(uintptr_t miaddr,uint_t vers)880 nfs_print_mi(uintptr_t miaddr, uint_t vers)
881 {
882 mntinfo_t *mi;
883 char str[INET6_ADDRSTRLEN] = "";
884
885 mi = mdb_alloc(sizeof (*mi), UM_SLEEP | UM_GC);
886 if (mdb_vread(mi, sizeof (*mi), miaddr) == -1) {
887 mdb_warn("can't read mntinfo");
888 return;
889 }
890
891 mdb_printf("\nServer list: %p\n", mi->mi_servers);
892 nfs_addr_by_servinfo((uintptr_t)mi->mi_curr_serv, str, sizeof (str));
893 mdb_printf("Curr Server: %p %s\n", mi->mi_curr_serv, str);
894 mdb_printf("Total:\n");
895 mdb_inc_indent(2);
896 mdb_printf("Server Non-responses: %u\n", mi->mi_noresponse);
897 mdb_printf("Server Failovers: %u\n\n", mi->mi_failover);
898 mdb_dec_indent(2);
899
900 mdb_printf("\nAsync Request queue:\n");
901 mdb_inc_indent(2);
902 mdb_printf("max threads: %u\n", mi->mi_max_threads);
903 mdb_printf("active threads: %u\n", mi->mi_threads[NFS_ASYNC_QUEUE]);
904 mdb_dec_indent(2);
905 }
906
907 static int
nfs_vfs_dcmd(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)908 nfs_vfs_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
909 {
910 vfs_t *vfs;
911 char buf[MAXNAMELEN];
912 int verbose = 0;
913
914 if ((flags & DCMD_ADDRSPEC) == 0) {
915 if (mdb_walk_dcmd("nfs_vfs", "nfs_vfs", argc, argv) == -1) {
916 mdb_warn("failed to walk nfs_vfs");
917 return (DCMD_ERR);
918 }
919 return (DCMD_OK);
920 }
921
922 if (mdb_getopts(argc, argv,
923 'v', MDB_OPT_SETBITS, TRUE, &verbose, NULL) != argc)
924 return (DCMD_USAGE);
925
926 vfs = mdb_alloc(sizeof (*vfs), UM_SLEEP | UM_GC);
927
928 if (mdb_vread(vfs, sizeof (*vfs), addr) == -1) {
929 mdb_warn("failed to read vfs");
930 return (DCMD_ERR);
931 }
932
933 mdb_printf("vfs_t->%p, data = %p, ops = %p\n",
934 addr, vfs->vfs_data, vfs->vfs_op);
935
936 /* do not need do vread for vfs_mntpt because take address */
937 if (mdb_readstr(buf, MAXNAMELEN,
938 (uintptr_t)&vfs->vfs_mntpt->rs_string) == -1)
939 return (DCMD_ERR);
940
941 mdb_inc_indent(2);
942
943 mdb_printf("mount point: %s\n", buf);
944 if (mdb_readstr(buf, MAXNAMELEN,
945 (uintptr_t)&vfs->vfs_resource->rs_string) == -1) {
946 mdb_warn("can't read rs_string");
947 goto err;
948 }
949 mdb_printf("mount from: %s\n", buf);
950
951 if (verbose) {
952 uintptr_t nfs4_ops;
953 mntopt_t m;
954 uint_t i;
955
956 mdb_printf("vfs_flags: %b\n", vfs->vfs_flag, vfs_flags);
957 mdb_printf("mount opts: ");
958 for (i = 0; i < vfs->vfs_mntopts.mo_count; i++) {
959 uintptr_t a = (uintptr_t)(vfs->vfs_mntopts.mo_list + i);
960
961 if (mdb_vread(&m, sizeof (m), a) == -1) {
962 mdb_warn("can't read mntopt");
963 continue;
964 }
965 if (m.mo_flags & MO_EMPTY)
966 continue;
967
968 if (mdb_readstr(buf, sizeof (buf),
969 (uintptr_t)m.mo_name) == -1) {
970 mdb_warn("can't read mo_name");
971 continue;
972 }
973 if (m.mo_flags & MO_HASVALUE) {
974 char val[64];
975
976 if (mdb_readstr(val, sizeof (val),
977 (uintptr_t)m.mo_arg) == -1) {
978 mdb_warn("can't read mo_arg");
979 continue;
980 }
981 mdb_printf("%s(%s), ", buf, val);
982 } else
983 mdb_printf("%s, ", buf);
984 }
985 mdb_printf("\n+--------------------------------------+\n");
986
987 if (mdb_readvar(&nfs4_ops, "nfs4_vfsops") == -1) {
988 mdb_warn("failed read %s", "nfs4_vfsops");
989 goto err;
990 }
991 if (nfs4_ops == (uintptr_t)vfs->vfs_op) {
992 nfs_print_mi4((uintptr_t)VFTOMI4(vfs), 1);
993 } else {
994 int vers = 3;
995 uintptr_t nfs3_ops;
996
997 if (mdb_readvar(&nfs3_ops, "nfs3_vfsops") == -1) {
998 mdb_warn("failed read %s", "nfs3_vfsops");
999 goto err;
1000 }
1001 if (nfs3_ops != (uintptr_t)vfs->vfs_op)
1002 vers = 2;
1003
1004 nfs_print_mi((uintptr_t)VFTOMI(vfs), vers);
1005 }
1006 }
1007 mdb_dec_indent(2);
1008 mdb_printf("\n");
1009 return (DCMD_OK);
1010 err:
1011 mdb_dec_indent(2);
1012 mdb_printf("\n");
1013 return (DCMD_ERR);
1014 }
1015
1016
1017 static int
nfs4_diag_dcmd(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)1018 nfs4_diag_dcmd(uintptr_t addr, uint_t flags, int argc,
1019 const mdb_arg_t *argv)
1020 {
1021 mntinfo4_t *mi;
1022 vfs_t *vfs;
1023 char buf[MAXNAMELEN];
1024
1025 if ((flags & DCMD_ADDRSPEC) == 0) {
1026 if (mdb_walk_dcmd("nfs4_mnt", "nfs4_diag", argc,
1027 argv) == -1) {
1028 mdb_warn("failed to walk nfs4_mnt");
1029 return (DCMD_ERR);
1030 }
1031 return (DCMD_OK);
1032 }
1033
1034 mi = mdb_alloc(sizeof (*mi), UM_SLEEP | UM_GC);
1035 if (mdb_vread(mi, sizeof (*mi), addr) == -1) {
1036 mdb_warn("can't read mntinfo4");
1037 return (WALK_ERR);
1038 }
1039
1040 vfs = mdb_alloc(sizeof (*vfs), UM_SLEEP | UM_GC);
1041 if (mdb_vread(vfs, sizeof (*vfs), (uintptr_t)mi->mi_vfsp) == -1) {
1042 mdb_warn("failed to read vfs");
1043 return (DCMD_ERR);
1044 }
1045
1046 mdb_printf("****************************************\n");
1047 mdb_printf("vfs: %-16p mi: %-16p\n", mi->mi_vfsp, addr);
1048
1049 if (mdb_readstr(buf, MAXNAMELEN,
1050 (uintptr_t)&vfs->vfs_mntpt->rs_string) == -1)
1051 return (DCMD_ERR);
1052
1053 mdb_inc_indent(2);
1054 mdb_printf("mount point: %s\n", buf);
1055 if (mdb_readstr(buf, MAXNAMELEN,
1056 (uintptr_t)&vfs->vfs_resource->rs_string) == -1) {
1057 mdb_warn("can't read rs_string");
1058 mdb_dec_indent(2);
1059 return (DCMD_ERR);
1060 }
1061 mdb_printf("mount from: %s\n", buf);
1062 nfs4_print_messages(addr + OFFSETOF(mntinfo4_t, mi_msg_list));
1063 mdb_dec_indent(2);
1064 mdb_printf("\n");
1065 return (DCMD_OK);
1066 }
1067
1068 static void
nfs4_diag_help(void)1069 nfs4_diag_help(void)
1070 {
1071 mdb_printf(" <mntinfo4_t>::nfs4_diag <-s>\n"
1072 " -> assumes client is an illumos NFSv4 client\n");
1073 }
1074
1075 static int
nfs_rnode4_cb(uintptr_t addr,const void * data,void * arg)1076 nfs_rnode4_cb(uintptr_t addr, const void *data, void *arg)
1077 {
1078 const rnode4_t *rp = data;
1079 nfs_rnode_cbdata_t *cbd = arg;
1080 vnode_t *vp;
1081
1082 if (addr == 0)
1083 return (WALK_DONE);
1084
1085 vp = mdb_alloc(sizeof (*vp), UM_SLEEP | UM_GC);
1086 if (mdb_vread(vp, sizeof (*vp), (uintptr_t)rp->r_vnode) == -1) {
1087 mdb_warn("can't read vnode_t %p", (uintptr_t)rp->r_vnode);
1088 return (WALK_ERR);
1089 }
1090
1091 if (cbd->vfs_addr != 0 &&
1092 cbd->vfs_addr != (uintptr_t)vp->v_vfsp)
1093 return (WALK_NEXT);
1094
1095 if (cbd->printed_hdr == 0) {
1096 mdb_printf("%-16s %-16s %-16s %-8s\n"
1097 "%-16s %-8s %-8s %s\n",
1098 "Address", "r_vnode", "vfsp", "r_fh",
1099 "r_server", "r_error", "r_flags", "r_count");
1100 cbd->printed_hdr = 1;
1101 }
1102
1103 mdb_printf("%-?p %-8p %-8p %-8p\n"
1104 "%-16p %-8u %-8x %u\n",
1105 addr, rp->r_vnode, vp->v_vfsp, rp->r_fh,
1106 rp->r_server, (int)rp->r_error, rp->r_flags, rp->r_count);
1107
1108 return (WALK_NEXT);
1109 }
1110
1111 static int
nfs_rnode4_dcmd(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)1112 nfs_rnode4_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
1113 {
1114 nfs_rnode_cbdata_t *cbd;
1115 rnode4_t *rp;
1116
1117 cbd = mdb_zalloc(sizeof (*cbd), UM_SLEEP | UM_GC);
1118
1119 if ((flags & DCMD_ADDRSPEC) == 0) {
1120 if (mdb_walk("nfs_rtable4", nfs_rnode4_cb, cbd) == -1) {
1121 mdb_warn("failed to walk nfs_rnode4");
1122 return (DCMD_ERR);
1123 }
1124 return (DCMD_OK);
1125 }
1126
1127 /* address was specified */
1128 rp = mdb_alloc(sizeof (*rp), UM_SLEEP | UM_GC);
1129 if (mdb_vread(rp, sizeof (*rp), addr) == -1) {
1130 mdb_warn("can't read rnode4_t");
1131 return (DCMD_ERR);
1132 }
1133
1134 nfs_rnode4_cb(addr, rp, cbd);
1135 return (DCMD_OK);
1136 }
1137
1138 static void
nfs_rnode4_help(void)1139 nfs_rnode4_help(void)
1140 {
1141 mdb_printf("<rnode4 addr>::nfs_rnode4\n\n"
1142 "This prints NFSv4 rnode at address specified. If address\n"
1143 "is not specified, walks entire NFSv4 rnode table.\n");
1144 }
1145
1146 static int
nfs_rnode4find_dcmd(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)1147 nfs_rnode4find_dcmd(uintptr_t addr, uint_t flags, int argc,
1148 const mdb_arg_t *argv)
1149 {
1150 nfs_rnode_cbdata_t *cbd;
1151
1152 cbd = mdb_zalloc(sizeof (*cbd), UM_SLEEP | UM_GC);
1153
1154 if ((flags & DCMD_ADDRSPEC) == 0) {
1155 mdb_printf("requires address of vfs_t\n");
1156 return (DCMD_USAGE);
1157 }
1158
1159 cbd->vfs_addr = addr;
1160 if (mdb_walk("nfs_rtable4", nfs_rnode4_cb, cbd) == -1) {
1161 mdb_warn("failed to walk nfs_rnode4");
1162 return (DCMD_ERR);
1163 }
1164 return (DCMD_OK);
1165 }
1166
1167 static void
nfs_rnode4find_help(void)1168 nfs_rnode4find_help(void)
1169 {
1170 mdb_printf("<vfs addr>::nfs_rnode4find\n\n"
1171 "This prints all NFSv4 rnodes that belong to\n"
1172 "the VFS address specified\n");
1173 }
1174
1175 static int nfs_help_dcmd(uintptr_t, uint_t, int, const mdb_arg_t *);
1176
1177 extern int nfs_stat_dcmd(uintptr_t, uint_t, int, const mdb_arg_t *);
1178
1179 static const mdb_dcmd_t dcmds[] = {
1180 /* svc */
1181 {
1182 "svc_pool", "?[-v] [poolid ...]",
1183 "display SVCPOOL information\n"
1184 "\t\t\t(Optional address of SVCPOOL)",
1185 svc_pool_dcmd, svc_pool_help
1186 },
1187 {
1188 "svc_mxprt", ":[-w]",
1189 "display master xprt info given SVCMASTERXPRT",
1190 svc_mxprt_dcmd, svc_mxprt_help
1191 },
1192 /* rfs4 */
1193 {
1194 "rfs4_db", "?",
1195 "dump NFSv4 server database\n"
1196 "\t\t\t(Optional address of zone_t)",
1197 rfs4_db_dcmd
1198 },
1199 {
1200 "rfs4_tbl", ":[-vw]",
1201 "dump NFSv4 server table given rfs4_table_t",
1202 rfs4_tbl_dcmd, rfs4_tbl_help
1203 },
1204 {
1205 "rfs4_idx", ":[-w]",
1206 "dump NFSv4 server index given rfs4_index_t",
1207 rfs4_idx_dcmd, rfs4_idx_help
1208 },
1209 {
1210 "rfs4_bkt", ":",
1211 "dump NFSv4 server index buckets given rfs4_index_t",
1212 rfs4_bkt_dcmd
1213 },
1214 {
1215 "rfs4_oo", "?",
1216 "dump NFSv4 rfs4_openowner_t structures from bucket data\n"
1217 "\t\t\t(Optional address of rfs4_openowner_t)",
1218 rfs4_oo_dcmd
1219 },
1220 {
1221 "rfs4_osid", "?[-v]",
1222 "dump NFSv4 rfs4_state_t structures from bucket data\n"
1223 "\t\t\t(Optional address of rfs4_state_t)",
1224 rfs4_osid_dcmd
1225 },
1226 {
1227 "rfs4_file", "?[-v]",
1228 "dump NFSv4 rfs4_file_t structures from bucket data\n"
1229 "\t\t\t(Optional address of rfs4_file_t)",
1230 rfs4_file_dcmd
1231 },
1232 {
1233 "rfs4_deleg", "?[-v]",
1234 "dump NFSv4 rfs4_deleg_state_t structures from bucket data\n"
1235 "\t\t\t(Optional address of rfs4_deleg_state_t)",
1236 rfs4_deleg_dcmd
1237 },
1238 {
1239 "rfs4_lo", "?",
1240 "dump NFSv4 rfs4_lockowner_t structures from bucket data\n"
1241 "\t\t\t(Optional address of rfs4_lockowner_t)",
1242 rfs4_lo_dcmd
1243 },
1244 {
1245 "rfs4_lsid", "?[-v]",
1246 "dump NFSv4 rfs4_lo_state_t structures from bucket data\n"
1247 "\t\t\t(Optional address of rfs4_lo_state_t)",
1248 rfs4_lsid_dcmd
1249 },
1250 {
1251 "rfs4_client", "?[-c <clientid>]",
1252 "dump NFSv4 rfs4_client_t structures from bucket data\n"
1253 "\t\t\t(Optional address of rfs4_client_t)",
1254 rfs4_client_dcmd, rfs4_client_help
1255 },
1256 /* NFS server */
1257 {
1258 "nfs_expvis", ":",
1259 "dump exp_visible_t structure",
1260 nfs_expvis_dcmd
1261 },
1262 {
1263 "nfs_expinfo", ":",
1264 "dump struct exportinfo",
1265 nfs_expinfo_dcmd
1266 },
1267 {
1268 "nfs_exptable", "?",
1269 "dump exportinfo structures for a zone\n"
1270 "\t\t\t(Optional address of zone_t)",
1271 nfs_exptable_dcmd
1272 },
1273 {
1274 "nfs_exptable_path", "?",
1275 "dump exportinfo structures for a zone\n"
1276 "\t\t\t(Optional address of zone_t)",
1277 nfs_exptable_path_dcmd
1278 },
1279 {
1280 "nfs_nstree", "?[-v]",
1281 "dump NFS server pseudo namespace tree for a zone\n"
1282 "\t\t\t(Optional address of zone_t)",
1283 nfs_nstree_dcmd, nfs_nstree_help
1284 },
1285 {
1286 "nfs_fid_hashdist", ":[-v]",
1287 "show fid hash distribution of the exportinfo table",
1288 nfs_fid_hashdist_dcmd, nfs_hashdist_help
1289 },
1290 {
1291 "nfs_path_hashdist", "[-v]",
1292 "show path hash distribution of the exportinfo table",
1293 nfs_path_hashdist_dcmd, nfs_hashdist_help
1294 },
1295 /* NFSv4 idmap */
1296 {
1297 "nfs4_idmap", ":",
1298 "dump nfsidmap_t",
1299 nfs4_idmap_dcmd
1300 },
1301 {
1302 "nfs4_idmap_info", "?[u2s | g2s | s2u | s2g ...]",
1303 "dump NFSv4 idmap information\n"
1304 "\t\t\t(Optional address of zone_t)",
1305 nfs4_idmap_info_dcmd, nfs4_idmap_info_help
1306 },
1307 /* NFS client */
1308 {
1309 "nfs_mntinfo", "?[-v]",
1310 "print mntinfo_t information\n"
1311 "\t\t\t(Optional address of mntinfo_t)",
1312 nfs_mntinfo_dcmd, nfs_mntinfo_help
1313 },
1314 {
1315 "nfs_servinfo", ":[-v]",
1316 "print servinfo_t information",
1317 nfs_servinfo_dcmd, nfs_servinfo_help
1318 },
1319 /* WIP */
1320 {
1321 "nfs4_mntinfo", "?[-mv]",
1322 "print mntinfo4_t information\n"
1323 "\t\t\t(Optional address of mntinfo4_t)",
1324 nfs4_mntinfo_dcmd, nfs4_mntinfo_help
1325 },
1326 {
1327 "nfs4_servinfo", ":[-v]",
1328 "print servinfo4_t information",
1329 nfs4_servinfo_dcmd, nfs4_servinfo_help
1330 },
1331 {
1332 "nfs4_server_info", "?[-cs]",
1333 "print nfs4_server_t information",
1334 nfs4_server_info_dcmd, nfs4_server_info_help
1335 },
1336 /* WIP */
1337 {
1338 "nfs4_mimsg", ":[-s]",
1339 "print queued messages for given address of mi_msg_list",
1340 nfs4_mimsg_dcmd, nfs4_mimsg_help
1341 },
1342 {
1343 "nfs4_fname", ":",
1344 "print path name of nfs4_fname_t specified",
1345 nfs4_fname_dcmd
1346 },
1347 {
1348 "nfs4_svnode", ":",
1349 "print svnode_t info at specified address",
1350 nfs4_svnode_dcmd
1351 },
1352
1353
1354 /* NFSv2/3/4 clnt */
1355 {
1356 "nfs_vfs", "?[-v]",
1357 "print all nfs vfs struct (-v for mntinfo)\n"
1358 "\t\t\t(Optional address of vfs_t)",
1359 nfs_vfs_dcmd
1360 },
1361
1362
1363 /* NFSv4 clnt */
1364 {
1365 "nfs_rnode4", "?",
1366 "dump NFSv4 rnodes\n"
1367 "\t\t\t(Optional address of rnode4_t)",
1368 nfs_rnode4_dcmd, nfs_rnode4_help
1369 },
1370 {
1371 "nfs4_diag", "?[-s]",
1372 "print queued recovery messages for NFSv4 client\n"
1373 "\t\t\t(Optional address of mntinfo4_t)",
1374 nfs4_diag_dcmd, nfs4_diag_help
1375 },
1376 {
1377 "nfs_rnode4find", ":",
1378 "dump NFSv4 rnodes for given vfs_t",
1379 nfs_rnode4find_dcmd, nfs_rnode4find_help
1380 },
1381 {
1382 "nfs4_foo", ":[-v]",
1383 "dump free open owners for NFSv4 client",
1384 nfs4_foo_dcmd
1385 },
1386 {
1387 "nfs4_oob", ":[-v]",
1388 "dump open owners for NFSv4 client",
1389 nfs4_oob_dcmd
1390 },
1391 {
1392 "nfs4_os", "?[-v]",
1393 "dump open streams for NFSv4 Client\n"
1394 "\t\t\t(Optional address of rnode4_t)",
1395 nfs4_os_dcmd
1396 },
1397
1398 /* generic commands */
1399 {
1400 "nfs_stat", "?[-csb][-234][-anr] | $[count]",
1401 "Print NFS statistics for zone\n"
1402 "\t\t\t(Optional address of zone_t)",
1403 nfs_stat_dcmd
1404 },
1405 {
1406 "nfs_help", "[-dw]",
1407 "Show nfs commands",
1408 nfs_help_dcmd
1409 },
1410
1411 {NULL, NULL, NULL, NULL}
1412 };
1413
1414 static const mdb_walker_t walkers[] = {
1415 /* svc */
1416 {
1417 "svc_pool", "walk SVCPOOL structs for given zone",
1418 svc_pool_walk_init, svc_pool_walk_step
1419 },
1420 {
1421 "svc_mxprt", "walk master xprts",
1422 svc_mxprt_walk_init, svc_mxprt_walk_step
1423 },
1424 /* rfs4 */
1425 {
1426 "rfs4_db_tbl", "walk NFSv4 server rfs4_table_t structs",
1427 rfs4_db_tbl_walk_init, rfs4_db_tbl_walk_step
1428 },
1429 {
1430 "rfs4_db_idx", "walk NFSv4 server rfs4_index_t structs",
1431 rfs4_db_idx_walk_init, rfs4_db_idx_walk_step
1432 },
1433 {
1434 "rfs4_db_bkt", "walk NFSv4 server buckets for given index",
1435 rfs4_db_bkt_walk_init, rfs4_db_bkt_walk_step,
1436 rfs4_db_bkt_walk_fini
1437 },
1438 /* NFS server */
1439 {
1440 "nfs_expinfo", "walk exportinfo structures from the exptable",
1441 nfs_expinfo_walk_init, hash_table_walk_step,
1442 nfs_expinfo_walk_fini, &nfs_expinfo_arg
1443 },
1444 {
1445 "nfs_expinfo_path",
1446 "walk exportinfo structures from the exptable_path_hash",
1447 nfs_expinfo_walk_init, hash_table_walk_step,
1448 nfs_expinfo_walk_fini, &nfs_expinfo_path_arg
1449 },
1450 {
1451 "nfs_expvis", "walk list of exp_visible structs",
1452 nfs_expvis_walk_init, nfs_expvis_walk_step
1453 },
1454 {
1455 "nfssrv_globals", "walk list of zones NFS globals",
1456 nfssrv_globals_walk_init, nfssrv_globals_walk_step
1457 },
1458 /* NFSv4 idmap */
1459 {
1460 "nfs4_u2s", "walk uid-to-string idmap cache for given zone",
1461 nfs4_idmap_walk_init, hash_table_walk_step,
1462 nfs4_idmap_walk_fini,
1463 (void *)OFFSETOF(struct nfsidmap_globals, u2s_ci)
1464 },
1465 {
1466 "nfs4_s2u", "walk string-to-uid idmap cache for given zone",
1467 nfs4_idmap_walk_init, hash_table_walk_step,
1468 nfs4_idmap_walk_fini,
1469 (void *)OFFSETOF(struct nfsidmap_globals, s2u_ci)
1470 },
1471 {
1472 "nfs4_g2s", "walk gid-to-string idmap cache for given zone",
1473 nfs4_idmap_walk_init, hash_table_walk_step,
1474 nfs4_idmap_walk_fini,
1475 (void *)OFFSETOF(struct nfsidmap_globals, g2s_ci)
1476 },
1477 {
1478 "nfs4_s2g", "walk string-to-gid idmap cache for given zone",
1479 nfs4_idmap_walk_init, hash_table_walk_step,
1480 nfs4_idmap_walk_fini,
1481 (void *)OFFSETOF(struct nfsidmap_globals, s2g_ci)
1482 },
1483 /* NFS client */
1484 {
1485 "nfs_rtable", "walk rnodes in rtable cache",
1486 nfs_rtable_walk_init, hash_table_walk_step,
1487 hash_table_walk_fini, &nfs_rtable_arg
1488 },
1489 {
1490 "nfs_rtable4", "walk rnode4s in rtable4 cache",
1491 nfs_rtable4_walk_init, hash_table_walk_step,
1492 hash_table_walk_fini, &nfs_rtable4_arg
1493 },
1494 {
1495 "nfs_vfs", "walk NFS-mounted vfs structs",
1496 nfs_vfs_walk_init, nfs_vfs_walk_step, nfs_vfs_walk_fini
1497 },
1498 {
1499 "nfs_mnt", "walk NFSv2/3-mounted vfs structs, pass mntinfo",
1500 nfs_mnt_walk_init, nfs_mnt_walk_step, nfs_mnt_walk_fini
1501 },
1502 {
1503 "nfs4_mnt", "walk NFSv4-mounted vfs structs, pass mntinfo4",
1504 nfs4_mnt_walk_init, nfs4_mnt_walk_step, nfs4_mnt_walk_fini
1505 },
1506 {
1507 "nfs_serv", "walk linkedlist of servinfo structs",
1508 nfs_serv_walk_init, nfs_serv_walk_step
1509 },
1510 {
1511 "nfs4_serv", "walk linkedlist of servinfo4 structs",
1512 nfs4_serv_walk_init, nfs4_serv_walk_step
1513 },
1514 {
1515 "nfs4_svnode", "walk svnode list at given svnode address",
1516 nfs4_svnode_walk_init, nfs4_svnode_walk_step
1517 },
1518 {
1519 "nfs4_server", "walk nfs4_server_t structs",
1520 nfs4_server_walk_init, nfs4_server_walk_step
1521 },
1522 {
1523 "nfs_async", "walk list of async requests",
1524 nfs_async_walk_init, nfs_async_walk_step
1525 },
1526 {
1527 "nfs4_async", "walk list of NFSv4 async requests",
1528 nfs4_async_walk_init, nfs4_async_walk_step
1529 },
1530 {
1531 "nfs_acache_rnode", "walk acache entries for a given rnode",
1532 nfs_acache_rnode_walk_init, nfs_acache_rnode_walk_step
1533 },
1534 {
1535 "nfs_acache", "walk entire nfs_access_cache",
1536 nfs_acache_walk_init, hash_table_walk_step, nfs_acache_walk_fini
1537 },
1538 {
1539 "nfs_acache4_rnode",
1540 "walk acache4 entries for a given NFSv4 rnode",
1541 nfs_acache4_rnode_walk_init, nfs_acache4_rnode_walk_step
1542 },
1543 {
1544 "nfs_acache4", "walk entire nfs4_access_cache",
1545 nfs_acache4_walk_init, hash_table_walk_step,
1546 nfs_acache4_walk_fini
1547 },
1548
1549 {NULL, NULL, NULL, NULL}
1550 };
1551
1552
1553 static int
nfs_help_dcmd(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)1554 nfs_help_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
1555 {
1556 int i = 0;
1557 uint_t opt_d = FALSE;
1558 uint_t opt_w = FALSE;
1559
1560 if ((flags & DCMD_ADDRSPEC) != 0)
1561 return (DCMD_USAGE);
1562
1563 if (argc == 0) {
1564 mdb_printf("::nfs_help -w -d\n");
1565 mdb_printf(" -w Will show nfs specific walkers\n");
1566 mdb_printf(" -d Will show nfs specific dcmds\n");
1567 return (DCMD_ERR);
1568 }
1569
1570 if (mdb_getopts(argc, argv,
1571 'd', MDB_OPT_SETBITS, TRUE, &opt_d,
1572 'w', MDB_OPT_SETBITS, TRUE, &opt_w, NULL) != argc)
1573 return (DCMD_USAGE);
1574
1575 if (opt_d) {
1576 for (i = 0; dcmds[i].dc_name != NULL; i++)
1577 mdb_printf("%-20s %s\n", dcmds[i].dc_name,
1578 dcmds[i].dc_descr);
1579 }
1580 if (opt_w) {
1581 for (i = 0; walkers[i].walk_name != NULL; i++)
1582 mdb_printf("%-20s %s\n", walkers[i].walk_name,
1583 walkers[i].walk_descr);
1584 }
1585 return (DCMD_OK);
1586
1587 }
1588
1589 static const mdb_modinfo_t modinfo = {
1590 MDB_API_VERSION,
1591 dcmds,
1592 walkers
1593 };
1594
1595 const mdb_modinfo_t *
_mdb_init(void)1596 _mdb_init(void)
1597 {
1598 return (&modinfo);
1599 }
1600