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