1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2003 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 #include "mdinclude.h" 30 31 typedef struct submirror_cb { 32 minor_t un_self_id; 33 int un_nsm; 34 ushort_t mm_un_nsm; 35 }submirror_cb_t; 36 37 void 38 print_setname(int setno) 39 { 40 char setname[1024]; 41 42 if (setno != 0) { 43 if (mdb_readstr(setname, 1024, 44 (uintptr_t)set_dbs[setno].s_setname) == -1) { 45 mdb_warn("failed to read setname at 0x%p\n", 46 set_dbs[setno].s_setname); 47 } 48 mdb_printf("%s/", setname); 49 } 50 } 51 52 void 53 print_stripe(void *un_addr, void *mdcptr, uint_t verbose) 54 { 55 ms_unit_t ms; 56 int setno; 57 minor_t un_self_id; 58 md_parent_t un_parent; 59 diskaddr_t un_total_blocks; 60 61 /* read in the device */ 62 un_self_id = ((mdc_unit_t *)mdcptr)->un_self_id; 63 un_parent = ((mdc_unit_t *)mdcptr)->un_parent; 64 un_total_blocks = ((mdc_unit_t *)mdcptr)->un_total_blocks; 65 if (mdb_vread(&ms, sizeof (ms_unit_t), 66 (uintptr_t)un_addr) == -1) { 67 mdb_warn("failed to read ms_unit_t at %p\n", un_addr); 68 return; 69 } 70 71 setno = MD_MIN2SET(un_self_id); 72 print_setname(setno); 73 74 mdb_printf("d%u: ", MD_MIN2UNIT(un_self_id)); 75 if (un_parent == ((unit_t)-1)) { 76 mdb_printf("Concat/Stripe"); 77 } else { 78 mdb_printf("Subdevice of d%u", MD_MIN2UNIT(un_parent)); 79 } 80 if (verbose) { 81 mdb_printf("\t< %p::print ms_unit_t >\n", un_addr); 82 } else { 83 mdb_printf("\t< %p>\n", un_addr); 84 } 85 mdb_inc_indent(2); 86 mdb_printf("Size: %llu blocks\n", un_total_blocks); 87 mdb_printf("Rows: %u\n", ms.un_nrows); 88 mdb_dec_indent(2); 89 } 90 91 /* ARGSUSED */ 92 int 93 print_submirror(uintptr_t addr, void *arg, submirror_cb_t *data) 94 { 95 uintptr_t un_addr; 96 mdc_unit_t mdc_sm; 97 98 if (mdb_vread(&un_addr, sizeof (void *), addr) == -1) { 99 mdb_warn("failed to read submirror at %p\n", addr); 100 return (WALK_ERR); 101 } 102 if (un_addr != NULL) { 103 if (mdb_vread(&mdc_sm, sizeof (mdc_unit_t), un_addr) == -1) { 104 mdb_warn("failed to read mdc_unit_t at %p", un_addr); 105 return (WALK_ERR); 106 } 107 if (mdc_sm.un_parent == data->un_self_id) { 108 /* this is one of the sub mirrors */ 109 mdb_printf("Submirror %u: d%u ", 110 data->un_nsm, MD_MIN2UNIT(mdc_sm.un_self_id)); 111 mdb_printf("Size: %llu\n", mdc_sm.un_total_blocks); 112 data->un_nsm++; 113 if (data->un_nsm == data->mm_un_nsm) 114 return (WALK_DONE); 115 } 116 } 117 return (WALK_NEXT); 118 } 119 120 void 121 print_mirror(void *un_addr, void *mdcptr, uint_t verbose) 122 { 123 mm_unit_t mm; 124 void **ptr; 125 int setno = 0; 126 minor_t un_self_id; 127 diskaddr_t un_total_blocks; 128 ushort_t mm_un_nsm; 129 submirror_cb_t data; 130 131 /* read in the device */ 132 if (mdb_vread(&mm, sizeof (mm_unit_t), 133 (uintptr_t)un_addr) == -1) { 134 mdb_warn("failed to read mm_unit_t at %p\n", un_addr); 135 return; 136 } 137 un_self_id = ((mdc_unit_t *)mdcptr)->un_self_id; 138 un_total_blocks = ((mdc_unit_t *)mdcptr)->un_total_blocks; 139 mm_un_nsm = mm.un_nsm; 140 setno = MD_MIN2SET(un_self_id); 141 print_setname(setno); 142 143 mdb_printf("d%u: Mirror", MD_MIN2UNIT(un_self_id)); 144 if (verbose) { 145 mdb_printf("\t< %p::print mm_unit_t >\n", un_addr); 146 } else { 147 mdb_printf("\t< %p >\n", un_addr); 148 } 149 mdb_inc_indent(2); 150 mdb_printf("Size: %llu blocks\n", un_total_blocks); 151 /* 152 * find the sub mirrors, search through each metadevice looking 153 * at the un_parent. 154 */ 155 ptr = mdset[setno].s_un; 156 157 data.un_self_id = un_self_id; 158 data.un_nsm = 0; 159 data.mm_un_nsm = mm_un_nsm; 160 161 if (mdb_pwalk("md_units", (mdb_walk_cb_t)print_submirror, &data, 162 (uintptr_t)ptr) == -1) { 163 mdb_warn("unable to walk units\n"); 164 return; 165 } 166 167 mdb_dec_indent(2); 168 } 169 170 void 171 print_raid(void *un_addr, void *mdcptr, uint_t verbose) 172 { 173 mr_unit_t mr; 174 minor_t un_self_id; 175 diskaddr_t un_total_blocks; 176 mdc_unit_t mdc_sc; 177 void **ptr; 178 void *addr; 179 int setno = 0; 180 int i; 181 minor_t sc_un_self_id; 182 md_parent_t sc_parent; 183 diskaddr_t sc_total_blocks; 184 185 /* read in the device */ 186 if (mdb_vread(&mr, sizeof (mr_unit_t), (uintptr_t)un_addr) == -1) { 187 mdb_warn("failed to read mr_unit_t at %p\n", un_addr); 188 return; 189 } 190 un_self_id = ((mdc_unit_t *)mdcptr)->un_self_id; 191 un_total_blocks = ((mdc_unit_t *)mdcptr)->un_total_blocks; 192 setno = MD_MIN2SET(un_self_id); 193 print_setname(setno); 194 195 mdb_printf("d%u: Raid", MD_MIN2UNIT(un_self_id)); 196 if (verbose) { 197 mdb_printf("\t< %p ::print mr_unit_t>\n", un_addr); 198 } else { 199 mdb_printf("\t< %p >\n", un_addr); 200 } 201 mdb_inc_indent(2); 202 mdb_printf("Size: %llu\n", un_total_blocks); 203 204 /* 205 * find the sub components if any, search through each metadevice 206 * looking at the un_parent. 207 */ 208 ptr = mdset[setno].s_un; 209 for (i = 0; i < md_nunits; i++, ptr++) { 210 if (mdb_vread(&addr, sizeof (void *), (uintptr_t)ptr) == -1) { 211 mdb_warn("failed to read addr at %p\n", ptr); 212 continue; 213 } 214 if (addr != NULL) { 215 if (mdb_vread(&mdc_sc, sizeof (mdc_unit_t), 216 (uintptr_t)addr) == -1) { 217 mdb_warn("failed to read mdc_unit_t at %p", 218 un_addr); 219 continue; 220 } 221 sc_parent = mdc_sc.un_parent; 222 sc_un_self_id = mdc_sc.un_self_id; 223 sc_total_blocks = mdc_sc.un_total_blocks; 224 if (sc_parent == un_self_id) { 225 /* this is one of the sub components */ 226 mdb_printf("Subdevice %u ", 227 MD_MIN2UNIT(sc_un_self_id)); 228 mdb_printf("Size: %llu\n", sc_total_blocks); 229 } 230 } 231 } 232 mdb_dec_indent(2); 233 } 234 235 void 236 print_sp(void *un_addr, void *mdcptr, uint_t verbose) 237 { 238 mp_unit_t mp; 239 minor_t un_self_id; 240 diskaddr_t un_total_blocks; 241 int setno = 0; 242 uintptr_t extaddr; 243 int i; 244 245 /* read in the device */ 246 if (mdb_vread(&mp, sizeof (mp_unit_t), (uintptr_t)un_addr) == -1) { 247 mdb_warn("failed to read mp_unit_t at %p\n", un_addr); 248 return; 249 } 250 un_self_id = ((mdc_unit_t *)mdcptr)->un_self_id; 251 un_total_blocks = ((mdc_unit_t *)mdcptr)->un_total_blocks; 252 setno = MD_MIN2SET(un_self_id); 253 print_setname(setno); 254 255 mdb_printf("d%u: Soft Partition", MD_MIN2UNIT(un_self_id)); 256 if (verbose) { 257 mdb_printf("\t< %p ::print mp_unit_t >\n", un_addr); 258 } else { 259 mdb_printf("\t< %p >\n", un_addr); 260 } 261 mdb_inc_indent(2); 262 mdb_printf("Size: %llu\n", un_total_blocks); 263 mdb_inc_indent(2); 264 mdb_printf("Extent\tStart Block\tBlock count\n"); 265 extaddr = (uintptr_t)un_addr + sizeof (mp_unit_t) - sizeof (mp_ext_t); 266 for (i = 0; i < mp.un_numexts; i++) { 267 mp_ext_t mpext; 268 269 if (mdb_vread(&mpext, sizeof (mp_ext_t), extaddr) == -1) { 270 mdb_warn("failed to read mp_ext_t at %p\n", extaddr); 271 return; 272 } 273 mdb_printf(" %d \t %llu\t %llu\n", 274 i, mpext.un_poff, mpext.un_len); 275 extaddr += sizeof (mp_ext_t); 276 } 277 mdb_dec_indent(2); 278 mdb_dec_indent(2); 279 280 } 281 282 void 283 print_trans(void *un_addr, void *mdcptr, uint_t verbose) 284 { 285 mt_unit_t mt; 286 minor_t un_self_id; 287 int setno = 0; 288 289 /* read in the device */ 290 if (mdb_vread(&mt, sizeof (mt_unit_t), (uintptr_t)un_addr) == -1) { 291 mdb_warn("failed to read mt_unit_t at %p\n", un_addr); 292 return; 293 } 294 un_self_id = ((mdc_unit32_od_t *)mdcptr)->un_self_id; 295 setno = MD_MIN2SET(un_self_id); 296 print_setname(setno); 297 298 mdb_printf("d%u: Trans", MD_MIN2UNIT(un_self_id)); 299 if (verbose) { 300 mdb_printf("\t< %p ::print mt_unit_t>\n", un_addr); 301 } else { 302 mdb_printf("\t< %p >\n", un_addr); 303 } 304 305 } 306 307 void 308 print_device(void *un_addr, void *mdcptr, uint_t verbose) 309 { 310 u_longlong_t un_type; 311 312 un_type = ((mdc_unit_t *)mdcptr)->un_type; 313 314 switch (un_type) { 315 case MD_DEVICE: /* stripe/concat */ 316 print_stripe(un_addr, mdcptr, verbose); 317 break; 318 case MD_METAMIRROR: 319 print_mirror(un_addr, mdcptr, verbose); 320 break; 321 case MD_METATRANS: 322 print_trans(un_addr, mdcptr, verbose); 323 break; 324 case MD_METARAID: 325 print_raid(un_addr, mdcptr, verbose); 326 break; 327 case MD_METASP: 328 print_sp(un_addr, mdcptr, verbose); 329 break; 330 case MD_UNDEFINED: 331 mdb_warn("undefined metadevice at %p\n", un_addr); 332 break; 333 default: 334 mdb_warn("invalid metadevice at %p\n", un_addr); 335 break; 336 } 337 } 338 339 /* ARGSUSED */ 340 /* 341 * usage: ::metastat [-v] 342 */ 343 int 344 metastat(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 345 { 346 mdc_unit_t mdc; 347 uintptr_t un_addr; 348 uint_t verbose = FALSE; 349 350 snarf_sets(); 351 352 if (mdb_getopts(argc, argv, 'v', MDB_OPT_SETBITS, TRUE, &verbose, NULL) 353 != argc) { 354 return (DCMD_USAGE); 355 } 356 357 if (!(flags & DCMD_ADDRSPEC)) { 358 if (mdb_walk_dcmd("md_units", "metastat", argc, 359 argv) == -1) { 360 mdb_warn("failed to walk units"); 361 return (DCMD_ERR); 362 } 363 return (DCMD_OK); 364 } 365 if (!(flags & DCMD_LOOP)) { 366 /* user passed set addr */ 367 if (mdb_pwalk_dcmd("md_units", "metastat", argc, 368 argv, addr) == -1) { 369 mdb_warn("failed to walk units"); 370 return (DCMD_ERR); 371 } 372 return (DCMD_OK); 373 } 374 375 if (mdb_vread(&un_addr, sizeof (void *), addr) == -1) { 376 mdb_warn("failed to read un_addr at %p", addr); 377 return (DCMD_ERR); 378 } 379 380 if (un_addr != NULL) { 381 if (mdb_vread(&mdc, sizeof (mdc_unit_t), un_addr) == -1) { 382 mdb_warn("failed to read mdc_unit_t at %p", un_addr); 383 return (DCMD_ERR); 384 } 385 print_device((void *)un_addr, (void *)&mdc, verbose); 386 mdb_dec_indent(2); 387 } 388 return (DCMD_OK); 389 } 390