/*
* 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 2003 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <sys/mdb_modapi.h>
/* Represents global soft state data in walk_step, walk_init */
/* Represents global soft state data in callback and related routines */
/*
* Primary attribute struct for buf extensions.
*/
struct __ddi_xbuf_attr {
void *xa_reserve_headp;
void *xa_attr_arg;
};
/*
* Provides soft state information like the number of elements, pointer
* to soft state elements etc
*/
/* structure to store soft state statistics */
typedef struct sd_str {
void *sd_state;
int current_list_count;
int valid_root_count;
int silent;
/*
* Function: buf_avforw_walk_init
*
* Description: MDB calls the init function to initiate the walk,
* in response to mdb_walk() function called by the
* dcmd 'buf_avforw' or when the user executes the
* walk dcmd 'address::walk buf_avforw'.
*
* Arguments: new mdb_walk_state_t structure. A new structure is
* created for each walk, so that multiple instances of
* the walker can be active simultaneously.
*/
static int
{
mdb_warn("buffer address required with the command\n");
return (WALK_ERR);
}
return (WALK_NEXT);
}
/*
* Function: buf_avforw_walk_step
*
* Description: The step function is invoked by the walker during each
* iteration. Its primary job is to determine the address
* of the next 'buf_avforw' object, read in the local copy
* of this object, call the callback 'buf_callback' function,
* and return its status. The iteration is terminated when
* the walker encounters a null queue pointer which signifies
* end of queue.
*
* Arguments: mdb_walk_state_t structure
*/
static int
{
int status;
/*
* if walk_addr is null then it effectively means an end of all
* buf structures, hence end the iterations.
*/
return (WALK_DONE);
}
/*
* Read the contents of the current object, invoke the callback
* and assign the next objects address to mdb_walk_state_t structure.
*/
return (WALK_DONE);
}
wsp->walk_cbdata);
return (status);
}
/*
* Function: buf_callback
*
* Description: This is the callback function called by the 'buf_avforw'
* walker when 'buf_avforw' dcmd is invoked.
* It is called during each walk step. It displays the contents
* of the current object (addr) passed to it by the step
* function. It also prints the header and footer during the
* first and the last iteration of the walker.
*
* Arguments: addr -> current buf_avforw objects address.
* walk_data -> private storage for the walker.
* buf_entries -> private data for the callback. It represents
* the count of objects processed so far.
*/
static int
{
/*
* If this is the first invocation of the command, print a
* header line for the output that will follow.
*/
if (*count == 0) {
mdb_printf("============================\n");
mdb_printf("Walking buf list via av_forw\n");
mdb_printf("============================\n");
}
/*
* read the object and print the contents.
*/
mdb_eval("$<buf");
mdb_printf("---\n");
(*count)++;
/* if this is the last entry and print the footer */
mdb_printf("---------------------------\n");
mdb_printf("---------------------------\n");
return (WALK_DONE);
}
return (WALK_NEXT);
}
/*
* Function: buf_avforw_walk_fini
*
* Description: The buf_avforw_walk_fini is called when the walk is terminated
* in response to WALK_DONE in buf_avforw_walk_step. It frees
* the walk_data structure.
*
* Arguments: mdb_walk_state_t structure
*/
static void
{
}
/*
* Function: dump_xbuf_attr
*
* Description: Prints the contents of Xbuf queue.
*
* Arguments: object contents pointer and address.
*/
static void
{
mdb_printf("0x%8lx:\tmutex\t\tallocsize\tpending\n",
mdb_printf(" \t%lx\t\t%d\t\t%d\n",
mdb_printf("0x%8lx:\tactive_limit\tactive_count\tactive_lowater\n",
mdb_printf(" \t%lx\t\t%lx\t\t%lx\n",
mdb_printf("0x%8lx:\theadp\t\ttailp\n",
mdb_printf(" \t%lx%c\t%lx\n",
"0x%8lx:\treserve_mutex\treserve_limit\treserve_count\treserve_headp\n",
mdb_printf(" \t%lx\t\t%lx\t\t%lx\t\t%lx\n",
mdb_printf("0x%8lx:\ttimeid\t\ttq\n",
mdb_printf(" \t%lx%c\t%lx\n",
}
/*
* Function: init_softstate_members
*
* Description: Initialize mdb_walk_state_t structure with either 'sd' or
* 'ssd' related information.
*
* Arguments: new mdb_walk_state_t structure
*/
static int
{
/*
* store the soft state statistics variables like non-zero
* soft state entries, base address, actual count of soft state
* processed etc.
*/
SD_DATA(current_list_count) = 0;
SD_DATA(valid_root_count) = 0;
return (WALK_ERR);
}
return (WALK_NEXT);
}
#if (!defined(__fibre))
/*
* Function: sd_state_walk_init
*
* Description: MDB calls the init function to initiate the walk,
* in response to mdb_walk() function called by the
* dcmd 'sd_state' or when the user executes the
* walk dcmd '::walk sd_state'.
* The init function initializes the walker to either
* the user specified address or the default kernel
* 'sd_state' pointer.
*
* Arguments: new mdb_walk_state_t structure
*/
static int
{
mdb_warn("failed to read 'sd_state'");
return (WALK_ERR);
}
return (init_softstate_members(wsp));
}
#else
/*
* Function: ssd_state_walk_init
*
* Description: MDB calls the init function to initiate the walk,
* in response to mdb_walk() function called by the
* dcmd 'ssd_state' or when the user executes the
* walk dcmd '::walk ssd_state'.
* The init function initializes the walker to either
* the user specified address or the default kernel
* 'ssd_state' pointer.
*
* Arguments: new mdb_walk_state_t structure
*/
static int
{
mdb_warn("failed to read 'ssd_state'");
return (WALK_ERR);
}
return (init_softstate_members(wsp));
}
#endif
/*
* Function: sd_state_walk_step
*
* Description: The step function is invoked by the walker during each
* iteration. Its primary job is to determine the address
* of the next 'soft state' object, read in the local copy
* of this object, call the callback 'sd_callback' function,
* and return its status. The iteration is terminated when
* the soft state counter equals the total soft state count
* obtained initially.
*
* Arguments: mdb_walk_state_t structure
*/
static int
{
int status;
void *tp;
/*
* If all the soft state entries have been processed then stop
* future iterations.
*/
return (WALK_DONE);
}
/*
* read the object contents, invoke the callback and set the
* mdb_walk_state_t structure to the next object.
*/
return (WALK_ERR);
}
wsp->walk_cbdata);
if (tp != 0) {
/* Count the number of non-zero un entries. */
}
return (status);
}
/*
* Function: sd_state_walk_fini
*
* Description: The sd_state_walk_fini is called when the walk is terminated
* in response to WALK_DONE in sd_state_walk_step. It frees
* the walk_data structure.
*
* Arguments: mdb_walk_state_t structure
*/
static void
{
}
/*
* Function: process_semo_sleepq
*
* Description: Iterate over the semoclose wait Q members of the soft state.
* Print the contents of each member. In case of silent mode
* the contents are avoided and only the address is printed.
*
* Arguments: starting queue address, print mode.
*/
static int
{
int semo_sleepq_count = 0;
/* Set up to process the device's semoclose wait Q */
if (!silent) {
mdb_printf("\nSEMOCLOSE SLEEP Q:\n");
mdb_printf("----------\n");
}
while (rootBuf) {
/* Process the device's cmd. wait Q */
if (!silent) {
mdb_printf("SEMOCLOSE SLEEP Q list entry:\n");
mdb_printf("------------------\n");
}
rootBuf) == -1) {
return (FAIL);
}
if (!silent) {
mdb_eval("$<buf");
mdb_printf("---\n");
}
}
mdb_printf("------------------------------\n");
mdb_printf("Processed %d SEMOCLOSE SLEEP Q entries\n",
mdb_printf("------------------------------\n");
}
return (SUCCESS);
}
/*
* Function: process_sdlun_waitq
*
* Description: Iterate over the wait Q members of the soft state.
* Print the contents of each member. In case of silent mode
* the contents are avoided and only the address is printed.
*
* Arguments: starting queue address, print mode.
*/
static int
{
int sdLunQ_count = 0;
if (!silent) {
mdb_printf("\nUN WAIT Q:\n");
mdb_printf("----------\n");
}
while (rootBuf) {
/* Process the device's cmd. wait Q */
if (!silent) {
mdb_printf("UN WAIT Q list entry:\n");
mdb_printf("------------------\n");
}
mdb_warn("failed to read buf at %p",
return (FAIL);
}
if (!silent) {
mdb_eval("$<buf");
mdb_printf("---\n");
}
++sdLunQ_count;
}
mdb_printf("------------------------------\n");
mdb_printf("------------------------------\n");
}
return (SUCCESS);
}
/*
* Function: process_xbuf
*
* Description: Iterate over the Xbuf Attr and Xbuf Attr wait Q of the soft
* state.
* Print the contents of each member. In case of silent mode
* the contents are avoided and only the address is printed.
*
* Arguments: starting xbuf address, print mode.
*/
static int
{
void *xba_root;
int xbuf_q_count = 0;
mdb_printf("---------------------------\n");
mdb_printf("No XBUF ATTR entry\n");
mdb_printf("---------------------------\n");
return (SUCCESS);
}
/* Process the Xbuf Attr struct for a device. */
xbuf_attr) == -1) {
return (FAIL);
}
if (!silent) {
mdb_printf("\nXBUF ATTR:\n");
mdb_printf("----------\n");
mdb_printf("---\n");
mdb_printf("\nXBUF Q:\n");
mdb_printf("-------\n");
}
/* Process the Xbuf Attr wait Q, if there are any entries. */
if (!silent) {
mdb_printf("XBUF_Q list entry:\n");
mdb_printf("------------------\n");
}
mdb_warn("failed to read buf at %p",
return (FAIL);
}
if (!silent) {
mdb_eval("$<buf");
mdb_printf("---\n");
}
++xbuf_q_count;
}
mdb_printf("---------------------------\n");
mdb_printf("---------------------------\n");
}
return (SUCCESS);
}
/*
* Function: print_footer
*
* Description: Prints the footer if all the soft state entries are processed.
*
* Arguments: private storage of the walker.
*/
static void
{
if (SD_DATA_IN_CBACK(current_list_count) >=
mdb_printf("---------------------------\n");
mdb_printf("Processed %d UN softstate entries\n",
mdb_printf("---------------------------\n");
}
}
/*
* Function: sd_callback
*
* Description: This is the callback function called by the
* invokes the walker.
* It is called during each walk step. It displays the contents
* of the current soft state object (addr) passed to it by the
* step function. It also prints the header and footer during the
* first and the last step of the walker.
* The contents of the soft state also includes various queues
* it includes like Xbuf, semo_close, sdlun_waitq.
*
* Arguments: addr -> current soft state objects address.
* walk_data -> private storage for the walker.
* flg_silent -> private data for the callback. It represents
* the silent mode of operation.
*/
static int
{
/*
* If this is the first invocation of the command, print a
* header line for the output that will follow.
*/
if (SD_DATA_IN_CBACK(current_list_count) == 0) {
mdb_printf("walking sd_state units via ptr: %lx\n",
mdb_printf("%d entries in sd_state table\n",
}
addr);
mdb_printf("--------------\n");
/* if null soft state iterate over to next one */
if (addr == 0) {
return (SUCCESS);
}
/*
* For each buf, we need to read the sd_lun struct,
* and then print out its contents, and get the next.
*/
sizeof (sdLun)) {
if (!silent) {
mdb_eval("$<sd_lun");
mdb_printf("---\n");
}
} else {
return (FAIL);
}
/* process device Xbuf Attr struct and wait Q */
/* process device cmd wait Q */
/* process device semoclose wait Q */
silent);
}
/* print the actual number of soft state processed */
return (SUCCESS);
}
#if (!defined(__fibre))
/*
* Function: dcmd_sd_state
*
* Description: Scans through the sd soft state entries and prints their
* contents including of various queues it contains. It uses
* 'sd_state' walker to perform a global walk. If a particular
* soft state address is specified than it performs the above job
* itself (local walk).
*
* Arguments: addr -> user specified address or NULL if no address is
* specified.
* flags -> integer reflecting whether an address was specified,
* or if it was invoked by the walker in a loop etc.
* argc -> the number of arguments supplied to the dcmd.
* argv -> the actual arguments supplied by the user.
*/
/*ARGSUSED*/
static int
{
/* Enable the silent mode if '-s' option specified the user */
!= argc) {
return (DCMD_USAGE);
}
/*
* If no address is specified on the command line, perform
* a global walk invoking 'sd_state' walker. If a particular address
* is specified then print the soft state and its queues.
*/
if (!(flags & DCMD_ADDRSPEC)) {
return (DCMD_OK);
} else {
mdb_printf("--------------\n");
/* read the sd_lun struct and print the contents */
if (!silent) {
mdb_eval("$<sd_lun");
mdb_printf("---\n");
}
} else {
return (DCMD_OK);
}
/* process Xbuf Attr struct and wait Q for the soft state */
/* process device' cmd wait Q */
/* process device's semoclose wait Q */
}
}
return (DCMD_OK);
}
#else
/*
* Function: dcmd_ssd_state
*
* Description: Scans through the ssd soft state entries and prints their
* contents including of various queues it contains. It uses
* 'ssd_state' walker to perform a global walk. If a particular
* soft state address is specified than it performs the above job
* itself (local walk).
*
* Arguments: addr -> user specified address or NULL if no address is
* specified.
* flags -> integer reflecting whether an address was specified,
* or if it was invoked by the walker in a loop etc.
* argc -> the number of arguments supplied to the dcmd.
* argv -> the actual arguments supplied by the user.
*/
/*ARGSUSED*/
static int
{
/* Enable the silent mode if '-s' option specified the user */
!= argc) {
return (DCMD_USAGE);
}
/*
* If no address is specified on the command line, perform
* a global walk invoking 'sd_state' walker. If a particular address
* is specified then print the soft state and its queues.
*/
if (!(flags & DCMD_ADDRSPEC)) {
return (DCMD_OK);
} else {
mdb_printf("--------------\n");
/* read the sd_lun struct and print the contents */
if (!silent) {
mdb_eval("$<sd_lun");
mdb_printf("---\n");
}
} else {
return (DCMD_OK);
}
/* process Xbuf Attr struct and wait Q for the soft state */
/* process device' cmd wait Q */
/* process device's semoclose wait Q */
}
}
return (DCMD_OK);
}
#endif
/*
* Function: dcmd_buf_avforw
*
* Description: Scans through the buf list via av_forw and prints
* their contents.
* It uses the 'buf_avforw' walker to perform the walk.
*
* Arguments: addr -> user specified address.
* flags -> integer reflecting whether an address was specified,
* or if it was invoked by the walker in a loop etc.
* argc -> the number of arguments supplied to the dcmd.
* argv -> the actual arguments supplied by the user.
*/
/*ARGSUSED*/
static int
{
int buf_entries = 0;
/* it does not take any arguments */
if (argc != 0)
return (DCMD_USAGE);
/*
* If no address was specified on the command line, print the
* error msg, else scan and
* print out all the buffers available by invoking buf_avforw walker.
*/
if ((flags & DCMD_ADDRSPEC)) {
addr);
return (DCMD_OK);
} else {
mdb_printf("buffer address required with the command\n");
}
return (DCMD_USAGE);
}
/*
* MDB module linkage information:
*
* List of structures describing our dcmds, a list of structures
* describing our walkers, and a function named _mdb_init to return a pointer
* to our module information.
*/
#if (!defined(__fibre))
#else
#endif
{ NULL }
};
{ "buf_avforw", "walk list of buf_t structures via av_forw",
#if (!defined(__fibre))
{ "sd_state", "walk all sd soft state queues",
#else
{ "ssd_state", "walk all ssd soft state queues",
#endif
{ NULL }
};
};
/*
* Function: _mdb_init
*
* Description: Returns mdb_modinfo_t structure which provides linkage and
* module identification information to the debugger.
*
* Arguments: void
*/
const mdb_modinfo_t *
_mdb_init(void)
{
return (&modinfo);
}