1 0 stevel /* 2 0 stevel * CDDL HEADER START 3 0 stevel * 4 0 stevel * The contents of this file are subject to the terms of the 5 1623 tw21770 * Common Development and Distribution License (the "License"). 6 1623 tw21770 * You may not use this file except in compliance with the License. 7 0 stevel * 8 0 stevel * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 0 stevel * or http://www.opensolaris.org/os/licensing. 10 0 stevel * See the License for the specific language governing permissions 11 0 stevel * and limitations under the License. 12 0 stevel * 13 0 stevel * When distributing Covered Code, include this CDDL HEADER in each 14 0 stevel * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 0 stevel * If applicable, add the following below this CDDL HEADER, with the 16 0 stevel * fields enclosed by brackets "[]" replaced with your own identifying 17 0 stevel * information: Portions Copyright [yyyy] [name of copyright owner] 18 0 stevel * 19 0 stevel * CDDL HEADER END 20 0 stevel */ 21 0 stevel /* 22 9818 Andrew * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23 0 stevel * Use is subject to license terms. 24 0 stevel */ 25 0 stevel 26 0 stevel 27 0 stevel #include <stdio.h> 28 0 stevel #include <errno.h> 29 0 stevel #include <unistd.h> 30 0 stevel #include <string.h> 31 0 stevel 32 0 stevel #include <meta.h> 33 0 stevel #include <sys/lvm/md_mddb.h> 34 0 stevel #include <sdssc.h> 35 0 stevel 36 0 stevel /* 37 0 stevel * print metadevice status 38 0 stevel */ 39 0 stevel 40 0 stevel 41 0 stevel #define MD_PROBE_OPEN_T "probe open test" 42 0 stevel 43 0 stevel /* used to keep track of the softparts on the same underlying device */ 44 0 stevel struct sp_base_list { 45 0 stevel struct sp_base_list *next; 46 0 stevel char *base; 47 0 stevel }; 48 0 stevel 49 0 stevel /* 50 0 stevel * Function prototypes 51 0 stevel */ 52 0 stevel static void probe_all_devs(mdsetname_t *sp); 53 0 stevel 54 0 stevel static int print_devid(mdsetname_t *sp, mdnamelist_t *nlp, FILE *fp, 55 0 stevel md_error_t *ep); 56 0 stevel 57 0 stevel static md_common_t *get_concise_unit(mdsetname_t *sp, mdname_t *np, 58 0 stevel md_error_t *ep); 59 0 stevel static void print_all_sets(mdprtopts_t options, int concise_flag, 60 0 stevel int quiet_flg); 61 0 stevel static void print_specific_set(mdsetname_t *sp, mdprtopts_t options, 62 0 stevel int concise_flag, int quiet_flg); 63 0 stevel static void print_concise_diskset(mdsetname_t *sp); 64 0 stevel static void print_concise_namelist(mdsetname_t *sp, mdnamelist_t **nl, 65 0 stevel char mtype); 66 0 stevel static void print_concise_md(int indent, mdsetname_t *sp, mdname_t *np); 67 0 stevel static void print_concise_mirror(int indent, mdsetname_t *sp, 68 0 stevel md_mirror_t *mirror); 69 0 stevel static void print_concise_raid(int indent, mdsetname_t *sp, 70 0 stevel md_raid_t *raid); 71 0 stevel static void print_concise_stripe(int indent, mdsetname_t *sp, 72 0 stevel md_stripe_t *stripe); 73 0 stevel static void print_concise_sp(int indent, mdsetname_t *sp, md_sp_t *part); 74 0 stevel static void print_concise_trans(int indent, mdsetname_t *sp, 75 0 stevel md_trans_t *trans); 76 0 stevel static void free_names(mdnamelist_t **nlp); 77 0 stevel static char *get_sm_state(md_mirror_t *mirror, int i, 78 0 stevel md_status_t mirror_status, uint_t tstate); 79 0 stevel static char *get_raid_col_state(md_raidcol_t *colp, uint_t tstate); 80 0 stevel static char *get_stripe_state(md_comp_t *mdcp, uint_t tstate); 81 0 stevel static char *get_hs_state(md_hs_t *hsp); 82 0 stevel static struct sp_base_list *sp_add_done(md_sp_t *part, struct sp_base_list *lp); 83 0 stevel static int sp_done(md_sp_t *part, struct sp_base_list *lp); 84 0 stevel static int sp_match(md_sp_t *part, struct sp_base_list *lp); 85 0 stevel static void sp_free_list(struct sp_base_list *lp); 86 0 stevel 87 0 stevel 88 0 stevel /* 89 0 stevel * print named hotspare pool or metadevice 90 0 stevel */ 91 0 stevel static int 92 0 stevel print_name( 93 0 stevel mdsetname_t **spp, 94 0 stevel char *uname, 95 0 stevel mdnamelist_t **nlistpp, 96 0 stevel char *fname, 97 0 stevel FILE *fp, 98 0 stevel mdprtopts_t options, 99 0 stevel int *meta_print_trans_msgp, 100 0 stevel mdnamelist_t **lognlpp, 101 0 stevel md_error_t *ep 102 0 stevel ) 103 0 stevel { 104 0 stevel mdname_t *namep; 105 0 stevel char *miscname; 106 0 stevel 107 0 stevel /* recurse */ 108 0 stevel options |= PRINT_SUBDEVS; 109 0 stevel 110 0 stevel /* hotspare pool */ 111 1623 tw21770 if (is_existing_hsp(*spp, uname)) { 112 0 stevel mdhspname_t *hspnamep; 113 0 stevel 114 0 stevel /* get hotsparepool */ 115 0 stevel if ((hspnamep = metahspname(spp, uname, ep)) == NULL) 116 0 stevel return (-1); 117 0 stevel 118 0 stevel /* check for ownership */ 119 0 stevel assert(*spp != NULL); 120 0 stevel if (meta_check_ownership(*spp, ep) != 0) 121 0 stevel return (-1); 122 0 stevel 123 0 stevel /* print hotspare pool */ 124 0 stevel return (meta_hsp_print(*spp, hspnamep, lognlpp, fname, fp, 125 0 stevel options, ep)); 126 0 stevel } 127 0 stevel 128 0 stevel /* get metadevice */ 129 1623 tw21770 if (((namep = metaname(spp, uname, META_DEVICE, ep)) == NULL) || 130 0 stevel (metachkmeta(namep, ep) != 0)) 131 0 stevel return (-1); 132 0 stevel 133 0 stevel /* check for ownership */ 134 0 stevel assert(*spp != NULL); 135 0 stevel if (meta_check_ownership(*spp, ep) != 0) 136 0 stevel return (-1); 137 0 stevel 138 0 stevel if ((miscname = metagetmiscname(namep, ep)) != NULL) { 139 0 stevel if (strcmp(miscname, MD_TRANS) == 0) { 140 0 stevel *meta_print_trans_msgp = 1; 141 0 stevel } 142 0 stevel } 143 0 stevel 144 0 stevel /* print metadevice */ 145 0 stevel return (meta_print_name(*spp, namep, nlistpp, fname, fp, options, 146 0 stevel lognlpp, ep)); 147 0 stevel } 148 0 stevel 149 0 stevel /* 150 0 stevel * print the per set flags 151 0 stevel */ 152 0 stevel /*ARGSUSED*/ 153 0 stevel static int 154 0 stevel print_setstat( 155 0 stevel mdsetname_t **spp, 156 0 stevel char *fname, 157 0 stevel FILE *fp, 158 0 stevel mdprtopts_t options, 159 0 stevel md_error_t *ep 160 0 stevel ) 161 0 stevel { 162 0 stevel int rval = -1; 163 1623 tw21770 char *cname = NULL; 164 0 stevel char *cp = NULL; 165 0 stevel md_gs_stat_parm_t gsp; 166 0 stevel 167 0 stevel 168 1623 tw21770 if (fname != NULL && strchr(fname, '/') != NULL) { 169 1623 tw21770 /* get the canonical name */ 170 1623 tw21770 cname = meta_name_getname(spp, fname, META_DEVICE, ep); 171 2077 tw21770 if (cname == NULL) 172 1623 tw21770 return (-1); 173 1623 tw21770 Free(cname); 174 0 stevel } 175 0 stevel 176 0 stevel if ((cp = getenv("MD_DEBUG")) == NULL) 177 0 stevel return (0); 178 0 stevel 179 0 stevel if (strstr(cp, "SETINFO") == NULL) 180 0 stevel return (0); 181 0 stevel 182 0 stevel (void) memset(&gsp, '\0', sizeof (md_gs_stat_parm_t)); 183 0 stevel gsp.gs_setno = (*spp)->setno; 184 0 stevel 185 0 stevel if (metaioctl(MD_GET_SETSTAT, &gsp, &gsp.gs_mde, NULL) != 0) 186 0 stevel return (mdstealerror(ep, &gsp.gs_mde)); 187 0 stevel 188 0 stevel if (fprintf(fp, "Status for set %d = ", gsp.gs_setno) == EOF) 189 0 stevel goto out; 190 0 stevel 191 0 stevel if (meta_prbits(fp, NULL, gsp.gs_status, MD_SET_STAT_BITS) == EOF) 192 0 stevel goto out; 193 0 stevel 194 0 stevel 195 0 stevel if (fprintf(fp, "\n") == EOF) 196 0 stevel goto out; 197 0 stevel 198 0 stevel /* success */ 199 0 stevel rval = 0; 200 0 stevel 201 0 stevel /* cleanup, return error */ 202 0 stevel out: 203 0 stevel if (rval != 0) 204 0 stevel (void) mdsyserror(ep, errno, fname); 205 0 stevel 206 0 stevel return (rval); 207 0 stevel } 208 0 stevel 209 0 stevel /* 210 0 stevel * check_replica_state: 211 0 stevel * If the replica state is stale or the set has been halted 212 0 stevel * this routine returns an error. 213 0 stevel */ 214 0 stevel static int 215 0 stevel check_replica_state(mdsetname_t *sp, md_error_t *ep) 216 0 stevel { 217 0 stevel mddb_config_t c; 218 0 stevel 219 0 stevel (void) memset(&c, 0, sizeof (c)); 220 0 stevel c.c_id = 0; 221 0 stevel c.c_setno = sp->setno; 222 0 stevel 223 0 stevel if (metaioctl(MD_DB_GETDEV, &c, &c.c_mde, NULL) != 0) { 224 0 stevel if (mdismddberror(&c.c_mde, MDE_DB_INVALID)) 225 11053 Surya (void) mdstealerror(ep, &c.c_mde); 226 0 stevel return (-1); 227 0 stevel } 228 0 stevel 229 0 stevel if (c.c_flags & MDDB_C_STALE) { 230 0 stevel return (mdmddberror(ep, MDE_DB_STALE, NODEV32, sp->setno, 231 6630 sk102515 0, NULL)); 232 0 stevel } else 233 0 stevel return (0); 234 0 stevel } 235 0 stevel 236 0 stevel static void 237 0 stevel print_trans_msg(mdprtopts_t options, int meta_print_trans_msg) 238 0 stevel { 239 0 stevel if (meta_print_trans_msg != 0) { 240 11053 Surya (void) fprintf(stderr, "\n\n"); 241 0 stevel if (options & PRINT_SHORT) { 242 11053 Surya (void) fprintf(stderr, gettext(MD_SHORT_EOF_TRANS_MSG)); 243 11053 Surya (void) fprintf(stderr, 244 11053 Surya gettext(MD_SHORT_EOF_TRANS_WARNING)); 245 0 stevel } else { 246 11053 Surya (void) fprintf(stderr, gettext(MD_EOF_TRANS_MSG)); 247 11053 Surya (void) fprintf(stderr, gettext(MD_EOF_TRANS_WARNING)); 248 0 stevel } 249 0 stevel } 250 0 stevel } 251 0 stevel 252 0 stevel /* 253 0 stevel * print usage message 254 0 stevel * 255 0 stevel */ 256 0 stevel static void 257 0 stevel usage( 258 0 stevel mdsetname_t *sp, 259 0 stevel int eval 260 0 stevel ) 261 0 stevel { 262 0 stevel (void) fprintf(stderr, gettext("\ 263 1623 tw21770 usage: %s [-s setname] [-a][-c][-B][-D][-r][-i][-p] [-t] [metadevice...]\n"), 264 0 stevel myname); 265 0 stevel md_exit(sp, eval); 266 0 stevel } 267 0 stevel 268 0 stevel /* 269 0 stevel * mainline. crack command line arguments. 270 0 stevel */ 271 0 stevel int 272 0 stevel main( 273 0 stevel int argc, 274 0 stevel char *argv[] 275 0 stevel ) 276 0 stevel { 277 1623 tw21770 char *sname = MD_LOCAL_NAME; 278 0 stevel mdsetname_t *sp = NULL; 279 0 stevel mdprtopts_t options = PRINT_HEADER | PRINT_DEVID | PRINT_FAST; 280 0 stevel int c; 281 0 stevel char *p; 282 0 stevel md_error_t status = mdnullerror; 283 0 stevel md_error_t *ep = &status; 284 0 stevel int eval = 0; 285 0 stevel int inquire = 0; 286 0 stevel int quiet_flg = 0; 287 1623 tw21770 int set_flg = 0; 288 0 stevel int error; 289 0 stevel int all_sets_flag = 0; 290 0 stevel int concise_flag = 0; 291 0 stevel mdnamelist_t *nlistp = NULL; 292 0 stevel mdname_t *namep; 293 0 stevel int devcnt = 0; 294 0 stevel mdnamelist_t *lognlp = NULL; 295 0 stevel uint_t hsi; 296 0 stevel int meta_print_trans_msg = 0; 297 0 stevel 298 0 stevel /* 299 0 stevel * Get the locale set up before calling any other routines 300 0 stevel * with messages to ouput. Just in case we're not in a build 301 0 stevel * environment, make sure that TEXT_DOMAIN gets set to 302 0 stevel * something. 303 0 stevel */ 304 0 stevel #if !defined(TEXT_DOMAIN) 305 0 stevel #define TEXT_DOMAIN "SYS_TEST" 306 0 stevel #endif 307 0 stevel (void) setlocale(LC_ALL, ""); 308 0 stevel (void) textdomain(TEXT_DOMAIN); 309 0 stevel 310 0 stevel if (sdssc_bind_library() == SDSSC_OKAY) 311 0 stevel if (sdssc_cmd_proxy(argc, argv, SDSSC_PROXY_PRIMARY, 312 6630 sk102515 &error) == SDSSC_PROXY_DONE) 313 0 stevel exit(error); 314 0 stevel 315 0 stevel /* initialize */ 316 0 stevel if (md_init(argc, argv, 0, 1, ep) != 0) { 317 0 stevel mde_perror(ep, ""); 318 0 stevel md_exit(sp, 1); 319 0 stevel } 320 0 stevel 321 0 stevel /* parse arguments */ 322 0 stevel optind = 1; 323 0 stevel opterr = 1; 324 1623 tw21770 while ((c = getopt(argc, argv, "acSs:hpBDrtiq?")) != -1) { 325 0 stevel switch (c) { 326 0 stevel case 'a': 327 0 stevel all_sets_flag++; 328 0 stevel break; 329 0 stevel 330 0 stevel case 'c': 331 0 stevel concise_flag++; 332 0 stevel quiet_flg++; 333 0 stevel break; 334 0 stevel 335 0 stevel case 'S': 336 0 stevel options |= PRINT_SETSTAT_ONLY; 337 0 stevel break; 338 0 stevel 339 0 stevel case 's': 340 0 stevel sname = optarg; 341 1623 tw21770 set_flg++; 342 0 stevel break; 343 0 stevel 344 0 stevel case 'h': 345 0 stevel usage(sp, 0); 346 0 stevel break; 347 0 stevel 348 0 stevel case 'p': 349 0 stevel options |= PRINT_SHORT; 350 0 stevel options &= ~PRINT_DEVID; 351 0 stevel break; 352 0 stevel 353 0 stevel case 't': 354 0 stevel options |= PRINT_TIMES; 355 0 stevel break; 356 0 stevel 357 0 stevel case 'i': 358 0 stevel inquire++; 359 0 stevel break; 360 0 stevel 361 0 stevel case 'B': 362 0 stevel options |= PRINT_LARGEDEVICES; 363 0 stevel break; 364 1623 tw21770 case 'D': 365 1623 tw21770 options |= PRINT_FN; 366 1623 tw21770 break; 367 0 stevel case 'r': /* defunct option */ 368 0 stevel break; 369 0 stevel case 'q': 370 0 stevel quiet_flg++; 371 0 stevel break; 372 0 stevel case '?': 373 0 stevel if (optopt == '?') 374 0 stevel usage(sp, 0); 375 0 stevel /*FALLTHROUGH*/ 376 0 stevel default: 377 0 stevel usage(sp, 1); 378 0 stevel break; 379 0 stevel } 380 0 stevel } 381 0 stevel argc -= optind; 382 0 stevel argv += optind; 383 0 stevel 384 1623 tw21770 if (all_sets_flag && set_flg) { 385 11053 Surya (void) fprintf(stderr, gettext("metastat: " 386 1623 tw21770 "incompatible options: -a and -s\n")); 387 1623 tw21770 usage(sp, 1); 388 1623 tw21770 } 389 0 stevel 390 1623 tw21770 /* get set context */ 391 1623 tw21770 if ((sp = metasetname(sname, ep)) == NULL) { 392 1623 tw21770 mde_perror(ep, ""); 393 1623 tw21770 md_exit(sp, 1); 394 0 stevel } 395 0 stevel 396 0 stevel /* make sure that the mddb is not stale. Else print a warning */ 397 0 stevel 398 0 stevel if (check_replica_state(sp, ep)) { 399 0 stevel if (mdismddberror(ep, MDE_DB_STALE)) { 400 11053 Surya (void) fprintf(stdout, gettext( 401 0 stevel "****\nWARNING: Stale " 402 0 stevel "state database replicas. Metastat output " 403 0 stevel "may be inaccurate.\n****\n\n")); 404 0 stevel } 405 0 stevel } 406 0 stevel 407 0 stevel /* if inquire is set. We probe first */ 408 0 stevel if (inquire) { 409 0 stevel if (geteuid() != 0) { 410 11053 Surya (void) fprintf(stderr, gettext("metastat: -i " 411 6630 sk102515 "option requires super-user privilages\n")); 412 0 stevel md_exit(sp, 1); 413 0 stevel } 414 0 stevel probe_all_devs(sp); 415 0 stevel } 416 0 stevel /* print debug stuff */ 417 0 stevel if (((p = getenv("MD_DEBUG")) != NULL) && 418 0 stevel (strstr(p, "STAT") != NULL)) { 419 0 stevel options |= (PRINT_SETSTAT | PRINT_DEBUG | PRINT_TIMES); 420 0 stevel } 421 0 stevel 422 0 stevel if ((options & PRINT_SETSTAT) || (options & PRINT_SETSTAT_ONLY)) { 423 0 stevel if (print_setstat(&sp, argv[0], stdout, options, ep)) { 424 0 stevel mde_perror(ep, ""); 425 0 stevel md_exit(sp, 1); 426 0 stevel } 427 0 stevel if (options & PRINT_SETSTAT_ONLY) 428 0 stevel md_exit(sp, 0); 429 0 stevel } 430 0 stevel 431 0 stevel /* status all devices */ 432 0 stevel if (argc == 0) { 433 0 stevel if (all_sets_flag) { 434 6630 sk102515 print_all_sets(options, concise_flag, quiet_flg); 435 0 stevel } else { 436 6630 sk102515 print_specific_set(sp, options, concise_flag, 437 6630 sk102515 quiet_flg); 438 0 stevel } 439 0 stevel 440 0 stevel if (meta_smf_isonline(meta_smf_getmask(), ep) == 0) { 441 0 stevel mde_perror(ep, ""); 442 0 stevel md_exit(sp, 1); 443 0 stevel } 444 0 stevel 445 0 stevel /* success */ 446 0 stevel md_exit(sp, 0); 447 0 stevel } 448 0 stevel /* print named device types */ 449 0 stevel while (devcnt < argc) { 450 0 stevel char *uname = argv[devcnt]; 451 1623 tw21770 char *cname = NULL; 452 1623 tw21770 453 1623 tw21770 /* get the canonical name */ 454 1623 tw21770 cname = meta_name_getname(&sp, uname, META_DEVICE, ep); 455 1623 tw21770 if (cname == NULL) { 456 1623 tw21770 /* already printed the error */ 457 1623 tw21770 mdclrerror(ep); 458 1623 tw21770 eval = 1; 459 1623 tw21770 ++devcnt; 460 1623 tw21770 continue; 461 1623 tw21770 } 462 0 stevel 463 0 stevel if (concise_flag) { 464 6630 sk102515 mdname_t *np; 465 0 stevel 466 6630 sk102515 np = metaname(&sp, cname, META_DEVICE, ep); 467 6630 sk102515 if (np == NULL) { 468 6630 sk102515 mde_perror(ep, ""); 469 6630 sk102515 mdclrerror(ep); 470 6630 sk102515 eval = 1; 471 6630 sk102515 } else { 472 6630 sk102515 print_concise_md(0, sp, np); 473 6630 sk102515 } 474 0 stevel 475 0 stevel } else { 476 6630 sk102515 if (print_name(&sp, cname, &nlistp, NULL, stdout, 477 6630 sk102515 options, &meta_print_trans_msg, &lognlp, ep) != 0) { 478 6630 sk102515 mde_perror(ep, ""); 479 6630 sk102515 mdclrerror(ep); 480 6630 sk102515 eval = 1; 481 6630 sk102515 } 482 0 stevel } 483 1623 tw21770 Free(cname); 484 0 stevel ++devcnt; 485 0 stevel } 486 0 stevel 487 0 stevel /* print metadevice & relocation device id */ 488 0 stevel if ((options & PRINT_DEVID) && (eval != 1) && !quiet_flg) { 489 0 stevel devcnt = 0; 490 0 stevel 491 0 stevel while (devcnt < argc) { 492 0 stevel char *uname = argv[devcnt]; 493 1623 tw21770 char *cname = NULL; 494 1623 tw21770 495 1623 tw21770 /* get the canonical name */ 496 1623 tw21770 cname = meta_name_getname(&sp, uname, META_DEVICE, ep); 497 1623 tw21770 if (cname == NULL) { 498 1623 tw21770 mde_perror(ep, ""); 499 1623 tw21770 mdclrerror(ep); 500 1623 tw21770 ++devcnt; 501 1623 tw21770 continue; 502 1623 tw21770 } 503 0 stevel 504 0 stevel /* hotspare pools */ 505 1623 tw21770 if (is_existing_hsp(sp, cname)) { 506 0 stevel mdhspname_t *hspnamep; 507 0 stevel md_hsp_t *hsp; 508 0 stevel 509 0 stevel /* get hotsparepool */ 510 1623 tw21770 if ((hspnamep = metahspname(&sp, cname, 511 6630 sk102515 ep)) == NULL) 512 0 stevel eval = 1; 513 0 stevel 514 0 stevel if ((hsp = meta_get_hsp(sp, hspnamep, 515 6630 sk102515 ep)) == NULL) 516 0 stevel eval = 1; 517 0 stevel 518 0 stevel for (hsi = 0; 519 0 stevel hsi < hsp->hotspares.hotspares_len; 520 0 stevel hsi++) { 521 0 stevel 522 0 stevel namep = hsp->hotspares. 523 0 stevel hotspares_val[hsi].hsnamep; 524 0 stevel 525 1623 tw21770 if (!(options & 526 1623 tw21770 (PRINT_LARGEDEVICES | PRINT_FN))) { 527 0 stevel /* meta_getdevs populates the */ 528 0 stevel /* nlistp structure for use */ 529 0 stevel if (meta_getdevs(sp, namep, 530 0 stevel &nlistp, ep) != 0) 531 0 stevel eval = 1; 532 0 stevel } 533 0 stevel 534 0 stevel } 535 0 stevel 536 0 stevel } else { 537 0 stevel 538 0 stevel /* get metadevice */ 539 1623 tw21770 if (((namep = metaname(&sp, cname, 540 6630 sk102515 META_DEVICE, ep)) == NULL) || 541 6630 sk102515 (metachkmeta(namep, ep) != 0)) 542 0 stevel eval = 1; 543 0 stevel 544 1623 tw21770 if (!(options & 545 1623 tw21770 (PRINT_LARGEDEVICES | PRINT_FN))) { 546 0 stevel /* meta_getdevs populates the */ 547 0 stevel /* nlistp structure for use */ 548 0 stevel if (meta_getdevs(sp, namep, &nlistp, ep) 549 0 stevel != 0) 550 0 stevel eval = 1; 551 0 stevel } 552 0 stevel } 553 1623 tw21770 Free(cname); 554 0 stevel ++devcnt; 555 0 stevel } 556 0 stevel if (print_devid(sp, nlistp, stdout, ep) != 0) 557 0 stevel eval = 1; 558 0 stevel 559 0 stevel 560 0 stevel } 561 0 stevel 562 0 stevel print_trans_msg(options, meta_print_trans_msg); 563 0 stevel 564 0 stevel if (meta_smf_isonline(meta_smf_getmask(), ep) == 0) { 565 0 stevel mde_perror(ep, ""); 566 0 stevel md_exit(sp, 1); 567 0 stevel } 568 0 stevel 569 0 stevel /* return success */ 570 0 stevel md_exit(sp, eval); 571 0 stevel /*NOTREACHED*/ 572 0 stevel return (eval); 573 0 stevel } 574 0 stevel 575 0 stevel static void 576 0 stevel print_all_sets(mdprtopts_t options, int concise_flag, int quiet_flg) 577 0 stevel { 578 0 stevel uint_t max_sets; 579 0 stevel md_error_t error = mdnullerror; 580 0 stevel int i; 581 0 stevel 582 0 stevel if ((max_sets = get_max_sets(&error)) == 0) { 583 6630 sk102515 return; 584 0 stevel } 585 0 stevel 586 0 stevel if (!mdisok(&error)) { 587 6630 sk102515 mdclrerror(&error); 588 6630 sk102515 return; 589 0 stevel } 590 0 stevel 591 0 stevel /* for each possible set number, see if we really have a diskset */ 592 0 stevel for (i = 0; i < max_sets; i++) { 593 6630 sk102515 mdsetname_t *sp; 594 0 stevel 595 6630 sk102515 if ((sp = metasetnosetname(i, &error)) == NULL) { 596 6630 sk102515 if (!mdisok(&error) && 597 6630 sk102515 mdisrpcerror(&error, RPC_PROGNOTREGISTERED)) { 598 6630 sk102515 /* metad rpc program not registered - no metasets */ 599 6630 sk102515 break; 600 6630 sk102515 } 601 6630 sk102515 602 6630 sk102515 mdclrerror(&error); 603 6630 sk102515 continue; 604 6630 sk102515 } 605 6630 sk102515 mdclrerror(&error); 606 6630 sk102515 607 6630 sk102515 if (meta_check_ownership(sp, &error) == 0) { 608 6630 sk102515 /* we own the set, so we can print the metadevices */ 609 6630 sk102515 print_specific_set(sp, options, concise_flag, 610 6630 sk102515 quiet_flg); 611 6630 sk102515 (void) printf("\n"); 612 0 stevel } 613 0 stevel 614 6630 sk102515 metaflushsetname(sp); 615 0 stevel } 616 0 stevel } 617 0 stevel 618 0 stevel static void 619 0 stevel print_specific_set(mdsetname_t *sp, mdprtopts_t options, int concise_flag, 620 0 stevel int quiet_flg) 621 0 stevel { 622 0 stevel md_error_t status = mdnullerror; 623 0 stevel md_error_t *ep = &status; 624 0 stevel int meta_print_trans_msg = 0; 625 0 stevel 626 0 stevel /* check for ownership */ 627 0 stevel assert(sp != NULL); 628 0 stevel if (meta_check_ownership(sp, ep) != 0) { 629 6630 sk102515 mde_perror(ep, ""); 630 6630 sk102515 md_exit(sp, 1); 631 0 stevel } 632 0 stevel 633 0 stevel if (concise_flag) { 634 6630 sk102515 print_concise_diskset(sp); 635 0 stevel 636 0 stevel } else { 637 6630 sk102515 mdnamelist_t *nlistp = NULL; 638 0 stevel 639 6630 sk102515 /* status devices */ 640 6630 sk102515 if (meta_print_all(sp, NULL, &nlistp, stdout, options, 641 6630 sk102515 &meta_print_trans_msg, ep) != 0) { 642 0 stevel mde_perror(ep, ""); 643 0 stevel md_exit(sp, 1); 644 0 stevel } 645 6630 sk102515 646 6630 sk102515 /* print relocation device id on all dev's */ 647 6630 sk102515 if ((options & PRINT_DEVID) && !quiet_flg) { 648 6630 sk102515 /* 649 6630 sk102515 * Ignore return value from meta_getalldevs since 650 6630 sk102515 * it will return a failure if even one device cannot 651 6630 sk102515 * be found - which could occur in the case of device 652 6630 sk102515 * failure or a device being powered off during 653 6630 sk102515 * upgrade. Even if meta_getalldevs fails, the 654 6630 sk102515 * data in nlistp is still valid. 655 6630 sk102515 */ 656 6630 sk102515 if (!(options & (PRINT_LARGEDEVICES | PRINT_FN))) { 657 6630 sk102515 (void) meta_getalldevs(sp, &nlistp, 0, ep); 658 6630 sk102515 } 659 6630 sk102515 if (nlistp != NULL) { 660 6630 sk102515 if (print_devid(sp, nlistp, stdout, ep) != 0) { 661 6630 sk102515 mde_perror(ep, ""); 662 6630 sk102515 md_exit(sp, 1); 663 6630 sk102515 } 664 6630 sk102515 } 665 6630 sk102515 } 666 0 stevel } 667 0 stevel 668 0 stevel print_trans_msg(options, meta_print_trans_msg); 669 0 stevel } 670 0 stevel 671 0 stevel /* 672 0 stevel * print_devid prints out cxtxdx and devid for devices passed in a 673 0 stevel * mdnamelist_t structure 674 0 stevel */ 675 0 stevel static int 676 0 stevel print_devid( 677 0 stevel mdsetname_t *sp, 678 0 stevel mdnamelist_t *nlp, 679 0 stevel FILE *fp, 680 0 stevel md_error_t *ep 681 0 stevel ) 682 0 stevel { 683 0 stevel int retval = 0; 684 0 stevel mdnamelist_t *onlp = NULL; 685 0 stevel mddevid_t *ldevidp = NULL; 686 0 stevel mddevid_t *nextp; 687 0 stevel 688 0 stevel /* make a non-duplicate list of nlp */ 689 0 stevel for (onlp = nlp; (onlp != NULL); onlp = onlp->next) { 690 0 stevel meta_create_non_dup_list(onlp->namep, &ldevidp); 691 0 stevel } 692 0 stevel 693 0 stevel retval = meta_print_devid(sp, fp, ldevidp, ep); 694 0 stevel 695 0 stevel /* cleanup */ 696 0 stevel for (nextp = ldevidp; nextp != NULL; ldevidp = nextp) { 697 0 stevel Free(ldevidp->ctdname); 698 0 stevel nextp = ldevidp->next; 699 0 stevel Free(ldevidp); 700 0 stevel } 701 0 stevel 702 0 stevel return (retval); 703 0 stevel } 704 0 stevel 705 0 stevel /* 706 0 stevel * probedev issues ioctls for all the metadevices 707 0 stevel */ 708 0 stevel 709 0 stevel 710 0 stevel 711 0 stevel 712 0 stevel /* 713 0 stevel * Failure return's a 1 714 0 stevel */ 715 0 stevel int 716 0 stevel hotspare_ok(char *bname) 717 0 stevel { 718 0 stevel int fd; 719 0 stevel char buf[512]; 720 0 stevel 721 0 stevel if ((fd = open(bname, O_RDONLY)) < 0) 722 0 stevel return (0); 723 6630 sk102515 if (read(fd, buf, sizeof (buf)) < 0) { 724 6630 sk102515 (void) close(fd); 725 0 stevel return (0); 726 6630 sk102515 } 727 6630 sk102515 (void) close(fd); 728 0 stevel return (1); 729 0 stevel } 730 0 stevel 731 0 stevel void 732 0 stevel delete_hotspares_impl(mdsetname_t *sp, mdhspname_t *hspnp, md_hsp_t *hspp) 733 0 stevel { 734 0 stevel md_hs_t *hsp; 735 0 stevel uint_t hsi; 736 0 stevel char *bname; 737 0 stevel md_error_t e = mdnullerror; 738 0 stevel int deleted_hs = 0; 739 0 stevel 740 0 stevel for (hsi = 0; (hsi < hspp->hotspares.hotspares_len); ++hsi) { 741 0 stevel mdnamelist_t *nlp; 742 0 stevel 743 0 stevel hsp = &hspp->hotspares.hotspares_val[hsi]; 744 0 stevel bname = hsp->hsnamep->bname; 745 0 stevel nlp = NULL; 746 11053 Surya (void) metanamelist_append(&nlp, hsp->hsnamep); 747 0 stevel /* print hotspare */ 748 0 stevel if (hsp->state == HSS_AVAILABLE) { 749 0 stevel if (hotspare_ok(bname)) 750 0 stevel continue; 751 0 stevel 752 11053 Surya (void) fprintf(stderr, 753 6630 sk102515 "NOTICE: Hotspare %s in %s has failed.\n" 754 6630 sk102515 "\tDeleting %s since it not in use\n\n", 755 6630 sk102515 bname, hspnp->hspname, bname); 756 0 stevel 757 0 stevel if (meta_hs_delete(sp, hspnp, nlp, 0, &e) != NULL) { 758 0 stevel mde_perror(&e, ""); 759 9818 Andrew mdclrerror(&e); 760 0 stevel } else { 761 0 stevel deleted_hs++; 762 0 stevel } 763 0 stevel } 764 0 stevel } 765 0 stevel } 766 0 stevel 767 0 stevel 768 0 stevel 769 0 stevel /* 770 0 stevel * Generic routine to issue ioctls 771 0 stevel */ 772 0 stevel 773 0 stevel void 774 0 stevel md_setprobetest(md_probedev_t *iocp) 775 0 stevel { 776 0 stevel (void) strcpy(iocp->test_name, MD_PROBE_OPEN_T); 777 0 stevel } 778 0 stevel 779 0 stevel int 780 0 stevel md_probe_ioctl(mdsetname_t *sp, mdnamelist_t *nlp, int ndevs, char *drvname) 781 0 stevel { 782 0 stevel mdnamelist_t *p; 783 0 stevel mdname_t *np; 784 6630 sk102515 md_probedev_t probe_ioc, *iocp; 785 6630 sk102515 int i, retval = 0; 786 0 stevel /* 787 0 stevel * Allocate space for all the metadevices and fill in 788 0 stevel * the minor numbers. 789 0 stevel */ 790 0 stevel 791 11053 Surya (void) memset(&probe_ioc, 0, sizeof (probe_ioc)); 792 0 stevel iocp = &probe_ioc; 793 0 stevel 794 0 stevel if ((iocp->mnum_list = (uintptr_t)calloc(ndevs, sizeof (minor_t))) 795 0 stevel == 0) { 796 0 stevel perror("md_probe_ioctl: calloc"); 797 0 stevel return (-1); 798 0 stevel } 799 0 stevel 800 0 stevel MD_SETDRIVERNAME(iocp, drvname, sp->setno); 801 0 stevel md_setprobetest(iocp); 802 0 stevel 803 0 stevel iocp->nmdevs = ndevs; 804 0 stevel 805 0 stevel for (p = nlp, i = 0; p; p = p->next, i++) { 806 0 stevel np = p->namep; 807 62 jeanm ((minor_t *)(uintptr_t)iocp->mnum_list)[i] = 808 62 jeanm meta_getminor(np->dev); 809 0 stevel } 810 0 stevel 811 0 stevel 812 0 stevel if (metaioctl(MD_IOCPROBE_DEV, iocp, &(iocp->mde), NULL) != 0) 813 0 stevel retval = -1; 814 9818 Andrew Free((void *)(uintptr_t)iocp->mnum_list); 815 0 stevel return (retval); 816 0 stevel } 817 0 stevel /* 818 0 stevel * 819 0 stevel * - remove p from nlp list 820 0 stevel * - put it on the toplp list. 821 0 stevel * - update the p to the next element 822 0 stevel */ 823 0 stevel 824 0 stevel void 825 0 stevel add_to_list(mdnamelist_t **curpp, mdnamelist_t **prevpp, mdnamelist_t **newlpp) 826 0 stevel { 827 0 stevel mdnamelist_t *p, *prevp, *nlp; 828 0 stevel 829 0 stevel p = *curpp; 830 0 stevel prevp = *prevpp; 831 0 stevel nlp = *newlpp; 832 0 stevel 833 0 stevel if (prevp == p) { 834 0 stevel /* if first element reset prevp */ 835 0 stevel prevp = p->next; 836 0 stevel p->next = nlp; 837 0 stevel nlp = p; 838 0 stevel p = prevp; 839 0 stevel } else { 840 0 stevel prevp->next = p->next; 841 0 stevel p->next = nlp; 842 0 stevel nlp = p; 843 0 stevel p = prevp->next; 844 0 stevel } 845 0 stevel *curpp = p; 846 0 stevel *prevpp = prevp; 847 0 stevel *newlpp = nlp; 848 0 stevel } 849 0 stevel /* 850 0 stevel * Scans the given list of metadeivces and returns a list of top level 851 0 stevel * metadevices. 852 0 stevel * Note: The orignal list is not valid at the end and is set to NULL. 853 0 stevel */ 854 0 stevel 855 0 stevel int 856 0 stevel get_toplevel_mds(mdsetname_t *sp, mdnamelist_t **lpp, 857 0 stevel mdnamelist_t **top_pp) 858 0 stevel { 859 0 stevel mdnamelist_t *p, *prevp, *toplp; 860 0 stevel int ntopmd; 861 0 stevel md_common_t *mdp; 862 0 stevel md_error_t e = mdnullerror; 863 0 stevel 864 0 stevel ntopmd = 0; 865 0 stevel prevp = p = *lpp; 866 0 stevel toplp = NULL; 867 0 stevel 868 0 stevel while (p) { 869 0 stevel if ((mdp = meta_get_unit(sp, p->namep, &e)) == NULL) { 870 0 stevel prevp = p; 871 0 stevel p = p->next; 872 0 stevel continue; 873 0 stevel } 874 0 stevel 875 0 stevel if (mdp->parent == MD_NO_PARENT) { 876 0 stevel /* increment the top level md count. */ 877 0 stevel ntopmd++; 878 0 stevel add_to_list(&p, &prevp, &toplp); 879 0 stevel } else { 880 0 stevel prevp = p; 881 0 stevel p = p->next; 882 0 stevel } 883 0 stevel } 884 0 stevel *lpp = NULL; 885 0 stevel *top_pp = toplp; 886 0 stevel 887 0 stevel return (ntopmd); 888 0 stevel } 889 0 stevel 890 0 stevel int 891 0 stevel get_namelist(mdnamelist_t **transdevlist, mdnamelist_t **devlist, 892 0 stevel char *dev_type) 893 0 stevel { 894 0 stevel mdnamelist_t *np, *prevp; 895 0 stevel md_error_t e = mdnullerror; 896 0 stevel char *type_name; 897 0 stevel int i = 0; 898 0 stevel 899 0 stevel prevp = np = *transdevlist; 900 0 stevel while (np) { 901 0 stevel if ((type_name = metagetmiscname(np->namep, &e)) == NULL) { 902 0 stevel *devlist = NULL; 903 0 stevel return (-1); 904 0 stevel } 905 0 stevel if (strcmp(type_name, dev_type) == 0) { 906 0 stevel /* move it to the devlist */ 907 0 stevel add_to_list(&np, &prevp, devlist); 908 0 stevel i++; 909 0 stevel } else { 910 0 stevel prevp = np; 911 0 stevel np = np->next; 912 0 stevel } 913 0 stevel } 914 0 stevel return (i); 915 0 stevel } 916 0 stevel 917 0 stevel 918 0 stevel mdnamelist_t * 919 0 stevel create_nlp(mdsetname_t *sp) 920 0 stevel { 921 0 stevel mdnamelist_t *np; 922 0 stevel md_error_t e = mdnullerror; 923 0 stevel 924 0 stevel if (np = (mdnamelist_t *)malloc(sizeof (mdnamelist_t))) { 925 0 stevel np->next = NULL; 926 0 stevel return (np); 927 0 stevel } else { 928 0 stevel /* error condition below */ 929 0 stevel mde_perror(&e, "create_nlp: malloc failed\n"); 930 0 stevel md_exit(sp, 1); 931 0 stevel } 932 62 jeanm return (0); 933 0 stevel } 934 0 stevel 935 0 stevel /* 936 0 stevel * Create a list of metadevices associated with trans. top_pp points to 937 0 stevel * this list. The number of components in the list are also returned. 938 0 stevel */ 939 0 stevel int 940 0 stevel create_trans_compslist(mdsetname_t *sp, mdnamelist_t **lpp, 941 0 stevel mdnamelist_t **top_pp) 942 0 stevel { 943 0 stevel mdnamelist_t *p, *tailp, *toplp, *newlp; 944 0 stevel int ntoptrans; 945 0 stevel md_error_t e = mdnullerror; 946 0 stevel md_trans_t *tp; 947 0 stevel 948 0 stevel ntoptrans = 0; 949 0 stevel p = *lpp; 950 0 stevel tailp = toplp = NULL; 951 0 stevel /* 952 0 stevel * Scan the current list of trans devices. From that 953 0 stevel * extract all the lower level metadevices and put them on 954 0 stevel * toplp list. 955 0 stevel */ 956 0 stevel 957 0 stevel while (p) { 958 0 stevel if (tp = meta_get_trans(sp, p->namep, &e)) { 959 0 stevel /* 960 0 stevel * Check the master and log devices to see if they 961 0 stevel * are metadevices 962 0 stevel */ 963 0 stevel if (metaismeta(tp->masternamep)) { 964 0 stevel /* get a mdnamelist_t. */ 965 0 stevel newlp = create_nlp(sp); 966 0 stevel newlp->namep = tp->masternamep; 967 0 stevel if (toplp == NULL) { 968 0 stevel toplp = tailp = newlp; 969 0 stevel } else { 970 0 stevel tailp->next = newlp; 971 0 stevel tailp = newlp; 972 0 stevel } 973 0 stevel ntoptrans++; 974 0 stevel } 975 0 stevel 976 0 stevel if (tp->lognamep && metaismeta(tp->lognamep)) { 977 0 stevel newlp = create_nlp(sp); 978 0 stevel newlp->namep = tp->lognamep; 979 0 stevel if (toplp == NULL) { 980 0 stevel toplp = tailp = newlp; 981 0 stevel } else { 982 0 stevel tailp->next = newlp; 983 0 stevel tailp = newlp; 984 0 stevel } 985 0 stevel ntoptrans++; 986 0 stevel } 987 0 stevel p = p->next; 988 0 stevel } 989 0 stevel } 990 0 stevel *top_pp = toplp; 991 0 stevel return (ntoptrans); 992 0 stevel } 993 0 stevel 994 0 stevel void 995 0 stevel probe_mirror_devs(mdsetname_t *sp) 996 0 stevel { 997 0 stevel mdnamelist_t *nlp, *toplp; 998 0 stevel int cnt; 999 0 stevel md_error_t e = mdnullerror; 1000 0 stevel 1001 0 stevel nlp = toplp = NULL; 1002 0 stevel 1003 0 stevel if (meta_get_mirror_names(sp, &nlp, 0, &e) > 0) { 1004 0 stevel /* 1005 0 stevel * We have some mirrors to probe 1006 0 stevel * get a list of top-level mirrors 1007 0 stevel */ 1008 0 stevel 1009 0 stevel cnt = get_toplevel_mds(sp, &nlp, &toplp); 1010 0 stevel if (cnt && (md_probe_ioctl(sp, toplp, cnt, MD_MIRROR) < 0)) 1011 0 stevel perror("MD_IOCPROBE_DEV"); 1012 9818 Andrew } else { 1013 9818 Andrew mdclrerror(&e); 1014 0 stevel } 1015 0 stevel metafreenamelist(nlp); 1016 0 stevel metafreenamelist(toplp); 1017 0 stevel 1018 0 stevel } 1019 0 stevel 1020 0 stevel void 1021 0 stevel probe_raid_devs(mdsetname_t *sp) 1022 0 stevel { 1023 0 stevel mdnamelist_t *nlp, *toplp; 1024 0 stevel int cnt; 1025 0 stevel md_error_t e = mdnullerror; 1026 0 stevel 1027 0 stevel nlp = toplp = NULL; 1028 0 stevel 1029 0 stevel if (meta_get_raid_names(sp, &nlp, 0, &e) > 0) { 1030 0 stevel /* 1031 0 stevel * We have some mirrors to probe 1032 0 stevel * get a list of top-level mirrors 1033 0 stevel */ 1034 0 stevel 1035 0 stevel cnt = get_toplevel_mds(sp, &nlp, &toplp); 1036 0 stevel 1037 0 stevel if (cnt && (md_probe_ioctl(sp, toplp, cnt, MD_RAID) < 0)) 1038 0 stevel perror("MD_IOCPROBE_DEV"); 1039 9818 Andrew } else { 1040 9818 Andrew mdclrerror(&e); 1041 0 stevel } 1042 0 stevel metafreenamelist(nlp); 1043 0 stevel metafreenamelist(toplp); 1044 0 stevel } 1045 0 stevel 1046 0 stevel /* 1047 0 stevel * Trans probes are diffenent. -- so whats new. 1048 0 stevel * we separate out the master and log device and then issue the 1049 0 stevel * probe calls. 1050 0 stevel * Since the underlying device could be disk, stripe, RAID or miror, 1051 0 stevel * we have to sort them out and then call the ioctl for each. 1052 0 stevel */ 1053 0 stevel 1054 0 stevel void 1055 0 stevel probe_trans_devs(mdsetname_t *sp) 1056 0 stevel { 1057 0 stevel mdnamelist_t *nlp, *toplp; 1058 0 stevel mdnamelist_t *trans_raidlp, *trans_mmlp, *trans_stripelp; 1059 0 stevel int cnt; 1060 0 stevel md_error_t e = mdnullerror; 1061 0 stevel 1062 0 stevel nlp = toplp = NULL; 1063 0 stevel trans_raidlp = trans_mmlp = trans_stripelp = NULL; 1064 0 stevel 1065 0 stevel if (meta_get_trans_names(sp, &nlp, 0, &e) > 0) { 1066 0 stevel /* 1067 0 stevel * get a list of master and log metadevices. 1068 0 stevel */ 1069 0 stevel 1070 0 stevel cnt = create_trans_compslist(sp, &nlp, &toplp); 1071 0 stevel 1072 0 stevel /* underlying RAID-5 components */ 1073 0 stevel 1074 0 stevel cnt = get_namelist(&toplp, &trans_raidlp, MD_RAID); 1075 0 stevel if ((cnt > 0) && (md_probe_ioctl(sp, trans_raidlp, cnt, 1076 0 stevel MD_RAID) < 0)) 1077 0 stevel perror("MD_IOCPROBE_DEV"); 1078 0 stevel 1079 0 stevel metafreenamelist(trans_raidlp); 1080 0 stevel 1081 0 stevel /* underlying mirror components */ 1082 0 stevel 1083 0 stevel cnt = get_namelist(&toplp, &trans_mmlp, MD_MIRROR); 1084 0 stevel 1085 0 stevel if ((cnt > 0) && (md_probe_ioctl(sp, trans_mmlp, cnt, 1086 0 stevel MD_MIRROR) < 0)) 1087 0 stevel perror("MD_IOCPROBE_DEV"); 1088 0 stevel 1089 0 stevel metafreenamelist(trans_mmlp); 1090 0 stevel 1091 0 stevel /* underlying stripe components */ 1092 0 stevel 1093 0 stevel cnt = get_namelist(&toplp, &trans_stripelp, MD_STRIPE); 1094 0 stevel if ((cnt > 0) && (md_probe_ioctl(sp, trans_stripelp, cnt, 1095 0 stevel MD_STRIPE) < 0)) 1096 0 stevel perror("MD_IOCPROBE_DEV"); 1097 0 stevel metafreenamelist(trans_stripelp); 1098 0 stevel metafreenamelist(nlp); 1099 9818 Andrew } else { 1100 9818 Andrew mdclrerror(&e); 1101 0 stevel } 1102 0 stevel } 1103 0 stevel 1104 0 stevel /* 1105 0 stevel * probe hot spares. This is differs from other approaches since 1106 0 stevel * there are no read/write routines through md. We check at the physical 1107 0 stevel * component level and then delete it if its bad. 1108 0 stevel */ 1109 0 stevel 1110 0 stevel void 1111 0 stevel probe_hotspare_devs(mdsetname_t *sp) 1112 0 stevel { 1113 0 stevel mdhspnamelist_t *hspnlp = NULL; 1114 0 stevel mdhspnamelist_t *p; 1115 0 stevel md_hsp_t *hspp; 1116 0 stevel md_error_t e = mdnullerror; 1117 0 stevel 1118 9818 Andrew if (meta_get_hsp_names(sp, &hspnlp, 0, &e) <= 0) { 1119 9818 Andrew mdclrerror(&e); 1120 0 stevel return; 1121 0 stevel } 1122 0 stevel for (p = hspnlp; (p != NULL); p = p->next) { 1123 0 stevel mdhspname_t *hspnp = p->hspnamep; 1124 0 stevel 1125 0 stevel if ((hspp = meta_get_hsp(sp, hspnp, &e)) == NULL) 1126 0 stevel continue; 1127 0 stevel 1128 0 stevel if (hspp->hotspares.hotspares_len != 0) { 1129 0 stevel delete_hotspares_impl(sp, hspnp, hspp); 1130 0 stevel } 1131 0 stevel } 1132 0 stevel metafreehspnamelist(hspnlp); 1133 9818 Andrew mdclrerror(&e); 1134 0 stevel } 1135 0 stevel 1136 0 stevel static void 1137 0 stevel probe_all_devs(mdsetname_t *sp) 1138 0 stevel { 1139 0 stevel probe_hotspare_devs(sp); 1140 0 stevel probe_mirror_devs(sp); 1141 0 stevel probe_raid_devs(sp); 1142 0 stevel probe_trans_devs(sp); 1143 0 stevel } 1144 0 stevel 1145 0 stevel /* 1146 0 stevel * The following functions are used to print the concise output 1147 0 stevel * of the metastat coommand (-c option). 1148 0 stevel * 1149 0 stevel * Normally the output for metastat is performed within libmeta via 1150 0 stevel * the *_report functions within each of the metadevice specific files in 1151 0 stevel * libmeta. However, it is usually bad architecture for a library to 1152 0 stevel * perform output since there are so many different ways that an application 1153 0 stevel * can choose to do output (e.g. GUI, CLI, CIM, SNMP, etc.). So, for the 1154 0 stevel * concise output option we have moved the CLI output to the metastat 1155 0 stevel * code and just use libmeta as the source of data to be printed. 1156 0 stevel * 1157 0 stevel * This function gets all of the different top-level metadevices in the set 1158 0 stevel * and prints them. It calls the print_concise_md() function to recursively 1159 0 stevel * print the metadevices that underly the top-level metadevices. It does 1160 0 stevel * special handling for soft partitions so that all of the SPs on the 1161 0 stevel * same underlying device are grouped and then that underlying device 1162 0 stevel * is only printed once. 1163 0 stevel */ 1164 0 stevel static void 1165 0 stevel print_concise_diskset(mdsetname_t *sp) 1166 0 stevel { 1167 0 stevel md_error_t error = mdnullerror; 1168 0 stevel mdnamelist_t *nl = NULL; 1169 0 stevel mdhspnamelist_t *hsp_list = NULL; 1170 0 stevel 1171 0 stevel /* 1172 0 stevel * We do extra handling for soft parts since we want to find 1173 0 stevel * all of the SPs on the same underlying device, group them and 1174 0 stevel * print them together before printing the underlying device just 1175 0 stevel * once. This logic doesn't apply to any other metadevice type. 1176 0 stevel */ 1177 0 stevel if (meta_get_sp_names(sp, &nl, 0, &error) >= 0) { 1178 6630 sk102515 mdnamelist_t *nlp; 1179 6630 sk102515 /* keep track of the softparts on the same underlying device */ 1180 6630 sk102515 struct sp_base_list *base_list = NULL; 1181 0 stevel 1182 6630 sk102515 for (nlp = nl; nlp != NULL; nlp = nlp->next) { 1183 6630 sk102515 mdname_t *mdn; 1184 6630 sk102515 md_sp_t *soft_part; 1185 6630 sk102515 mdnamelist_t *tnlp; 1186 0 stevel 1187 6630 sk102515 mdn = metaname(&sp, nlp->namep->cname, 1188 6630 sk102515 META_DEVICE, &error); 1189 6630 sk102515 mdclrerror(&error); 1190 6630 sk102515 if (mdn == NULL) { 1191 6630 sk102515 print_concise_entry(0, nlp->namep->cname, 1192 6630 sk102515 0, 'p'); 1193 11053 Surya (void) printf("\n"); 1194 6630 sk102515 continue; 1195 6630 sk102515 } 1196 6630 sk102515 1197 6630 sk102515 soft_part = meta_get_sp_common(sp, mdn, 1, &error); 1198 6630 sk102515 mdclrerror(&error); 1199 6630 sk102515 1200 6630 sk102515 if (soft_part == NULL || 1201 6630 sk102515 MD_HAS_PARENT(soft_part->common.parent) || 1202 6630 sk102515 sp_done(soft_part, base_list)) 1203 6630 sk102515 continue; 1204 6630 sk102515 1205 6630 sk102515 /* print this soft part */ 1206 6630 sk102515 print_concise_entry(0, soft_part->common.namep->cname, 1207 6630 sk102515 soft_part->common.size, 'p'); 1208 6630 sk102515 (void) printf(" %s\n", soft_part->compnamep->cname); 1209 6630 sk102515 1210 6630 sk102515 /* 1211 6630 sk102515 * keep track of the underlying device of 1212 6630 sk102515 * this soft part 1213 6630 sk102515 */ 1214 6630 sk102515 base_list = sp_add_done(soft_part, base_list); 1215 6630 sk102515 1216 6630 sk102515 /* 1217 6630 sk102515 * now print all of the other soft parts on the same 1218 6630 sk102515 * underlying device 1219 6630 sk102515 */ 1220 6630 sk102515 for (tnlp = nlp->next; tnlp != NULL; tnlp = 1221 6630 sk102515 tnlp->next) { 1222 6630 sk102515 md_sp_t *part; 1223 6630 sk102515 1224 6630 sk102515 mdn = metaname(&sp, tnlp->namep->cname, 1225 6630 sk102515 META_DEVICE, &error); 1226 6630 sk102515 1227 6630 sk102515 mdclrerror(&error); 1228 6630 sk102515 if (mdn == NULL) 1229 6630 sk102515 continue; 1230 6630 sk102515 1231 6630 sk102515 part = meta_get_sp_common(sp, mdn, 1, &error); 1232 6630 sk102515 mdclrerror(&error); 1233 6630 sk102515 1234 6630 sk102515 if (part == NULL || MD_HAS_PARENT( 1235 6630 sk102515 part->common.parent) || 1236 6630 sk102515 ! sp_match(part, base_list)) 1237 6630 sk102515 continue; 1238 6630 sk102515 1239 6630 sk102515 /* on the same base so print this soft part */ 1240 6630 sk102515 print_concise_entry(0, 1241 6630 sk102515 part->common.namep->cname, 1242 6630 sk102515 part->common.size, 'p'); 1243 6630 sk102515 (void) printf(" %s\n", part->compnamep->cname); 1244 6630 sk102515 } 1245 6630 sk102515 1246 6630 sk102515 /* 1247 6630 sk102515 * print the common metadevice hierarchy 1248 6630 sk102515 * under these soft parts 1249 6630 sk102515 */ 1250 6630 sk102515 print_concise_md(META_INDENT, sp, soft_part->compnamep); 1251 0 stevel } 1252 0 stevel 1253 6630 sk102515 free_names(&nl); 1254 6630 sk102515 sp_free_list(base_list); 1255 0 stevel } 1256 0 stevel mdclrerror(&error); 1257 0 stevel 1258 0 stevel if (meta_get_trans_names(sp, &nl, 0, &error) >= 0) 1259 6630 sk102515 print_concise_namelist(sp, &nl, 't'); 1260 0 stevel mdclrerror(&error); 1261 0 stevel 1262 0 stevel if (meta_get_mirror_names(sp, &nl, 0, &error) >= 0) 1263 6630 sk102515 print_concise_namelist(sp, &nl, 'm'); 1264 0 stevel mdclrerror(&error); 1265 0 stevel 1266 0 stevel if (meta_get_raid_names(sp, &nl, 0, &error) >= 0) 1267 6630 sk102515 print_concise_namelist(sp, &nl, 'r'); 1268 0 stevel mdclrerror(&error); 1269 0 stevel 1270 0 stevel if (meta_get_stripe_names(sp, &nl, 0, &error) >= 0) 1271 6630 sk102515 print_concise_namelist(sp, &nl, 's'); 1272 0 stevel mdclrerror(&error); 1273 0 stevel 1274 0 stevel if (meta_get_hsp_names(sp, &hsp_list, 0, &error) >= 0) { 1275 6630 sk102515 mdhspnamelist_t *nlp; 1276 0 stevel 1277 6630 sk102515 for (nlp = hsp_list; nlp != NULL; nlp = nlp->next) { 1278 0 stevel md_hsp_t *hsp; 1279 0 stevel 1280 0 stevel print_concise_entry(0, nlp->hspnamep->hspname, 0, 'h'); 1281 0 stevel 1282 0 stevel hsp = meta_get_hsp_common(sp, nlp->hspnamep, 1, &error); 1283 0 stevel mdclrerror(&error); 1284 0 stevel if (hsp != NULL) { 1285 6630 sk102515 int i; 1286 0 stevel 1287 6630 sk102515 for (i = 0; i < hsp->hotspares.hotspares_len; i++) { 1288 6630 sk102515 md_hs_t *hs; 1289 6630 sk102515 char *state; 1290 0 stevel 1291 6630 sk102515 hs = &hsp->hotspares.hotspares_val[i]; 1292 0 stevel 1293 6630 sk102515 (void) printf(" %s", hs->hsnamep->cname); 1294 0 stevel 1295 6630 sk102515 state = get_hs_state(hs); 1296 6630 sk102515 if (state != NULL) 1297 6630 sk102515 (void) printf(" (%s)", state); 1298 6630 sk102515 } 1299 0 stevel } 1300 0 stevel 1301 0 stevel (void) printf("\n"); 1302 6630 sk102515 } 1303 0 stevel 1304 9818 Andrew mdclrerror(&error); 1305 6630 sk102515 metafreehspnamelist(hsp_list); 1306 0 stevel } 1307 0 stevel } 1308 0 stevel 1309 0 stevel /* 1310 0 stevel * Print the top-level metadevices in the name list for concise output. 1311 0 stevel */ 1312 0 stevel static void 1313 0 stevel print_concise_namelist(mdsetname_t *sp, mdnamelist_t **nl, char mtype) 1314 0 stevel { 1315 0 stevel mdnamelist_t *nlp; 1316 0 stevel md_error_t error = mdnullerror; 1317 0 stevel 1318 0 stevel for (nlp = *nl; nlp != NULL; nlp = nlp->next) { 1319 6630 sk102515 mdname_t *mdn; 1320 6630 sk102515 md_common_t *u; 1321 0 stevel 1322 6630 sk102515 mdn = metaname(&sp, nlp->namep->cname, META_DEVICE, &error); 1323 6630 sk102515 mdclrerror(&error); 1324 6630 sk102515 if (mdn == NULL) { 1325 6630 sk102515 print_concise_entry(0, nlp->namep->cname, 0, mtype); 1326 11053 Surya (void) printf("\n"); 1327 6630 sk102515 continue; 1328 6630 sk102515 } 1329 0 stevel 1330 6630 sk102515 u = get_concise_unit(sp, mdn, &error); 1331 6630 sk102515 mdclrerror(&error); 1332 0 stevel 1333 6630 sk102515 if (u != NULL && !MD_HAS_PARENT(u->parent)) 1334 6630 sk102515 print_concise_md(0, sp, mdn); 1335 0 stevel } 1336 0 stevel 1337 0 stevel free_names(nl); 1338 0 stevel } 1339 0 stevel 1340 0 stevel /* 1341 0 stevel * Concise mirror output. 1342 0 stevel */ 1343 0 stevel static void 1344 0 stevel print_concise_mirror(int indent, mdsetname_t *sp, md_mirror_t *mirror) 1345 0 stevel { 1346 0 stevel md_error_t error = mdnullerror; 1347 0 stevel int i; 1348 0 stevel md_status_t status = mirror->common.state; 1349 0 stevel 1350 0 stevel if (mirror == NULL) 1351 6630 sk102515 return; 1352 0 stevel 1353 0 stevel print_concise_entry(indent, mirror->common.namep->cname, 1354 0 stevel mirror->common.size, 'm'); 1355 0 stevel 1356 0 stevel for (i = 0; i < NMIRROR; i++) { 1357 6630 sk102515 uint_t tstate = 0; 1358 6630 sk102515 char *state; 1359 0 stevel 1360 6630 sk102515 if (mirror->submirrors[i].submirnamep == NULL) 1361 6630 sk102515 continue; 1362 6630 sk102515 (void) printf(" %s", mirror->submirrors[i].submirnamep->cname); 1363 0 stevel 1364 6630 sk102515 if (mirror->submirrors[i].state & SMS_OFFLINE) { 1365 6630 sk102515 (void) printf(gettext(" (offline)")); 1366 6630 sk102515 continue; 1367 6630 sk102515 } 1368 0 stevel 1369 6630 sk102515 if (metaismeta(mirror->submirrors[i].submirnamep)) 1370 6630 sk102515 (void) meta_get_tstate( 1371 6630 sk102515 mirror->submirrors[i].submirnamep->dev, 1372 6630 sk102515 &tstate, &error); 1373 0 stevel 1374 9818 Andrew mdclrerror(&error); 1375 6630 sk102515 state = get_sm_state(mirror, i, status, tstate); 1376 6630 sk102515 if (state != NULL) 1377 6630 sk102515 (void) printf(" (%s)", state); 1378 0 stevel } 1379 0 stevel 1380 0 stevel (void) printf("\n"); 1381 0 stevel 1382 734 mw145384 indent += META_INDENT; 1383 0 stevel for (i = 0; i < NMIRROR; i++) { 1384 6630 sk102515 if (mirror->submirrors[i].submirnamep == NULL) 1385 6630 sk102515 continue; 1386 0 stevel 1387 6630 sk102515 print_concise_md(indent, sp, mirror->submirrors[i].submirnamep); 1388 0 stevel } 1389 0 stevel } 1390 0 stevel 1391 0 stevel /* 1392 0 stevel * Concise raid output. 1393 0 stevel */ 1394 0 stevel static void 1395 0 stevel print_concise_raid(int indent, mdsetname_t *sp, md_raid_t *raid) 1396 0 stevel { 1397 0 stevel md_error_t error = mdnullerror; 1398 0 stevel int i; 1399 0 stevel uint_t tstate = 0; 1400 0 stevel 1401 0 stevel if (raid == NULL) 1402 6630 sk102515 return; 1403 0 stevel 1404 0 stevel print_concise_entry(indent, raid->common.namep->cname, 1405 0 stevel raid->common.size, 'r'); 1406 0 stevel 1407 0 stevel if (metaismeta(raid->common.namep)) 1408 6630 sk102515 (void) meta_get_tstate(raid->common.namep->dev, 1409 6630 sk102515 &tstate, &error); 1410 0 stevel 1411 0 stevel for (i = 0; i < raid->cols.cols_len; i++) { 1412 6630 sk102515 md_raidcol_t *colp = &raid->cols.cols_val[i]; 1413 6630 sk102515 mdname_t *namep = ((colp->hsnamep != NULL) ? 1414 6630 sk102515 colp->hsnamep : colp->colnamep); 1415 6630 sk102515 char *hsname = ((colp->hsnamep != NULL) ? 1416 6630 sk102515 colp->hsnamep->cname : NULL); 1417 6630 sk102515 char *col_state = NULL; 1418 0 stevel 1419 6630 sk102515 (void) printf(" %s", colp->colnamep->cname); 1420 0 stevel 1421 6630 sk102515 if (metaismeta(namep)) { 1422 6630 sk102515 uint_t tstate = 0; 1423 0 stevel 1424 6630 sk102515 (void) meta_get_tstate(namep->dev, &tstate, &error); 1425 9818 Andrew mdclrerror(&error); 1426 6630 sk102515 col_state = get_raid_col_state(colp, tstate); 1427 0 stevel 1428 6630 sk102515 } else { 1429 6630 sk102515 if (tstate != 0) 1430 6630 sk102515 col_state = "-"; 1431 6630 sk102515 else 1432 6630 sk102515 col_state = get_raid_col_state(colp, tstate); 1433 6630 sk102515 } 1434 0 stevel 1435 6630 sk102515 if (col_state != NULL) { 1436 6630 sk102515 if (hsname != NULL) 1437 6630 sk102515 (void) printf(" (%s-%s)", col_state, hsname); 1438 6630 sk102515 else 1439 6630 sk102515 (void) printf(" (%s)", col_state); 1440 0 stevel 1441 6630 sk102515 } else if (hsname != NULL) { 1442 6630 sk102515 (void) printf(gettext(" (spared-%s)"), hsname); 1443 6630 sk102515 } 1444 0 stevel } 1445 0 stevel 1446 0 stevel (void) printf("\n"); 1447 0 stevel 1448 734 mw145384 indent += META_INDENT; 1449 0 stevel for (i = 0; i < raid->cols.cols_len; i++) { 1450 6630 sk102515 print_concise_md(indent, sp, raid->cols.cols_val[i].colnamep); 1451 0 stevel } 1452 0 stevel } 1453 0 stevel 1454 0 stevel /* 1455 0 stevel * Concise stripe output. 1456 0 stevel */ 1457 0 stevel static void 1458 0 stevel print_concise_stripe(int indent, mdsetname_t *sp, md_stripe_t *stripe) 1459 0 stevel { 1460 0 stevel md_error_t error = mdnullerror; 1461 0 stevel int i; 1462 0 stevel uint_t top_tstate = 0; 1463 0 stevel 1464 0 stevel if (stripe == NULL) 1465 6630 sk102515 return; 1466 0 stevel 1467 0 stevel print_concise_entry(indent, stripe->common.namep->cname, 1468 0 stevel stripe->common.size, 's'); 1469 0 stevel 1470 0 stevel if (metaismeta(stripe->common.namep)) 1471 6630 sk102515 (void) meta_get_tstate(stripe->common.namep->dev, &top_tstate, 1472 6630 sk102515 &error); 1473 0 stevel mdclrerror(&error); 1474 0 stevel 1475 0 stevel for (i = 0; i < stripe->rows.rows_len; i++) { 1476 6630 sk102515 md_row_t *rowp; 1477 6630 sk102515 int j; 1478 0 stevel 1479 6630 sk102515 rowp = &stripe->rows.rows_val[i]; 1480 0 stevel 1481 6630 sk102515 for (j = 0; j < rowp->comps.comps_len; j++) { 1482 6630 sk102515 md_comp_t *comp; 1483 6630 sk102515 uint_t tstate = 0; 1484 6630 sk102515 char *comp_state = NULL; 1485 6630 sk102515 char *hsname; 1486 0 stevel 1487 6630 sk102515 comp = &rowp->comps.comps_val[j]; 1488 6630 sk102515 (void) printf(" %s", comp->compnamep->cname); 1489 0 stevel 1490 6630 sk102515 if (metaismeta(comp->compnamep)) { 1491 6630 sk102515 uint_t tstate = 0; 1492 6630 sk102515 (void) meta_get_tstate(comp->compnamep->dev, 1493 6630 sk102515 &tstate, &error); 1494 9818 Andrew mdclrerror(&error); 1495 6630 sk102515 comp_state = get_stripe_state(comp, tstate); 1496 6630 sk102515 } else { 1497 6630 sk102515 if (top_tstate != 0) 1498 6630 sk102515 comp_state = "-"; 1499 6630 sk102515 else 1500 6630 sk102515 comp_state = get_stripe_state(comp, tstate); 1501 6630 sk102515 } 1502 6630 sk102515 1503 6630 sk102515 hsname = ((comp->hsnamep != NULL) ? 1504 6630 sk102515 comp->hsnamep->cname : NULL); 1505 6630 sk102515 1506 6630 sk102515 if (comp_state != NULL) { 1507 6630 sk102515 if (hsname != NULL) 1508 6630 sk102515 (void) printf(" (%s-%s)", 1509 6630 sk102515 comp_state, hsname); 1510 6630 sk102515 else 1511 6630 sk102515 (void) printf(" (%s)", comp_state); 1512 6630 sk102515 1513 6630 sk102515 } else if (hsname != NULL) { 1514 6630 sk102515 (void) printf(gettext(" (spared-%s)"), hsname); 1515 6630 sk102515 } 1516 0 stevel } 1517 0 stevel } 1518 0 stevel 1519 0 stevel (void) printf("\n"); 1520 0 stevel 1521 734 mw145384 indent += META_INDENT; 1522 0 stevel for (i = 0; i < stripe->rows.rows_len; i++) { 1523 6630 sk102515 md_row_t *rowp; 1524 6630 sk102515 int j; 1525 0 stevel 1526 6630 sk102515 rowp = &stripe->rows.rows_val[i]; 1527 0 stevel 1528 6630 sk102515 for (j = 0; j < rowp->comps.comps_len; j++) { 1529 6630 sk102515 print_concise_md(indent, sp, 1530 6630 sk102515 rowp->comps.comps_val[j].compnamep); 1531 6630 sk102515 } 1532 0 stevel } 1533 0 stevel } 1534 0 stevel 1535 0 stevel /* 1536 0 stevel * Concise soft partition output. 1537 0 stevel */ 1538 0 stevel static void 1539 0 stevel print_concise_sp(int indent, mdsetname_t *sp, md_sp_t *part) 1540 0 stevel { 1541 0 stevel if (part == NULL) 1542 6630 sk102515 return; 1543 0 stevel 1544 0 stevel print_concise_entry(indent, part->common.namep->cname, 1545 0 stevel part->common.size, 'p'); 1546 0 stevel 1547 0 stevel (void) printf(" %s\n", part->compnamep->cname); 1548 0 stevel 1549 734 mw145384 print_concise_md(indent + META_INDENT, sp, part->compnamep); 1550 0 stevel } 1551 0 stevel 1552 0 stevel /* 1553 0 stevel * Concise trans output. 1554 0 stevel */ 1555 0 stevel static void 1556 0 stevel print_concise_trans(int indent, mdsetname_t *sp, md_trans_t *trans) 1557 0 stevel { 1558 0 stevel if (trans == NULL) 1559 6630 sk102515 return; 1560 0 stevel 1561 0 stevel print_concise_entry(indent, trans->common.namep->cname, 1562 0 stevel trans->common.size, 't'); 1563 0 stevel 1564 0 stevel if (trans->masternamep != NULL) 1565 6630 sk102515 (void) printf(" %s", trans->masternamep->cname); 1566 0 stevel 1567 0 stevel if (trans->lognamep != NULL) 1568 6630 sk102515 (void) printf(" %s", trans->lognamep->cname); 1569 0 stevel 1570 0 stevel (void) printf("\n"); 1571 0 stevel 1572 734 mw145384 indent += META_INDENT; 1573 0 stevel 1574 0 stevel print_concise_md(indent, sp, trans->masternamep); 1575 0 stevel 1576 0 stevel print_concise_md(indent, sp, trans->lognamep); 1577 0 stevel } 1578 0 stevel 1579 0 stevel /* 1580 0 stevel * Recursive function for concise metadevice nested output. 1581 0 stevel */ 1582 0 stevel static void 1583 0 stevel print_concise_md(int indent, mdsetname_t *sp, mdname_t *np) 1584 0 stevel { 1585 0 stevel md_error_t error = mdnullerror; 1586 0 stevel md_unit_t *u; 1587 0 stevel md_mirror_t *mirror; 1588 0 stevel md_raid_t *raid; 1589 0 stevel md_sp_t *soft_part; 1590 0 stevel md_stripe_t *stripe; 1591 0 stevel md_trans_t *trans; 1592 0 stevel 1593 0 stevel if (np == NULL || !metaismeta(np)) 1594 6630 sk102515 return; 1595 0 stevel 1596 9818 Andrew if ((u = meta_get_mdunit(sp, np, &error)) == NULL) { 1597 9818 Andrew mdclrerror(&error); 1598 6630 sk102515 return; 1599 9818 Andrew } 1600 0 stevel 1601 0 stevel switch (u->c.un_type) { 1602 6630 sk102515 case MD_DEVICE: 1603 6630 sk102515 stripe = meta_get_stripe_common(sp, np, 1, &error); 1604 6630 sk102515 print_concise_stripe(indent, sp, stripe); 1605 6630 sk102515 break; 1606 0 stevel 1607 6630 sk102515 case MD_METAMIRROR: 1608 6630 sk102515 mirror = meta_get_mirror(sp, np, &error); 1609 6630 sk102515 print_concise_mirror(indent, sp, mirror); 1610 6630 sk102515 break; 1611 0 stevel 1612 6630 sk102515 case MD_METATRANS: 1613 6630 sk102515 trans = meta_get_trans_common(sp, np, 1, &error); 1614 6630 sk102515 print_concise_trans(indent, sp, trans); 1615 6630 sk102515 break; 1616 0 stevel 1617 6630 sk102515 case MD_METARAID: 1618 6630 sk102515 raid = meta_get_raid_common(sp, np, 1, &error); 1619 6630 sk102515 print_concise_raid(indent, sp, raid); 1620 6630 sk102515 break; 1621 0 stevel 1622 6630 sk102515 case MD_METASP: 1623 6630 sk102515 soft_part = meta_get_sp_common(sp, np, 1, &error); 1624 6630 sk102515 print_concise_sp(indent, sp, soft_part); 1625 6630 sk102515 break; 1626 0 stevel 1627 6630 sk102515 default: 1628 6630 sk102515 return; 1629 0 stevel } 1630 9818 Andrew mdclrerror(&error); 1631 0 stevel } 1632 0 stevel 1633 0 stevel /* 1634 0 stevel * Given a name get the unit for use in concise output. We use the *_common 1635 0 stevel * routines in libmeta which allow us to specify the "fast" flag, thereby 1636 0 stevel * avoiding the DKIOCGGEOM ioctl that normally happens. 1637 0 stevel */ 1638 0 stevel static md_common_t * 1639 0 stevel get_concise_unit(mdsetname_t *sp, mdname_t *np, md_error_t *ep) 1640 0 stevel { 1641 0 stevel char *miscname; 1642 0 stevel 1643 0 stevel /* short circuit */ 1644 0 stevel if (np->drivenamep->unitp != NULL) 1645 0 stevel return (np->drivenamep->unitp); 1646 0 stevel if (metachkmeta(np, ep) != 0) 1647 0 stevel return (NULL); 1648 0 stevel 1649 0 stevel /* dispatch */ 1650 0 stevel if ((miscname = metagetmiscname(np, ep)) == NULL) 1651 0 stevel return (NULL); 1652 0 stevel else if (strcmp(miscname, MD_STRIPE) == 0) 1653 0 stevel return ((md_common_t *)meta_get_stripe_common(sp, np, 1, ep)); 1654 0 stevel else if (strcmp(miscname, MD_MIRROR) == 0) 1655 0 stevel return ((md_common_t *)meta_get_mirror(sp, np, ep)); 1656 0 stevel else if (strcmp(miscname, MD_TRANS) == 0) 1657 0 stevel return ((md_common_t *)meta_get_trans_common(sp, np, 1, ep)); 1658 0 stevel else if (strcmp(miscname, MD_RAID) == 0) 1659 0 stevel return ((md_common_t *)meta_get_raid_common(sp, np, 1, ep)); 1660 0 stevel else if (strcmp(miscname, MD_SP) == 0) 1661 0 stevel return ((md_common_t *)meta_get_sp_common(sp, np, 1, ep)); 1662 0 stevel else { 1663 0 stevel (void) mdmderror(ep, MDE_UNKNOWN_TYPE, meta_getminor(np->dev), 1664 0 stevel np->cname); 1665 0 stevel return (NULL); 1666 0 stevel } 1667 0 stevel } 1668 0 stevel 1669 0 stevel static void 1670 0 stevel free_names(mdnamelist_t **nlp) 1671 0 stevel { 1672 0 stevel mdnamelist_t *p; 1673 0 stevel 1674 0 stevel for (p = *nlp; p != NULL; p = p->next) { 1675 6630 sk102515 meta_invalidate_name(p->namep); 1676 6630 sk102515 p->namep = NULL; 1677 0 stevel } 1678 0 stevel metafreenamelist(*nlp); 1679 0 stevel *nlp = NULL; 1680 0 stevel } 1681 0 stevel 1682 0 stevel /* 1683 0 stevel * Submirror state for concise output. 1684 0 stevel */ 1685 0 stevel static char * 1686 0 stevel get_sm_state(md_mirror_t *mirror, int i, md_status_t mirror_status, 1687 0 stevel uint_t tstate) 1688 0 stevel { 1689 0 stevel sm_state_t state = mirror->submirrors[i].state; 1690 6630 sk102515 uint_t is_target = 1691 6630 sk102515 mirror->submirrors[i].flags & MD_SM_RESYNC_TARGET; 1692 0 stevel 1693 0 stevel /* 1694 0 stevel * Only return Unavailable if there is no flagged error on the 1695 0 stevel * submirror. If the mirror has received any writes since the submirror 1696 0 stevel * went into Unavailable state a resync is required. To alert the 1697 0 stevel * administrator to this we return a 'Needs maintenance' message. 1698 0 stevel */ 1699 0 stevel if ((tstate != 0) && (state & SMS_RUNNING)) 1700 0 stevel return (gettext("unavail")); 1701 0 stevel 1702 0 stevel /* all is well */ 1703 0 stevel if (state & SMS_RUNNING) { 1704 0 stevel if (!(mirror_status & MD_UN_OPT_NOT_DONE) || 1705 0 stevel ((mirror_status & MD_UN_OPT_NOT_DONE) && !is_target)) 1706 0 stevel return (NULL); 1707 0 stevel } 1708 0 stevel 1709 0 stevel /* resyncing, needs repair */ 1710 0 stevel if ((state & (SMS_COMP_RESYNC | SMS_ATTACHED_RESYNC | 1711 0 stevel SMS_OFFLINE_RESYNC)) || (mirror_status & MD_UN_OPT_NOT_DONE)) { 1712 0 stevel static char buf[MAXPATHLEN]; 1713 0 stevel 1714 0 stevel if (mirror_status & MD_UN_RESYNC_ACTIVE) { 1715 0 stevel 1716 6630 sk102515 if (mirror->common.revision & MD_64BIT_META_DEV) { 1717 6630 sk102515 (void) snprintf(buf, sizeof (buf), 1718 6630 sk102515 gettext("resync-%2d.%1d%%"), 1719 6630 sk102515 mirror->percent_done / 10, 1720 6630 sk102515 mirror->percent_done % 10); 1721 6630 sk102515 } else { 1722 6630 sk102515 (void) snprintf(buf, sizeof (buf), 1723 6630 sk102515 gettext("resync-%d%%"), mirror->percent_done); 1724 6630 sk102515 } 1725 6630 sk102515 return (buf); 1726 0 stevel } 1727 0 stevel return (gettext("maint")); 1728 0 stevel } 1729 0 stevel 1730 0 stevel /* needs repair */ 1731 0 stevel if (state & (SMS_COMP_ERRED | SMS_ATTACHED | SMS_OFFLINE)) 1732 0 stevel return (gettext("maint")); 1733 0 stevel 1734 0 stevel /* unknown */ 1735 0 stevel return (gettext("unknown")); 1736 0 stevel } 1737 0 stevel 1738 0 stevel /* 1739 0 stevel * Raid component state for concise output. 1740 0 stevel */ 1741 0 stevel static char * 1742 0 stevel get_raid_col_state(md_raidcol_t *colp, uint_t tstate) 1743 0 stevel { 1744 0 stevel if (tstate != 0) 1745 6630 sk102515 return (gettext("unavail")); 1746 0 stevel 1747 734 mw145384 return (meta_get_raid_col_state(colp->state)); 1748 0 stevel } 1749 0 stevel 1750 0 stevel /* 1751 0 stevel * Stripe state for concise output. 1752 0 stevel */ 1753 0 stevel static char * 1754 0 stevel get_stripe_state(md_comp_t *mdcp, uint_t tstate) 1755 0 stevel { 1756 0 stevel comp_state_t state = mdcp->state; 1757 0 stevel 1758 0 stevel if (tstate != 0) 1759 6630 sk102515 return ("unavail"); 1760 0 stevel 1761 734 mw145384 return (meta_get_stripe_state(state)); 1762 0 stevel } 1763 0 stevel 1764 0 stevel /* 1765 0 stevel * Hostspare state for concise output. 1766 0 stevel */ 1767 0 stevel static char * 1768 0 stevel get_hs_state(md_hs_t *hsp) 1769 0 stevel { 1770 0 stevel hotspare_states_t state = hsp->state; 1771 0 stevel 1772 734 mw145384 return (meta_get_hs_state(state)); 1773 0 stevel } 1774 0 stevel 1775 0 stevel 1776 0 stevel /* 1777 0 stevel * Keep track of printed soft partitions for concise output. 1778 0 stevel */ 1779 0 stevel static struct sp_base_list * 1780 0 stevel sp_add_done(md_sp_t *part, struct sp_base_list *lp) 1781 0 stevel { 1782 0 stevel struct sp_base_list *n; 1783 0 stevel 1784 0 stevel n = (struct sp_base_list *)malloc(sizeof (struct sp_base_list)); 1785 0 stevel if (n == NULL) 1786 6630 sk102515 return (lp); 1787 0 stevel 1788 0 stevel if ((n->base = strdup(part->compnamep->cname)) == NULL) { 1789 6630 sk102515 free(n); 1790 6630 sk102515 return (lp); 1791 0 stevel } 1792 0 stevel 1793 0 stevel n->next = lp; 1794 0 stevel 1795 0 stevel return (n); 1796 0 stevel } 1797 0 stevel 1798 0 stevel /* 1799 0 stevel * Keep track of printed soft partitions for concise output. 1800 0 stevel */ 1801 0 stevel static int 1802 0 stevel sp_done(md_sp_t *part, struct sp_base_list *lp) 1803 0 stevel { 1804 0 stevel for (; lp != NULL; lp = lp->next) { 1805 6630 sk102515 if (strcmp(lp->base, part->compnamep->cname) == 0) 1806 6630 sk102515 return (1); 1807 0 stevel } 1808 0 stevel 1809 0 stevel return (0); 1810 0 stevel } 1811 0 stevel 1812 0 stevel /* 1813 0 stevel * Check the first element for a match. 1814 0 stevel */ 1815 0 stevel static int 1816 0 stevel sp_match(md_sp_t *part, struct sp_base_list *lp) 1817 0 stevel { 1818 0 stevel if (lp != NULL && strcmp(lp->base, part->compnamep->cname) == 0) 1819 6630 sk102515 return (1); 1820 0 stevel 1821 0 stevel return (0); 1822 0 stevel } 1823 0 stevel 1824 0 stevel /* 1825 0 stevel * Free memory used for soft partition printed status in concise output. 1826 0 stevel */ 1827 0 stevel static void 1828 0 stevel sp_free_list(struct sp_base_list *lp) 1829 0 stevel { 1830 0 stevel struct sp_base_list *n; 1831 0 stevel 1832 0 stevel for (; lp != NULL; lp = n) { 1833 6630 sk102515 n = lp->next; 1834 6630 sk102515 free(lp->base); 1835 6630 sk102515 free(lp); 1836 0 stevel } 1837 0 stevel } 1838