1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 2003 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*7c478bd9Sstevel@tonic-gate 29*7c478bd9Sstevel@tonic-gate #include <sys/mdb_modapi.h> 30*7c478bd9Sstevel@tonic-gate #include <sys/scsi/scsi.h> 31*7c478bd9Sstevel@tonic-gate #include <sys/dkio.h> 32*7c478bd9Sstevel@tonic-gate #include <sys/taskq.h> 33*7c478bd9Sstevel@tonic-gate #include <sys/scsi/targets/sddef.h> 34*7c478bd9Sstevel@tonic-gate 35*7c478bd9Sstevel@tonic-gate /* Represents global soft state data in walk_step, walk_init */ 36*7c478bd9Sstevel@tonic-gate #define SD_DATA(param) ((sd_str_p)wsp->walk_data)->param 37*7c478bd9Sstevel@tonic-gate 38*7c478bd9Sstevel@tonic-gate /* Represents global soft state data in callback and related routines */ 39*7c478bd9Sstevel@tonic-gate #define SD_DATA_IN_CBACK(param) ((sd_str_p)walk_data)->param 40*7c478bd9Sstevel@tonic-gate 41*7c478bd9Sstevel@tonic-gate #define SUCCESS WALK_NEXT 42*7c478bd9Sstevel@tonic-gate #define FAIL WALK_ERR 43*7c478bd9Sstevel@tonic-gate 44*7c478bd9Sstevel@tonic-gate /* 45*7c478bd9Sstevel@tonic-gate * Primary attribute struct for buf extensions. 46*7c478bd9Sstevel@tonic-gate */ 47*7c478bd9Sstevel@tonic-gate struct __ddi_xbuf_attr { 48*7c478bd9Sstevel@tonic-gate kmutex_t xa_mutex; 49*7c478bd9Sstevel@tonic-gate size_t xa_allocsize; 50*7c478bd9Sstevel@tonic-gate uint32_t xa_pending; /* call to xbuf_iostart() is iminent */ 51*7c478bd9Sstevel@tonic-gate uint32_t xa_active_limit; 52*7c478bd9Sstevel@tonic-gate uint32_t xa_active_count; 53*7c478bd9Sstevel@tonic-gate uint32_t xa_active_lowater; 54*7c478bd9Sstevel@tonic-gate struct buf *xa_headp; /* FIFO buf queue head ptr */ 55*7c478bd9Sstevel@tonic-gate struct buf *xa_tailp; /* FIFO buf queue tail ptr */ 56*7c478bd9Sstevel@tonic-gate kmutex_t xa_reserve_mutex; 57*7c478bd9Sstevel@tonic-gate uint32_t xa_reserve_limit; 58*7c478bd9Sstevel@tonic-gate uint32_t xa_reserve_count; 59*7c478bd9Sstevel@tonic-gate void *xa_reserve_headp; 60*7c478bd9Sstevel@tonic-gate void (*xa_strategy)(struct buf *, void *, void *); 61*7c478bd9Sstevel@tonic-gate void *xa_attr_arg; 62*7c478bd9Sstevel@tonic-gate timeout_id_t xa_timeid; 63*7c478bd9Sstevel@tonic-gate taskq_t *xa_tq; 64*7c478bd9Sstevel@tonic-gate }; 65*7c478bd9Sstevel@tonic-gate 66*7c478bd9Sstevel@tonic-gate /* 67*7c478bd9Sstevel@tonic-gate * Provides soft state information like the number of elements, pointer 68*7c478bd9Sstevel@tonic-gate * to soft state elements etc 69*7c478bd9Sstevel@tonic-gate */ 70*7c478bd9Sstevel@tonic-gate typedef struct i_ddi_soft_state sd_state_str_t, *sd_state_str_ptr; 71*7c478bd9Sstevel@tonic-gate 72*7c478bd9Sstevel@tonic-gate /* structure to store soft state statistics */ 73*7c478bd9Sstevel@tonic-gate typedef struct sd_str { 74*7c478bd9Sstevel@tonic-gate void *sd_state; 75*7c478bd9Sstevel@tonic-gate uintptr_t current_root; 76*7c478bd9Sstevel@tonic-gate int current_list_count; 77*7c478bd9Sstevel@tonic-gate int valid_root_count; 78*7c478bd9Sstevel@tonic-gate int silent; 79*7c478bd9Sstevel@tonic-gate sd_state_str_t sd_state_data; 80*7c478bd9Sstevel@tonic-gate } sd_str_t, *sd_str_p; 81*7c478bd9Sstevel@tonic-gate 82*7c478bd9Sstevel@tonic-gate 83*7c478bd9Sstevel@tonic-gate /* 84*7c478bd9Sstevel@tonic-gate * Function: buf_avforw_walk_init 85*7c478bd9Sstevel@tonic-gate * 86*7c478bd9Sstevel@tonic-gate * Description: MDB calls the init function to initiate the walk, 87*7c478bd9Sstevel@tonic-gate * in response to mdb_walk() function called by the 88*7c478bd9Sstevel@tonic-gate * dcmd 'buf_avforw' or when the user executes the 89*7c478bd9Sstevel@tonic-gate * walk dcmd 'address::walk buf_avforw'. 90*7c478bd9Sstevel@tonic-gate * 91*7c478bd9Sstevel@tonic-gate * Arguments: new mdb_walk_state_t structure. A new structure is 92*7c478bd9Sstevel@tonic-gate * created for each walk, so that multiple instances of 93*7c478bd9Sstevel@tonic-gate * the walker can be active simultaneously. 94*7c478bd9Sstevel@tonic-gate */ 95*7c478bd9Sstevel@tonic-gate static int 96*7c478bd9Sstevel@tonic-gate buf_avforw_walk_init(mdb_walk_state_t *wsp) 97*7c478bd9Sstevel@tonic-gate { 98*7c478bd9Sstevel@tonic-gate if (wsp->walk_addr == NULL) { 99*7c478bd9Sstevel@tonic-gate mdb_warn("buffer address required with the command\n"); 100*7c478bd9Sstevel@tonic-gate return (WALK_ERR); 101*7c478bd9Sstevel@tonic-gate } 102*7c478bd9Sstevel@tonic-gate 103*7c478bd9Sstevel@tonic-gate wsp->walk_data = mdb_alloc(sizeof (buf_t), UM_SLEEP); 104*7c478bd9Sstevel@tonic-gate return (WALK_NEXT); 105*7c478bd9Sstevel@tonic-gate } 106*7c478bd9Sstevel@tonic-gate 107*7c478bd9Sstevel@tonic-gate 108*7c478bd9Sstevel@tonic-gate /* 109*7c478bd9Sstevel@tonic-gate * Function: buf_avforw_walk_step 110*7c478bd9Sstevel@tonic-gate * 111*7c478bd9Sstevel@tonic-gate * Description: The step function is invoked by the walker during each 112*7c478bd9Sstevel@tonic-gate * iteration. Its primary job is to determine the address 113*7c478bd9Sstevel@tonic-gate * of the next 'buf_avforw' object, read in the local copy 114*7c478bd9Sstevel@tonic-gate * of this object, call the callback 'buf_callback' function, 115*7c478bd9Sstevel@tonic-gate * and return its status. The iteration is terminated when 116*7c478bd9Sstevel@tonic-gate * the walker encounters a null queue pointer which signifies 117*7c478bd9Sstevel@tonic-gate * end of queue. 118*7c478bd9Sstevel@tonic-gate * 119*7c478bd9Sstevel@tonic-gate * Arguments: mdb_walk_state_t structure 120*7c478bd9Sstevel@tonic-gate */ 121*7c478bd9Sstevel@tonic-gate static int 122*7c478bd9Sstevel@tonic-gate buf_avforw_walk_step(mdb_walk_state_t *wsp) 123*7c478bd9Sstevel@tonic-gate { 124*7c478bd9Sstevel@tonic-gate int status; 125*7c478bd9Sstevel@tonic-gate 126*7c478bd9Sstevel@tonic-gate /* 127*7c478bd9Sstevel@tonic-gate * if walk_addr is null then it effectively means an end of all 128*7c478bd9Sstevel@tonic-gate * buf structures, hence end the iterations. 129*7c478bd9Sstevel@tonic-gate */ 130*7c478bd9Sstevel@tonic-gate if (wsp->walk_addr == NULL) { 131*7c478bd9Sstevel@tonic-gate return (WALK_DONE); 132*7c478bd9Sstevel@tonic-gate } 133*7c478bd9Sstevel@tonic-gate 134*7c478bd9Sstevel@tonic-gate /* 135*7c478bd9Sstevel@tonic-gate * Read the contents of the current object, invoke the callback 136*7c478bd9Sstevel@tonic-gate * and assign the next objects address to mdb_walk_state_t structure. 137*7c478bd9Sstevel@tonic-gate */ 138*7c478bd9Sstevel@tonic-gate if (mdb_vread(wsp->walk_data, sizeof (buf_t), wsp->walk_addr) == -1) { 139*7c478bd9Sstevel@tonic-gate mdb_warn("failed to read buf at %p", wsp->walk_addr); 140*7c478bd9Sstevel@tonic-gate return (WALK_DONE); 141*7c478bd9Sstevel@tonic-gate } 142*7c478bd9Sstevel@tonic-gate 143*7c478bd9Sstevel@tonic-gate status = wsp->walk_callback(wsp->walk_addr, wsp->walk_data, 144*7c478bd9Sstevel@tonic-gate wsp->walk_cbdata); 145*7c478bd9Sstevel@tonic-gate wsp->walk_addr = (uintptr_t)(((buf_t *)wsp->walk_data)->av_forw); 146*7c478bd9Sstevel@tonic-gate 147*7c478bd9Sstevel@tonic-gate return (status); 148*7c478bd9Sstevel@tonic-gate } 149*7c478bd9Sstevel@tonic-gate 150*7c478bd9Sstevel@tonic-gate /* 151*7c478bd9Sstevel@tonic-gate * Function: buf_callback 152*7c478bd9Sstevel@tonic-gate * 153*7c478bd9Sstevel@tonic-gate * Description: This is the callback function called by the 'buf_avforw' 154*7c478bd9Sstevel@tonic-gate * walker when 'buf_avforw' dcmd is invoked. 155*7c478bd9Sstevel@tonic-gate * It is called during each walk step. It displays the contents 156*7c478bd9Sstevel@tonic-gate * of the current object (addr) passed to it by the step 157*7c478bd9Sstevel@tonic-gate * function. It also prints the header and footer during the 158*7c478bd9Sstevel@tonic-gate * first and the last iteration of the walker. 159*7c478bd9Sstevel@tonic-gate * 160*7c478bd9Sstevel@tonic-gate * Arguments: addr -> current buf_avforw objects address. 161*7c478bd9Sstevel@tonic-gate * walk_data -> private storage for the walker. 162*7c478bd9Sstevel@tonic-gate * buf_entries -> private data for the callback. It represents 163*7c478bd9Sstevel@tonic-gate * the count of objects processed so far. 164*7c478bd9Sstevel@tonic-gate */ 165*7c478bd9Sstevel@tonic-gate static int 166*7c478bd9Sstevel@tonic-gate buf_callback(uintptr_t addr, const void *walk_data, void *buf_entries) 167*7c478bd9Sstevel@tonic-gate { 168*7c478bd9Sstevel@tonic-gate int *count = (int *)buf_entries; 169*7c478bd9Sstevel@tonic-gate 170*7c478bd9Sstevel@tonic-gate /* 171*7c478bd9Sstevel@tonic-gate * If this is the first invocation of the command, print a 172*7c478bd9Sstevel@tonic-gate * header line for the output that will follow. 173*7c478bd9Sstevel@tonic-gate */ 174*7c478bd9Sstevel@tonic-gate if (*count == 0) { 175*7c478bd9Sstevel@tonic-gate mdb_printf("============================\n"); 176*7c478bd9Sstevel@tonic-gate mdb_printf("Walking buf list via av_forw\n"); 177*7c478bd9Sstevel@tonic-gate mdb_printf("============================\n"); 178*7c478bd9Sstevel@tonic-gate } 179*7c478bd9Sstevel@tonic-gate 180*7c478bd9Sstevel@tonic-gate /* 181*7c478bd9Sstevel@tonic-gate * read the object and print the contents. 182*7c478bd9Sstevel@tonic-gate */ 183*7c478bd9Sstevel@tonic-gate mdb_set_dot(addr); 184*7c478bd9Sstevel@tonic-gate mdb_eval("$<buf"); 185*7c478bd9Sstevel@tonic-gate 186*7c478bd9Sstevel@tonic-gate mdb_printf("---\n"); 187*7c478bd9Sstevel@tonic-gate (*count)++; 188*7c478bd9Sstevel@tonic-gate 189*7c478bd9Sstevel@tonic-gate /* if this is the last entry and print the footer */ 190*7c478bd9Sstevel@tonic-gate if (((buf_t *)walk_data)->av_forw == NULL) { 191*7c478bd9Sstevel@tonic-gate mdb_printf("---------------------------\n"); 192*7c478bd9Sstevel@tonic-gate mdb_printf("Processed %d Buf entries\n", *count); 193*7c478bd9Sstevel@tonic-gate mdb_printf("---------------------------\n"); 194*7c478bd9Sstevel@tonic-gate return (WALK_DONE); 195*7c478bd9Sstevel@tonic-gate } 196*7c478bd9Sstevel@tonic-gate 197*7c478bd9Sstevel@tonic-gate return (WALK_NEXT); 198*7c478bd9Sstevel@tonic-gate } 199*7c478bd9Sstevel@tonic-gate 200*7c478bd9Sstevel@tonic-gate /* 201*7c478bd9Sstevel@tonic-gate * Function: buf_avforw_walk_fini 202*7c478bd9Sstevel@tonic-gate * 203*7c478bd9Sstevel@tonic-gate * Description: The buf_avforw_walk_fini is called when the walk is terminated 204*7c478bd9Sstevel@tonic-gate * in response to WALK_DONE in buf_avforw_walk_step. It frees 205*7c478bd9Sstevel@tonic-gate * the walk_data structure. 206*7c478bd9Sstevel@tonic-gate * 207*7c478bd9Sstevel@tonic-gate * Arguments: mdb_walk_state_t structure 208*7c478bd9Sstevel@tonic-gate */ 209*7c478bd9Sstevel@tonic-gate static void 210*7c478bd9Sstevel@tonic-gate buf_avforw_walk_fini(mdb_walk_state_t *wsp) 211*7c478bd9Sstevel@tonic-gate { 212*7c478bd9Sstevel@tonic-gate mdb_free(wsp->walk_data, sizeof (buf_t)); 213*7c478bd9Sstevel@tonic-gate } 214*7c478bd9Sstevel@tonic-gate 215*7c478bd9Sstevel@tonic-gate /* 216*7c478bd9Sstevel@tonic-gate * Function: dump_xbuf_attr 217*7c478bd9Sstevel@tonic-gate * 218*7c478bd9Sstevel@tonic-gate * Description: Prints the contents of Xbuf queue. 219*7c478bd9Sstevel@tonic-gate * 220*7c478bd9Sstevel@tonic-gate * Arguments: object contents pointer and address. 221*7c478bd9Sstevel@tonic-gate */ 222*7c478bd9Sstevel@tonic-gate static void 223*7c478bd9Sstevel@tonic-gate dump_xbuf_attr(struct __ddi_xbuf_attr *xba_ptr, uintptr_t mem_addr) 224*7c478bd9Sstevel@tonic-gate { 225*7c478bd9Sstevel@tonic-gate mdb_printf("0x%8lx:\tmutex\t\tallocsize\tpending\n", 226*7c478bd9Sstevel@tonic-gate mem_addr + offsetof(struct __ddi_xbuf_attr, xa_mutex)); 227*7c478bd9Sstevel@tonic-gate 228*7c478bd9Sstevel@tonic-gate mdb_printf(" \t%lx\t\t%d\t\t%d\n", 229*7c478bd9Sstevel@tonic-gate xba_ptr->xa_mutex._opaque[0], xba_ptr->xa_allocsize, 230*7c478bd9Sstevel@tonic-gate xba_ptr->xa_pending); 231*7c478bd9Sstevel@tonic-gate mdb_printf("0x%8lx:\tactive_limit\tactive_count\tactive_lowater\n", 232*7c478bd9Sstevel@tonic-gate mem_addr + offsetof(struct __ddi_xbuf_attr, xa_active_limit)); 233*7c478bd9Sstevel@tonic-gate 234*7c478bd9Sstevel@tonic-gate mdb_printf(" \t%lx\t\t%lx\t\t%lx\n", 235*7c478bd9Sstevel@tonic-gate xba_ptr->xa_active_limit, xba_ptr->xa_active_count, 236*7c478bd9Sstevel@tonic-gate xba_ptr->xa_active_lowater); 237*7c478bd9Sstevel@tonic-gate mdb_printf("0x%8lx:\theadp\t\ttailp\n", 238*7c478bd9Sstevel@tonic-gate mem_addr + offsetof(struct __ddi_xbuf_attr, xa_headp)); 239*7c478bd9Sstevel@tonic-gate 240*7c478bd9Sstevel@tonic-gate mdb_printf(" \t%lx%c\t%lx\n", 241*7c478bd9Sstevel@tonic-gate xba_ptr->xa_headp, (xba_ptr->xa_headp == 0?'\t':' '), 242*7c478bd9Sstevel@tonic-gate xba_ptr->xa_tailp); 243*7c478bd9Sstevel@tonic-gate mdb_printf( 244*7c478bd9Sstevel@tonic-gate "0x%8lx:\treserve_mutex\treserve_limit\treserve_count\treserve_headp\n", 245*7c478bd9Sstevel@tonic-gate mem_addr + offsetof(struct __ddi_xbuf_attr, xa_reserve_mutex)); 246*7c478bd9Sstevel@tonic-gate 247*7c478bd9Sstevel@tonic-gate mdb_printf(" \t%lx\t\t%lx\t\t%lx\t\t%lx\n", 248*7c478bd9Sstevel@tonic-gate xba_ptr->xa_reserve_mutex._opaque[0], xba_ptr->xa_reserve_limit, 249*7c478bd9Sstevel@tonic-gate xba_ptr->xa_reserve_count, xba_ptr->xa_reserve_headp); 250*7c478bd9Sstevel@tonic-gate 251*7c478bd9Sstevel@tonic-gate mdb_printf("0x%8lx:\ttimeid\t\ttq\n", 252*7c478bd9Sstevel@tonic-gate mem_addr + offsetof(struct __ddi_xbuf_attr, xa_timeid)); 253*7c478bd9Sstevel@tonic-gate 254*7c478bd9Sstevel@tonic-gate mdb_printf(" \t%lx%c\t%lx\n", 255*7c478bd9Sstevel@tonic-gate xba_ptr->xa_timeid, (xba_ptr->xa_timeid == 0?'\t':' '), 256*7c478bd9Sstevel@tonic-gate xba_ptr->xa_tq); 257*7c478bd9Sstevel@tonic-gate } 258*7c478bd9Sstevel@tonic-gate 259*7c478bd9Sstevel@tonic-gate /* 260*7c478bd9Sstevel@tonic-gate * Function: init_softstate_members 261*7c478bd9Sstevel@tonic-gate * 262*7c478bd9Sstevel@tonic-gate * Description: Initialize mdb_walk_state_t structure with either 'sd' or 263*7c478bd9Sstevel@tonic-gate * 'ssd' related information. 264*7c478bd9Sstevel@tonic-gate * 265*7c478bd9Sstevel@tonic-gate * Arguments: new mdb_walk_state_t structure 266*7c478bd9Sstevel@tonic-gate */ 267*7c478bd9Sstevel@tonic-gate static int 268*7c478bd9Sstevel@tonic-gate init_softstate_members(mdb_walk_state_t *wsp) 269*7c478bd9Sstevel@tonic-gate { 270*7c478bd9Sstevel@tonic-gate wsp->walk_data = mdb_alloc(sizeof (sd_str_t), UM_SLEEP); 271*7c478bd9Sstevel@tonic-gate 272*7c478bd9Sstevel@tonic-gate /* 273*7c478bd9Sstevel@tonic-gate * store the soft state statistics variables like non-zero 274*7c478bd9Sstevel@tonic-gate * soft state entries, base address, actual count of soft state 275*7c478bd9Sstevel@tonic-gate * processed etc. 276*7c478bd9Sstevel@tonic-gate */ 277*7c478bd9Sstevel@tonic-gate SD_DATA(sd_state) = (sd_state_str_ptr)wsp->walk_addr; 278*7c478bd9Sstevel@tonic-gate 279*7c478bd9Sstevel@tonic-gate SD_DATA(current_list_count) = 0; 280*7c478bd9Sstevel@tonic-gate SD_DATA(valid_root_count) = 0; 281*7c478bd9Sstevel@tonic-gate 282*7c478bd9Sstevel@tonic-gate if (mdb_vread((void *)&SD_DATA(sd_state_data), 283*7c478bd9Sstevel@tonic-gate sizeof (sd_state_str_t), wsp->walk_addr) == -1) { 284*7c478bd9Sstevel@tonic-gate mdb_warn("failed to sd_state at %p", wsp->walk_addr); 285*7c478bd9Sstevel@tonic-gate return (WALK_ERR); 286*7c478bd9Sstevel@tonic-gate } 287*7c478bd9Sstevel@tonic-gate 288*7c478bd9Sstevel@tonic-gate wsp->walk_addr = (uintptr_t)(SD_DATA(sd_state_data.array)); 289*7c478bd9Sstevel@tonic-gate 290*7c478bd9Sstevel@tonic-gate SD_DATA(current_root) = wsp->walk_addr; 291*7c478bd9Sstevel@tonic-gate return (WALK_NEXT); 292*7c478bd9Sstevel@tonic-gate } 293*7c478bd9Sstevel@tonic-gate 294*7c478bd9Sstevel@tonic-gate #if (!defined(__fibre)) 295*7c478bd9Sstevel@tonic-gate /* 296*7c478bd9Sstevel@tonic-gate * Function: sd_state_walk_init 297*7c478bd9Sstevel@tonic-gate * 298*7c478bd9Sstevel@tonic-gate * Description: MDB calls the init function to initiate the walk, 299*7c478bd9Sstevel@tonic-gate * in response to mdb_walk() function called by the 300*7c478bd9Sstevel@tonic-gate * dcmd 'sd_state' or when the user executes the 301*7c478bd9Sstevel@tonic-gate * walk dcmd '::walk sd_state'. 302*7c478bd9Sstevel@tonic-gate * The init function initializes the walker to either 303*7c478bd9Sstevel@tonic-gate * the user specified address or the default kernel 304*7c478bd9Sstevel@tonic-gate * 'sd_state' pointer. 305*7c478bd9Sstevel@tonic-gate * 306*7c478bd9Sstevel@tonic-gate * Arguments: new mdb_walk_state_t structure 307*7c478bd9Sstevel@tonic-gate */ 308*7c478bd9Sstevel@tonic-gate static int 309*7c478bd9Sstevel@tonic-gate sd_state_walk_init(mdb_walk_state_t *wsp) 310*7c478bd9Sstevel@tonic-gate { 311*7c478bd9Sstevel@tonic-gate if (wsp->walk_addr == NULL && 312*7c478bd9Sstevel@tonic-gate mdb_readvar(&wsp->walk_addr, "sd_state") == -1) { 313*7c478bd9Sstevel@tonic-gate mdb_warn("failed to read 'sd_state'"); 314*7c478bd9Sstevel@tonic-gate return (WALK_ERR); 315*7c478bd9Sstevel@tonic-gate } 316*7c478bd9Sstevel@tonic-gate 317*7c478bd9Sstevel@tonic-gate return (init_softstate_members(wsp)); 318*7c478bd9Sstevel@tonic-gate } 319*7c478bd9Sstevel@tonic-gate 320*7c478bd9Sstevel@tonic-gate #else 321*7c478bd9Sstevel@tonic-gate 322*7c478bd9Sstevel@tonic-gate /* 323*7c478bd9Sstevel@tonic-gate * Function: ssd_state_walk_init 324*7c478bd9Sstevel@tonic-gate * 325*7c478bd9Sstevel@tonic-gate * Description: MDB calls the init function to initiate the walk, 326*7c478bd9Sstevel@tonic-gate * in response to mdb_walk() function called by the 327*7c478bd9Sstevel@tonic-gate * dcmd 'ssd_state' or when the user executes the 328*7c478bd9Sstevel@tonic-gate * walk dcmd '::walk ssd_state'. 329*7c478bd9Sstevel@tonic-gate * The init function initializes the walker to either 330*7c478bd9Sstevel@tonic-gate * the user specified address or the default kernel 331*7c478bd9Sstevel@tonic-gate * 'ssd_state' pointer. 332*7c478bd9Sstevel@tonic-gate * 333*7c478bd9Sstevel@tonic-gate * Arguments: new mdb_walk_state_t structure 334*7c478bd9Sstevel@tonic-gate */ 335*7c478bd9Sstevel@tonic-gate static int 336*7c478bd9Sstevel@tonic-gate ssd_state_walk_init(mdb_walk_state_t *wsp) 337*7c478bd9Sstevel@tonic-gate { 338*7c478bd9Sstevel@tonic-gate if (wsp->walk_addr == NULL && 339*7c478bd9Sstevel@tonic-gate mdb_readvar(&wsp->walk_addr, "ssd_state") == -1) { 340*7c478bd9Sstevel@tonic-gate mdb_warn("failed to read 'ssd_state'"); 341*7c478bd9Sstevel@tonic-gate return (WALK_ERR); 342*7c478bd9Sstevel@tonic-gate } 343*7c478bd9Sstevel@tonic-gate 344*7c478bd9Sstevel@tonic-gate return (init_softstate_members(wsp)); 345*7c478bd9Sstevel@tonic-gate } 346*7c478bd9Sstevel@tonic-gate #endif 347*7c478bd9Sstevel@tonic-gate 348*7c478bd9Sstevel@tonic-gate 349*7c478bd9Sstevel@tonic-gate /* 350*7c478bd9Sstevel@tonic-gate * Function: sd_state_walk_step 351*7c478bd9Sstevel@tonic-gate * 352*7c478bd9Sstevel@tonic-gate * Description: The step function is invoked by the walker during each 353*7c478bd9Sstevel@tonic-gate * iteration. Its primary job is to determine the address 354*7c478bd9Sstevel@tonic-gate * of the next 'soft state' object, read in the local copy 355*7c478bd9Sstevel@tonic-gate * of this object, call the callback 'sd_callback' function, 356*7c478bd9Sstevel@tonic-gate * and return its status. The iteration is terminated when 357*7c478bd9Sstevel@tonic-gate * the soft state counter equals the total soft state count 358*7c478bd9Sstevel@tonic-gate * obtained initially. 359*7c478bd9Sstevel@tonic-gate * 360*7c478bd9Sstevel@tonic-gate * Arguments: mdb_walk_state_t structure 361*7c478bd9Sstevel@tonic-gate */ 362*7c478bd9Sstevel@tonic-gate static int 363*7c478bd9Sstevel@tonic-gate sd_state_walk_step(mdb_walk_state_t *wsp) 364*7c478bd9Sstevel@tonic-gate { 365*7c478bd9Sstevel@tonic-gate int status; 366*7c478bd9Sstevel@tonic-gate void *tp; 367*7c478bd9Sstevel@tonic-gate 368*7c478bd9Sstevel@tonic-gate /* 369*7c478bd9Sstevel@tonic-gate * If all the soft state entries have been processed then stop 370*7c478bd9Sstevel@tonic-gate * future iterations. 371*7c478bd9Sstevel@tonic-gate */ 372*7c478bd9Sstevel@tonic-gate if (SD_DATA(current_list_count) >= SD_DATA(sd_state_data.n_items)) { 373*7c478bd9Sstevel@tonic-gate return (WALK_DONE); 374*7c478bd9Sstevel@tonic-gate } 375*7c478bd9Sstevel@tonic-gate 376*7c478bd9Sstevel@tonic-gate /* 377*7c478bd9Sstevel@tonic-gate * read the object contents, invoke the callback and set the 378*7c478bd9Sstevel@tonic-gate * mdb_walk_state_t structure to the next object. 379*7c478bd9Sstevel@tonic-gate */ 380*7c478bd9Sstevel@tonic-gate if (mdb_vread(&tp, sizeof (void *), wsp->walk_addr) == -1) { 381*7c478bd9Sstevel@tonic-gate mdb_warn("failed to read at %p", wsp->walk_addr); 382*7c478bd9Sstevel@tonic-gate return (WALK_ERR); 383*7c478bd9Sstevel@tonic-gate } 384*7c478bd9Sstevel@tonic-gate 385*7c478bd9Sstevel@tonic-gate status = wsp->walk_callback((uintptr_t)tp, wsp->walk_data, 386*7c478bd9Sstevel@tonic-gate wsp->walk_cbdata); 387*7c478bd9Sstevel@tonic-gate if (tp != 0) { 388*7c478bd9Sstevel@tonic-gate /* Count the number of non-zero un entries. */ 389*7c478bd9Sstevel@tonic-gate SD_DATA(valid_root_count++); 390*7c478bd9Sstevel@tonic-gate } 391*7c478bd9Sstevel@tonic-gate 392*7c478bd9Sstevel@tonic-gate wsp->walk_addr += sizeof (void *); 393*7c478bd9Sstevel@tonic-gate SD_DATA(current_list_count++); 394*7c478bd9Sstevel@tonic-gate return (status); 395*7c478bd9Sstevel@tonic-gate } 396*7c478bd9Sstevel@tonic-gate 397*7c478bd9Sstevel@tonic-gate 398*7c478bd9Sstevel@tonic-gate /* 399*7c478bd9Sstevel@tonic-gate * Function: sd_state_walk_fini 400*7c478bd9Sstevel@tonic-gate * 401*7c478bd9Sstevel@tonic-gate * Description: The sd_state_walk_fini is called when the walk is terminated 402*7c478bd9Sstevel@tonic-gate * in response to WALK_DONE in sd_state_walk_step. It frees 403*7c478bd9Sstevel@tonic-gate * the walk_data structure. 404*7c478bd9Sstevel@tonic-gate * 405*7c478bd9Sstevel@tonic-gate * Arguments: mdb_walk_state_t structure 406*7c478bd9Sstevel@tonic-gate */ 407*7c478bd9Sstevel@tonic-gate static void 408*7c478bd9Sstevel@tonic-gate sd_state_walk_fini(mdb_walk_state_t *wsp) 409*7c478bd9Sstevel@tonic-gate { 410*7c478bd9Sstevel@tonic-gate mdb_free(wsp->walk_data, sizeof (sd_str_t)); 411*7c478bd9Sstevel@tonic-gate } 412*7c478bd9Sstevel@tonic-gate 413*7c478bd9Sstevel@tonic-gate /* 414*7c478bd9Sstevel@tonic-gate * Function: process_semo_sleepq 415*7c478bd9Sstevel@tonic-gate * 416*7c478bd9Sstevel@tonic-gate * Description: Iterate over the semoclose wait Q members of the soft state. 417*7c478bd9Sstevel@tonic-gate * Print the contents of each member. In case of silent mode 418*7c478bd9Sstevel@tonic-gate * the contents are avoided and only the address is printed. 419*7c478bd9Sstevel@tonic-gate * 420*7c478bd9Sstevel@tonic-gate * Arguments: starting queue address, print mode. 421*7c478bd9Sstevel@tonic-gate */ 422*7c478bd9Sstevel@tonic-gate static int 423*7c478bd9Sstevel@tonic-gate process_semo_sleepq(uintptr_t walk_addr, int silent) 424*7c478bd9Sstevel@tonic-gate { 425*7c478bd9Sstevel@tonic-gate uintptr_t rootBuf; 426*7c478bd9Sstevel@tonic-gate buf_t currentBuf; 427*7c478bd9Sstevel@tonic-gate int semo_sleepq_count = 0; 428*7c478bd9Sstevel@tonic-gate 429*7c478bd9Sstevel@tonic-gate /* Set up to process the device's semoclose wait Q */ 430*7c478bd9Sstevel@tonic-gate rootBuf = walk_addr; 431*7c478bd9Sstevel@tonic-gate 432*7c478bd9Sstevel@tonic-gate if (!silent) { 433*7c478bd9Sstevel@tonic-gate mdb_printf("\nSEMOCLOSE SLEEP Q:\n"); 434*7c478bd9Sstevel@tonic-gate mdb_printf("----------\n"); 435*7c478bd9Sstevel@tonic-gate } 436*7c478bd9Sstevel@tonic-gate 437*7c478bd9Sstevel@tonic-gate mdb_printf("SEMOCLOSE sleep Q head: %lx\n", rootBuf); 438*7c478bd9Sstevel@tonic-gate 439*7c478bd9Sstevel@tonic-gate while (rootBuf) { 440*7c478bd9Sstevel@tonic-gate /* Process the device's cmd. wait Q */ 441*7c478bd9Sstevel@tonic-gate if (!silent) { 442*7c478bd9Sstevel@tonic-gate mdb_printf("SEMOCLOSE SLEEP Q list entry:\n"); 443*7c478bd9Sstevel@tonic-gate mdb_printf("------------------\n"); 444*7c478bd9Sstevel@tonic-gate } 445*7c478bd9Sstevel@tonic-gate 446*7c478bd9Sstevel@tonic-gate if (mdb_vread((void *)¤tBuf, sizeof (buf_t), 447*7c478bd9Sstevel@tonic-gate rootBuf) == -1) { 448*7c478bd9Sstevel@tonic-gate mdb_warn("failed to read buf at %p", rootBuf); 449*7c478bd9Sstevel@tonic-gate return (FAIL); 450*7c478bd9Sstevel@tonic-gate } 451*7c478bd9Sstevel@tonic-gate 452*7c478bd9Sstevel@tonic-gate if (!silent) { 453*7c478bd9Sstevel@tonic-gate mdb_set_dot(rootBuf); 454*7c478bd9Sstevel@tonic-gate mdb_eval("$<buf"); 455*7c478bd9Sstevel@tonic-gate mdb_printf("---\n"); 456*7c478bd9Sstevel@tonic-gate } 457*7c478bd9Sstevel@tonic-gate ++semo_sleepq_count; 458*7c478bd9Sstevel@tonic-gate rootBuf = (uintptr_t)currentBuf.av_forw; 459*7c478bd9Sstevel@tonic-gate } 460*7c478bd9Sstevel@tonic-gate 461*7c478bd9Sstevel@tonic-gate if (rootBuf == NULL) { 462*7c478bd9Sstevel@tonic-gate mdb_printf("------------------------------\n"); 463*7c478bd9Sstevel@tonic-gate mdb_printf("Processed %d SEMOCLOSE SLEEP Q entries\n", 464*7c478bd9Sstevel@tonic-gate semo_sleepq_count); 465*7c478bd9Sstevel@tonic-gate mdb_printf("------------------------------\n"); 466*7c478bd9Sstevel@tonic-gate 467*7c478bd9Sstevel@tonic-gate } 468*7c478bd9Sstevel@tonic-gate return (SUCCESS); 469*7c478bd9Sstevel@tonic-gate } 470*7c478bd9Sstevel@tonic-gate 471*7c478bd9Sstevel@tonic-gate /* 472*7c478bd9Sstevel@tonic-gate * Function: process_sdlun_waitq 473*7c478bd9Sstevel@tonic-gate * 474*7c478bd9Sstevel@tonic-gate * Description: Iterate over the wait Q members of the soft state. 475*7c478bd9Sstevel@tonic-gate * Print the contents of each member. In case of silent mode 476*7c478bd9Sstevel@tonic-gate * the contents are avoided and only the address is printed. 477*7c478bd9Sstevel@tonic-gate * 478*7c478bd9Sstevel@tonic-gate * Arguments: starting queue address, print mode. 479*7c478bd9Sstevel@tonic-gate */ 480*7c478bd9Sstevel@tonic-gate static int 481*7c478bd9Sstevel@tonic-gate process_sdlun_waitq(uintptr_t walk_addr, int silent) 482*7c478bd9Sstevel@tonic-gate { 483*7c478bd9Sstevel@tonic-gate uintptr_t rootBuf; 484*7c478bd9Sstevel@tonic-gate buf_t currentBuf; 485*7c478bd9Sstevel@tonic-gate int sdLunQ_count = 0; 486*7c478bd9Sstevel@tonic-gate 487*7c478bd9Sstevel@tonic-gate rootBuf = walk_addr; 488*7c478bd9Sstevel@tonic-gate 489*7c478bd9Sstevel@tonic-gate if (!silent) { 490*7c478bd9Sstevel@tonic-gate mdb_printf("\nUN WAIT Q:\n"); 491*7c478bd9Sstevel@tonic-gate mdb_printf("----------\n"); 492*7c478bd9Sstevel@tonic-gate } 493*7c478bd9Sstevel@tonic-gate mdb_printf("UN wait Q head: %lx\n", rootBuf); 494*7c478bd9Sstevel@tonic-gate 495*7c478bd9Sstevel@tonic-gate while (rootBuf) { 496*7c478bd9Sstevel@tonic-gate /* Process the device's cmd. wait Q */ 497*7c478bd9Sstevel@tonic-gate if (!silent) { 498*7c478bd9Sstevel@tonic-gate mdb_printf("UN WAIT Q list entry:\n"); 499*7c478bd9Sstevel@tonic-gate mdb_printf("------------------\n"); 500*7c478bd9Sstevel@tonic-gate } 501*7c478bd9Sstevel@tonic-gate 502*7c478bd9Sstevel@tonic-gate if (mdb_vread(¤tBuf, sizeof (buf_t), 503*7c478bd9Sstevel@tonic-gate (uintptr_t)rootBuf) == -1) { 504*7c478bd9Sstevel@tonic-gate mdb_warn("failed to read buf at %p", 505*7c478bd9Sstevel@tonic-gate (uintptr_t)rootBuf); 506*7c478bd9Sstevel@tonic-gate return (FAIL); 507*7c478bd9Sstevel@tonic-gate } 508*7c478bd9Sstevel@tonic-gate 509*7c478bd9Sstevel@tonic-gate if (!silent) { 510*7c478bd9Sstevel@tonic-gate mdb_set_dot(rootBuf); 511*7c478bd9Sstevel@tonic-gate mdb_eval("$<buf"); 512*7c478bd9Sstevel@tonic-gate mdb_printf("---\n"); 513*7c478bd9Sstevel@tonic-gate } 514*7c478bd9Sstevel@tonic-gate 515*7c478bd9Sstevel@tonic-gate rootBuf = (uintptr_t)currentBuf.av_forw; 516*7c478bd9Sstevel@tonic-gate ++sdLunQ_count; 517*7c478bd9Sstevel@tonic-gate } 518*7c478bd9Sstevel@tonic-gate 519*7c478bd9Sstevel@tonic-gate if (rootBuf == NULL) { 520*7c478bd9Sstevel@tonic-gate mdb_printf("------------------------------\n"); 521*7c478bd9Sstevel@tonic-gate mdb_printf("Processed %d UN WAIT Q entries\n", sdLunQ_count); 522*7c478bd9Sstevel@tonic-gate mdb_printf("------------------------------\n"); 523*7c478bd9Sstevel@tonic-gate } 524*7c478bd9Sstevel@tonic-gate 525*7c478bd9Sstevel@tonic-gate return (SUCCESS); 526*7c478bd9Sstevel@tonic-gate } 527*7c478bd9Sstevel@tonic-gate 528*7c478bd9Sstevel@tonic-gate /* 529*7c478bd9Sstevel@tonic-gate * Function: process_xbuf 530*7c478bd9Sstevel@tonic-gate * 531*7c478bd9Sstevel@tonic-gate * Description: Iterate over the Xbuf Attr and Xbuf Attr wait Q of the soft 532*7c478bd9Sstevel@tonic-gate * state. 533*7c478bd9Sstevel@tonic-gate * Print the contents of each member. In case of silent mode 534*7c478bd9Sstevel@tonic-gate * the contents are avoided and only the address is printed. 535*7c478bd9Sstevel@tonic-gate * 536*7c478bd9Sstevel@tonic-gate * Arguments: starting xbuf address, print mode. 537*7c478bd9Sstevel@tonic-gate */ 538*7c478bd9Sstevel@tonic-gate static int 539*7c478bd9Sstevel@tonic-gate process_xbuf(uintptr_t xbuf_attr, int silent) 540*7c478bd9Sstevel@tonic-gate { 541*7c478bd9Sstevel@tonic-gate struct __ddi_xbuf_attr xba; 542*7c478bd9Sstevel@tonic-gate buf_t xba_current; 543*7c478bd9Sstevel@tonic-gate void *xba_root; 544*7c478bd9Sstevel@tonic-gate int xbuf_q_count = 0; 545*7c478bd9Sstevel@tonic-gate 546*7c478bd9Sstevel@tonic-gate if (xbuf_attr == NULL) { 547*7c478bd9Sstevel@tonic-gate mdb_printf("---------------------------\n"); 548*7c478bd9Sstevel@tonic-gate mdb_printf("No XBUF ATTR entry\n"); 549*7c478bd9Sstevel@tonic-gate mdb_printf("---------------------------\n"); 550*7c478bd9Sstevel@tonic-gate return (SUCCESS); 551*7c478bd9Sstevel@tonic-gate } 552*7c478bd9Sstevel@tonic-gate 553*7c478bd9Sstevel@tonic-gate /* Process the Xbuf Attr struct for a device. */ 554*7c478bd9Sstevel@tonic-gate if (mdb_vread((void *)&xba, sizeof (struct __ddi_xbuf_attr), 555*7c478bd9Sstevel@tonic-gate xbuf_attr) == -1) { 556*7c478bd9Sstevel@tonic-gate mdb_warn("failed to read xbuf_attr at %p", xbuf_attr); 557*7c478bd9Sstevel@tonic-gate return (FAIL); 558*7c478bd9Sstevel@tonic-gate } 559*7c478bd9Sstevel@tonic-gate 560*7c478bd9Sstevel@tonic-gate if (!silent) { 561*7c478bd9Sstevel@tonic-gate mdb_printf("\nXBUF ATTR:\n"); 562*7c478bd9Sstevel@tonic-gate mdb_printf("----------\n"); 563*7c478bd9Sstevel@tonic-gate 564*7c478bd9Sstevel@tonic-gate dump_xbuf_attr(&xba, xbuf_attr); 565*7c478bd9Sstevel@tonic-gate mdb_printf("---\n"); 566*7c478bd9Sstevel@tonic-gate 567*7c478bd9Sstevel@tonic-gate mdb_printf("\nXBUF Q:\n"); 568*7c478bd9Sstevel@tonic-gate mdb_printf("-------\n"); 569*7c478bd9Sstevel@tonic-gate } 570*7c478bd9Sstevel@tonic-gate 571*7c478bd9Sstevel@tonic-gate mdb_printf("xbuf Q head: %lx\n", xba.xa_headp); 572*7c478bd9Sstevel@tonic-gate 573*7c478bd9Sstevel@tonic-gate xba_root = (void *) xba.xa_headp; 574*7c478bd9Sstevel@tonic-gate 575*7c478bd9Sstevel@tonic-gate /* Process the Xbuf Attr wait Q, if there are any entries. */ 576*7c478bd9Sstevel@tonic-gate while ((uintptr_t)xba_root) { 577*7c478bd9Sstevel@tonic-gate if (!silent) { 578*7c478bd9Sstevel@tonic-gate mdb_printf("XBUF_Q list entry:\n"); 579*7c478bd9Sstevel@tonic-gate mdb_printf("------------------\n"); 580*7c478bd9Sstevel@tonic-gate } 581*7c478bd9Sstevel@tonic-gate 582*7c478bd9Sstevel@tonic-gate if (mdb_vread((void *)&xba_current, sizeof (buf_t), 583*7c478bd9Sstevel@tonic-gate (uintptr_t)xba_root) == -1) { 584*7c478bd9Sstevel@tonic-gate mdb_warn("failed to read buf at %p", 585*7c478bd9Sstevel@tonic-gate (uintptr_t)xba_root); 586*7c478bd9Sstevel@tonic-gate return (FAIL); 587*7c478bd9Sstevel@tonic-gate } 588*7c478bd9Sstevel@tonic-gate if (!silent) { 589*7c478bd9Sstevel@tonic-gate mdb_set_dot((uintptr_t)xba_root); 590*7c478bd9Sstevel@tonic-gate mdb_eval("$<buf"); 591*7c478bd9Sstevel@tonic-gate mdb_printf("---\n"); 592*7c478bd9Sstevel@tonic-gate } 593*7c478bd9Sstevel@tonic-gate ++xbuf_q_count; 594*7c478bd9Sstevel@tonic-gate 595*7c478bd9Sstevel@tonic-gate xba_root = (void *)xba_current.av_forw; 596*7c478bd9Sstevel@tonic-gate } 597*7c478bd9Sstevel@tonic-gate 598*7c478bd9Sstevel@tonic-gate if (xba_root == NULL) { 599*7c478bd9Sstevel@tonic-gate mdb_printf("---------------------------\n"); 600*7c478bd9Sstevel@tonic-gate mdb_printf("Processed %d XBUF Q entries\n", xbuf_q_count); 601*7c478bd9Sstevel@tonic-gate mdb_printf("---------------------------\n"); 602*7c478bd9Sstevel@tonic-gate } 603*7c478bd9Sstevel@tonic-gate return (SUCCESS); 604*7c478bd9Sstevel@tonic-gate } 605*7c478bd9Sstevel@tonic-gate 606*7c478bd9Sstevel@tonic-gate /* 607*7c478bd9Sstevel@tonic-gate * Function: print_footer 608*7c478bd9Sstevel@tonic-gate * 609*7c478bd9Sstevel@tonic-gate * Description: Prints the footer if all the soft state entries are processed. 610*7c478bd9Sstevel@tonic-gate * 611*7c478bd9Sstevel@tonic-gate * Arguments: private storage of the walker. 612*7c478bd9Sstevel@tonic-gate */ 613*7c478bd9Sstevel@tonic-gate static void 614*7c478bd9Sstevel@tonic-gate print_footer(const void *walk_data) 615*7c478bd9Sstevel@tonic-gate { 616*7c478bd9Sstevel@tonic-gate if (SD_DATA_IN_CBACK(current_list_count) >= 617*7c478bd9Sstevel@tonic-gate (SD_DATA_IN_CBACK(sd_state_data.n_items) - 1)) { 618*7c478bd9Sstevel@tonic-gate mdb_printf("---------------------------\n"); 619*7c478bd9Sstevel@tonic-gate mdb_printf("Processed %d UN softstate entries\n", 620*7c478bd9Sstevel@tonic-gate SD_DATA_IN_CBACK(valid_root_count)); 621*7c478bd9Sstevel@tonic-gate mdb_printf("---------------------------\n"); 622*7c478bd9Sstevel@tonic-gate } 623*7c478bd9Sstevel@tonic-gate } 624*7c478bd9Sstevel@tonic-gate 625*7c478bd9Sstevel@tonic-gate /* 626*7c478bd9Sstevel@tonic-gate * Function: sd_callback 627*7c478bd9Sstevel@tonic-gate * 628*7c478bd9Sstevel@tonic-gate * Description: This is the callback function called by the 629*7c478bd9Sstevel@tonic-gate * 'sd_state/ssd_state' walker when 'sd_state/ssd_state' dcmd 630*7c478bd9Sstevel@tonic-gate * invokes the walker. 631*7c478bd9Sstevel@tonic-gate * It is called during each walk step. It displays the contents 632*7c478bd9Sstevel@tonic-gate * of the current soft state object (addr) passed to it by the 633*7c478bd9Sstevel@tonic-gate * step function. It also prints the header and footer during the 634*7c478bd9Sstevel@tonic-gate * first and the last step of the walker. 635*7c478bd9Sstevel@tonic-gate * The contents of the soft state also includes various queues 636*7c478bd9Sstevel@tonic-gate * it includes like Xbuf, semo_close, sdlun_waitq. 637*7c478bd9Sstevel@tonic-gate * 638*7c478bd9Sstevel@tonic-gate * Arguments: addr -> current soft state objects address. 639*7c478bd9Sstevel@tonic-gate * walk_data -> private storage for the walker. 640*7c478bd9Sstevel@tonic-gate * flg_silent -> private data for the callback. It represents 641*7c478bd9Sstevel@tonic-gate * the silent mode of operation. 642*7c478bd9Sstevel@tonic-gate */ 643*7c478bd9Sstevel@tonic-gate static int 644*7c478bd9Sstevel@tonic-gate sd_callback(uintptr_t addr, const void *walk_data, void *flg_silent) 645*7c478bd9Sstevel@tonic-gate { 646*7c478bd9Sstevel@tonic-gate struct sd_lun sdLun; 647*7c478bd9Sstevel@tonic-gate int silent = *(int *)flg_silent; 648*7c478bd9Sstevel@tonic-gate 649*7c478bd9Sstevel@tonic-gate /* 650*7c478bd9Sstevel@tonic-gate * If this is the first invocation of the command, print a 651*7c478bd9Sstevel@tonic-gate * header line for the output that will follow. 652*7c478bd9Sstevel@tonic-gate */ 653*7c478bd9Sstevel@tonic-gate if (SD_DATA_IN_CBACK(current_list_count) == 0) { 654*7c478bd9Sstevel@tonic-gate mdb_printf("walk_addr = %lx\n", SD_DATA_IN_CBACK(sd_state)); 655*7c478bd9Sstevel@tonic-gate mdb_printf("walking sd_state units via ptr: %lx\n", 656*7c478bd9Sstevel@tonic-gate SD_DATA_IN_CBACK(current_root)); 657*7c478bd9Sstevel@tonic-gate mdb_printf("%d entries in sd_state table\n", 658*7c478bd9Sstevel@tonic-gate SD_DATA_IN_CBACK(sd_state_data.n_items)); 659*7c478bd9Sstevel@tonic-gate } 660*7c478bd9Sstevel@tonic-gate 661*7c478bd9Sstevel@tonic-gate mdb_printf("\nun %d: %lx\n", SD_DATA_IN_CBACK(current_list_count), 662*7c478bd9Sstevel@tonic-gate addr); 663*7c478bd9Sstevel@tonic-gate 664*7c478bd9Sstevel@tonic-gate mdb_printf("--------------\n"); 665*7c478bd9Sstevel@tonic-gate 666*7c478bd9Sstevel@tonic-gate /* if null soft state iterate over to next one */ 667*7c478bd9Sstevel@tonic-gate if (addr == 0) { 668*7c478bd9Sstevel@tonic-gate print_footer(walk_data); 669*7c478bd9Sstevel@tonic-gate return (SUCCESS); 670*7c478bd9Sstevel@tonic-gate } 671*7c478bd9Sstevel@tonic-gate /* 672*7c478bd9Sstevel@tonic-gate * For each buf, we need to read the sd_lun struct, 673*7c478bd9Sstevel@tonic-gate * and then print out its contents, and get the next. 674*7c478bd9Sstevel@tonic-gate */ 675*7c478bd9Sstevel@tonic-gate else if (mdb_vread(&sdLun, sizeof (struct sd_lun), (uintptr_t)addr) == 676*7c478bd9Sstevel@tonic-gate sizeof (sdLun)) { 677*7c478bd9Sstevel@tonic-gate if (!silent) { 678*7c478bd9Sstevel@tonic-gate mdb_set_dot(addr); 679*7c478bd9Sstevel@tonic-gate mdb_eval("$<sd_lun"); 680*7c478bd9Sstevel@tonic-gate mdb_printf("---\n"); 681*7c478bd9Sstevel@tonic-gate } 682*7c478bd9Sstevel@tonic-gate } else { 683*7c478bd9Sstevel@tonic-gate mdb_warn("failed to read softstate at %p", addr); 684*7c478bd9Sstevel@tonic-gate return (FAIL); 685*7c478bd9Sstevel@tonic-gate } 686*7c478bd9Sstevel@tonic-gate 687*7c478bd9Sstevel@tonic-gate /* process device Xbuf Attr struct and wait Q */ 688*7c478bd9Sstevel@tonic-gate process_xbuf((uintptr_t)sdLun.un_xbuf_attr, silent); 689*7c478bd9Sstevel@tonic-gate 690*7c478bd9Sstevel@tonic-gate /* process device cmd wait Q */ 691*7c478bd9Sstevel@tonic-gate process_sdlun_waitq((uintptr_t)sdLun.un_waitq_headp, silent); 692*7c478bd9Sstevel@tonic-gate 693*7c478bd9Sstevel@tonic-gate /* process device semoclose wait Q */ 694*7c478bd9Sstevel@tonic-gate if (sdLun.un_semoclose._opaque[1] == 0) { 695*7c478bd9Sstevel@tonic-gate process_semo_sleepq((uintptr_t)sdLun.un_semoclose._opaque[0], 696*7c478bd9Sstevel@tonic-gate silent); 697*7c478bd9Sstevel@tonic-gate } 698*7c478bd9Sstevel@tonic-gate 699*7c478bd9Sstevel@tonic-gate /* print the actual number of soft state processed */ 700*7c478bd9Sstevel@tonic-gate print_footer(walk_data); 701*7c478bd9Sstevel@tonic-gate return (SUCCESS); 702*7c478bd9Sstevel@tonic-gate } 703*7c478bd9Sstevel@tonic-gate 704*7c478bd9Sstevel@tonic-gate #if (!defined(__fibre)) 705*7c478bd9Sstevel@tonic-gate /* 706*7c478bd9Sstevel@tonic-gate * Function: dcmd_sd_state 707*7c478bd9Sstevel@tonic-gate * 708*7c478bd9Sstevel@tonic-gate * Description: Scans through the sd soft state entries and prints their 709*7c478bd9Sstevel@tonic-gate * contents including of various queues it contains. It uses 710*7c478bd9Sstevel@tonic-gate * 'sd_state' walker to perform a global walk. If a particular 711*7c478bd9Sstevel@tonic-gate * soft state address is specified than it performs the above job 712*7c478bd9Sstevel@tonic-gate * itself (local walk). 713*7c478bd9Sstevel@tonic-gate * 714*7c478bd9Sstevel@tonic-gate * Arguments: addr -> user specified address or NULL if no address is 715*7c478bd9Sstevel@tonic-gate * specified. 716*7c478bd9Sstevel@tonic-gate * flags -> integer reflecting whether an address was specified, 717*7c478bd9Sstevel@tonic-gate * or if it was invoked by the walker in a loop etc. 718*7c478bd9Sstevel@tonic-gate * argc -> the number of arguments supplied to the dcmd. 719*7c478bd9Sstevel@tonic-gate * argv -> the actual arguments supplied by the user. 720*7c478bd9Sstevel@tonic-gate */ 721*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 722*7c478bd9Sstevel@tonic-gate static int 723*7c478bd9Sstevel@tonic-gate dcmd_sd_state(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 724*7c478bd9Sstevel@tonic-gate { 725*7c478bd9Sstevel@tonic-gate struct sd_lun sdLun; 726*7c478bd9Sstevel@tonic-gate uint_t silent = 0; 727*7c478bd9Sstevel@tonic-gate 728*7c478bd9Sstevel@tonic-gate /* Enable the silent mode if '-s' option specified the user */ 729*7c478bd9Sstevel@tonic-gate if (mdb_getopts(argc, argv, 's', MDB_OPT_SETBITS, TRUE, &silent, NULL) 730*7c478bd9Sstevel@tonic-gate != argc) { 731*7c478bd9Sstevel@tonic-gate return (DCMD_USAGE); 732*7c478bd9Sstevel@tonic-gate } 733*7c478bd9Sstevel@tonic-gate 734*7c478bd9Sstevel@tonic-gate /* 735*7c478bd9Sstevel@tonic-gate * If no address is specified on the command line, perform 736*7c478bd9Sstevel@tonic-gate * a global walk invoking 'sd_state' walker. If a particular address 737*7c478bd9Sstevel@tonic-gate * is specified then print the soft state and its queues. 738*7c478bd9Sstevel@tonic-gate */ 739*7c478bd9Sstevel@tonic-gate if (!(flags & DCMD_ADDRSPEC)) { 740*7c478bd9Sstevel@tonic-gate mdb_walk("sd_state", sd_callback, (void *)&silent); 741*7c478bd9Sstevel@tonic-gate return (DCMD_OK); 742*7c478bd9Sstevel@tonic-gate } else { 743*7c478bd9Sstevel@tonic-gate mdb_printf("\nun: %lx\n", addr); 744*7c478bd9Sstevel@tonic-gate mdb_printf("--------------\n"); 745*7c478bd9Sstevel@tonic-gate 746*7c478bd9Sstevel@tonic-gate /* read the sd_lun struct and print the contents */ 747*7c478bd9Sstevel@tonic-gate if (mdb_vread(&sdLun, sizeof (struct sd_lun), 748*7c478bd9Sstevel@tonic-gate (uintptr_t)addr) == sizeof (sdLun)) { 749*7c478bd9Sstevel@tonic-gate 750*7c478bd9Sstevel@tonic-gate if (!silent) { 751*7c478bd9Sstevel@tonic-gate mdb_set_dot(addr); 752*7c478bd9Sstevel@tonic-gate mdb_eval("$<sd_lun"); 753*7c478bd9Sstevel@tonic-gate mdb_printf("---\n"); 754*7c478bd9Sstevel@tonic-gate } 755*7c478bd9Sstevel@tonic-gate } else { 756*7c478bd9Sstevel@tonic-gate mdb_warn("failed to read softstate at %p", addr); 757*7c478bd9Sstevel@tonic-gate return (DCMD_OK); 758*7c478bd9Sstevel@tonic-gate } 759*7c478bd9Sstevel@tonic-gate 760*7c478bd9Sstevel@tonic-gate /* process Xbuf Attr struct and wait Q for the soft state */ 761*7c478bd9Sstevel@tonic-gate process_xbuf((uintptr_t)sdLun.un_xbuf_attr, silent); 762*7c478bd9Sstevel@tonic-gate 763*7c478bd9Sstevel@tonic-gate /* process device' cmd wait Q */ 764*7c478bd9Sstevel@tonic-gate process_sdlun_waitq((uintptr_t)sdLun.un_waitq_headp, silent); 765*7c478bd9Sstevel@tonic-gate 766*7c478bd9Sstevel@tonic-gate /* process device's semoclose wait Q */ 767*7c478bd9Sstevel@tonic-gate if (sdLun.un_semoclose._opaque[1] == 0) { 768*7c478bd9Sstevel@tonic-gate process_semo_sleepq( 769*7c478bd9Sstevel@tonic-gate (uintptr_t)sdLun.un_semoclose._opaque[0], silent); 770*7c478bd9Sstevel@tonic-gate } 771*7c478bd9Sstevel@tonic-gate } 772*7c478bd9Sstevel@tonic-gate return (DCMD_OK); 773*7c478bd9Sstevel@tonic-gate } 774*7c478bd9Sstevel@tonic-gate 775*7c478bd9Sstevel@tonic-gate #else 776*7c478bd9Sstevel@tonic-gate 777*7c478bd9Sstevel@tonic-gate /* 778*7c478bd9Sstevel@tonic-gate * Function: dcmd_ssd_state 779*7c478bd9Sstevel@tonic-gate * 780*7c478bd9Sstevel@tonic-gate * Description: Scans through the ssd soft state entries and prints their 781*7c478bd9Sstevel@tonic-gate * contents including of various queues it contains. It uses 782*7c478bd9Sstevel@tonic-gate * 'ssd_state' walker to perform a global walk. If a particular 783*7c478bd9Sstevel@tonic-gate * soft state address is specified than it performs the above job 784*7c478bd9Sstevel@tonic-gate * itself (local walk). 785*7c478bd9Sstevel@tonic-gate * 786*7c478bd9Sstevel@tonic-gate * Arguments: addr -> user specified address or NULL if no address is 787*7c478bd9Sstevel@tonic-gate * specified. 788*7c478bd9Sstevel@tonic-gate * flags -> integer reflecting whether an address was specified, 789*7c478bd9Sstevel@tonic-gate * or if it was invoked by the walker in a loop etc. 790*7c478bd9Sstevel@tonic-gate * argc -> the number of arguments supplied to the dcmd. 791*7c478bd9Sstevel@tonic-gate * argv -> the actual arguments supplied by the user. 792*7c478bd9Sstevel@tonic-gate */ 793*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 794*7c478bd9Sstevel@tonic-gate static int 795*7c478bd9Sstevel@tonic-gate dcmd_ssd_state(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 796*7c478bd9Sstevel@tonic-gate { 797*7c478bd9Sstevel@tonic-gate struct sd_lun sdLun; 798*7c478bd9Sstevel@tonic-gate uint_t silent = 0; 799*7c478bd9Sstevel@tonic-gate 800*7c478bd9Sstevel@tonic-gate /* Enable the silent mode if '-s' option specified the user */ 801*7c478bd9Sstevel@tonic-gate if (mdb_getopts(argc, argv, 's', MDB_OPT_SETBITS, TRUE, &silent, NULL) 802*7c478bd9Sstevel@tonic-gate != argc) { 803*7c478bd9Sstevel@tonic-gate return (DCMD_USAGE); 804*7c478bd9Sstevel@tonic-gate } 805*7c478bd9Sstevel@tonic-gate 806*7c478bd9Sstevel@tonic-gate /* 807*7c478bd9Sstevel@tonic-gate * If no address is specified on the command line, perform 808*7c478bd9Sstevel@tonic-gate * a global walk invoking 'sd_state' walker. If a particular address 809*7c478bd9Sstevel@tonic-gate * is specified then print the soft state and its queues. 810*7c478bd9Sstevel@tonic-gate */ 811*7c478bd9Sstevel@tonic-gate if (!(flags & DCMD_ADDRSPEC)) { 812*7c478bd9Sstevel@tonic-gate mdb_walk("ssd_state", sd_callback, (void *)&silent); 813*7c478bd9Sstevel@tonic-gate return (DCMD_OK); 814*7c478bd9Sstevel@tonic-gate } else { 815*7c478bd9Sstevel@tonic-gate mdb_printf("\nun: %lx\n", addr); 816*7c478bd9Sstevel@tonic-gate mdb_printf("--------------\n"); 817*7c478bd9Sstevel@tonic-gate 818*7c478bd9Sstevel@tonic-gate /* read the sd_lun struct and print the contents */ 819*7c478bd9Sstevel@tonic-gate if (mdb_vread(&sdLun, sizeof (struct sd_lun), 820*7c478bd9Sstevel@tonic-gate (uintptr_t)addr) == sizeof (sdLun)) { 821*7c478bd9Sstevel@tonic-gate if (!silent) { 822*7c478bd9Sstevel@tonic-gate mdb_set_dot(addr); 823*7c478bd9Sstevel@tonic-gate mdb_eval("$<sd_lun"); 824*7c478bd9Sstevel@tonic-gate mdb_printf("---\n"); 825*7c478bd9Sstevel@tonic-gate } 826*7c478bd9Sstevel@tonic-gate } else { 827*7c478bd9Sstevel@tonic-gate mdb_warn("failed to read softstate at %p", addr); 828*7c478bd9Sstevel@tonic-gate return (DCMD_OK); 829*7c478bd9Sstevel@tonic-gate } 830*7c478bd9Sstevel@tonic-gate 831*7c478bd9Sstevel@tonic-gate /* process Xbuf Attr struct and wait Q for the soft state */ 832*7c478bd9Sstevel@tonic-gate process_xbuf((uintptr_t)sdLun.un_xbuf_attr, silent); 833*7c478bd9Sstevel@tonic-gate 834*7c478bd9Sstevel@tonic-gate /* process device' cmd wait Q */ 835*7c478bd9Sstevel@tonic-gate process_sdlun_waitq((uintptr_t)sdLun.un_waitq_headp, silent); 836*7c478bd9Sstevel@tonic-gate 837*7c478bd9Sstevel@tonic-gate /* process device's semoclose wait Q */ 838*7c478bd9Sstevel@tonic-gate if (sdLun.un_semoclose._opaque[1] == 0) { 839*7c478bd9Sstevel@tonic-gate process_semo_sleepq( 840*7c478bd9Sstevel@tonic-gate (uintptr_t)sdLun.un_semoclose._opaque[0], silent); 841*7c478bd9Sstevel@tonic-gate } 842*7c478bd9Sstevel@tonic-gate } 843*7c478bd9Sstevel@tonic-gate return (DCMD_OK); 844*7c478bd9Sstevel@tonic-gate } 845*7c478bd9Sstevel@tonic-gate #endif 846*7c478bd9Sstevel@tonic-gate 847*7c478bd9Sstevel@tonic-gate /* 848*7c478bd9Sstevel@tonic-gate * Function: dcmd_buf_avforw 849*7c478bd9Sstevel@tonic-gate * 850*7c478bd9Sstevel@tonic-gate * Description: Scans through the buf list via av_forw and prints 851*7c478bd9Sstevel@tonic-gate * their contents. 852*7c478bd9Sstevel@tonic-gate * It uses the 'buf_avforw' walker to perform the walk. 853*7c478bd9Sstevel@tonic-gate * 854*7c478bd9Sstevel@tonic-gate * Arguments: addr -> user specified address. 855*7c478bd9Sstevel@tonic-gate * flags -> integer reflecting whether an address was specified, 856*7c478bd9Sstevel@tonic-gate * or if it was invoked by the walker in a loop etc. 857*7c478bd9Sstevel@tonic-gate * argc -> the number of arguments supplied to the dcmd. 858*7c478bd9Sstevel@tonic-gate * argv -> the actual arguments supplied by the user. 859*7c478bd9Sstevel@tonic-gate */ 860*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 861*7c478bd9Sstevel@tonic-gate static int 862*7c478bd9Sstevel@tonic-gate dcmd_buf_avforw(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 863*7c478bd9Sstevel@tonic-gate { 864*7c478bd9Sstevel@tonic-gate int buf_entries = 0; 865*7c478bd9Sstevel@tonic-gate 866*7c478bd9Sstevel@tonic-gate /* it does not take any arguments */ 867*7c478bd9Sstevel@tonic-gate if (argc != 0) 868*7c478bd9Sstevel@tonic-gate return (DCMD_USAGE); 869*7c478bd9Sstevel@tonic-gate 870*7c478bd9Sstevel@tonic-gate /* 871*7c478bd9Sstevel@tonic-gate * If no address was specified on the command line, print the 872*7c478bd9Sstevel@tonic-gate * error msg, else scan and 873*7c478bd9Sstevel@tonic-gate * print out all the buffers available by invoking buf_avforw walker. 874*7c478bd9Sstevel@tonic-gate */ 875*7c478bd9Sstevel@tonic-gate if ((flags & DCMD_ADDRSPEC)) { 876*7c478bd9Sstevel@tonic-gate mdb_pwalk("buf_avforw", buf_callback, (void *)&buf_entries, 877*7c478bd9Sstevel@tonic-gate addr); 878*7c478bd9Sstevel@tonic-gate return (DCMD_OK); 879*7c478bd9Sstevel@tonic-gate } else { 880*7c478bd9Sstevel@tonic-gate mdb_printf("buffer address required with the command\n"); 881*7c478bd9Sstevel@tonic-gate } 882*7c478bd9Sstevel@tonic-gate 883*7c478bd9Sstevel@tonic-gate return (DCMD_USAGE); 884*7c478bd9Sstevel@tonic-gate } 885*7c478bd9Sstevel@tonic-gate 886*7c478bd9Sstevel@tonic-gate /* 887*7c478bd9Sstevel@tonic-gate * MDB module linkage information: 888*7c478bd9Sstevel@tonic-gate * 889*7c478bd9Sstevel@tonic-gate * List of structures describing our dcmds, a list of structures 890*7c478bd9Sstevel@tonic-gate * describing our walkers, and a function named _mdb_init to return a pointer 891*7c478bd9Sstevel@tonic-gate * to our module information. 892*7c478bd9Sstevel@tonic-gate */ 893*7c478bd9Sstevel@tonic-gate 894*7c478bd9Sstevel@tonic-gate static const mdb_dcmd_t dcmds[] = { 895*7c478bd9Sstevel@tonic-gate { "buf_avforw", ":", "buf_t list via av_forw", dcmd_buf_avforw}, 896*7c478bd9Sstevel@tonic-gate #if (!defined(__fibre)) 897*7c478bd9Sstevel@tonic-gate { "sd_state", "[-s]", "sd soft state list", dcmd_sd_state}, 898*7c478bd9Sstevel@tonic-gate #else 899*7c478bd9Sstevel@tonic-gate { "ssd_state", "[-s]", "ssd soft state list", dcmd_ssd_state}, 900*7c478bd9Sstevel@tonic-gate #endif 901*7c478bd9Sstevel@tonic-gate { NULL } 902*7c478bd9Sstevel@tonic-gate }; 903*7c478bd9Sstevel@tonic-gate 904*7c478bd9Sstevel@tonic-gate static const mdb_walker_t walkers[] = { 905*7c478bd9Sstevel@tonic-gate { "buf_avforw", "walk list of buf_t structures via av_forw", 906*7c478bd9Sstevel@tonic-gate buf_avforw_walk_init, buf_avforw_walk_step, buf_avforw_walk_fini }, 907*7c478bd9Sstevel@tonic-gate #if (!defined(__fibre)) 908*7c478bd9Sstevel@tonic-gate { "sd_state", "walk all sd soft state queues", 909*7c478bd9Sstevel@tonic-gate sd_state_walk_init, sd_state_walk_step, sd_state_walk_fini }, 910*7c478bd9Sstevel@tonic-gate #else 911*7c478bd9Sstevel@tonic-gate { "ssd_state", "walk all ssd soft state queues", 912*7c478bd9Sstevel@tonic-gate ssd_state_walk_init, sd_state_walk_step, sd_state_walk_fini }, 913*7c478bd9Sstevel@tonic-gate #endif 914*7c478bd9Sstevel@tonic-gate { NULL } 915*7c478bd9Sstevel@tonic-gate }; 916*7c478bd9Sstevel@tonic-gate 917*7c478bd9Sstevel@tonic-gate static const mdb_modinfo_t modinfo = { 918*7c478bd9Sstevel@tonic-gate MDB_API_VERSION, dcmds, walkers 919*7c478bd9Sstevel@tonic-gate }; 920*7c478bd9Sstevel@tonic-gate 921*7c478bd9Sstevel@tonic-gate /* 922*7c478bd9Sstevel@tonic-gate * Function: _mdb_init 923*7c478bd9Sstevel@tonic-gate * 924*7c478bd9Sstevel@tonic-gate * Description: Returns mdb_modinfo_t structure which provides linkage and 925*7c478bd9Sstevel@tonic-gate * module identification information to the debugger. 926*7c478bd9Sstevel@tonic-gate * 927*7c478bd9Sstevel@tonic-gate * Arguments: void 928*7c478bd9Sstevel@tonic-gate */ 929*7c478bd9Sstevel@tonic-gate const mdb_modinfo_t * 930*7c478bd9Sstevel@tonic-gate _mdb_init(void) 931*7c478bd9Sstevel@tonic-gate { 932*7c478bd9Sstevel@tonic-gate return (&modinfo); 933*7c478bd9Sstevel@tonic-gate } 934