/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (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 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#include <sys/dditypes.h>
#include <sys/mdb_modapi.h>
#include <stmf_impl.h>
#include <lun_map.h>
#include <stmf_state.h>
#include <fct_impl.h>
#include "cmd_options.h"
static int
{
"stmf_state") == -1) {
mdb_warn("failed to read stmf_state");
return (WALK_ERR);
}
}
return (WALK_NEXT);
}
static int
{
return (WALK_DONE);
mdb_warn("failed to read stmf_i_local_port_t at %p",
return (WALK_ERR);
}
if (wsp->walk_callback)
wsp->walk_cbdata);
return (status);
}
static void
{
}
static int
{
return (DCMD_OK);
if (verbose) {
/* here assume the alias is maximumly 1024 bytes */
== -1) {
mdb_warn("failed to read stmf_i_local_port at %p",
ilportp);
return (DCMD_ERR);
}
mdb_warn("failed to read stmf_local_port at %p",
return (DCMD_ERR);
}
mdb_warn("failed to read memory at %p",
return (DCMD_ERR);
}
if (lport.lport_alias)
}
return (DCMD_OK);
}
/*ARGSUSED*/
static int
{
int i;
int verbose = 0;
for (i = 0; i < argc; i++) {
if (ptr[0] == '-')
ptr++;
while (*ptr) {
if (*ptr == 'v')
verbose = 1;
ptr++;
}
}
return (DCMD_ERR);
return (DCMD_OK);
}
struct stmf_i_local_port *
{
return (NULL);
}
}
return (NULL);
}
}
/*ARGSUSED*/
static int
{
int i;
int verbose = 0;
for (i = 0; i < argc; i++) {
if (ptr[0] == '-')
ptr++;
while (*ptr) {
if (*ptr == 'v')
verbose = 1;
ptr++;
}
}
mdb_warn("address of stmf_i_local_port should be specified\n");
return (DCMD_ERR);
}
/*
* Input should be stmf_i_local_port_t.
*/
!= sizeof (struct stmf_i_local_port)) {
return (DCMD_ERR);
}
while (issp) {
mdb_warn("failed to read stmf_i_scsi_session_t at %p",
issp);
return (DCMD_ERR);
}
if (verbose) {
}
}
return (DCMD_OK);
}
/*ARGSUSED*/
static int
{
int i;
int verbose = 0;
for (i = 0; i < argc; i++) {
if (ptr[0] == '-')
ptr++;
while (*ptr) {
if (*ptr == 'v')
verbose = 1;
ptr++;
}
}
== -1) {
mdb_warn("failed to read stmf_state");
return (DCMD_ERR);
}
while (ilup) {
== -1) {
return (DCMD_ERR);
}
if (verbose) {
/* XXX lu_alias? what is its size? */
}
}
return (DCMD_OK);
}
/*ARGSUSED*/
static int
{
int i;
int verbose = 0;
for (i = 0; i < argc; i++) {
if (ptr[0] == '-')
ptr++;
while (*ptr) {
if (*ptr == 'v')
verbose = 1;
ptr++;
}
}
== -1) {
mdb_warn("failed to read stmf_state");
return (DCMD_ERR);
}
while (ilpp) {
mdb_warn("failed to read stmf_i_lu_provider_t at %p",
ilpp);
return (DCMD_ERR);
}
if (verbose) {
}
}
return (DCMD_OK);
}
/*ARGSUSED*/
static int
{
int i;
int verbose = 0;
for (i = 0; i < argc; i++) {
if (ptr[0] == '-')
ptr++;
while (*ptr) {
if (*ptr == 'v')
verbose = 1;
ptr++;
}
}
== -1) {
mdb_warn("failed to read stmf_state");
return (DCMD_ERR);
}
while (ippp) {
mdb_warn("failed to read stmf_i_port_provider_t at %p",
ippp);
return (DCMD_ERR);
}
if (verbose) {
}
}
return (DCMD_OK);
}
static int rp_index;
/*
* Cervert stmf_i_local_port to fct_i_local_port
*/
/*ARGSUSED*/
static struct fct_i_local_port *
{
if (!(flags & DCMD_ADDRSPEC)) {
mdb_warn("stmf_i_local_port address should be specified");
return (NULL);
}
/*
* Input should be stmf_i_local_port_t.
*/
!= sizeof (struct stmf_i_local_port)) {
mdb_warn("Unable to read in stmf_i_local_port\n");
return (NULL);
}
mdb_warn("Unable to read in stmf_local_port\n");
return (NULL);
}
!= sizeof (fct_local_port_t)) {
mdb_warn("Unable to read in fct_local_port\n");
return (NULL);
}
return (fport.port_fct_private);
}
static int
{
int i;
int verbose = 0;
for (i = 0; i < argc; i++) {
if (ptr[0] == '-')
ptr++;
while (*ptr) {
if (*ptr == 'v')
verbose = 1;
ptr++;
}
}
if (iportp) {
if (verbose) {
/* is the alias always 16 bytes in size ? */
!= sizeof (fct_i_local_port_t)) {
mdb_warn("Unable to read in fct_i_local_port"
"at %p\n", iportp);
return (DCMD_ERR);
}
if (iport.iport_alias &&
!= sizeof (alias)) {
mdb_warn("Unable to read in memory at %p",
return (DCMD_ERR);
}
if (iport.iport_alias)
}
}
return (DCMD_OK);
}
/*
* by wwn, we can only find one local port
*/
static struct stmf_i_local_port *
{
0, NULL);
return (NULL);
!= sizeof (fct_i_local_port_t)) {
mdb_warn("Unable to read in fct_i_local_port\n");
return (NULL);
}
!= sizeof (fct_local_port_t)) {
mdb_warn("Unable to read in fct_local_port\n");
return (NULL);
}
#if 0
mdb_printf("pwwn=%02x%02x%02x%02x%02x%02x%02x%02x\n",
#endif
return (siport);
}
}
return (NULL);
}
/*ARGSUSED*/
static int
{
/* need to free options manually ? */
mdb_printf("lpname=<wwn.12345678 or 12345678> "
"should be specified\n");
return (DCMD_OK);
}
return (DCMD_OK);
}
static int
{
mdb_warn("Can not perform global walk");
return (WALK_ERR);
}
/*
* Input should be fct_i_local_port_t.
*/
!= sizeof (struct fct_i_local_port)) {
mdb_warn("Unable to read in fct_i_local_port\n");
return (WALK_ERR);
}
!= sizeof (struct fct_local_port)) {
mdb_warn("Unable to read in fct_local_port\n");
return (WALK_ERR);
}
rp_index = 0;
return (WALK_NEXT);
}
static int
{
return (WALK_DONE);
if (rp_index++ >= port_max_logins)
return (WALK_DONE);
mdb_warn("failed to read address of fct_i_remote_port_t at %p",
return (WALK_DONE);
}
wsp->walk_cbdata);
return (status);
}
static void
{
}
/*
* to set remote_port
*/
/*ARGSUSED*/
static int
{
return (WALK_NEXT);
}
static int
{
int i;
int verbose = 0;
for (i = 0; i < argc; i++) {
if (ptr[0] == '-')
ptr++;
while (*ptr) {
if (*ptr == 'v')
verbose = 1;
ptr++;
}
}
if (!(flags & DCMD_ADDRSPEC)) {
mdb_warn("fct_i_local_port_t address should be specified");
return (DCMD_ERR);
}
fct_irp_walk_i(&ws);
if (irpp) {
if (verbose) {
mdb_warn("Unable to read in "
"fct_i_remote_port at %p\n", irpp);
return (DCMD_ERR);
}
}
}
}
fct_irp_walk_f(&ws);
return (DCMD_OK);
}
static fct_i_remote_port_t *
{
int ret;
fct_irp_walk_f(&ws);
return (NULL);
}
fct_irp_walk_f(&ws);
return (NULL);
}
}
return (irp);
}
}
fct_irp_walk_f(&ws);
/*
* If it is WALK_DONE, there may be one remote port there
*/
return (irp);
}
return (NULL);
}
static struct stmf_i_local_port *
{
!= sizeof (struct fct_i_remote_port)) {
mdb_warn("Unable to read in fct_i_remote_port\n");
return (NULL);
}
!= sizeof (struct fct_remote_port)) {
mdb_warn("Unable to read in fct_remote_port\n");
return (NULL);
}
!= sizeof (struct fct_local_port)) {
mdb_warn("Unable to read in fct_local_port\n");
return (NULL);
}
!= sizeof (struct stmf_local_port)) {
mdb_warn("Unable to read in stmf_local_port\n");
return (NULL);
}
return (lport.lport_stmf_private);
}
/*
* by wwn, we may find more than one remote port, so we need to know its
* corresponding local port
*/
static struct fct_i_remote_port *
{
return (NULL);
!= sizeof (struct fct_i_remote_port)) {
mdb_warn("Unable to read in fct_i_remote_port\n");
break;
}
!= sizeof (struct fct_remote_port)) {
mdb_warn("Unable to read in fct_remote_port\n");
break;
}
break;
}
}
return (ret);
}
/*ARGSUSED*/
static int
{
/* need to free options manually ? */
options->rp_defined == 0)) {
mdb_printf("rpname=<wwn.12345678> or rp=<3000586778734>"
" should be specified\n");
return (DCMD_OK);
}
mdb_printf("rpname=<wwn.12345678> or rp=<3000586778734>"
" should be specified, but not both\n");
return (DCMD_OK);
}
if (options->rp_defined) {
mdb_printf("stmf_i_local_port=%p,"
" fct_i_remote_port=%p\n",
return (DCMD_OK);
}
/* if options->rpname_defined */
mdb_printf("stmf_i_local_port=%p, "
"fct_i_remote_port=%p\n",
}
return (DCMD_OK);
}
struct find_options *, void *);
/*ARGSUSED*/
static void
{
mdb_warn("Unable to read in fct_i_cmd\n");
return;
}
mdb_warn("Unable to read in fct_cmd\n");
return;
}
int colon_printed = 0;
!= sizeof (struct scsi_task)) {
mdb_warn("Unable to read in scsi_task\n");
return;
}
if (options->show_task_flags) {
mdb_printf(":");
colon_printed = 1;
}
if (options->show_lport) {
if (colon_printed == 0) {
mdb_printf(":");
colon_printed = 1;
}
}
mdb_printf("\n");
}
}
static void
void *arg)
{
mdb_warn("Unable to read in fct_i_cmd\n");
return;
}
mdb_warn("Unable to read in fct_cmd\n");
return;
}
/* arg is a pointer to fct_i_remote_port */
mdb_warn("Unable to read in fct_i_remote_port\n");
return;
}
int colon_printed = 0;
!= sizeof (struct scsi_task)) {
mdb_warn("Unable to read in scsi_task\n");
return;
}
if (options->show_task_flags) {
mdb_printf(":");
colon_printed = 1;
}
if (options->show_lport) {
if (colon_printed == 0) {
mdb_printf(":");
colon_printed = 1;
}
}
mdb_printf("\n");
}
}
/*ARGSUSED*/
static void
{
}
/*
* find outstanding cmds (fct_i_cmd) on local port
*/
static int
{
int i;
return (DCMD_ERR);
mdb_warn("Unable to read in fct_i_local_port\n");
return (DCMD_ERR);
}
mdb_warn("Unable to read in fct_local_port\n");
return (DCMD_ERR);
}
for (i = 0; i < port.port_max_xchges; i++) {
mdb_warn("Unable to read in fct_cmd_slot\n");
return (DCMD_ERR);
}
else
}
slotp ++;
}
return (DCMD_OK);
}
/*ARGSUSED*/
static int
{
mdb_printf("lpname=<wwn.12345678> or rpname=<wwn.12345678>"
" should be specified\n");
return (DCMD_OK);
}
if (options->lpname_defined) {
return (DCMD_ERR);
return (DCMD_OK);
}
if (options->rpname_defined) {
!= NULL) {
}
}
}
return (DCMD_OK);
}
/*ARGSUSED*/
static int
{
mdb_printf("lpname=<wwn.12345678> should be specified\n");
return (DCMD_OK);
}
return (DCMD_ERR);
return (DCMD_OK);
}
static int
{
int i;
int verbose = 0;
for (i = 0; i < argc; i++) {
if (ptr[0] == '-')
ptr++;
while (*ptr) {
if (*ptr == 'v')
verbose = 1;
ptr++;
}
}
if (!(flags & DCMD_ADDRSPEC)) {
mdb_warn("fct_i_local_port_t address should be specified");
return (DCMD_ERR);
}
!= sizeof (struct fct_i_local_port)) {
return (DCMD_ERR);
}
while (icmdp) {
return (DCMD_ERR);
}
if (verbose) {
}
}
return (DCMD_OK);
}
/*
* Walker to list the addresses of all the active STMF scsi tasks (scsi_task_t),
* given a stmf_worker address
*
* To list all the active STMF scsi tasks, use
* "::walk stmf_worker |::walk stmf_scsi_task"
* To list the active tasks of a particular worker, use
* <stmf_worker addr>::walk stmf_scsi_task
*/
static int
{
/*
* Input should be a stmf_worker, so read it to get the
* worker_task_head to get the start of the task list
*/
mdb_warn("<worker addr>::walk stmf_scsi_task\n");
return (WALK_ERR);
}
sizeof (stmf_worker_t)) {
mdb_warn("failed to read in the task address\n");
return (WALK_ERR);
}
return (WALK_NEXT);
}
static int
{
int status;
return (WALK_DONE);
}
/* Save the stmf_i_scsi_task for use later to get the next entry */
mdb_warn("failed to read stmf_i_scsi_task at %p",
return (WALK_DONE);
}
return (DCMD_ERR);
}
wsp->walk_cbdata);
return (status);
}
static void
{
}
/*ARGSUSED*/
static int
{
/*
* A stmf_worker address is given to the left of ::stmf_scsi_task
* i.e. display the scsi_task for the given worker
*/
if (!(flags & DCMD_ADDRSPEC)) {
argv) == -1) {
mdb_warn("Failed to walk the stmf_scsi_task entries");
return (DCMD_ERR);
}
return (DCMD_OK);
}
mdb_printf("%<u>%-19s %-10s %-19s%</u>\n",
"scsi_task_t", "Flags", "LPort");
}
addr) != sizeof (stmf_worker_t)) {
mdb_warn("failed to read in the worker address");
return (DCMD_ERR);
}
/* Read the scsi_task */
return (DCMD_OK);
}
mdb_warn("failed to read stmf_i_scsi_task_t at %p",
return (DCMD_ERR);
}
return (DCMD_ERR);
}
if ((flags & DCMD_PIPE_OUT)) {
} else {
/* pretty print */
mdb_printf("%-19p %-10x %-19p\n",
}
return (DCMD_OK);
}
/*
* Walker to list the addresses of all the stmf_worker in the queue
*/
typedef struct stmf_worker_walk_data {
int worker_current;
int worker_count;
/* stmf_workers_state definition from stmf.c (static) */
enum {
/*
* Initialize the stmf_worker_t walker by either using the given starting
* address, or reading the value of the kernel's global stmf_workers pointer.
*/
/*ARGSUSED*/
static int
{
int worker_state;
int nworkers;
mdb_warn("failed to read stmf_workers_state");
return (WALK_ERR);
}
if (worker_state != STMF_WORKERS_ENABLED) {
mdb_warn("stmf_workers_state not initialized");
return (WALK_ERR);
}
/*
* Look up the stmf_nworkers_accepting_cmds to
* determine number of entries in the worker queue
*/
mdb_warn("failed to read stmf_nworkers_accepting_cmds");
return (WALK_ERR);
}
mdb_warn("failed to read stmf_workers");
return (WALK_ERR);
}
walk_data->worker_current = 0;
return (WALK_NEXT);
}
static int
{
int status;
return (WALK_DONE);
}
return (WALK_DONE);
}
wsp->walk_cbdata);
return (status);
}
static void
{
}
int
{
if (!(flags & DCMD_ADDRSPEC)) {
argv) == -1) {
mdb_warn("Failed to walk the stmf_worker entries");
return (DCMD_ERR);
}
return (DCMD_OK);
}
addr) != sizeof (stmf_worker_t)) {
return (DCMD_ERR);
}
if (flags & DCMD_PIPE_OUT) {
} else {
/* pretty print */
if (DCMD_HDRSPEC(flags)) {
mdb_printf("%<u>%-19s %-10s %-10s %-10s%</u>\n",
"stmf_worker_t", "State", "Ref_Count", "Tasks");
}
"ACTIVE" : "TERMINATED",
}
return (DCMD_OK);
}
struct find_options *
{
int i;
int len;
char *ptr;
int ret;
if (argc == 0)
return (NULL);
for (i = 0; i < argc; i++) {
case MDB_TYPE_STRING:
break;
case MDB_TYPE_IMMEDIATE:
case MDB_TYPE_CHAR:
mdb_printf("unknown type\n");
}
mdb_printf("invalid argument: %s\n",
goto out;
}
ptr++; /* point to value now */
ptr += 4;
if (ret == -1)
goto out;
#if 0
mdb_printf("wwn=%02x%02x%02x%02x%02x%02x%02x%02x\n",
#endif
(void *)(unsigned long)mdb_strtoull(ptr);
ptr += 4;
if (ret == -1)
goto out;
char *s;
int l;
for (;;) {
if (s)
l = s - ptr;
else
if (l == strlen("task_flags") &&
else if (l == strlen("lport") &&
else {
mdb_printf("unknown shower: %s\n",
ptr);
goto out;
}
if (s == NULL)
break;
ptr = s + 1;
}
} else {
mdb_printf("unknown argument: %s\n",
goto out;
}
}
return (options);
out:
return (NULL);
}
int
{
int i;
char *p;
if (strlen(s) > 16) {
mdb_printf("invalid wwn %s\n", s);
return (-1);
}
/* figure out wwn from the tail to beginning */
wwn[i] = mdb_strtoull(p);
*p = 0;
}
return (0);
}
void
fct_find_cmds_help(void)
{
"Find all cached fct_i_cmd_t for a local port. If a local port \n"
"name is specified, find all pending cmds for it and print the \n"
"address. Example:\n"
" fct_find_cmds lpname=<wwn.12345678 or 12345678>\n");
}
void
stmf_find_ilport_help(void)
{
"Find the fct_i_local_port if local port name is "
"specified. Example:\n"
" stmf_find_ilport lpname=<wwn.12345678 or 12345678>\n");
}
void
stmf_find_fct_irp_help(void)
{
"If a remote port name or stmf_i_remote_port_t address is\n"
"specified, loop through all local ports, to which this remote \n"
"port has logged in, print address for stmf_i_local_port_t and \n"
"stmf_i_remote_port. Example:\n"
" stmf_find_fct_irp rpname=<wwn.12345678 or 12345678>\n"
" stmf_find_fct_irp rp=<3000586778734>\n");
}
void
stmf_find_tasks_help(void)
{
"remote port. Various different fields for each task are printed\n"
"depending on what is requested. Example:\n"
" stmf_find_tasks rpname=<wwn.12345678 or 12345678>\n"
" stmf_find_tasks lpname=<wwn.12345678 or 12345678> "
"show=task_flags,lport\n");
}
void
stmf_scsi_task_help(void)
{
"List all active scsi_task_t on a given stmf_worker_t. Example\n"
" addr::stmf_scsi_task\n");
}
{ "stmf_ilports", "[-v]",
"Print a list of stmf_i_local_port", stmf_ilports },
{ "ilport2iport", "?[-v]",
"Convert stmf_i_local_port to corresponding fct_i_local_port",
ilport2iport },
{ "stmf_iss", "?[-v]",
"List all active sessions for a given local port",
stmf_iss },
{ "stmf_i_lu_providers", "[-v]",
"Print a list of stmf_i_lu_provider", stmf_i_lu_providers },
{ "stmf_i_port_providers", "[-v]",
"Print a list of stmf_i_port_provider", stmf_i_port_providers },
{ "fct_irps", "?[-v]",
"Print all fct_i_remote_port for a given fct_i_local_port",
fct_irps },
{ "fct_icmds", "?[-v]",
"Print all cached fct_i_cmd_t on fct_i_local_port",
fct_icmds },
{ "fct_find_cmds", "lpname",
"Find all fct_i_cmd_t for a given local port",
{ "stmf_find_ilport", "lpname",
"Find local port information based on its wwn",
{ "stmf_find_fct_irp", "rpname|rp",
"Print fct remote port information based on its wwn",
{ "stmf_find_tasks", "lpname|rpname [show]",
"Find all pending task for a local port or remote port",
{ "stmf_scsi_task", ":",
"List all the active STMF SCSI tasks per worker", stmf_scsi_task,
{ NULL }
};
{ "stmf_scsi_task", "Walk active STMF SCSI tasks per worker",
{ NULL }
};
};
const mdb_modinfo_t *
_mdb_init(void)
{
return (&modinfo);
}