10Sstevel@tonic-gate /*
20Sstevel@tonic-gate * CDDL HEADER START
30Sstevel@tonic-gate *
40Sstevel@tonic-gate * The contents of this file are subject to the terms of the
56583Smeem * Common Development and Distribution License (the "License").
66583Smeem * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate *
80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate * See the License for the specific language governing permissions
110Sstevel@tonic-gate * and limitations under the License.
120Sstevel@tonic-gate *
130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate *
190Sstevel@tonic-gate * CDDL HEADER END
200Sstevel@tonic-gate */
210Sstevel@tonic-gate /*
22*8752SPeter.Memishian@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
230Sstevel@tonic-gate * Use is subject to license terms.
240Sstevel@tonic-gate */
250Sstevel@tonic-gate
260Sstevel@tonic-gate #include <mdb/mdb_modapi.h>
270Sstevel@tonic-gate #include <mdb/mdb_ks.h>
280Sstevel@tonic-gate
29*8752SPeter.Memishian@Sun.COM #include <ctype.h>
300Sstevel@tonic-gate #include <sys/types.h>
310Sstevel@tonic-gate #include <sys/strsubr.h>
320Sstevel@tonic-gate #include <sys/stream.h>
330Sstevel@tonic-gate #include <sys/modctl.h>
340Sstevel@tonic-gate #include <sys/strft.h>
350Sstevel@tonic-gate #include <sys/strsun.h>
360Sstevel@tonic-gate #include <sys/sysmacros.h>
370Sstevel@tonic-gate
380Sstevel@tonic-gate #include "streams.h"
390Sstevel@tonic-gate
400Sstevel@tonic-gate typedef struct str_flags {
410Sstevel@tonic-gate uint_t strf_flag;
420Sstevel@tonic-gate const char *strf_name;
430Sstevel@tonic-gate const char *strf_descr;
440Sstevel@tonic-gate } strflags_t;
450Sstevel@tonic-gate
460Sstevel@tonic-gate typedef struct str_types {
470Sstevel@tonic-gate const char *strt_name;
480Sstevel@tonic-gate int strt_value;
490Sstevel@tonic-gate const char *strt_descr;
500Sstevel@tonic-gate } strtypes_t;
510Sstevel@tonic-gate
520Sstevel@tonic-gate typedef struct ftblk_data {
530Sstevel@tonic-gate ftblk_t ft_data; /* Copy of ftblk */
540Sstevel@tonic-gate int ft_ix; /* Index in event list */
550Sstevel@tonic-gate boolean_t ft_in_evlist; /* Iterating through evlist */
560Sstevel@tonic-gate } ftblkdata_t;
570Sstevel@tonic-gate
580Sstevel@tonic-gate typedef void qprint_func(queue_t *, queue_t *);
590Sstevel@tonic-gate typedef void sdprint_func(stdata_t *, stdata_t *);
600Sstevel@tonic-gate
610Sstevel@tonic-gate #define SF(flag) flag, #flag
620Sstevel@tonic-gate
630Sstevel@tonic-gate /*
640Sstevel@tonic-gate * Queue flags
650Sstevel@tonic-gate */
660Sstevel@tonic-gate static const strflags_t qf[] = {
670Sstevel@tonic-gate { SF(QENAB), "Queue is already enabled to run" },
680Sstevel@tonic-gate { SF(QWANTR), "Someone wants to read Q" },
690Sstevel@tonic-gate { SF(QWANTW), "Someone wants to write Q" },
700Sstevel@tonic-gate { SF(QFULL), "Q is considered full" },
710Sstevel@tonic-gate { SF(QREADR), "This is the reader (first) Q" },
720Sstevel@tonic-gate { SF(QUSE), "This queue in use (allocation)" },
730Sstevel@tonic-gate { SF(QNOENB), "Don't enable Q via putq" },
740Sstevel@tonic-gate { SF(QWANTRMQSYNC), "Want to remove sync stream Q" },
750Sstevel@tonic-gate { SF(QBACK), "queue has been back-enabled" },
760Sstevel@tonic-gate { SF(0x00000200), "unused (was QHLIST)" },
770Sstevel@tonic-gate { SF(0x00000400), "unused (was QUNSAFE)" },
780Sstevel@tonic-gate { SF(QPAIR), "per queue-pair syncq" },
790Sstevel@tonic-gate { SF(QPERQ), "per queue-instance syncq" },
800Sstevel@tonic-gate { SF(QPERMOD), "per module syncq" },
810Sstevel@tonic-gate { SF(QMTSAFE), "stream module is MT-safe" },
820Sstevel@tonic-gate { SF(QMTOUTPERIM), "Has outer perimeter" },
830Sstevel@tonic-gate { SF(QINSERVICE), "service routine executing" },
840Sstevel@tonic-gate { SF(QWCLOSE), "will not be enabled" },
850Sstevel@tonic-gate { SF(QEND), "last queue in stream" },
860Sstevel@tonic-gate { SF(QWANTWSYNC), "Streamhead wants to write Q" },
870Sstevel@tonic-gate { SF(QSYNCSTR), "Q supports Synchronous STREAMS" },
880Sstevel@tonic-gate { SF(QISDRV), "the Queue is attached to a driver" },
890Sstevel@tonic-gate { SF(0x00400000), "unused (was QHOT)" },
900Sstevel@tonic-gate { SF(0x00800000), "unused (was QNEXTHOT)" },
910Sstevel@tonic-gate { SF(0x01000000), "unused (was _QNEXTLESS)" },
920Sstevel@tonic-gate { SF(0x02000000), "unused" },
930Sstevel@tonic-gate { SF(_QINSERTING), "module is inserted with _I_INSERT" },
940Sstevel@tonic-gate { SF(_QREMOVING) "module is removed with _I_REMOVE" },
950Sstevel@tonic-gate { SF(_QASSOCIATED), "queue is associated with a device" },
96761Smeem { 0, NULL, NULL }
970Sstevel@tonic-gate };
980Sstevel@tonic-gate
990Sstevel@tonic-gate /*
1000Sstevel@tonic-gate * Syncq flags
1010Sstevel@tonic-gate */
1020Sstevel@tonic-gate static const struct str_flags sqf[] = {
1030Sstevel@tonic-gate { SF(SQ_EXCL), "Exclusive access to inner perimeter" },
1040Sstevel@tonic-gate { SF(SQ_BLOCKED), "qprocsoff in progress" },
1050Sstevel@tonic-gate { SF(SQ_FROZEN), "freezestr in progress" },
1060Sstevel@tonic-gate { SF(SQ_WRITER), "qwriter(OUTER) pending or running" },
1070Sstevel@tonic-gate { SF(SQ_MESSAGES), "There are messages on syncq" },
1080Sstevel@tonic-gate { SF(SQ_WANTWAKEUP) "Thread waiting on sq_wait" },
1090Sstevel@tonic-gate { SF(SQ_WANTEXWAKEUP), "Thread waiting on sq_exwait" },
1100Sstevel@tonic-gate { SF(SQ_EVENTS), "There are events on syncq" },
111761Smeem { 0, NULL, NULL }
1120Sstevel@tonic-gate };
1130Sstevel@tonic-gate
1140Sstevel@tonic-gate /*
1150Sstevel@tonic-gate * Syncq types
1160Sstevel@tonic-gate */
1170Sstevel@tonic-gate static const struct str_flags sqt[] = {
1180Sstevel@tonic-gate { SF(SQ_CIPUT), "Concurrent inner put procedure" },
1190Sstevel@tonic-gate { SF(SQ_CISVC), "Concurrent inner svc procedure" },
1200Sstevel@tonic-gate { SF(SQ_CIOC), "Concurrent inner open/close" },
1210Sstevel@tonic-gate { SF(SQ_CICB), "Concurrent inner callback" },
1220Sstevel@tonic-gate { SF(SQ_COPUT), "Concurrent outer put procedure" },
1230Sstevel@tonic-gate { SF(SQ_COSVC), "Concurrent outer svc procedure" },
1240Sstevel@tonic-gate { SF(SQ_COOC), "Concurrent outer open/close" },
1250Sstevel@tonic-gate { SF(SQ_COCB), "Concurrent outer callback" },
126761Smeem { 0, NULL, NULL }
1270Sstevel@tonic-gate };
1280Sstevel@tonic-gate
1290Sstevel@tonic-gate /*
1300Sstevel@tonic-gate * Stdata flags
1310Sstevel@tonic-gate */
1320Sstevel@tonic-gate static const struct str_flags stdf[] = {
1330Sstevel@tonic-gate { SF(IOCWAIT), "someone is doing an ioctl" },
1340Sstevel@tonic-gate { SF(RSLEEP), "someone wants to read/recv msg" },
1350Sstevel@tonic-gate { SF(WSLEEP), "someone wants to write" },
1360Sstevel@tonic-gate { SF(STRPRI), "an M_PCPROTO is at stream head" },
1370Sstevel@tonic-gate { SF(STRHUP), "device has vanished" },
1380Sstevel@tonic-gate { SF(STWOPEN), "waiting for 1st open" },
1390Sstevel@tonic-gate { SF(STPLEX), "stream is being multiplexed" },
1400Sstevel@tonic-gate { SF(STRISTTY), "stream is a terminal" },
1410Sstevel@tonic-gate { SF(STRGETINPROG), "(k)strgetmsg is running" },
1420Sstevel@tonic-gate { SF(IOCWAITNE), "STR_NOERROR ioctl running" },
1430Sstevel@tonic-gate { SF(STRDERR), "fatal read error from M_ERROR" },
1440Sstevel@tonic-gate { SF(STWRERR), "fatal write error from M_ERROR" },
1450Sstevel@tonic-gate { SF(STRDERRNONPERSIST), "nonpersistent read errors" },
1460Sstevel@tonic-gate { SF(STWRERRNONPERSIST), "nonpersistent write errors" },
1470Sstevel@tonic-gate { SF(STRCLOSE), "wait for a close to complete" },
1480Sstevel@tonic-gate { SF(SNDMREAD), "used for read notification" },
1490Sstevel@tonic-gate { SF(OLDNDELAY), "use old NDELAY TTY semantics" },
1500Sstevel@tonic-gate { SF(0x00020000), "unused" },
1510Sstevel@tonic-gate { SF(0x00040000), "unused" },
1520Sstevel@tonic-gate { SF(STRTOSTOP), "block background writes" },
1536583Smeem { SF(STRCMDWAIT), "someone is doing an _I_CMD" },
1540Sstevel@tonic-gate { SF(0x00200000), "unused" },
1550Sstevel@tonic-gate { SF(STRMOUNT), "stream is mounted" },
1560Sstevel@tonic-gate { SF(STRNOTATMARK), "Not at mark (when empty read q)" },
1570Sstevel@tonic-gate { SF(STRDELIM), "generate delimited messages" },
1580Sstevel@tonic-gate { SF(STRATMARK), "at mark (due to MSGMARKNEXT)" },
1590Sstevel@tonic-gate { SF(STZCNOTIFY), "wait for zerocopy mblk to be acked" },
1600Sstevel@tonic-gate { SF(STRPLUMB), "stream plumbing changes in progress" },
1610Sstevel@tonic-gate { SF(STREOF), "End-of-file indication" },
1620Sstevel@tonic-gate { SF(STREOPENFAIL), "re-open has failed" },
1630Sstevel@tonic-gate { SF(STRMATE), "this stream is a mate" },
1640Sstevel@tonic-gate { SF(STRHASLINKS), "there are I_LINKs under this stream" },
165761Smeem { 0, NULL, NULL }
1660Sstevel@tonic-gate };
1670Sstevel@tonic-gate
1680Sstevel@tonic-gate static const struct str_flags mbf[] = {
1690Sstevel@tonic-gate { SF(MSGMARK), "last byte of message is marked" },
1700Sstevel@tonic-gate { SF(MSGNOLOOP), "don't loop message to write side" },
1710Sstevel@tonic-gate { SF(MSGDELIM), "message is delimited" },
1720Sstevel@tonic-gate { SF(0x08), "unused" },
1730Sstevel@tonic-gate { SF(MSGMARKNEXT), "Private: b_next's first byte marked" },
1740Sstevel@tonic-gate { SF(MSGNOTMARKNEXT), "Private: ... not marked" },
175761Smeem { 0, NULL, NULL }
1760Sstevel@tonic-gate };
1770Sstevel@tonic-gate
1780Sstevel@tonic-gate #define M_DATA_T 0xff
1790Sstevel@tonic-gate
1800Sstevel@tonic-gate static const strtypes_t mbt[] = {
1810Sstevel@tonic-gate { "M_DATA", M_DATA_T, "regular data" },
1820Sstevel@tonic-gate { "M_PROTO", M_PROTO, "protocol control" },
1830Sstevel@tonic-gate { "M_MULTIDATA", M_MULTIDATA, "multidata" },
1840Sstevel@tonic-gate { "M_BREAK", M_BREAK, "line break" },
1850Sstevel@tonic-gate { "M_PASSFP", M_PASSFP, "pass file pointer" },
1860Sstevel@tonic-gate { "M_EVENT", M_EVENT, "Obsoleted: do not use" },
1870Sstevel@tonic-gate { "M_SIG", M_SIG, "generate process signal" },
1880Sstevel@tonic-gate { "M_DELAY", M_DELAY, "real-time xmit delay" },
1890Sstevel@tonic-gate { "M_CTL", M_CTL, "device-specific control message" },
1900Sstevel@tonic-gate { "M_IOCTL", M_IOCTL, "ioctl; set/get params" },
1910Sstevel@tonic-gate { "M_SETOPTS", M_SETOPTS, "set stream head options" },
1920Sstevel@tonic-gate { "M_RSE", M_RSE, "reserved for RSE use only" },
1930Sstevel@tonic-gate { "M_IOCACK", M_IOCACK, "acknowledge ioctl" },
1940Sstevel@tonic-gate { "M_IOCNAK", M_IOCNAK, "negative ioctl acknowledge" },
1950Sstevel@tonic-gate { "M_PCPROTO", M_PCPROTO, "priority proto message" },
1960Sstevel@tonic-gate { "M_PCSIG", M_PCSIG, "generate process signal" },
1970Sstevel@tonic-gate { "M_READ", M_READ, "generate read notification" },
1980Sstevel@tonic-gate { "M_FLUSH", M_FLUSH, "flush your queues" },
1990Sstevel@tonic-gate { "M_STOP", M_STOP, "stop transmission immediately" },
2000Sstevel@tonic-gate { "M_START", M_START, "restart transmission after stop" },
2010Sstevel@tonic-gate { "M_HANGUP", M_HANGUP, "line disconnect" },
2020Sstevel@tonic-gate { "M_ERROR", M_ERROR, "send error to stream head" },
2030Sstevel@tonic-gate { "M_COPYIN", M_COPYIN, "request to copyin data" },
2040Sstevel@tonic-gate { "M_COPYOUT", M_COPYOUT, "request to copyout data" },
2050Sstevel@tonic-gate { "M_IOCDATA", M_IOCDATA, "response to M_COPYIN and M_COPYOUT" },
2060Sstevel@tonic-gate { "M_PCRSE", M_PCRSE, "reserved for RSE use only" },
2070Sstevel@tonic-gate { "M_STOPI", M_STOPI, "stop reception immediately" },
2080Sstevel@tonic-gate { "M_STARTI", M_STARTI, "restart reception after stop" },
2090Sstevel@tonic-gate { "M_PCEVENT", M_PCEVENT, "Obsoleted: do not use" },
2100Sstevel@tonic-gate { "M_UNHANGUP", M_UNHANGUP, "line reconnect" },
2116583Smeem { "M_CMD", M_CMD, "out-of-band ioctl command" },
212761Smeem { NULL, 0, NULL }
2130Sstevel@tonic-gate };
2140Sstevel@tonic-gate
2150Sstevel@tonic-gate /* Allocation flow trace events, starting from 0 */
2160Sstevel@tonic-gate static const char *ftev_alloc[] = {
217*8752SPeter.Memishian@Sun.COM /* 0 */ "allocb",
218*8752SPeter.Memishian@Sun.COM /* 1 */ "esballoc",
219*8752SPeter.Memishian@Sun.COM /* 2 */ "desballoc",
220*8752SPeter.Memishian@Sun.COM /* 3 */ "esballoca",
221*8752SPeter.Memishian@Sun.COM /* 4 */ "desballoca",
222*8752SPeter.Memishian@Sun.COM /* 5 */ "allocbig",
223*8752SPeter.Memishian@Sun.COM /* 6 */ "allocbw",
224*8752SPeter.Memishian@Sun.COM /* 7 */ "bcallocb",
225*8752SPeter.Memishian@Sun.COM /* 8 */ "freeb",
226*8752SPeter.Memishian@Sun.COM /* 9 */ "dupb",
227*8752SPeter.Memishian@Sun.COM /* A */ "copyb",
2280Sstevel@tonic-gate };
2290Sstevel@tonic-gate
2300Sstevel@tonic-gate #define FTEV_PROC_START FTEV_PUT
2310Sstevel@tonic-gate
2320Sstevel@tonic-gate /* Procedures recorded by flow tracing, starting from 0x100 */
2330Sstevel@tonic-gate static const char *ftev_proc[] = {
234*8752SPeter.Memishian@Sun.COM /* 100 */ "put",
235*8752SPeter.Memishian@Sun.COM /* 101 */ "0x101",
236*8752SPeter.Memishian@Sun.COM /* 102 */ "0x102",
237*8752SPeter.Memishian@Sun.COM /* 103 */ "0x103",
238*8752SPeter.Memishian@Sun.COM /* 104 */ "0x104",
239*8752SPeter.Memishian@Sun.COM /* 105 */ "putq",
240*8752SPeter.Memishian@Sun.COM /* 106 */ "getq",
241*8752SPeter.Memishian@Sun.COM /* 107 */ "rmvq",
242*8752SPeter.Memishian@Sun.COM /* 108 */ "insq",
243*8752SPeter.Memishian@Sun.COM /* 109 */ "putbq",
244*8752SPeter.Memishian@Sun.COM /* 10A */ "flushq",
245*8752SPeter.Memishian@Sun.COM /* 10B */ "0x10b",
246*8752SPeter.Memishian@Sun.COM /* 10C */ "0x10c",
247*8752SPeter.Memishian@Sun.COM /* 10D */ "putnext",
248*8752SPeter.Memishian@Sun.COM /* 10E */ "rwnext",
2490Sstevel@tonic-gate };
2500Sstevel@tonic-gate
2510Sstevel@tonic-gate static const char *db_control_types[] = {
2520Sstevel@tonic-gate /* 00 */ "data",
2530Sstevel@tonic-gate /* 01 */ "proto",
2540Sstevel@tonic-gate /* 02 */ "multidata",
255*8752SPeter.Memishian@Sun.COM /* 03 */ "0x03",
256*8752SPeter.Memishian@Sun.COM /* 04 */ "0x04",
257*8752SPeter.Memishian@Sun.COM /* 05 */ "0x05",
258*8752SPeter.Memishian@Sun.COM /* 06 */ "0x06",
259*8752SPeter.Memishian@Sun.COM /* 07 */ "0x07",
2600Sstevel@tonic-gate /* 08 */ "break",
2610Sstevel@tonic-gate /* 09 */ "passfp",
2620Sstevel@tonic-gate /* 0a */ "event",
2630Sstevel@tonic-gate /* 0b */ "sig",
2640Sstevel@tonic-gate /* 0c */ "delay",
2650Sstevel@tonic-gate /* 0d */ "ctl",
2660Sstevel@tonic-gate /* 0e */ "ioctl",
2670Sstevel@tonic-gate /* 0f */ "unused",
2680Sstevel@tonic-gate /* 10 */ "setopts",
2690Sstevel@tonic-gate /* 11 */ "rse",
2700Sstevel@tonic-gate };
2710Sstevel@tonic-gate
2720Sstevel@tonic-gate static const char *db_control_hipri_types[] = {
2730Sstevel@tonic-gate /* 81 */ "iocack",
2740Sstevel@tonic-gate /* 82 */ "iocnak",
2750Sstevel@tonic-gate /* 83 */ "pcproto",
2760Sstevel@tonic-gate /* 84 */ "pcsig",
2770Sstevel@tonic-gate /* 85 */ "read",
2780Sstevel@tonic-gate /* 86 */ "flush",
2790Sstevel@tonic-gate /* 87 */ "stop",
2800Sstevel@tonic-gate /* 88 */ "start",
2810Sstevel@tonic-gate /* 89 */ "hangup",
2820Sstevel@tonic-gate /* 8a */ "error",
2830Sstevel@tonic-gate /* 8b */ "copyin",
2840Sstevel@tonic-gate /* 8c */ "copyout",
2850Sstevel@tonic-gate /* 8d */ "iocdata",
2860Sstevel@tonic-gate /* 8e */ "pcrse",
2870Sstevel@tonic-gate /* 8f */ "stopi",
2880Sstevel@tonic-gate /* 90 */ "starti",
2890Sstevel@tonic-gate /* 91 */ "pcevent",
2900Sstevel@tonic-gate /* 92 */ "unhangup",
291*8752SPeter.Memishian@Sun.COM /* 93 */ "cmd",
2920Sstevel@tonic-gate };
2930Sstevel@tonic-gate
2940Sstevel@tonic-gate #define A_SIZE(a) (sizeof (a) / sizeof (a[0]))
2950Sstevel@tonic-gate
2960Sstevel@tonic-gate static void ft_printevent(ushort_t);
2970Sstevel@tonic-gate
2980Sstevel@tonic-gate static int
streams_parse_flag(const strflags_t ftable[],const char * arg,uint32_t * flag)2990Sstevel@tonic-gate streams_parse_flag(const strflags_t ftable[], const char *arg, uint32_t *flag)
3000Sstevel@tonic-gate {
3010Sstevel@tonic-gate int i;
3020Sstevel@tonic-gate
3030Sstevel@tonic-gate for (i = 0; ftable[i].strf_name != NULL; i++) {
3040Sstevel@tonic-gate if (strcasecmp(arg, ftable[i].strf_name) == 0) {
3050Sstevel@tonic-gate *flag |= (1 << i);
3060Sstevel@tonic-gate return (0);
3070Sstevel@tonic-gate }
3080Sstevel@tonic-gate }
3090Sstevel@tonic-gate
3100Sstevel@tonic-gate return (-1);
3110Sstevel@tonic-gate }
3120Sstevel@tonic-gate
3130Sstevel@tonic-gate static void
streams_flag_usage(const strflags_t ftable[])3140Sstevel@tonic-gate streams_flag_usage(const strflags_t ftable[])
3150Sstevel@tonic-gate {
3160Sstevel@tonic-gate int i;
3170Sstevel@tonic-gate
3180Sstevel@tonic-gate for (i = 0; ftable[i].strf_name != NULL; i++)
3190Sstevel@tonic-gate mdb_printf("%-14s %s\n",
3200Sstevel@tonic-gate ftable[i].strf_name, ftable[i].strf_descr);
3210Sstevel@tonic-gate }
3220Sstevel@tonic-gate
3230Sstevel@tonic-gate static int
streams_parse_type(const strtypes_t ftable[],const char * arg,uint32_t * flag)3240Sstevel@tonic-gate streams_parse_type(const strtypes_t ftable[], const char *arg, uint32_t *flag)
3250Sstevel@tonic-gate {
3260Sstevel@tonic-gate int i;
3270Sstevel@tonic-gate
3280Sstevel@tonic-gate for (i = 0; ftable[i].strt_name != NULL; i++) {
3290Sstevel@tonic-gate if (strcasecmp(arg, ftable[i].strt_name) == 0) {
3300Sstevel@tonic-gate *flag = ftable[i].strt_value;
3310Sstevel@tonic-gate return (0);
3320Sstevel@tonic-gate }
3330Sstevel@tonic-gate }
3340Sstevel@tonic-gate
3350Sstevel@tonic-gate return (-1);
3360Sstevel@tonic-gate }
3370Sstevel@tonic-gate
3380Sstevel@tonic-gate static void
streams_type_usage(const strtypes_t ftable[])3390Sstevel@tonic-gate streams_type_usage(const strtypes_t ftable[])
3400Sstevel@tonic-gate {
3410Sstevel@tonic-gate int i;
3420Sstevel@tonic-gate
3430Sstevel@tonic-gate for (i = 0; ftable[i].strt_name != NULL; i++)
3440Sstevel@tonic-gate mdb_printf("%-12s %s\n",
3450Sstevel@tonic-gate ftable[i].strt_name, ftable[i].strt_descr);
3460Sstevel@tonic-gate }
3470Sstevel@tonic-gate
3480Sstevel@tonic-gate int
queue(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)3490Sstevel@tonic-gate queue(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
3500Sstevel@tonic-gate {
3510Sstevel@tonic-gate const int QUEUE_FLGDELT = (int)(sizeof (uintptr_t) * 2 + 15);
3520Sstevel@tonic-gate
3530Sstevel@tonic-gate char name[MODMAXNAMELEN];
3540Sstevel@tonic-gate int nblks = 0;
3550Sstevel@tonic-gate uintptr_t maddr;
3560Sstevel@tonic-gate mblk_t mblk;
3570Sstevel@tonic-gate queue_t q;
3580Sstevel@tonic-gate
3590Sstevel@tonic-gate const char *mod = NULL, *flag = NULL, *not_flag = NULL;
3600Sstevel@tonic-gate uint_t quiet = FALSE;
3610Sstevel@tonic-gate uint_t verbose = FALSE;
3620Sstevel@tonic-gate uint32_t mask = 0, not_mask = 0;
3630Sstevel@tonic-gate uintptr_t syncq = 0;
3640Sstevel@tonic-gate
3650Sstevel@tonic-gate if (!(flags & DCMD_ADDRSPEC)) {
3660Sstevel@tonic-gate if (mdb_walk_dcmd("genunix`queue_cache", "genunix`queue",
3670Sstevel@tonic-gate argc, argv) == -1) {
3680Sstevel@tonic-gate mdb_warn("failed to walk queue cache");
3690Sstevel@tonic-gate return (DCMD_ERR);
3700Sstevel@tonic-gate }
3710Sstevel@tonic-gate return (DCMD_OK);
3720Sstevel@tonic-gate }
3730Sstevel@tonic-gate
3740Sstevel@tonic-gate if (flags & DCMD_PIPE_OUT)
3750Sstevel@tonic-gate quiet = TRUE;
3760Sstevel@tonic-gate
3770Sstevel@tonic-gate if (mdb_getopts(argc, argv,
3780Sstevel@tonic-gate 'v', MDB_OPT_SETBITS, TRUE, &verbose,
3790Sstevel@tonic-gate 'q', MDB_OPT_SETBITS, TRUE, &quiet,
3800Sstevel@tonic-gate 'm', MDB_OPT_STR, &mod,
3810Sstevel@tonic-gate 'f', MDB_OPT_STR, &flag,
3820Sstevel@tonic-gate 'F', MDB_OPT_STR, ¬_flag,
3830Sstevel@tonic-gate 's', MDB_OPT_UINTPTR, &syncq,
3840Sstevel@tonic-gate NULL) != argc)
3850Sstevel@tonic-gate return (DCMD_USAGE);
3860Sstevel@tonic-gate
3870Sstevel@tonic-gate /*
3880Sstevel@tonic-gate * If any of the filtering flags is specified, don't print anything
3890Sstevel@tonic-gate * except the matching pointer.
3900Sstevel@tonic-gate */
3910Sstevel@tonic-gate if (flag != NULL || not_flag != NULL || mod != NULL || syncq != NULL)
3920Sstevel@tonic-gate quiet = TRUE;
3930Sstevel@tonic-gate
3940Sstevel@tonic-gate if (DCMD_HDRSPEC(flags) && !quiet) {
3950Sstevel@tonic-gate mdb_printf("%?s %-13s %6s %4s\n",
3960Sstevel@tonic-gate "ADDR", "MODULE", "FLAGS", "NBLK");
3970Sstevel@tonic-gate }
3980Sstevel@tonic-gate
3990Sstevel@tonic-gate if (flag != NULL && streams_parse_flag(qf, flag, &mask) == -1) {
4000Sstevel@tonic-gate mdb_warn("unrecognized queue flag '%s'\n", flag);
4010Sstevel@tonic-gate streams_flag_usage(qf);
4020Sstevel@tonic-gate return (DCMD_USAGE);
4030Sstevel@tonic-gate }
4040Sstevel@tonic-gate
4050Sstevel@tonic-gate if (not_flag != NULL &&
4060Sstevel@tonic-gate streams_parse_flag(qf, not_flag, ¬_mask) == -1) {
4070Sstevel@tonic-gate mdb_warn("unrecognized queue flag '%s'\n", flag);
4080Sstevel@tonic-gate streams_flag_usage(qf);
4090Sstevel@tonic-gate return (DCMD_USAGE);
4100Sstevel@tonic-gate }
4110Sstevel@tonic-gate
4120Sstevel@tonic-gate if (mdb_vread(&q, sizeof (q), addr) == -1) {
4130Sstevel@tonic-gate mdb_warn("couldn't read queue at %p", addr);
4140Sstevel@tonic-gate return (DCMD_ERR);
4150Sstevel@tonic-gate }
4160Sstevel@tonic-gate
4170Sstevel@tonic-gate for (maddr = (uintptr_t)q.q_first; maddr != NULL; nblks++) {
4180Sstevel@tonic-gate if (mdb_vread(&mblk, sizeof (mblk), maddr) == -1) {
4190Sstevel@tonic-gate mdb_warn("couldn't read mblk %p for queue %p",
4200Sstevel@tonic-gate maddr, addr);
4210Sstevel@tonic-gate break;
4220Sstevel@tonic-gate }
4230Sstevel@tonic-gate maddr = (uintptr_t)mblk.b_next;
4240Sstevel@tonic-gate }
4250Sstevel@tonic-gate
4260Sstevel@tonic-gate (void) mdb_qname(&q, name, sizeof (name));
4270Sstevel@tonic-gate
4280Sstevel@tonic-gate /*
4290Sstevel@tonic-gate * If queue doesn't pass filtering criteria, don't print anything and
4300Sstevel@tonic-gate * just return.
4310Sstevel@tonic-gate */
4320Sstevel@tonic-gate
4330Sstevel@tonic-gate if (mod != NULL && strcmp(mod, name) != 0)
4340Sstevel@tonic-gate return (DCMD_OK);
4350Sstevel@tonic-gate
4360Sstevel@tonic-gate if (mask != 0 && !(q.q_flag & mask))
4370Sstevel@tonic-gate return (DCMD_OK);
4380Sstevel@tonic-gate
4390Sstevel@tonic-gate if (not_mask != 0 && (q.q_flag & not_mask))
4400Sstevel@tonic-gate return (DCMD_OK);
4410Sstevel@tonic-gate
4420Sstevel@tonic-gate if (syncq != 0 && q.q_syncq != (syncq_t *)syncq)
4430Sstevel@tonic-gate return (DCMD_OK);
4440Sstevel@tonic-gate
4450Sstevel@tonic-gate /*
4460Sstevel@tonic-gate * Options are specified for filtering, so If any option is specified on
4470Sstevel@tonic-gate * the command line, just print address and exit.
4480Sstevel@tonic-gate */
4490Sstevel@tonic-gate if (quiet) {
4500Sstevel@tonic-gate mdb_printf("%0?p\n", addr);
4510Sstevel@tonic-gate return (DCMD_OK);
4520Sstevel@tonic-gate }
4530Sstevel@tonic-gate
4540Sstevel@tonic-gate mdb_printf("%0?p %-13s %06x %4d %0?p\n",
4550Sstevel@tonic-gate addr, name, q.q_flag, nblks, q.q_first);
4560Sstevel@tonic-gate
4570Sstevel@tonic-gate if (verbose) {
4580Sstevel@tonic-gate int i, arm = 0;
4590Sstevel@tonic-gate
4600Sstevel@tonic-gate for (i = 0; qf[i].strf_name != NULL; i++) {
4610Sstevel@tonic-gate if (!(q.q_flag & (1 << i)))
4620Sstevel@tonic-gate continue;
4630Sstevel@tonic-gate if (!arm) {
4640Sstevel@tonic-gate mdb_printf("%*s|\n%*s+--> ",
4650Sstevel@tonic-gate QUEUE_FLGDELT, "", QUEUE_FLGDELT, "");
4660Sstevel@tonic-gate arm = 1;
4670Sstevel@tonic-gate } else
4680Sstevel@tonic-gate mdb_printf("%*s ", QUEUE_FLGDELT, "");
4690Sstevel@tonic-gate
4700Sstevel@tonic-gate mdb_printf("%-12s %s\n",
4710Sstevel@tonic-gate qf[i].strf_name, qf[i].strf_descr);
4720Sstevel@tonic-gate }
4730Sstevel@tonic-gate }
4740Sstevel@tonic-gate
4750Sstevel@tonic-gate return (DCMD_OK);
4760Sstevel@tonic-gate }
4770Sstevel@tonic-gate
4780Sstevel@tonic-gate int
syncq(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)4790Sstevel@tonic-gate syncq(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
4800Sstevel@tonic-gate {
4810Sstevel@tonic-gate const int SYNC_FLGDELT = (int)(sizeof (uintptr_t) * 2 + 1);
4820Sstevel@tonic-gate const int SYNC_TYPDELT = (int)(sizeof (uintptr_t) * 2 + 5);
4830Sstevel@tonic-gate syncq_t sq;
4840Sstevel@tonic-gate
4850Sstevel@tonic-gate const char *flag = NULL, *not_flag = NULL;
4860Sstevel@tonic-gate const char *typ = NULL, *not_typ = NULL;
4870Sstevel@tonic-gate uint_t verbose = FALSE;
4880Sstevel@tonic-gate uint_t quiet = FALSE;
4890Sstevel@tonic-gate uint32_t mask = 0, not_mask = 0;
4900Sstevel@tonic-gate uint32_t tmask = 0, not_tmask = 0;
4910Sstevel@tonic-gate uint8_t sqtype = 0;
4920Sstevel@tonic-gate
4930Sstevel@tonic-gate if (!(flags & DCMD_ADDRSPEC)) {
4940Sstevel@tonic-gate if (mdb_walk_dcmd("genunix`syncq_cache", "genunix`syncq",
4950Sstevel@tonic-gate argc, argv) == -1) {
4960Sstevel@tonic-gate mdb_warn("failed to walk syncq cache");
4970Sstevel@tonic-gate return (DCMD_ERR);
4980Sstevel@tonic-gate }
4990Sstevel@tonic-gate return (DCMD_OK);
5000Sstevel@tonic-gate }
5010Sstevel@tonic-gate
5020Sstevel@tonic-gate if (flags & DCMD_PIPE_OUT)
5030Sstevel@tonic-gate quiet = TRUE;
5040Sstevel@tonic-gate
5050Sstevel@tonic-gate if (mdb_getopts(argc, argv,
5060Sstevel@tonic-gate 'v', MDB_OPT_SETBITS, TRUE, &verbose,
5070Sstevel@tonic-gate 'q', MDB_OPT_SETBITS, TRUE, &quiet,
5080Sstevel@tonic-gate 'f', MDB_OPT_STR, &flag,
5090Sstevel@tonic-gate 'F', MDB_OPT_STR, ¬_flag,
5100Sstevel@tonic-gate 't', MDB_OPT_STR, &typ,
5110Sstevel@tonic-gate 'T', MDB_OPT_STR, ¬_typ,
5120Sstevel@tonic-gate NULL) != argc)
5130Sstevel@tonic-gate return (DCMD_USAGE);
5140Sstevel@tonic-gate
5150Sstevel@tonic-gate /*
5160Sstevel@tonic-gate * If any of the filtering flags is specified, don't print anything
5170Sstevel@tonic-gate * except the matching pointer.
5180Sstevel@tonic-gate */
5190Sstevel@tonic-gate if (flag != NULL || not_flag != NULL || typ != NULL || not_typ != NULL)
5200Sstevel@tonic-gate quiet = TRUE;
5210Sstevel@tonic-gate
5220Sstevel@tonic-gate if (DCMD_HDRSPEC(flags) && !quiet) {
5230Sstevel@tonic-gate mdb_printf("%?s %s %s %s %s %?s %s %s\n",
5240Sstevel@tonic-gate "ADDR", "FLG", "TYP", "CNT", "NQS", "OUTER", "SF", "PRI");
5250Sstevel@tonic-gate }
5260Sstevel@tonic-gate
5270Sstevel@tonic-gate if (flag != NULL && streams_parse_flag(sqf, flag, &mask) == -1) {
5280Sstevel@tonic-gate mdb_warn("unrecognized syncq flag '%s'\n", flag);
5290Sstevel@tonic-gate streams_flag_usage(sqf);
5300Sstevel@tonic-gate return (DCMD_USAGE);
5310Sstevel@tonic-gate }
5320Sstevel@tonic-gate
5330Sstevel@tonic-gate if (typ != NULL && streams_parse_flag(sqt, typ, &tmask) == -1) {
5340Sstevel@tonic-gate mdb_warn("unrecognized syncq type '%s'\n", typ);
5350Sstevel@tonic-gate streams_flag_usage(sqt);
5360Sstevel@tonic-gate return (DCMD_USAGE);
5370Sstevel@tonic-gate }
5380Sstevel@tonic-gate
5390Sstevel@tonic-gate if (not_flag != NULL && streams_parse_flag(sqf, not_flag, ¬_mask)
5400Sstevel@tonic-gate == -1) {
5410Sstevel@tonic-gate mdb_warn("unrecognized syncq flag '%s'\n", not_flag);
5420Sstevel@tonic-gate streams_flag_usage(sqf);
5430Sstevel@tonic-gate return (DCMD_USAGE);
5440Sstevel@tonic-gate }
5450Sstevel@tonic-gate
5460Sstevel@tonic-gate if (not_typ != NULL && streams_parse_flag(sqt, not_typ, ¬_tmask)
5470Sstevel@tonic-gate == -1) {
5480Sstevel@tonic-gate mdb_warn("unrecognized syncq type '%s'\n", not_typ);
5490Sstevel@tonic-gate streams_flag_usage(sqt);
5500Sstevel@tonic-gate return (DCMD_USAGE);
5510Sstevel@tonic-gate }
5520Sstevel@tonic-gate
5530Sstevel@tonic-gate if (mdb_vread(&sq, sizeof (sq), addr) == -1) {
5540Sstevel@tonic-gate mdb_warn("couldn't read syncq at %p", addr);
5550Sstevel@tonic-gate return (DCMD_ERR);
5560Sstevel@tonic-gate }
5570Sstevel@tonic-gate
5580Sstevel@tonic-gate if (mask != 0 && !(sq.sq_flags & mask))
5590Sstevel@tonic-gate return (DCMD_OK);
5600Sstevel@tonic-gate
5610Sstevel@tonic-gate if (not_mask != 0 && (sq.sq_flags & not_mask))
5620Sstevel@tonic-gate return (DCMD_OK);
5630Sstevel@tonic-gate
5640Sstevel@tonic-gate sqtype = (sq.sq_type >> 8) & 0xff;
5650Sstevel@tonic-gate
5660Sstevel@tonic-gate if (tmask != 0 && !(sqtype & tmask))
5670Sstevel@tonic-gate return (DCMD_OK);
5680Sstevel@tonic-gate
5690Sstevel@tonic-gate if (not_tmask != 0 && (sqtype & not_tmask))
5700Sstevel@tonic-gate return (DCMD_OK);
5710Sstevel@tonic-gate
5720Sstevel@tonic-gate /*
5730Sstevel@tonic-gate * Options are specified for filtering, so If any option is specified on
5740Sstevel@tonic-gate * the command line, just print address and exit.
5750Sstevel@tonic-gate */
5760Sstevel@tonic-gate if (quiet) {
5770Sstevel@tonic-gate mdb_printf("%0?p\n", addr);
5780Sstevel@tonic-gate return (DCMD_OK);
5790Sstevel@tonic-gate }
5800Sstevel@tonic-gate
5810Sstevel@tonic-gate mdb_printf("%0?p %02x %02x %-3u %-3u %0?p %1x %-3d\n",
5820Sstevel@tonic-gate addr, sq.sq_flags & 0xff, sqtype, sq.sq_count,
5830Sstevel@tonic-gate sq.sq_nqueues, sq.sq_outer, sq.sq_svcflags, sq.sq_pri);
5840Sstevel@tonic-gate
5850Sstevel@tonic-gate if (verbose) {
5860Sstevel@tonic-gate int i, arm = 0;
5870Sstevel@tonic-gate
5880Sstevel@tonic-gate for (i = 0; sqf[i].strf_name != NULL; i++) {
5890Sstevel@tonic-gate if (!(sq.sq_flags & (1 << i)))
5900Sstevel@tonic-gate continue;
5910Sstevel@tonic-gate if (!arm) {
5920Sstevel@tonic-gate mdb_printf("%*s|\n%*s+--> ",
5930Sstevel@tonic-gate SYNC_FLGDELT, "", SYNC_FLGDELT, "");
5940Sstevel@tonic-gate arm = 1;
5950Sstevel@tonic-gate } else
5960Sstevel@tonic-gate mdb_printf("%*s ", SYNC_FLGDELT, "");
5970Sstevel@tonic-gate
5980Sstevel@tonic-gate mdb_printf("%-12s %s\n",
5990Sstevel@tonic-gate sqf[i].strf_name, sqf[i].strf_descr);
6000Sstevel@tonic-gate }
6010Sstevel@tonic-gate
6020Sstevel@tonic-gate for (i = 0; sqt[i].strf_name != NULL; i++) {
6030Sstevel@tonic-gate if (!(sqtype & (1 << i)))
6040Sstevel@tonic-gate continue;
6050Sstevel@tonic-gate if (!arm) {
6060Sstevel@tonic-gate mdb_printf("%*s|\n%*s+--> ",
6070Sstevel@tonic-gate SYNC_TYPDELT, "", SYNC_TYPDELT, "");
6080Sstevel@tonic-gate arm = 1;
6090Sstevel@tonic-gate } else
6100Sstevel@tonic-gate mdb_printf("%*s ", SYNC_TYPDELT, "");
6110Sstevel@tonic-gate
6120Sstevel@tonic-gate mdb_printf("%-12s %s\n",
6130Sstevel@tonic-gate sqt[i].strf_name, sqt[i].strf_descr);
6140Sstevel@tonic-gate }
6150Sstevel@tonic-gate }
6160Sstevel@tonic-gate
6170Sstevel@tonic-gate return (DCMD_OK);
6180Sstevel@tonic-gate }
6190Sstevel@tonic-gate
6200Sstevel@tonic-gate int
stdata(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)6210Sstevel@tonic-gate stdata(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
6220Sstevel@tonic-gate {
6230Sstevel@tonic-gate const int STREAM_FLGDELT = (int)(sizeof (uintptr_t) * 2 + 10);
6240Sstevel@tonic-gate
6250Sstevel@tonic-gate stdata_t sd;
6260Sstevel@tonic-gate
6270Sstevel@tonic-gate const char *flag = NULL, *not_flag = NULL;
6280Sstevel@tonic-gate uint_t verbose = FALSE;
6290Sstevel@tonic-gate uint_t quiet = FALSE;
6300Sstevel@tonic-gate uint32_t mask = 0, not_mask = 0;
6310Sstevel@tonic-gate
6320Sstevel@tonic-gate if (!(flags & DCMD_ADDRSPEC)) {
6330Sstevel@tonic-gate if (mdb_walk_dcmd("genunix`stream_head_cache",
6340Sstevel@tonic-gate "genunix`stdata", argc, argv) == -1) {
6350Sstevel@tonic-gate mdb_warn("failed to walk stream head cache");
6360Sstevel@tonic-gate return (DCMD_ERR);
6370Sstevel@tonic-gate }
6380Sstevel@tonic-gate return (DCMD_OK);
6390Sstevel@tonic-gate }
6400Sstevel@tonic-gate
6410Sstevel@tonic-gate if (flags & DCMD_PIPE_OUT)
6420Sstevel@tonic-gate quiet = TRUE;
6430Sstevel@tonic-gate
6440Sstevel@tonic-gate if (mdb_getopts(argc, argv,
6450Sstevel@tonic-gate 'v', MDB_OPT_SETBITS, TRUE, &verbose,
6460Sstevel@tonic-gate 'q', MDB_OPT_SETBITS, TRUE, &quiet,
6470Sstevel@tonic-gate 'f', MDB_OPT_STR, &flag,
6480Sstevel@tonic-gate 'F', MDB_OPT_STR, ¬_flag,
6490Sstevel@tonic-gate NULL) != argc)
6500Sstevel@tonic-gate return (DCMD_USAGE);
6510Sstevel@tonic-gate
6520Sstevel@tonic-gate /*
6530Sstevel@tonic-gate * If any of the filtering flags is specified, don't print anything
6540Sstevel@tonic-gate * except the matching pointer.
6550Sstevel@tonic-gate */
6560Sstevel@tonic-gate if (flag != NULL || not_flag != NULL)
6570Sstevel@tonic-gate quiet = TRUE;
6580Sstevel@tonic-gate
6590Sstevel@tonic-gate if (DCMD_HDRSPEC(flags) && !quiet) {
6600Sstevel@tonic-gate mdb_printf("%?s %?s %8s %?s %s %s\n",
6610Sstevel@tonic-gate "ADDR", "WRQ", "FLAGS", "VNODE", "N/A", "REF");
6620Sstevel@tonic-gate }
6630Sstevel@tonic-gate
6640Sstevel@tonic-gate if (flag != NULL && streams_parse_flag(stdf, flag, &mask) == -1) {
6650Sstevel@tonic-gate mdb_warn("unrecognized stream flag '%s'\n", flag);
6660Sstevel@tonic-gate streams_flag_usage(stdf);
6670Sstevel@tonic-gate return (DCMD_USAGE);
6680Sstevel@tonic-gate }
6690Sstevel@tonic-gate
6700Sstevel@tonic-gate if (not_flag != NULL &&
6710Sstevel@tonic-gate streams_parse_flag(stdf, not_flag, ¬_mask) == -1) {
6720Sstevel@tonic-gate mdb_warn("unrecognized stream flag '%s'\n", flag);
6730Sstevel@tonic-gate streams_flag_usage(stdf);
6740Sstevel@tonic-gate return (DCMD_USAGE);
6750Sstevel@tonic-gate }
6760Sstevel@tonic-gate
6770Sstevel@tonic-gate if (mdb_vread(&sd, sizeof (sd), addr) == -1) {
6780Sstevel@tonic-gate mdb_warn("couldn't read stdata at %p", addr);
6790Sstevel@tonic-gate return (DCMD_ERR);
6800Sstevel@tonic-gate }
6810Sstevel@tonic-gate
6820Sstevel@tonic-gate /*
6830Sstevel@tonic-gate * If stream doesn't pass filtering criteria, don't print anything and
6840Sstevel@tonic-gate * just return.
6850Sstevel@tonic-gate */
6860Sstevel@tonic-gate
6870Sstevel@tonic-gate if (mask != 0 && !(sd.sd_flag & mask))
6880Sstevel@tonic-gate return (DCMD_OK);
6890Sstevel@tonic-gate
6900Sstevel@tonic-gate if (not_mask != 0 && (sd.sd_flag & not_mask))
6910Sstevel@tonic-gate return (DCMD_OK);
6920Sstevel@tonic-gate
6930Sstevel@tonic-gate /*
6940Sstevel@tonic-gate * Options are specified for filtering, so If any option is specified on
6950Sstevel@tonic-gate * the command line, just print address and exit.
6960Sstevel@tonic-gate */
6970Sstevel@tonic-gate if (quiet) {
6980Sstevel@tonic-gate mdb_printf("%0?p\n", addr);
6990Sstevel@tonic-gate return (DCMD_OK);
7000Sstevel@tonic-gate }
7010Sstevel@tonic-gate
7020Sstevel@tonic-gate mdb_printf("%0?p %0?p %08x %0?p %d/%d %d\n",
7030Sstevel@tonic-gate addr, sd.sd_wrq, sd.sd_flag, sd.sd_vnode,
7040Sstevel@tonic-gate sd.sd_pushcnt, sd.sd_anchor, sd.sd_refcnt);
7050Sstevel@tonic-gate
7060Sstevel@tonic-gate if (verbose) {
7070Sstevel@tonic-gate int i, arm = 0;
7080Sstevel@tonic-gate
7090Sstevel@tonic-gate for (i = 0; stdf[i].strf_name != NULL; i++) {
7100Sstevel@tonic-gate if (!(sd.sd_flag & (1 << i)))
7110Sstevel@tonic-gate continue;
7120Sstevel@tonic-gate if (!arm) {
7130Sstevel@tonic-gate mdb_printf("%*s|\n%*s+--> ",
7140Sstevel@tonic-gate STREAM_FLGDELT, "", STREAM_FLGDELT, "");
7150Sstevel@tonic-gate arm = 1;
7160Sstevel@tonic-gate } else
7170Sstevel@tonic-gate mdb_printf("%*s ", STREAM_FLGDELT, "");
7180Sstevel@tonic-gate
7190Sstevel@tonic-gate mdb_printf("%-12s %s\n",
7200Sstevel@tonic-gate stdf[i].strf_name, stdf[i].strf_descr);
7210Sstevel@tonic-gate }
7220Sstevel@tonic-gate }
7230Sstevel@tonic-gate
7240Sstevel@tonic-gate return (DCMD_OK);
7250Sstevel@tonic-gate }
7260Sstevel@tonic-gate
7270Sstevel@tonic-gate /*ARGSUSED*/
7280Sstevel@tonic-gate static void
qprint_syncq(queue_t * addr,queue_t * q)7290Sstevel@tonic-gate qprint_syncq(queue_t *addr, queue_t *q)
7300Sstevel@tonic-gate {
7310Sstevel@tonic-gate mdb_printf("%p\n", q->q_syncq);
7320Sstevel@tonic-gate }
7330Sstevel@tonic-gate
7340Sstevel@tonic-gate /*ARGSUSED*/
7350Sstevel@tonic-gate static void
qprint_stream(queue_t * addr,queue_t * q)7360Sstevel@tonic-gate qprint_stream(queue_t *addr, queue_t *q)
7370Sstevel@tonic-gate {
7380Sstevel@tonic-gate mdb_printf("%p\n", q->q_stream);
7390Sstevel@tonic-gate }
7400Sstevel@tonic-gate
7410Sstevel@tonic-gate static void
qprint_wrq(queue_t * addr,queue_t * q)7420Sstevel@tonic-gate qprint_wrq(queue_t *addr, queue_t *q)
7430Sstevel@tonic-gate {
7440Sstevel@tonic-gate mdb_printf("%p\n", ((q)->q_flag & QREADR? (addr)+1: (addr)));
7450Sstevel@tonic-gate }
7460Sstevel@tonic-gate
7470Sstevel@tonic-gate static void
qprint_rdq(queue_t * addr,queue_t * q)7480Sstevel@tonic-gate qprint_rdq(queue_t *addr, queue_t *q)
7490Sstevel@tonic-gate {
7500Sstevel@tonic-gate mdb_printf("%p\n", ((q)->q_flag & QREADR? (addr): (addr)-1));
7510Sstevel@tonic-gate }
7520Sstevel@tonic-gate
7530Sstevel@tonic-gate static void
qprint_otherq(queue_t * addr,queue_t * q)7540Sstevel@tonic-gate qprint_otherq(queue_t *addr, queue_t *q)
7550Sstevel@tonic-gate {
7560Sstevel@tonic-gate mdb_printf("%p\n", ((q)->q_flag & QREADR? (addr)+1: (addr)-1));
7570Sstevel@tonic-gate }
7580Sstevel@tonic-gate
7590Sstevel@tonic-gate static int
q2x(uintptr_t addr,int argc,qprint_func prfunc)7600Sstevel@tonic-gate q2x(uintptr_t addr, int argc, qprint_func prfunc)
7610Sstevel@tonic-gate {
7620Sstevel@tonic-gate queue_t q;
7630Sstevel@tonic-gate
7640Sstevel@tonic-gate if (argc != 0)
7650Sstevel@tonic-gate return (DCMD_USAGE);
7660Sstevel@tonic-gate
7670Sstevel@tonic-gate if (mdb_vread(&q, sizeof (q), addr) == -1) {
7680Sstevel@tonic-gate mdb_warn("couldn't read queue at %p", addr);
7690Sstevel@tonic-gate return (DCMD_ERR);
7700Sstevel@tonic-gate }
7710Sstevel@tonic-gate
7720Sstevel@tonic-gate prfunc((queue_t *)addr, &q);
7730Sstevel@tonic-gate
7740Sstevel@tonic-gate return (DCMD_OK);
7750Sstevel@tonic-gate }
7760Sstevel@tonic-gate
7770Sstevel@tonic-gate /*ARGSUSED*/
7780Sstevel@tonic-gate int
q2syncq(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)7790Sstevel@tonic-gate q2syncq(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
7800Sstevel@tonic-gate {
7810Sstevel@tonic-gate return (q2x(addr, argc, qprint_syncq));
7820Sstevel@tonic-gate }
7830Sstevel@tonic-gate
7840Sstevel@tonic-gate /*ARGSUSED*/
7850Sstevel@tonic-gate int
q2stream(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)7860Sstevel@tonic-gate q2stream(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
7870Sstevel@tonic-gate {
7880Sstevel@tonic-gate return (q2x(addr, argc, qprint_stream));
7890Sstevel@tonic-gate }
7900Sstevel@tonic-gate
7910Sstevel@tonic-gate /*ARGSUSED*/
7920Sstevel@tonic-gate int
q2rdq(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)7930Sstevel@tonic-gate q2rdq(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
7940Sstevel@tonic-gate {
7950Sstevel@tonic-gate return (q2x(addr, argc, qprint_rdq));
7960Sstevel@tonic-gate }
7970Sstevel@tonic-gate
7980Sstevel@tonic-gate /*ARGSUSED*/
7990Sstevel@tonic-gate int
q2wrq(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)8000Sstevel@tonic-gate q2wrq(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
8010Sstevel@tonic-gate {
8020Sstevel@tonic-gate return (q2x(addr, argc, qprint_wrq));
8030Sstevel@tonic-gate }
8040Sstevel@tonic-gate
8050Sstevel@tonic-gate /*ARGSUSED*/
8060Sstevel@tonic-gate int
q2otherq(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)8070Sstevel@tonic-gate q2otherq(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
8080Sstevel@tonic-gate {
8090Sstevel@tonic-gate return (q2x(addr, argc, qprint_otherq));
8100Sstevel@tonic-gate }
8110Sstevel@tonic-gate
8120Sstevel@tonic-gate static int
sd2x(uintptr_t addr,int argc,sdprint_func prfunc)8130Sstevel@tonic-gate sd2x(uintptr_t addr, int argc, sdprint_func prfunc)
8140Sstevel@tonic-gate {
8150Sstevel@tonic-gate stdata_t sd;
8160Sstevel@tonic-gate
8170Sstevel@tonic-gate if (argc != 0)
8180Sstevel@tonic-gate return (DCMD_USAGE);
8190Sstevel@tonic-gate
8200Sstevel@tonic-gate if (mdb_vread(&sd, sizeof (sd), addr) == -1) {
8210Sstevel@tonic-gate mdb_warn("couldn't read stream head at %p", addr);
8220Sstevel@tonic-gate return (DCMD_ERR);
8230Sstevel@tonic-gate }
8240Sstevel@tonic-gate
8250Sstevel@tonic-gate prfunc((stdata_t *)addr, &sd);
8260Sstevel@tonic-gate
8270Sstevel@tonic-gate return (DCMD_OK);
8280Sstevel@tonic-gate }
8290Sstevel@tonic-gate
8300Sstevel@tonic-gate /*ARGSUSED*/
8310Sstevel@tonic-gate static void
sdprint_wrq(stdata_t * addr,stdata_t * sd)8320Sstevel@tonic-gate sdprint_wrq(stdata_t *addr, stdata_t *sd)
8330Sstevel@tonic-gate {
8340Sstevel@tonic-gate mdb_printf("%p\n", sd->sd_wrq);
8350Sstevel@tonic-gate }
8360Sstevel@tonic-gate
8370Sstevel@tonic-gate static void
sdprint_mate(stdata_t * addr,stdata_t * sd)8380Sstevel@tonic-gate sdprint_mate(stdata_t *addr, stdata_t *sd)
8390Sstevel@tonic-gate {
8400Sstevel@tonic-gate mdb_printf("%p\n", sd->sd_mate ? sd->sd_mate : addr);
8410Sstevel@tonic-gate }
8420Sstevel@tonic-gate
8430Sstevel@tonic-gate /*ARGSUSED*/
8440Sstevel@tonic-gate int
str2mate(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)8450Sstevel@tonic-gate str2mate(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
8460Sstevel@tonic-gate {
8470Sstevel@tonic-gate return (sd2x(addr, argc, sdprint_mate));
8480Sstevel@tonic-gate }
8490Sstevel@tonic-gate
8500Sstevel@tonic-gate /*ARGSUSED*/
8510Sstevel@tonic-gate int
str2wrq(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)8520Sstevel@tonic-gate str2wrq(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
8530Sstevel@tonic-gate {
8540Sstevel@tonic-gate return (sd2x(addr, argc, sdprint_wrq));
8550Sstevel@tonic-gate }
8560Sstevel@tonic-gate
8570Sstevel@tonic-gate /*
8580Sstevel@tonic-gate * If this syncq is a part of the queue pair structure, find the queue for it.
8590Sstevel@tonic-gate */
8600Sstevel@tonic-gate /*ARGSUSED*/
8610Sstevel@tonic-gate int
syncq2q(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)8620Sstevel@tonic-gate syncq2q(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
8630Sstevel@tonic-gate {
8640Sstevel@tonic-gate syncq_t sq;
8650Sstevel@tonic-gate queue_t q;
8660Sstevel@tonic-gate queue_t *qp;
8670Sstevel@tonic-gate
8680Sstevel@tonic-gate if (argc != 0)
8690Sstevel@tonic-gate return (DCMD_USAGE);
8700Sstevel@tonic-gate
8710Sstevel@tonic-gate if (mdb_vread(&sq, sizeof (sq), addr) == -1) {
8720Sstevel@tonic-gate mdb_warn("couldn't read syncq at %p", addr);
8730Sstevel@tonic-gate return (DCMD_ERR);
8740Sstevel@tonic-gate }
8750Sstevel@tonic-gate
8760Sstevel@tonic-gate /* Try to find its queue */
8770Sstevel@tonic-gate qp = (queue_t *)addr - 2;
8780Sstevel@tonic-gate
8790Sstevel@tonic-gate if ((mdb_vread(&q, sizeof (q), (uintptr_t)qp) == -1) ||
8800Sstevel@tonic-gate (q.q_syncq != (syncq_t *)addr)) {
8810Sstevel@tonic-gate mdb_warn("syncq2q: %p is not part of any queue\n", addr);
8820Sstevel@tonic-gate return (DCMD_ERR);
8830Sstevel@tonic-gate } else
8840Sstevel@tonic-gate mdb_printf("%p\n", qp);
8850Sstevel@tonic-gate
8860Sstevel@tonic-gate return (DCMD_OK);
8870Sstevel@tonic-gate }
8880Sstevel@tonic-gate
8890Sstevel@tonic-gate int
queue_walk_init(mdb_walk_state_t * wsp)8900Sstevel@tonic-gate queue_walk_init(mdb_walk_state_t *wsp)
8910Sstevel@tonic-gate {
8920Sstevel@tonic-gate if (wsp->walk_addr == NULL &&
8930Sstevel@tonic-gate mdb_readvar(&wsp->walk_addr, "qhead") == -1) {
8940Sstevel@tonic-gate mdb_warn("failed to read 'qhead'");
8950Sstevel@tonic-gate return (WALK_ERR);
8960Sstevel@tonic-gate }
8970Sstevel@tonic-gate
8980Sstevel@tonic-gate wsp->walk_data = mdb_alloc(sizeof (queue_t), UM_SLEEP);
8990Sstevel@tonic-gate return (WALK_NEXT);
9000Sstevel@tonic-gate }
9010Sstevel@tonic-gate
9020Sstevel@tonic-gate int
queue_link_step(mdb_walk_state_t * wsp)9030Sstevel@tonic-gate queue_link_step(mdb_walk_state_t *wsp)
9040Sstevel@tonic-gate {
9050Sstevel@tonic-gate int status;
9060Sstevel@tonic-gate
9070Sstevel@tonic-gate if (wsp->walk_addr == NULL)
9080Sstevel@tonic-gate return (WALK_DONE);
9090Sstevel@tonic-gate
9100Sstevel@tonic-gate if (mdb_vread(wsp->walk_data, sizeof (queue_t), wsp->walk_addr) == -1) {
9110Sstevel@tonic-gate mdb_warn("failed to read queue at %p", wsp->walk_addr);
9120Sstevel@tonic-gate return (WALK_DONE);
9130Sstevel@tonic-gate }
9140Sstevel@tonic-gate
9150Sstevel@tonic-gate status = wsp->walk_callback(wsp->walk_addr, wsp->walk_data,
9160Sstevel@tonic-gate wsp->walk_cbdata);
9170Sstevel@tonic-gate
9180Sstevel@tonic-gate wsp->walk_addr = (uintptr_t)(((queue_t *)wsp->walk_data)->q_link);
9190Sstevel@tonic-gate return (status);
9200Sstevel@tonic-gate }
9210Sstevel@tonic-gate
9220Sstevel@tonic-gate int
queue_next_step(mdb_walk_state_t * wsp)9230Sstevel@tonic-gate queue_next_step(mdb_walk_state_t *wsp)
9240Sstevel@tonic-gate {
9250Sstevel@tonic-gate int status;
9260Sstevel@tonic-gate
9270Sstevel@tonic-gate if (wsp->walk_addr == NULL)
9280Sstevel@tonic-gate return (WALK_DONE);
9290Sstevel@tonic-gate
9300Sstevel@tonic-gate if (mdb_vread(wsp->walk_data, sizeof (queue_t), wsp->walk_addr) == -1) {
9310Sstevel@tonic-gate mdb_warn("failed to read queue at %p", wsp->walk_addr);
9320Sstevel@tonic-gate return (WALK_DONE);
9330Sstevel@tonic-gate }
9340Sstevel@tonic-gate
9350Sstevel@tonic-gate status = wsp->walk_callback(wsp->walk_addr, wsp->walk_data,
9360Sstevel@tonic-gate wsp->walk_cbdata);
9370Sstevel@tonic-gate
9380Sstevel@tonic-gate wsp->walk_addr = (uintptr_t)(((queue_t *)wsp->walk_data)->q_next);
9390Sstevel@tonic-gate return (status);
9400Sstevel@tonic-gate }
9410Sstevel@tonic-gate
9420Sstevel@tonic-gate void
queue_walk_fini(mdb_walk_state_t * wsp)9430Sstevel@tonic-gate queue_walk_fini(mdb_walk_state_t *wsp)
9440Sstevel@tonic-gate {
9450Sstevel@tonic-gate mdb_free(wsp->walk_data, sizeof (queue_t));
9460Sstevel@tonic-gate }
9470Sstevel@tonic-gate
9480Sstevel@tonic-gate int
str_walk_init(mdb_walk_state_t * wsp)9490Sstevel@tonic-gate str_walk_init(mdb_walk_state_t *wsp)
9500Sstevel@tonic-gate {
9510Sstevel@tonic-gate stdata_t s;
9520Sstevel@tonic-gate
9530Sstevel@tonic-gate if (wsp->walk_addr == NULL) {
9540Sstevel@tonic-gate mdb_warn("walk must begin at address of stdata_t\n");
9550Sstevel@tonic-gate return (WALK_ERR);
9560Sstevel@tonic-gate }
9570Sstevel@tonic-gate
9580Sstevel@tonic-gate if (mdb_vread(&s, sizeof (s), wsp->walk_addr) == -1) {
9590Sstevel@tonic-gate mdb_warn("failed to read stdata at %p", wsp->walk_addr);
9600Sstevel@tonic-gate return (WALK_ERR);
9610Sstevel@tonic-gate }
9620Sstevel@tonic-gate
9630Sstevel@tonic-gate wsp->walk_addr = (uintptr_t)s.sd_wrq;
9640Sstevel@tonic-gate wsp->walk_data = mdb_alloc(sizeof (queue_t) * 2, UM_SLEEP);
9650Sstevel@tonic-gate
9660Sstevel@tonic-gate return (WALK_NEXT);
9670Sstevel@tonic-gate }
9680Sstevel@tonic-gate
9690Sstevel@tonic-gate int
strr_walk_step(mdb_walk_state_t * wsp)9700Sstevel@tonic-gate strr_walk_step(mdb_walk_state_t *wsp)
9710Sstevel@tonic-gate {
9720Sstevel@tonic-gate queue_t *rq = wsp->walk_data, *wq = rq + 1;
9730Sstevel@tonic-gate int status;
9740Sstevel@tonic-gate
9750Sstevel@tonic-gate if (wsp->walk_addr == NULL)
9760Sstevel@tonic-gate return (WALK_DONE);
9770Sstevel@tonic-gate
9780Sstevel@tonic-gate if (mdb_vread(wsp->walk_data, sizeof (queue_t) * 2,
9790Sstevel@tonic-gate wsp->walk_addr - sizeof (queue_t)) == -1) {
9800Sstevel@tonic-gate mdb_warn("failed to read queue pair at %p",
9810Sstevel@tonic-gate wsp->walk_addr - sizeof (queue_t));
9820Sstevel@tonic-gate return (WALK_DONE);
9830Sstevel@tonic-gate }
9840Sstevel@tonic-gate
9850Sstevel@tonic-gate status = wsp->walk_callback(wsp->walk_addr - sizeof (queue_t),
9860Sstevel@tonic-gate rq, wsp->walk_cbdata);
9870Sstevel@tonic-gate
9880Sstevel@tonic-gate if (wq->q_next != NULL)
9890Sstevel@tonic-gate wsp->walk_addr = (uintptr_t)wq->q_next;
9900Sstevel@tonic-gate else
9910Sstevel@tonic-gate wsp->walk_addr = mdb_qwnext(wq);
9920Sstevel@tonic-gate
9930Sstevel@tonic-gate return (status);
9940Sstevel@tonic-gate }
9950Sstevel@tonic-gate
9960Sstevel@tonic-gate int
strw_walk_step(mdb_walk_state_t * wsp)9970Sstevel@tonic-gate strw_walk_step(mdb_walk_state_t *wsp)
9980Sstevel@tonic-gate {
9990Sstevel@tonic-gate queue_t *rq = wsp->walk_data, *wq = rq + 1;
10000Sstevel@tonic-gate int status;
10010Sstevel@tonic-gate
10020Sstevel@tonic-gate if (wsp->walk_addr == NULL)
10030Sstevel@tonic-gate return (WALK_DONE);
10040Sstevel@tonic-gate
10050Sstevel@tonic-gate if (mdb_vread(wsp->walk_data, sizeof (queue_t) * 2,
10060Sstevel@tonic-gate wsp->walk_addr - sizeof (queue_t)) == -1) {
10070Sstevel@tonic-gate mdb_warn("failed to read queue pair at %p",
10080Sstevel@tonic-gate wsp->walk_addr - sizeof (queue_t));
10090Sstevel@tonic-gate return (WALK_DONE);
10100Sstevel@tonic-gate }
10110Sstevel@tonic-gate
10120Sstevel@tonic-gate status = wsp->walk_callback(wsp->walk_addr, wq, wsp->walk_cbdata);
10130Sstevel@tonic-gate
10140Sstevel@tonic-gate if (wq->q_next != NULL)
10150Sstevel@tonic-gate wsp->walk_addr = (uintptr_t)wq->q_next;
10160Sstevel@tonic-gate else
10170Sstevel@tonic-gate wsp->walk_addr = mdb_qwnext(wq);
10180Sstevel@tonic-gate
10190Sstevel@tonic-gate return (status);
10200Sstevel@tonic-gate }
10210Sstevel@tonic-gate
10220Sstevel@tonic-gate void
str_walk_fini(mdb_walk_state_t * wsp)10230Sstevel@tonic-gate str_walk_fini(mdb_walk_state_t *wsp)
10240Sstevel@tonic-gate {
10250Sstevel@tonic-gate mdb_free(wsp->walk_data, sizeof (queue_t) * 2);
10260Sstevel@tonic-gate }
10270Sstevel@tonic-gate
10280Sstevel@tonic-gate static int
print_qpair(uintptr_t addr,const queue_t * q,uint_t * depth)10290Sstevel@tonic-gate print_qpair(uintptr_t addr, const queue_t *q, uint_t *depth)
10300Sstevel@tonic-gate {
10310Sstevel@tonic-gate static const char box_lid[] =
10320Sstevel@tonic-gate "+-----------------------+-----------------------+\n";
10330Sstevel@tonic-gate static const char box_sep[] =
10340Sstevel@tonic-gate "| | |\n";
10350Sstevel@tonic-gate
10360Sstevel@tonic-gate char wname[32], rname[32], info1[256], *info2;
10370Sstevel@tonic-gate
10380Sstevel@tonic-gate if (*depth != 0) {
10390Sstevel@tonic-gate mdb_printf(" | ^\n");
10400Sstevel@tonic-gate mdb_printf(" v |\n");
10410Sstevel@tonic-gate } else
10420Sstevel@tonic-gate mdb_printf("\n");
10430Sstevel@tonic-gate
10440Sstevel@tonic-gate (void) mdb_qname(_WR(q), wname, sizeof (wname));
10450Sstevel@tonic-gate (void) mdb_qname(_RD(q), rname, sizeof (rname));
10460Sstevel@tonic-gate
10470Sstevel@tonic-gate mdb_qinfo(_WR(q), info1, sizeof (info1));
10480Sstevel@tonic-gate if ((info2 = strchr(info1, '\n')) != NULL)
10490Sstevel@tonic-gate *info2++ = '\0';
10500Sstevel@tonic-gate else
10510Sstevel@tonic-gate info2 = "";
10520Sstevel@tonic-gate
10530Sstevel@tonic-gate mdb_printf(box_lid);
10540Sstevel@tonic-gate mdb_printf("| 0x%-19p | 0x%-19p | %s\n",
10550Sstevel@tonic-gate addr, addr - sizeof (queue_t), info1);
10560Sstevel@tonic-gate
10570Sstevel@tonic-gate mdb_printf("| %<b>%-21s%</b> | %<b>%-21s%</b> |", wname, rname);
10580Sstevel@tonic-gate mdb_flush(); /* Account for buffered terminal sequences */
10590Sstevel@tonic-gate
10600Sstevel@tonic-gate mdb_printf(" %s\n", info2);
10610Sstevel@tonic-gate mdb_printf(box_sep);
10620Sstevel@tonic-gate
10630Sstevel@tonic-gate mdb_qinfo(_RD(q), info1, sizeof (info1));
10640Sstevel@tonic-gate if ((info2 = strchr(info1, '\n')) != NULL)
10650Sstevel@tonic-gate *info2++ = '\0';
10660Sstevel@tonic-gate else
10670Sstevel@tonic-gate info2 = "";
10680Sstevel@tonic-gate
10690Sstevel@tonic-gate mdb_printf("| cnt = 0t%-13lu | cnt = 0t%-13lu | %s\n",
10700Sstevel@tonic-gate _WR(q)->q_count, _RD(q)->q_count, info1);
10710Sstevel@tonic-gate
10720Sstevel@tonic-gate mdb_printf("| flg = 0x%08x | flg = 0x%08x | %s\n",
10730Sstevel@tonic-gate _WR(q)->q_flag, _RD(q)->q_flag, info2);
10740Sstevel@tonic-gate
10750Sstevel@tonic-gate mdb_printf(box_lid);
10760Sstevel@tonic-gate *depth += 1;
10770Sstevel@tonic-gate return (0);
10780Sstevel@tonic-gate }
10790Sstevel@tonic-gate
10800Sstevel@tonic-gate /*ARGSUSED*/
10810Sstevel@tonic-gate int
stream(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)10820Sstevel@tonic-gate stream(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
10830Sstevel@tonic-gate {
10840Sstevel@tonic-gate uint_t d = 0; /* Depth counter for print_qpair */
10850Sstevel@tonic-gate
10860Sstevel@tonic-gate if (argc != 0 || !(flags & DCMD_ADDRSPEC))
10870Sstevel@tonic-gate return (DCMD_USAGE);
10880Sstevel@tonic-gate
10890Sstevel@tonic-gate if (mdb_pwalk("writeq", (mdb_walk_cb_t)print_qpair, &d, addr) == -1) {
10900Sstevel@tonic-gate mdb_warn("failed to walk writeq");
10910Sstevel@tonic-gate return (DCMD_ERR);
10920Sstevel@tonic-gate }
10930Sstevel@tonic-gate
10940Sstevel@tonic-gate return (DCMD_OK);
10950Sstevel@tonic-gate }
10960Sstevel@tonic-gate
10970Sstevel@tonic-gate int
mblk_walk_init(mdb_walk_state_t * wsp)10980Sstevel@tonic-gate mblk_walk_init(mdb_walk_state_t *wsp)
10990Sstevel@tonic-gate {
11000Sstevel@tonic-gate wsp->walk_data = mdb_alloc(sizeof (mblk_t), UM_SLEEP);
11010Sstevel@tonic-gate return (WALK_NEXT);
11020Sstevel@tonic-gate }
11030Sstevel@tonic-gate
11040Sstevel@tonic-gate int
b_cont_step(mdb_walk_state_t * wsp)11050Sstevel@tonic-gate b_cont_step(mdb_walk_state_t *wsp)
11060Sstevel@tonic-gate {
11070Sstevel@tonic-gate int status;
11080Sstevel@tonic-gate
11090Sstevel@tonic-gate if (wsp->walk_addr == NULL)
11100Sstevel@tonic-gate return (WALK_DONE);
11110Sstevel@tonic-gate
11120Sstevel@tonic-gate if (mdb_vread(wsp->walk_data, sizeof (mblk_t), wsp->walk_addr) == -1) {
11130Sstevel@tonic-gate mdb_warn("failed to read mblk at %p", wsp->walk_addr);
11140Sstevel@tonic-gate return (WALK_DONE);
11150Sstevel@tonic-gate }
11160Sstevel@tonic-gate
11170Sstevel@tonic-gate status = wsp->walk_callback(wsp->walk_addr, wsp->walk_data,
11180Sstevel@tonic-gate wsp->walk_cbdata);
11190Sstevel@tonic-gate
11200Sstevel@tonic-gate wsp->walk_addr = (uintptr_t)(((mblk_t *)wsp->walk_data)->b_cont);
11210Sstevel@tonic-gate return (status);
11220Sstevel@tonic-gate }
11230Sstevel@tonic-gate
11240Sstevel@tonic-gate int
b_next_step(mdb_walk_state_t * wsp)11250Sstevel@tonic-gate b_next_step(mdb_walk_state_t *wsp)
11260Sstevel@tonic-gate {
11270Sstevel@tonic-gate int status;
11280Sstevel@tonic-gate
11290Sstevel@tonic-gate if (wsp->walk_addr == NULL)
11300Sstevel@tonic-gate return (WALK_DONE);
11310Sstevel@tonic-gate
11320Sstevel@tonic-gate if (mdb_vread(wsp->walk_data, sizeof (mblk_t), wsp->walk_addr) == -1) {
11330Sstevel@tonic-gate mdb_warn("failed to read mblk at %p", wsp->walk_addr);
11340Sstevel@tonic-gate return (WALK_DONE);
11350Sstevel@tonic-gate }
11360Sstevel@tonic-gate
11370Sstevel@tonic-gate status = wsp->walk_callback(wsp->walk_addr, wsp->walk_data,
11380Sstevel@tonic-gate wsp->walk_cbdata);
11390Sstevel@tonic-gate
11400Sstevel@tonic-gate wsp->walk_addr = (uintptr_t)(((mblk_t *)wsp->walk_data)->b_next);
11410Sstevel@tonic-gate return (status);
11420Sstevel@tonic-gate }
11430Sstevel@tonic-gate
11440Sstevel@tonic-gate void
mblk_walk_fini(mdb_walk_state_t * wsp)11450Sstevel@tonic-gate mblk_walk_fini(mdb_walk_state_t *wsp)
11460Sstevel@tonic-gate {
11470Sstevel@tonic-gate mdb_free(wsp->walk_data, sizeof (mblk_t));
11480Sstevel@tonic-gate }
11490Sstevel@tonic-gate
11500Sstevel@tonic-gate /* ARGSUSED */
11510Sstevel@tonic-gate int
mblk2dblk(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)11520Sstevel@tonic-gate mblk2dblk(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
11530Sstevel@tonic-gate {
11540Sstevel@tonic-gate mblk_t mb;
11550Sstevel@tonic-gate
11560Sstevel@tonic-gate if (argc != 0)
11570Sstevel@tonic-gate return (DCMD_USAGE);
11580Sstevel@tonic-gate
11590Sstevel@tonic-gate if (mdb_vread(&mb, sizeof (mb), addr) == -1) {
11600Sstevel@tonic-gate mdb_warn("couldn't read mblk at %p", addr);
11610Sstevel@tonic-gate return (DCMD_ERR);
11620Sstevel@tonic-gate }
11630Sstevel@tonic-gate
11640Sstevel@tonic-gate mdb_printf("%p\n", mb.b_datap);
11650Sstevel@tonic-gate return (DCMD_OK);
11660Sstevel@tonic-gate }
11670Sstevel@tonic-gate
11680Sstevel@tonic-gate static void
mblk_error(int * error,uintptr_t addr,char * message)11690Sstevel@tonic-gate mblk_error(int *error, uintptr_t addr, char *message)
11700Sstevel@tonic-gate {
11710Sstevel@tonic-gate if (!*error)
11720Sstevel@tonic-gate mdb_printf("%?lx: ", addr);
11730Sstevel@tonic-gate else
11740Sstevel@tonic-gate mdb_printf(", ");
11750Sstevel@tonic-gate mdb_printf("%s", message);
11760Sstevel@tonic-gate *error = 1;
11770Sstevel@tonic-gate }
11780Sstevel@tonic-gate
11790Sstevel@tonic-gate int
mblk_verify(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)11800Sstevel@tonic-gate mblk_verify(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
11810Sstevel@tonic-gate {
11820Sstevel@tonic-gate mblk_t mb;
11830Sstevel@tonic-gate dblk_t db;
11840Sstevel@tonic-gate int error = 0;
11850Sstevel@tonic-gate
11860Sstevel@tonic-gate if (!(flags & DCMD_ADDRSPEC)) {
11870Sstevel@tonic-gate if (mdb_walk_dcmd("streams_mblk", "mblk_verify", argc, argv) ==
11880Sstevel@tonic-gate -1) {
11890Sstevel@tonic-gate mdb_warn("can't walk mblk cache");
11900Sstevel@tonic-gate return (DCMD_ERR);
11910Sstevel@tonic-gate }
11920Sstevel@tonic-gate return (DCMD_OK);
11930Sstevel@tonic-gate }
11940Sstevel@tonic-gate
11950Sstevel@tonic-gate if (mdb_vread(&mb, sizeof (mblk_t), addr) == -1) {
11960Sstevel@tonic-gate mdb_warn("can't read mblk_t at 0x%lx", addr);
11970Sstevel@tonic-gate return (DCMD_ERR);
11980Sstevel@tonic-gate }
11990Sstevel@tonic-gate
12000Sstevel@tonic-gate if (mdb_vread(&db, sizeof (dblk_t), (uintptr_t)mb.b_datap) == -1) {
12010Sstevel@tonic-gate mdb_warn("%?lx: invalid b_datap pointer\n", addr);
12020Sstevel@tonic-gate return (DCMD_ERR);
12030Sstevel@tonic-gate }
12040Sstevel@tonic-gate
12050Sstevel@tonic-gate if (mb.b_rptr < db.db_base || mb.b_rptr > db.db_lim)
12060Sstevel@tonic-gate mblk_error(&error, addr, "b_rptr out of range");
12070Sstevel@tonic-gate
12080Sstevel@tonic-gate if (mb.b_wptr < db.db_base || mb.b_wptr > db.db_lim)
12090Sstevel@tonic-gate mblk_error(&error, addr, "b_wptr out of range");
12100Sstevel@tonic-gate
12110Sstevel@tonic-gate if (error)
12120Sstevel@tonic-gate mdb_printf("\n");
12130Sstevel@tonic-gate
12140Sstevel@tonic-gate return (error ? DCMD_ERR : DCMD_OK);
12150Sstevel@tonic-gate }
12160Sstevel@tonic-gate
12170Sstevel@tonic-gate int
mblk_prt(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)12180Sstevel@tonic-gate mblk_prt(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
12190Sstevel@tonic-gate {
12200Sstevel@tonic-gate const int MBLK_FLGDELT = (int)(sizeof (uintptr_t) * 2 + 15);
12210Sstevel@tonic-gate mblk_t mblk;
12220Sstevel@tonic-gate dblk_t dblk;
12230Sstevel@tonic-gate int b_flag;
12240Sstevel@tonic-gate int db_type;
12250Sstevel@tonic-gate int mblklen;
12260Sstevel@tonic-gate uint64_t len = ~0UL;
12270Sstevel@tonic-gate uint64_t glen = ~0UL;
12280Sstevel@tonic-gate uint64_t llen = ~0UL;
12290Sstevel@tonic-gate uint64_t blen = ~0UL;
12300Sstevel@tonic-gate const char *dbtype;
12310Sstevel@tonic-gate const char *flag = NULL, *not_flag = NULL;
12320Sstevel@tonic-gate const char *typ = NULL, *not_typ = NULL;
12330Sstevel@tonic-gate uintptr_t dbaddr = 0;
12340Sstevel@tonic-gate uint32_t tmask = 0, not_tmask = 0;
12350Sstevel@tonic-gate uint32_t mask = 0, not_mask = 0;
12360Sstevel@tonic-gate uint_t quiet = FALSE;
12370Sstevel@tonic-gate uint_t verbose = FALSE;
12380Sstevel@tonic-gate
12390Sstevel@tonic-gate if (!(flags & DCMD_ADDRSPEC)) {
12400Sstevel@tonic-gate if (mdb_walk_dcmd("genunix`streams_mblk", "genunix`mblk",
12410Sstevel@tonic-gate argc, argv) == -1) {
12420Sstevel@tonic-gate mdb_warn("failed to walk mblk cache");
12430Sstevel@tonic-gate return (DCMD_ERR);
12440Sstevel@tonic-gate }
12450Sstevel@tonic-gate return (DCMD_OK);
12460Sstevel@tonic-gate }
12470Sstevel@tonic-gate
12480Sstevel@tonic-gate if (flags & DCMD_PIPE_OUT)
12490Sstevel@tonic-gate quiet = TRUE;
12500Sstevel@tonic-gate
12510Sstevel@tonic-gate if (mdb_getopts(argc, argv,
12526583Smeem 'v', MDB_OPT_SETBITS, TRUE, &verbose,
12536583Smeem 'q', MDB_OPT_SETBITS, TRUE, &quiet,
12546583Smeem 'f', MDB_OPT_STR, &flag,
12556583Smeem 'F', MDB_OPT_STR, ¬_flag,
12566583Smeem 't', MDB_OPT_STR, &typ,
12576583Smeem 'T', MDB_OPT_STR, ¬_typ,
12586583Smeem 'l', MDB_OPT_UINT64, &len,
12596583Smeem 'L', MDB_OPT_UINT64, &llen,
12606583Smeem 'G', MDB_OPT_UINT64, &glen,
12616583Smeem 'b', MDB_OPT_UINT64, &blen,
12626583Smeem 'd', MDB_OPT_UINTPTR, &dbaddr,
12630Sstevel@tonic-gate NULL) != argc)
12640Sstevel@tonic-gate return (DCMD_USAGE);
12650Sstevel@tonic-gate
12660Sstevel@tonic-gate /*
12670Sstevel@tonic-gate * If any of the filtering flags is specified, don't print anything
12680Sstevel@tonic-gate * except the matching pointer.
12690Sstevel@tonic-gate */
12700Sstevel@tonic-gate if ((flag != NULL) || (not_flag != NULL) || (typ != NULL) ||
12710Sstevel@tonic-gate (not_typ != NULL) || (len != ~0UL) || (glen != ~0UL) ||
12720Sstevel@tonic-gate (llen != ~0UL) || (blen != ~0UL) || (dbaddr != 0))
12730Sstevel@tonic-gate quiet = TRUE;
12740Sstevel@tonic-gate
12750Sstevel@tonic-gate if (flag != NULL && streams_parse_flag(mbf, flag, &mask) == -1) {
12760Sstevel@tonic-gate mdb_warn("unrecognized mblk flag '%s'\n", flag);
12770Sstevel@tonic-gate streams_flag_usage(mbf);
12780Sstevel@tonic-gate return (DCMD_USAGE);
12790Sstevel@tonic-gate }
12800Sstevel@tonic-gate
12810Sstevel@tonic-gate if (not_flag != NULL &&
12820Sstevel@tonic-gate streams_parse_flag(mbf, not_flag, ¬_mask) == -1) {
12830Sstevel@tonic-gate mdb_warn("unrecognized mblk flag '%s'\n", flag);
12840Sstevel@tonic-gate streams_flag_usage(mbf);
12850Sstevel@tonic-gate return (DCMD_USAGE);
12860Sstevel@tonic-gate }
12870Sstevel@tonic-gate
12880Sstevel@tonic-gate if (typ != NULL && streams_parse_type(mbt, typ, &tmask) == -1) {
12890Sstevel@tonic-gate mdb_warn("unrecognized dblk type '%s'\n", typ);
12900Sstevel@tonic-gate streams_type_usage(mbt);
12910Sstevel@tonic-gate return (DCMD_USAGE);
12920Sstevel@tonic-gate }
12930Sstevel@tonic-gate
12940Sstevel@tonic-gate if (not_typ != NULL && streams_parse_type(mbt, not_typ, ¬_tmask)
12950Sstevel@tonic-gate == -1) {
12960Sstevel@tonic-gate mdb_warn("unrecognized dblk type '%s'\n", not_typ);
12970Sstevel@tonic-gate streams_type_usage(mbt);
12980Sstevel@tonic-gate return (DCMD_USAGE);
12990Sstevel@tonic-gate }
13000Sstevel@tonic-gate
13010Sstevel@tonic-gate if (DCMD_HDRSPEC(flags) && !quiet) {
13020Sstevel@tonic-gate mdb_printf("%?s %2s %-7s %-5s %-5s %?s %?s\n",
13030Sstevel@tonic-gate "ADDR", "FL", "TYPE", "LEN", "BLEN", "RPTR", "DBLK");
13040Sstevel@tonic-gate }
13050Sstevel@tonic-gate
13060Sstevel@tonic-gate if (mdb_vread(&mblk, sizeof (mblk), addr) == -1) {
13070Sstevel@tonic-gate mdb_warn("couldn't read mblk at %p", addr);
13080Sstevel@tonic-gate return (DCMD_ERR);
13090Sstevel@tonic-gate }
13100Sstevel@tonic-gate b_flag = mblk.b_flag;
13110Sstevel@tonic-gate
13120Sstevel@tonic-gate if (mask != 0 && !(b_flag & mask))
13130Sstevel@tonic-gate return (DCMD_OK);
13140Sstevel@tonic-gate
13150Sstevel@tonic-gate if (not_mask != 0 && (b_flag & not_mask))
13160Sstevel@tonic-gate return (DCMD_OK);
13170Sstevel@tonic-gate
13180Sstevel@tonic-gate if (mdb_vread(&dblk, sizeof (dblk), (uintptr_t)(mblk.b_datap)) == -1) {
13190Sstevel@tonic-gate mdb_warn("couldn't read dblk at %p/%p", addr, mblk.b_datap);
13200Sstevel@tonic-gate return (DCMD_ERR);
13210Sstevel@tonic-gate }
13220Sstevel@tonic-gate db_type = dblk.db_type;
13230Sstevel@tonic-gate
13240Sstevel@tonic-gate /* M_DATA is 0, so tmask has special value 0xff for it */
13256583Smeem if (tmask != 0) {
13266583Smeem if ((tmask == M_DATA_T && db_type != M_DATA) ||
13276583Smeem (tmask != M_DATA_T && db_type != tmask))
13286583Smeem return (DCMD_OK);
13296583Smeem }
13300Sstevel@tonic-gate
13316583Smeem if (not_tmask != 0) {
13326583Smeem if ((not_tmask == M_DATA_T && db_type == M_DATA) ||
13336583Smeem (db_type == not_tmask))
13346583Smeem return (DCMD_OK);
13356583Smeem }
13360Sstevel@tonic-gate
13370Sstevel@tonic-gate if (dbaddr != 0 && (uintptr_t)mblk.b_datap != dbaddr)
13380Sstevel@tonic-gate return (DCMD_OK);
13390Sstevel@tonic-gate
13400Sstevel@tonic-gate mblklen = MBLKL(&mblk);
13410Sstevel@tonic-gate
13420Sstevel@tonic-gate if ((len != ~0UL) && (len != mblklen))
13430Sstevel@tonic-gate return (DCMD_OK);
13440Sstevel@tonic-gate
13450Sstevel@tonic-gate if ((llen != ~0Ul) && (mblklen > (int)llen))
13460Sstevel@tonic-gate return (DCMD_OK);
13470Sstevel@tonic-gate
13480Sstevel@tonic-gate if ((glen != ~0Ul) && (mblklen < (int)glen))
13490Sstevel@tonic-gate return (DCMD_OK);
13500Sstevel@tonic-gate
13510Sstevel@tonic-gate if ((blen != ~0UL) && (blen != (dblk.db_lim - dblk.db_base)))
13520Sstevel@tonic-gate return (DCMD_OK);
13530Sstevel@tonic-gate
13540Sstevel@tonic-gate /*
13550Sstevel@tonic-gate * Options are specified for filtering, so If any option is specified on
13560Sstevel@tonic-gate * the command line, just print address and exit.
13570Sstevel@tonic-gate */
13580Sstevel@tonic-gate if (quiet) {
13590Sstevel@tonic-gate mdb_printf("%0?p\n", addr);
13600Sstevel@tonic-gate return (DCMD_OK);
13610Sstevel@tonic-gate }
13620Sstevel@tonic-gate
13630Sstevel@tonic-gate /* Figure out symbolic DB_TYPE */
13640Sstevel@tonic-gate if (db_type < A_SIZE(db_control_types)) {
13650Sstevel@tonic-gate dbtype = db_control_types[db_type];
13660Sstevel@tonic-gate } else {
13670Sstevel@tonic-gate /*
13680Sstevel@tonic-gate * Must be a high-priority message -- adjust so that
13690Sstevel@tonic-gate * "QPCTL + 1" corresponds to db_control_hipri_types[0]
13700Sstevel@tonic-gate */
13710Sstevel@tonic-gate db_type -= (QPCTL + 1);
13720Sstevel@tonic-gate if (db_type >= 0 && db_type < A_SIZE(db_control_hipri_types))
13730Sstevel@tonic-gate dbtype = db_control_hipri_types[db_type];
13740Sstevel@tonic-gate else
13750Sstevel@tonic-gate dbtype = "UNKNOWN";
13760Sstevel@tonic-gate }
13770Sstevel@tonic-gate
13780Sstevel@tonic-gate mdb_printf("%0?p %-2x %-7s %-5d %-5d %0?p %0?p\n",
13790Sstevel@tonic-gate addr, b_flag, dbtype, mblklen, dblk.db_lim - dblk.db_base,
13800Sstevel@tonic-gate mblk.b_rptr, mblk.b_datap);
13810Sstevel@tonic-gate
13820Sstevel@tonic-gate if (verbose) {
13830Sstevel@tonic-gate int i, arm = 0;
13840Sstevel@tonic-gate
13850Sstevel@tonic-gate for (i = 0; mbf[i].strf_name != NULL; i++) {
13860Sstevel@tonic-gate if (!(b_flag & (1 << i)))
13870Sstevel@tonic-gate continue;
13880Sstevel@tonic-gate if (!arm) {
13890Sstevel@tonic-gate mdb_printf("%*s|\n%*s+--> ",
13900Sstevel@tonic-gate MBLK_FLGDELT, "", MBLK_FLGDELT, "");
13910Sstevel@tonic-gate arm = 1;
13920Sstevel@tonic-gate } else
13930Sstevel@tonic-gate mdb_printf("%*s ", MBLK_FLGDELT, "");
13940Sstevel@tonic-gate
13950Sstevel@tonic-gate mdb_printf("%-12s %s\n",
13960Sstevel@tonic-gate mbf[i].strf_name, mbf[i].strf_descr);
13970Sstevel@tonic-gate }
13980Sstevel@tonic-gate }
13990Sstevel@tonic-gate return (DCMD_OK);
14000Sstevel@tonic-gate }
14010Sstevel@tonic-gate
14020Sstevel@tonic-gate /*
14030Sstevel@tonic-gate * Streams flow trace walkers.
14040Sstevel@tonic-gate */
14050Sstevel@tonic-gate
14060Sstevel@tonic-gate int
strftblk_walk_init(mdb_walk_state_t * wsp)14070Sstevel@tonic-gate strftblk_walk_init(mdb_walk_state_t *wsp)
14080Sstevel@tonic-gate {
14090Sstevel@tonic-gate ftblkdata_t *ftd;
14100Sstevel@tonic-gate dblk_t db;
14110Sstevel@tonic-gate
14120Sstevel@tonic-gate /* Get the dblock from the address */
14130Sstevel@tonic-gate if (mdb_vread(&db, sizeof (dblk_t), wsp->walk_addr) == -1) {
14140Sstevel@tonic-gate mdb_warn("failed to read dblk at %p", wsp->walk_addr);
14150Sstevel@tonic-gate return (WALK_ERR);
14160Sstevel@tonic-gate }
14170Sstevel@tonic-gate
14180Sstevel@tonic-gate /* Is there any flow trace data? */
14190Sstevel@tonic-gate if (db.db_fthdr == NULL) {
14200Sstevel@tonic-gate return (WALK_DONE);
14210Sstevel@tonic-gate }
14220Sstevel@tonic-gate
14230Sstevel@tonic-gate wsp->walk_addr = (uintptr_t)((char *)db.db_fthdr +
14240Sstevel@tonic-gate offsetof(fthdr_t, first));
14250Sstevel@tonic-gate
14260Sstevel@tonic-gate ftd = mdb_alloc(sizeof (ftblkdata_t), UM_SLEEP);
14270Sstevel@tonic-gate ftd->ft_ix = 0;
14280Sstevel@tonic-gate ftd->ft_in_evlist = B_FALSE;
14290Sstevel@tonic-gate wsp->walk_data = ftd;
14300Sstevel@tonic-gate
14310Sstevel@tonic-gate return (WALK_NEXT);
14320Sstevel@tonic-gate }
14330Sstevel@tonic-gate
14340Sstevel@tonic-gate int
strftblk_step(mdb_walk_state_t * wsp)14350Sstevel@tonic-gate strftblk_step(mdb_walk_state_t *wsp)
14360Sstevel@tonic-gate {
14370Sstevel@tonic-gate ftblkdata_t *ftd;
14380Sstevel@tonic-gate ftblk_t *ftbp;
14390Sstevel@tonic-gate int status = WALK_NEXT;
14400Sstevel@tonic-gate
14410Sstevel@tonic-gate if (wsp->walk_addr == NULL)
14420Sstevel@tonic-gate return (WALK_DONE);
14430Sstevel@tonic-gate
14440Sstevel@tonic-gate ftd = (ftblkdata_t *)wsp->walk_data;
14450Sstevel@tonic-gate ftbp = &(ftd->ft_data);
14460Sstevel@tonic-gate
14470Sstevel@tonic-gate if (! ftd->ft_in_evlist) {
14480Sstevel@tonic-gate /* Read a new ft block */
14490Sstevel@tonic-gate if (mdb_vread(ftbp, sizeof (ftblk_t),
14500Sstevel@tonic-gate wsp->walk_addr) == -1) {
14510Sstevel@tonic-gate mdb_warn("failed to read ftblk at %p", wsp->walk_addr);
14520Sstevel@tonic-gate return (WALK_ERR);
14530Sstevel@tonic-gate }
14540Sstevel@tonic-gate /*
14550Sstevel@tonic-gate * Check correctness of the index field.
14560Sstevel@tonic-gate */
14570Sstevel@tonic-gate if (ftbp->ix < 0 || ftbp->ix > FTBLK_EVNTS) {
14580Sstevel@tonic-gate mdb_warn("ftblk: incorrect index value %i\n", ftbp->ix);
14590Sstevel@tonic-gate return (WALK_ERR);
14600Sstevel@tonic-gate }
14610Sstevel@tonic-gate ftd->ft_ix = 1;
14620Sstevel@tonic-gate ftd->ft_in_evlist = B_TRUE;
14630Sstevel@tonic-gate }
14640Sstevel@tonic-gate
14650Sstevel@tonic-gate if (ftd->ft_ix > ftbp->ix) {
14660Sstevel@tonic-gate ftd->ft_in_evlist = B_FALSE;
14670Sstevel@tonic-gate /* End of event list reached - move to the next event block */
14680Sstevel@tonic-gate wsp->walk_addr = (uintptr_t)ftbp->nxt;
14690Sstevel@tonic-gate } else {
14700Sstevel@tonic-gate /* Print event address */
14710Sstevel@tonic-gate status = wsp->walk_callback((uintptr_t)((char *)wsp->walk_addr +
14720Sstevel@tonic-gate offsetof(ftblk_t, ev) +
14730Sstevel@tonic-gate (ftd->ft_ix - 1) * sizeof (struct ftevnt)),
14740Sstevel@tonic-gate wsp->walk_data, wsp->walk_cbdata);
14750Sstevel@tonic-gate ftd->ft_ix++;
14760Sstevel@tonic-gate }
14770Sstevel@tonic-gate
14780Sstevel@tonic-gate return (status);
14790Sstevel@tonic-gate }
14800Sstevel@tonic-gate
14810Sstevel@tonic-gate void
strftblk_walk_fini(mdb_walk_state_t * wsp)14820Sstevel@tonic-gate strftblk_walk_fini(mdb_walk_state_t *wsp)
14830Sstevel@tonic-gate {
14840Sstevel@tonic-gate mdb_free(wsp->walk_data, sizeof (ftblkdata_t));
14850Sstevel@tonic-gate }
14860Sstevel@tonic-gate
1487*8752SPeter.Memishian@Sun.COM static const char *
getqname(const void * nameptr,char * buf,uint_t bufsize)1488*8752SPeter.Memishian@Sun.COM getqname(const void *nameptr, char *buf, uint_t bufsize)
1489*8752SPeter.Memishian@Sun.COM {
1490*8752SPeter.Memishian@Sun.COM char *cp;
1491*8752SPeter.Memishian@Sun.COM
1492*8752SPeter.Memishian@Sun.COM if (mdb_readstr(buf, bufsize, (uintptr_t)nameptr) == -1)
1493*8752SPeter.Memishian@Sun.COM goto fail;
1494*8752SPeter.Memishian@Sun.COM
1495*8752SPeter.Memishian@Sun.COM /*
1496*8752SPeter.Memishian@Sun.COM * Sanity-check the name we read. This is needed because the pointer
1497*8752SPeter.Memishian@Sun.COM * value may have been recycled for some other purpose in the kernel
1498*8752SPeter.Memishian@Sun.COM * (e.g., if the STREAMS module was unloaded).
1499*8752SPeter.Memishian@Sun.COM */
1500*8752SPeter.Memishian@Sun.COM for (cp = buf; *cp != '\0'; cp++) {
1501*8752SPeter.Memishian@Sun.COM if (!isprint(*cp))
1502*8752SPeter.Memishian@Sun.COM goto fail;
1503*8752SPeter.Memishian@Sun.COM }
1504*8752SPeter.Memishian@Sun.COM return (buf);
1505*8752SPeter.Memishian@Sun.COM fail:
1506*8752SPeter.Memishian@Sun.COM return (strncpy(buf, "?", bufsize));
1507*8752SPeter.Memishian@Sun.COM }
1508*8752SPeter.Memishian@Sun.COM
15090Sstevel@tonic-gate /*ARGSUSED*/
15100Sstevel@tonic-gate int
strftevent(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)15110Sstevel@tonic-gate strftevent(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
15120Sstevel@tonic-gate {
1513*8752SPeter.Memishian@Sun.COM int i;
1514*8752SPeter.Memishian@Sun.COM struct ftstk stk;
15150Sstevel@tonic-gate struct ftevnt ev;
1516*8752SPeter.Memishian@Sun.COM char name[FMNAMESZ + 1];
1517*8752SPeter.Memishian@Sun.COM boolean_t havestk = B_FALSE;
15180Sstevel@tonic-gate
15190Sstevel@tonic-gate if (!(flags & DCMD_ADDRSPEC))
15200Sstevel@tonic-gate return (DCMD_USAGE);
15210Sstevel@tonic-gate
15220Sstevel@tonic-gate if (DCMD_HDRSPEC(flags)) {
1523*8752SPeter.Memishian@Sun.COM mdb_printf("%?s %-18s %-9s %-18s %4s %s\n",
1524*8752SPeter.Memishian@Sun.COM "ADDR", "Q/CALLER", "QNEXT", "STACK", "DATA", "EVENT");
15250Sstevel@tonic-gate }
15260Sstevel@tonic-gate
15270Sstevel@tonic-gate if (mdb_vread(&ev, sizeof (ev), addr) == -1) {
1528*8752SPeter.Memishian@Sun.COM mdb_warn("couldn't read struct ftevnt at %p", addr);
15290Sstevel@tonic-gate return (DCMD_ERR);
15300Sstevel@tonic-gate }
15310Sstevel@tonic-gate
1532*8752SPeter.Memishian@Sun.COM mdb_printf("%0?p", addr);
1533*8752SPeter.Memishian@Sun.COM
1534*8752SPeter.Memishian@Sun.COM if (ev.evnt & FTEV_QMASK)
1535*8752SPeter.Memishian@Sun.COM mdb_printf(" %-18s", getqname(ev.mid, name, sizeof (name)));
1536*8752SPeter.Memishian@Sun.COM else
1537*8752SPeter.Memishian@Sun.COM mdb_printf(" %-18a", ev.mid);
1538*8752SPeter.Memishian@Sun.COM
1539*8752SPeter.Memishian@Sun.COM if ((ev.evnt & FTEV_MASK) == FTEV_PUTNEXT)
1540*8752SPeter.Memishian@Sun.COM mdb_printf(" %-9s", getqname(ev.midnext, name, sizeof (name)));
1541*8752SPeter.Memishian@Sun.COM else
1542*8752SPeter.Memishian@Sun.COM mdb_printf(" %-9s", "--");
15430Sstevel@tonic-gate
1544*8752SPeter.Memishian@Sun.COM if (ev.stk == NULL) {
1545*8752SPeter.Memishian@Sun.COM mdb_printf(" %-18s", "--");
1546*8752SPeter.Memishian@Sun.COM } else if (mdb_vread(&stk, sizeof (stk), (uintptr_t)ev.stk) == -1) {
1547*8752SPeter.Memishian@Sun.COM mdb_printf(" %-18s", "?");
1548*8752SPeter.Memishian@Sun.COM } else {
1549*8752SPeter.Memishian@Sun.COM mdb_printf(" %-18a", stk.fs_stk[0]);
1550*8752SPeter.Memishian@Sun.COM havestk = B_TRUE;
1551*8752SPeter.Memishian@Sun.COM }
15520Sstevel@tonic-gate
1553*8752SPeter.Memishian@Sun.COM mdb_printf(" %4x", ev.data);
15540Sstevel@tonic-gate ft_printevent(ev.evnt);
1555*8752SPeter.Memishian@Sun.COM mdb_printf("\n");
15560Sstevel@tonic-gate
1557*8752SPeter.Memishian@Sun.COM if (havestk) {
1558*8752SPeter.Memishian@Sun.COM for (i = 1; i < stk.fs_depth; i++) {
1559*8752SPeter.Memishian@Sun.COM mdb_printf("%?s %-18s %-9s %-18a\n", "", "", "",
1560*8752SPeter.Memishian@Sun.COM stk.fs_stk[i]);
1561*8752SPeter.Memishian@Sun.COM }
1562*8752SPeter.Memishian@Sun.COM }
15630Sstevel@tonic-gate
15640Sstevel@tonic-gate return (DCMD_OK);
15650Sstevel@tonic-gate }
15660Sstevel@tonic-gate
15670Sstevel@tonic-gate static void
ft_printevent(ushort_t ev)15680Sstevel@tonic-gate ft_printevent(ushort_t ev)
15690Sstevel@tonic-gate {
15700Sstevel@tonic-gate ushort_t proc_ev = (ev & (FTEV_PROC_START | 0xFF)) - FTEV_PROC_START;
15710Sstevel@tonic-gate ushort_t alloc_ev = ev & FTEV_CALLER;
15720Sstevel@tonic-gate
15730Sstevel@tonic-gate /* Get event class first */
15740Sstevel@tonic-gate if (ev & FTEV_PROC_START) {
15750Sstevel@tonic-gate if (proc_ev >= A_SIZE(ftev_proc))
1576*8752SPeter.Memishian@Sun.COM mdb_printf(" undefined");
15770Sstevel@tonic-gate else
1578*8752SPeter.Memishian@Sun.COM mdb_printf(" %s", ftev_proc[proc_ev]);
1579*8752SPeter.Memishian@Sun.COM } else if (alloc_ev >= A_SIZE(ftev_alloc)) {
1580*8752SPeter.Memishian@Sun.COM mdb_printf(" undefined");
1581*8752SPeter.Memishian@Sun.COM } else {
1582*8752SPeter.Memishian@Sun.COM mdb_printf(" %s", ftev_alloc[alloc_ev]);
1583*8752SPeter.Memishian@Sun.COM }
15840Sstevel@tonic-gate
15850Sstevel@tonic-gate /* Print event modifiers, if any */
1586*8752SPeter.Memishian@Sun.COM if (ev & (FTEV_PS | FTEV_CS | FTEV_ISWR)) {
1587*8752SPeter.Memishian@Sun.COM mdb_printf("|");
1588*8752SPeter.Memishian@Sun.COM if (ev & FTEV_ISWR)
1589*8752SPeter.Memishian@Sun.COM mdb_printf("W");
1590*8752SPeter.Memishian@Sun.COM if (ev & FTEV_CS)
1591*8752SPeter.Memishian@Sun.COM mdb_printf("C");
1592*8752SPeter.Memishian@Sun.COM if (ev & FTEV_PS)
1593*8752SPeter.Memishian@Sun.COM mdb_printf("P");
1594*8752SPeter.Memishian@Sun.COM }
15950Sstevel@tonic-gate }
15960Sstevel@tonic-gate
15970Sstevel@tonic-gate /*
15980Sstevel@tonic-gate * Help functions for STREAMS debugging facilities.
15990Sstevel@tonic-gate */
16000Sstevel@tonic-gate void
queue_help(void)16010Sstevel@tonic-gate queue_help(void)
16020Sstevel@tonic-gate {
16030Sstevel@tonic-gate mdb_printf("Print queue information for a given queue pointer.\n"
16040Sstevel@tonic-gate "\nWithout the address of a \"queue_t\" structure given, print "
16050Sstevel@tonic-gate "information about all\n"
16060Sstevel@tonic-gate "queues in the \"queue_cache\".\n\n"
16070Sstevel@tonic-gate "Options:\n"
16080Sstevel@tonic-gate " -v:\t\tbe verbose - print symbolic flags falues\n"
16090Sstevel@tonic-gate " -q:\t\tbe quiet - print queue pointer only\n"
16100Sstevel@tonic-gate " -f flag:\tprint only queues with flag set\n"
16110Sstevel@tonic-gate " -F flag:\tprint only queues with flag NOT set\n"
16120Sstevel@tonic-gate " -m modname:\tprint only queues with specified module name\n"
16130Sstevel@tonic-gate " -s syncq_addr:\tprint only queues which use specified syncq\n\n"
16140Sstevel@tonic-gate "Available conversions:\n"
16150Sstevel@tonic-gate " q2rdq: given a queue addr print read queue pointer\n"
16160Sstevel@tonic-gate " q2wrq: given a queue addr print write queue pointer\n"
16170Sstevel@tonic-gate " q2otherq: given a queue addr print other queue pointer\n"
16180Sstevel@tonic-gate " q2syncq: given a queue addr print syncq pointer"
16196583Smeem " (::help syncq)\n"
16200Sstevel@tonic-gate " q2stream: given a queue addr print its stream pointer\n"
16216583Smeem "\t\t(see ::help stream and ::help stdata)\n\n"
16220Sstevel@tonic-gate "To walk q_next pointer of the queue use\n"
16230Sstevel@tonic-gate " queue_addr::walk qnext\n");
16240Sstevel@tonic-gate }
16250Sstevel@tonic-gate
16260Sstevel@tonic-gate void
syncq_help(void)16270Sstevel@tonic-gate syncq_help(void)
16280Sstevel@tonic-gate {
16290Sstevel@tonic-gate mdb_printf("Print syncq information for a given syncq pointer.\n"
16300Sstevel@tonic-gate "\nWithout the address of a \"syncq_t\" structure given, print "
16310Sstevel@tonic-gate "information about all\n"
16320Sstevel@tonic-gate "syncqs in the \"syncq_cache\".\n\n"
16330Sstevel@tonic-gate "Options:\n"
16340Sstevel@tonic-gate " -v:\t\tbe verbose - print symbolic flags falues\n"
16350Sstevel@tonic-gate " -q:\t\tbe quiet - print syncq pointer only\n"
16360Sstevel@tonic-gate " -f flag:\tprint only syncqs with flag set\n"
16370Sstevel@tonic-gate " -F flag:\tprint only syncqs with flag NOT set\n"
16380Sstevel@tonic-gate " -t type:\tprint only syncqs with specified type\n"
16390Sstevel@tonic-gate " -T type:\tprint only syncqs with do NOT have specified type\n\n"
16400Sstevel@tonic-gate "Available conversions:\n"
16410Sstevel@tonic-gate " syncq2q:\tgiven a syncq addr print queue address of the\n"
16420Sstevel@tonic-gate "\t\t\tenclosing queue, if it is part of a queue\n\n"
16430Sstevel@tonic-gate "See also: \"::help queue\" and \"::help stdata\"\n");
16440Sstevel@tonic-gate }
16450Sstevel@tonic-gate
16460Sstevel@tonic-gate void
stdata_help(void)16470Sstevel@tonic-gate stdata_help(void)
16480Sstevel@tonic-gate {
16490Sstevel@tonic-gate mdb_printf("Print stdata information for a given stdata pointer.\n"
16500Sstevel@tonic-gate "\nWithout the address of a \"stdata_t\" structure given, print "
16510Sstevel@tonic-gate "information about all\n"
16520Sstevel@tonic-gate "stream head pointers from the \"stream_head_cache\".\n\n"
16530Sstevel@tonic-gate "Fields printed:\n"
16540Sstevel@tonic-gate " ADDR:\tstream head address\n"
16550Sstevel@tonic-gate " WRQ:\twrite queue pointer\n"
16560Sstevel@tonic-gate " FLAGS:\tstream head flags (use -v to show in symbolic form)\n"
16570Sstevel@tonic-gate " VNODE:\tstream vnode pointer\n"
16580Sstevel@tonic-gate " N/A:\tpushcount and anchor positions\n"
16590Sstevel@tonic-gate " REF:\tstream head reference counter\n\n"
16600Sstevel@tonic-gate "Options:\n"
16610Sstevel@tonic-gate " -v:\t\tbe verbose - print symbolic flags falues\n"
16620Sstevel@tonic-gate " -q:\t\tbe quiet - print stdata pointer only\n"
16630Sstevel@tonic-gate " -f flag:\tprint only stdatas with flag set\n"
16640Sstevel@tonic-gate " -F flag:\tprint only stdatas with flag NOT set\n\n"
16650Sstevel@tonic-gate "Available conversions:\n"
16660Sstevel@tonic-gate " str2mate:\tgiven a stream head addr print its mate\n"
16670Sstevel@tonic-gate " str2wrq:\tgiven a stream head addr print its write queue\n\n"
16680Sstevel@tonic-gate "See also: \"::help queue\" and \"::help syncq\"\n");
16690Sstevel@tonic-gate }
16700Sstevel@tonic-gate
16710Sstevel@tonic-gate void
mblk_help(void)16720Sstevel@tonic-gate mblk_help(void)
16730Sstevel@tonic-gate {
16740Sstevel@tonic-gate mdb_printf("Print mblock information for a given mblk pointer.\n"
16750Sstevel@tonic-gate "Without the address, print information about all mblocks.\n\n"
16760Sstevel@tonic-gate "Fields printed:\n"
16770Sstevel@tonic-gate " ADDR:\tmblk address\n"
16780Sstevel@tonic-gate " FL:\tFlags\n"
16790Sstevel@tonic-gate " TYPE:\tType of corresponding dblock\n"
16800Sstevel@tonic-gate " LEN:\tData length as b_wptr - b_rptr\n"
16810Sstevel@tonic-gate " BLEN:\tDblock space as db_lim - db_base\n"
16820Sstevel@tonic-gate " RPTR:\tRead pointer\n"
16830Sstevel@tonic-gate " DBLK:\tDblock pointer\n\n"
16840Sstevel@tonic-gate "Options:\n"
16850Sstevel@tonic-gate " -v:\t\tbe verbose - print symbolic flags falues\n"
16860Sstevel@tonic-gate " -q:\t\tbe quiet - print mblk pointer only\n"
16870Sstevel@tonic-gate " -d dbaddr:\t\tprint mblks with specified dblk address\n"
16880Sstevel@tonic-gate " -f flag:\tprint only mblks with flag set\n"
16890Sstevel@tonic-gate " -F flag:\tprint only mblks with flag NOT set\n"
16900Sstevel@tonic-gate " -t type:\tprint only mblks of specified db_type\n"
16910Sstevel@tonic-gate " -T type:\tprint only mblks other then the specified db_type\n"
16920Sstevel@tonic-gate " -l len:\t\ttprint only mblks with MBLKL == len\n"
16930Sstevel@tonic-gate " -L len:\t\tprint only mblks with MBLKL <= len \n"
16940Sstevel@tonic-gate " -G len:\t\tprint only mblks with MBLKL >= len \n"
16950Sstevel@tonic-gate " -b len:\t\tprint only mblks with db_lim - db_base == len\n"
16960Sstevel@tonic-gate "\n");
16970Sstevel@tonic-gate }
1698