streams.c revision 595aa6e48d8a5812a3a42afa5f63ee6f772c7f4e
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2005 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <mdb/mdb_modapi.h>
#include <sys/sysmacros.h>
#include "streams.h"
typedef struct str_flags {
const char *strf_name;
const char *strf_descr;
} strflags_t;
typedef struct str_types {
const char *strt_name;
int strt_value;
const char *strt_descr;
} strtypes_t;
typedef struct ftblk_data {
int ft_ix; /* Index in event list */
} ftblkdata_t;
/*
* Queue flags
*/
static const strflags_t qf[] = {
};
/*
* Syncq flags
*/
};
/*
* Syncq types
*/
};
/*
* Stdata flags
*/
};
};
#define M_DATA_T 0xff
static const strtypes_t mbt[] = {
};
/* Allocation flow trace events, starting from 0 */
static const char *ftev_alloc[] = {
/* 0 */ ":allocb",
/* 1 */ ":esballoc",
/* 2 */ ":desballoc",
/* 3 */ ":esballoca",
/* 4 */ ":desballoca",
/* 5 */ ":allocbig",
/* 6 */ ":allocbw",
/* 7 */ ":bcallocb",
/* 8 */ ":freeb",
/* 9 */ ":dupb",
/* A */ ":copyb",
};
#define FTEV_PROC_START FTEV_PUT
/* Procedures recorded by flow tracing, starting from 0x100 */
static const char *ftev_proc[] = {
/* 100 */ ":put",
/* 101 */ ":undefined (0x101)",
/* 102 */ ":undefined (0x102)",
/* 103 */ ":undefined (0x103)",
/* 104 */ ":undefined (0x104)",
/* 105 */ ":putq",
/* 106 */ ":getq",
/* 107 */ ":rmvq",
/* 108 */ ":insq",
/* 109 */ ":putbq",
/* 10A */ ":flushq",
/* 10B */ ":undefined (0x10b)",
/* 10C */ ":undefined (0x10c)",
/* 10D */ ":putnext",
/* 10E */ ":rwnext",
};
static const char *db_control_types[] = {
/* 00 */ "data",
/* 01 */ "proto",
/* 02 */ "multidata",
/* 03 */ "unused (0x03)",
/* 04 */ "unused (0x04)",
/* 05 */ "unused (0x05)",
/* 06 */ "unused (0x06)",
/* 07 */ "unused (0x07)",
/* 08 */ "break",
/* 09 */ "passfp",
/* 0a */ "event",
/* 0b */ "sig",
/* 0c */ "delay",
/* 0d */ "ctl",
/* 0e */ "ioctl",
/* 0f */ "unused",
/* 10 */ "setopts",
/* 11 */ "rse",
};
static const char *db_control_hipri_types[] = {
/* 81 */ "iocack",
/* 82 */ "iocnak",
/* 83 */ "pcproto",
/* 84 */ "pcsig",
/* 85 */ "read",
/* 86 */ "flush",
/* 87 */ "stop",
/* 88 */ "start",
/* 89 */ "hangup",
/* 8a */ "error",
/* 8b */ "copyin",
/* 8c */ "copyout",
/* 8d */ "iocdata",
/* 8e */ "pcrse",
/* 8f */ "stopi",
/* 90 */ "starti",
/* 91 */ "pcevent",
/* 92 */ "unhangup",
};
#define A_SIZE(a) (sizeof (a) / sizeof (a[0]))
static void ft_printevent(ushort_t);
static int
{
int i;
*flag |= (1 << i);
return (0);
}
}
return (-1);
}
static void
{
int i;
mdb_printf("%-14s %s\n",
}
static int
{
int i;
return (0);
}
}
return (-1);
}
static void
{
int i;
mdb_printf("%-12s %s\n",
}
int
{
char name[MODMAXNAMELEN];
int nblks = 0;
queue_t q;
if (!(flags & DCMD_ADDRSPEC)) {
mdb_warn("failed to walk queue cache");
return (DCMD_ERR);
}
return (DCMD_OK);
}
if (flags & DCMD_PIPE_OUT)
return (DCMD_USAGE);
/*
* If any of the filtering flags is specified, don't print anything
* except the matching pointer.
*/
mdb_printf("%?s %-13s %6s %4s\n",
"ADDR", "MODULE", "FLAGS", "NBLK");
}
return (DCMD_USAGE);
}
return (DCMD_USAGE);
}
return (DCMD_ERR);
}
mdb_warn("couldn't read mblk %p for queue %p",
break;
}
}
/*
* If queue doesn't pass filtering criteria, don't print anything and
* just return.
*/
return (DCMD_OK);
return (DCMD_OK);
return (DCMD_OK);
return (DCMD_OK);
/*
* Options are specified for filtering, so If any option is specified on
* the command line, just print address and exit.
*/
if (quiet) {
return (DCMD_OK);
}
mdb_printf("%0?p %-13s %06x %4d %0?p\n",
if (verbose) {
int i, arm = 0;
if (!(q.q_flag & (1 << i)))
continue;
if (!arm) {
mdb_printf("%*s|\n%*s+--> ",
arm = 1;
} else
mdb_printf("%-12s %s\n",
}
}
return (DCMD_OK);
}
int
{
if (!(flags & DCMD_ADDRSPEC)) {
mdb_warn("failed to walk syncq cache");
return (DCMD_ERR);
}
return (DCMD_OK);
}
if (flags & DCMD_PIPE_OUT)
return (DCMD_USAGE);
/*
* If any of the filtering flags is specified, don't print anything
* except the matching pointer.
*/
mdb_printf("%?s %s %s %s %s %?s %s %s\n",
"ADDR", "FLG", "TYP", "CNT", "NQS", "OUTER", "SF", "PRI");
}
return (DCMD_USAGE);
}
return (DCMD_USAGE);
}
== -1) {
return (DCMD_USAGE);
}
== -1) {
return (DCMD_USAGE);
}
return (DCMD_ERR);
}
return (DCMD_OK);
return (DCMD_OK);
return (DCMD_OK);
return (DCMD_OK);
/*
* Options are specified for filtering, so If any option is specified on
* the command line, just print address and exit.
*/
if (quiet) {
return (DCMD_OK);
}
mdb_printf("%0?p %02x %02x %-3u %-3u %0?p %1x %-3d\n",
if (verbose) {
int i, arm = 0;
continue;
if (!arm) {
mdb_printf("%*s|\n%*s+--> ",
arm = 1;
} else
mdb_printf("%-12s %s\n",
}
if (!(sqtype & (1 << i)))
continue;
if (!arm) {
mdb_printf("%*s|\n%*s+--> ",
arm = 1;
} else
mdb_printf("%-12s %s\n",
}
}
return (DCMD_OK);
}
int
{
if (!(flags & DCMD_ADDRSPEC)) {
if (mdb_walk_dcmd("genunix`stream_head_cache",
mdb_warn("failed to walk stream head cache");
return (DCMD_ERR);
}
return (DCMD_OK);
}
if (flags & DCMD_PIPE_OUT)
return (DCMD_USAGE);
/*
* If any of the filtering flags is specified, don't print anything
* except the matching pointer.
*/
mdb_printf("%?s %?s %8s %?s %s %s\n",
"ADDR", "WRQ", "FLAGS", "VNODE", "N/A", "REF");
}
return (DCMD_USAGE);
}
return (DCMD_USAGE);
}
return (DCMD_ERR);
}
/*
* If stream doesn't pass filtering criteria, don't print anything and
* just return.
*/
return (DCMD_OK);
return (DCMD_OK);
/*
* Options are specified for filtering, so If any option is specified on
* the command line, just print address and exit.
*/
if (quiet) {
return (DCMD_OK);
}
mdb_printf("%0?p %0?p %08x %0?p %d/%d %d\n",
if (verbose) {
int i, arm = 0;
continue;
if (!arm) {
mdb_printf("%*s|\n%*s+--> ",
arm = 1;
} else
mdb_printf("%-12s %s\n",
}
}
return (DCMD_OK);
}
/*ARGSUSED*/
static void
{
}
/*ARGSUSED*/
static void
{
}
static void
{
}
static void
{
}
static void
{
}
static int
{
queue_t q;
if (argc != 0)
return (DCMD_USAGE);
return (DCMD_ERR);
}
return (DCMD_OK);
}
/*ARGSUSED*/
int
{
}
/*ARGSUSED*/
int
{
}
/*ARGSUSED*/
int
{
}
/*ARGSUSED*/
int
{
}
/*ARGSUSED*/
int
{
}
static int
{
if (argc != 0)
return (DCMD_USAGE);
return (DCMD_ERR);
}
return (DCMD_OK);
}
/*ARGSUSED*/
static void
{
}
static void
{
}
/*ARGSUSED*/
int
{
}
/*ARGSUSED*/
int
{
}
/*
* If this syncq is a part of the queue pair structure, find the queue for it.
*/
/*ARGSUSED*/
int
{
queue_t q;
if (argc != 0)
return (DCMD_USAGE);
return (DCMD_ERR);
}
/* Try to find its queue */
return (DCMD_ERR);
} else
return (DCMD_OK);
}
int
{
mdb_warn("failed to read 'qhead'");
return (WALK_ERR);
}
return (WALK_NEXT);
}
int
{
int status;
return (WALK_DONE);
return (WALK_DONE);
}
wsp->walk_cbdata);
return (status);
}
int
{
int status;
return (WALK_DONE);
return (WALK_DONE);
}
wsp->walk_cbdata);
return (status);
}
void
{
}
int
{
stdata_t s;
mdb_warn("walk must begin at address of stdata_t\n");
return (WALK_ERR);
}
return (WALK_ERR);
}
return (WALK_NEXT);
}
int
{
int status;
return (WALK_DONE);
mdb_warn("failed to read queue pair at %p",
return (WALK_DONE);
}
else
return (status);
}
int
{
int status;
return (WALK_DONE);
mdb_warn("failed to read queue pair at %p",
return (WALK_DONE);
}
else
return (status);
}
void
{
}
static int
{
static const char box_lid[] =
"+-----------------------+-----------------------+\n";
static const char box_sep[] =
"| | |\n";
if (*depth != 0) {
mdb_printf(" | ^\n");
mdb_printf(" v |\n");
} else
mdb_printf("\n");
*info2++ = '\0';
else
info2 = "";
mdb_printf("| 0x%-19p | 0x%-19p | %s\n",
mdb_flush(); /* Account for buffered terminal sequences */
*info2++ = '\0';
else
info2 = "";
mdb_printf("| cnt = 0t%-13lu | cnt = 0t%-13lu | %s\n",
mdb_printf("| flg = 0x%08x | flg = 0x%08x | %s\n",
*depth += 1;
return (0);
}
/*ARGSUSED*/
int
{
uint_t d = 0; /* Depth counter for print_qpair */
return (DCMD_USAGE);
mdb_warn("failed to walk writeq");
return (DCMD_ERR);
}
return (DCMD_OK);
}
int
{
return (WALK_NEXT);
}
int
{
int status;
return (WALK_DONE);
return (WALK_DONE);
}
wsp->walk_cbdata);
return (status);
}
int
{
int status;
return (WALK_DONE);
return (WALK_DONE);
}
wsp->walk_cbdata);
return (status);
}
void
{
}
/* ARGSUSED */
int
{
if (argc != 0)
return (DCMD_USAGE);
return (DCMD_ERR);
}
return (DCMD_OK);
}
static void
{
if (!*error)
else
mdb_printf(", ");
*error = 1;
}
int
{
int error = 0;
if (!(flags & DCMD_ADDRSPEC)) {
-1) {
mdb_warn("can't walk mblk cache");
return (DCMD_ERR);
}
return (DCMD_OK);
}
return (DCMD_ERR);
}
return (DCMD_ERR);
}
if (error)
mdb_printf("\n");
}
int
{
int b_flag;
int db_type;
int mblklen;
const char *dbtype;
if (!(flags & DCMD_ADDRSPEC)) {
mdb_warn("failed to walk mblk cache");
return (DCMD_ERR);
}
return (DCMD_OK);
}
if (flags & DCMD_PIPE_OUT)
return (DCMD_USAGE);
/*
* If any of the filtering flags is specified, don't print anything
* except the matching pointer.
*/
return (DCMD_USAGE);
}
return (DCMD_USAGE);
}
return (DCMD_USAGE);
}
== -1) {
return (DCMD_USAGE);
}
mdb_printf("%?s %2s %-7s %-5s %-5s %?s %?s\n",
"ADDR", "FL", "TYPE", "LEN", "BLEN", "RPTR", "DBLK");
}
return (DCMD_ERR);
}
return (DCMD_OK);
return (DCMD_OK);
return (DCMD_ERR);
}
/* M_DATA is 0, so tmask has special value 0xff for it */
if ((tmask != 0) &&
return (DCMD_OK);
if ((not_tmask != 0) &&
return (DCMD_OK);
return (DCMD_OK);
return (DCMD_OK);
return (DCMD_OK);
return (DCMD_OK);
return (DCMD_OK);
/*
* Options are specified for filtering, so If any option is specified on
* the command line, just print address and exit.
*/
if (quiet) {
return (DCMD_OK);
}
/* Figure out symbolic DB_TYPE */
} else {
/*
* Must be a high-priority message -- adjust so that
* "QPCTL + 1" corresponds to db_control_hipri_types[0]
*/
else
dbtype = "UNKNOWN";
}
mdb_printf("%0?p %-2x %-7s %-5d %-5d %0?p %0?p\n",
if (verbose) {
int i, arm = 0;
if (!(b_flag & (1 << i)))
continue;
if (!arm) {
mdb_printf("%*s|\n%*s+--> ",
arm = 1;
} else
mdb_printf("%-12s %s\n",
}
}
return (DCMD_OK);
}
/*
* Streams flow trace walkers.
*/
int
{
/* Get the dblock from the address */
return (WALK_ERR);
}
/* Is there any flow trace data? */
return (WALK_DONE);
}
return (WALK_NEXT);
}
int
{
return (WALK_DONE);
if (! ftd->ft_in_evlist) {
/* Read a new ft block */
return (WALK_ERR);
}
/*
* Check correctness of the index field.
*/
return (WALK_ERR);
}
}
/* End of event list reached - move to the next event block */
} else {
/* Print event address */
}
return (status);
}
void
{
}
/*ARGSUSED*/
int
{
char modname[MODMAXNAMELEN];
if (!(flags & DCMD_ADDRSPEC))
return (DCMD_USAGE);
if (DCMD_HDRSPEC(flags)) {
mdb_printf("%?s %?s %s %s %-24s %s\n",
"ADDR", "MID", "EVNT", "DATA", "NAME", "EVENT");
}
return (DCMD_ERR);
}
mdb_printf("%0?p %0?p %4x %4x",
} else
mdb_printf("\n");
return (DCMD_OK);
}
static void
{
/* Get event class first */
if (ev & FTEV_PROC_START) {
mdb_printf(" undefined");
else
mdb_printf(" undefined");
else
/* Print event modifiers, if any */
mdb_printf(" | PS");
mdb_printf(" | CS");
mdb_printf(" | ISWR");
}
/*
* Help functions for STREAMS debugging facilities.
*/
void
queue_help(void)
{
mdb_printf("Print queue information for a given queue pointer.\n"
"\nWithout the address of a \"queue_t\" structure given, print "
"information about all\n"
"queues in the \"queue_cache\".\n\n"
"Options:\n"
" -v:\t\tbe verbose - print symbolic flags falues\n"
" -q:\t\tbe quiet - print queue pointer only\n"
" -f flag:\tprint only queues with flag set\n"
" -F flag:\tprint only queues with flag NOT set\n"
" -m modname:\tprint only queues with specified module name\n"
" -s syncq_addr:\tprint only queues which use specified syncq\n\n"
"Available conversions:\n"
" q2rdq: given a queue addr print read queue pointer\n"
" q2wrq: given a queue addr print write queue pointer\n"
" q2otherq: given a queue addr print other queue pointer\n"
" q2syncq: given a queue addr print syncq pointer"
" (::help syncq)\n"
" q2stream: given a queue addr print its stream pointer\n"
"\t\t(see ::help stream and ::help stdata)\n\n"
"To walk q_next pointer of the queue use\n"
" queue_addr::walk qnext\n");
}
void
syncq_help(void)
{
mdb_printf("Print syncq information for a given syncq pointer.\n"
"\nWithout the address of a \"syncq_t\" structure given, print "
"information about all\n"
"syncqs in the \"syncq_cache\".\n\n"
"Options:\n"
" -v:\t\tbe verbose - print symbolic flags falues\n"
" -q:\t\tbe quiet - print syncq pointer only\n"
" -f flag:\tprint only syncqs with flag set\n"
" -F flag:\tprint only syncqs with flag NOT set\n"
" -t type:\tprint only syncqs with specified type\n"
" -T type:\tprint only syncqs with do NOT have specified type\n\n"
"Available conversions:\n"
" syncq2q:\tgiven a syncq addr print queue address of the\n"
"\t\t\tenclosing queue, if it is part of a queue\n\n"
"See also: \"::help queue\" and \"::help stdata\"\n");
}
void
stdata_help(void)
{
mdb_printf("Print stdata information for a given stdata pointer.\n"
"\nWithout the address of a \"stdata_t\" structure given, print "
"information about all\n"
"stream head pointers from the \"stream_head_cache\".\n\n"
"Fields printed:\n"
" ADDR:\tstream head address\n"
" WRQ:\twrite queue pointer\n"
" FLAGS:\tstream head flags (use -v to show in symbolic form)\n"
" VNODE:\tstream vnode pointer\n"
" N/A:\tpushcount and anchor positions\n"
" REF:\tstream head reference counter\n\n"
"Options:\n"
" -v:\t\tbe verbose - print symbolic flags falues\n"
" -q:\t\tbe quiet - print stdata pointer only\n"
" -f flag:\tprint only stdatas with flag set\n"
" -F flag:\tprint only stdatas with flag NOT set\n\n"
"Available conversions:\n"
" str2mate:\tgiven a stream head addr print its mate\n"
" str2wrq:\tgiven a stream head addr print its write queue\n\n"
"See also: \"::help queue\" and \"::help syncq\"\n");
}
void
mblk_help(void)
{
mdb_printf("Print mblock information for a given mblk pointer.\n"
"Without the address, print information about all mblocks.\n\n"
"Fields printed:\n"
" ADDR:\tmblk address\n"
" FL:\tFlags\n"
" TYPE:\tType of corresponding dblock\n"
" LEN:\tData length as b_wptr - b_rptr\n"
" BLEN:\tDblock space as db_lim - db_base\n"
" RPTR:\tRead pointer\n"
" DBLK:\tDblock pointer\n\n"
"Options:\n"
" -v:\t\tbe verbose - print symbolic flags falues\n"
" -q:\t\tbe quiet - print mblk pointer only\n"
" -d dbaddr:\t\tprint mblks with specified dblk address\n"
" -f flag:\tprint only mblks with flag set\n"
" -F flag:\tprint only mblks with flag NOT set\n"
" -t type:\tprint only mblks of specified db_type\n"
" -T type:\tprint only mblks other then the specified db_type\n"
" -l len:\t\ttprint only mblks with MBLKL == len\n"
" -L len:\t\tprint only mblks with MBLKL <= len \n"
" -G len:\t\tprint only mblks with MBLKL >= len \n"
" -b len:\t\tprint only mblks with db_lim - db_base == len\n"
"\n");
}