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 (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26 /*
27 * Just in case we're not in a build environment, make sure that
28 * TEXT_DOMAIN gets set to something.
29 */
30 #if !defined(TEXT_DOMAIN)
31 #define TEXT_DOMAIN "SYS_TEST"
32 #endif
33
34 /*
35 * stripe operations
36 */
37
38 #include <limits.h>
39 #include <stdlib.h>
40 #include <meta.h>
41 #include <sys/lvm/md_stripe.h>
42 #include <sys/lvm/md_convert.h>
43
44 #define QUOTE(x) #x
45 #define VAL2STR(x) QUOTE(x)
46
47 /*
48 * replace stripe/concat
49 */
50 int
meta_stripe_replace(mdsetname_t * sp,mdname_t * stripenp,mdname_t * oldnp,mdname_t * newnp,mdcmdopts_t options,md_error_t * ep)51 meta_stripe_replace(
52 mdsetname_t *sp,
53 mdname_t *stripenp,
54 mdname_t *oldnp,
55 mdname_t *newnp,
56 mdcmdopts_t options,
57 md_error_t *ep
58 )
59 {
60 replace_params_t params;
61 md_dev64_t old_dev, new_dev;
62 diskaddr_t new_start_blk;
63 diskaddr_t new_end_blk, label, size, start_blk;
64
65 /* should have same set */
66 assert(sp != NULL);
67 assert(sp->setno == MD_MIN2SET(meta_getminor(stripenp->dev)));
68
69 new_dev = newnp->dev;
70 new_start_blk = newnp->start_blk;
71 new_end_blk = newnp->end_blk;
72
73 meta_invalidate_name(stripenp);
74
75 /* the old device binding is now established */
76 if ((old_dev = oldnp->dev) == NODEV64)
77 return (mdsyserror(ep, ENODEV, oldnp->cname));
78
79 if (((strcmp(oldnp->rname, newnp->rname) == 0) &&
80 (old_dev != new_dev))) {
81 newnp->dev = new_dev;
82 newnp->start_blk = new_start_blk;
83 newnp->end_blk = new_end_blk;
84 }
85
86 if ((size = metagetsize(newnp, ep)) == MD_DISKADDR_ERROR)
87 return (-1);
88 if ((label = metagetlabel(newnp, ep)) == MD_DISKADDR_ERROR)
89 return (-1);
90 if ((start_blk = metagetstart(sp, newnp, ep)) == MD_DISKADDR_ERROR)
91 return (-1);
92 if (start_blk >= size) {
93 (void) mdsyserror(ep, ENOSPC, newnp->cname);
94 return (-1);
95 }
96
97 /* In dryrun mode (DOIT not set) we must not alter the mddb */
98 if (options & MDCMD_DOIT) {
99 if (add_key_name(sp, newnp, NULL, ep) != 0)
100 return (-1);
101 }
102
103 /*
104 * There is no need to call meta_fixdevid() here as this function is
105 * only called by the metareplace -c command which actually does
106 * nothing (in terms of a resync) and thus does nothing with the devid.
107 */
108
109 (void) memset(¶ms, 0, sizeof (params));
110 params.mnum = meta_getminor(stripenp->dev);
111 MD_SETDRIVERNAME(¶ms, MD_STRIPE, sp->setno);
112
113 params.cmd = REPLACE_COMP;
114 params.old_dev = old_dev;
115 params.new_dev = new_dev;
116 params.new_key = newnp->key;
117 params.start_blk = newnp->start_blk;
118 params.number_blks = size;
119 /* Is this just a dryrun ? */
120 if ((options & MDCMD_DOIT) == 0) {
121 params.options |= MDIOCTL_DRYRUN;
122 }
123 if (label == 0)
124 params.has_label = 0;
125 else
126 params.has_label = 1;
127 if (metaioctl(MD_IOCREPLACE, ¶ms, ¶ms.mde, NULL) != 0) {
128 if (options & MDCMD_DOIT)
129 (void) del_key_name(sp, newnp, ep);
130 return (mdstealerror(ep, ¶ms.mde));
131 }
132 meta_invalidate_name(oldnp);
133 meta_invalidate_name(newnp);
134 meta_invalidate_name(stripenp);
135
136 if (options & MDCMD_PRINT) {
137 (void) printf(dgettext(TEXT_DOMAIN,
138 "%s: device %s is replaced with %s\n"),
139 stripenp->cname, oldnp->cname, newnp->cname);
140
141 }
142 return (0);
143 }
144
145
146 /*
147 * FUNCTION: meta_get_stripe_names()
148 * INPUT: sp - the set name to get stripes from
149 * options - options from the command line
150 * OUTPUT: nlpp - list of all stripe names
151 * ep - return error pointer
152 * RETURNS: int - -1 if error, 0 success
153 * PURPOSE: returns a list of all stripes in the metadb
154 * for all devices in the specified set
155 */
156 int
meta_get_stripe_names(mdsetname_t * sp,mdnamelist_t ** nlpp,int options,md_error_t * ep)157 meta_get_stripe_names(
158 mdsetname_t *sp,
159 mdnamelist_t **nlpp,
160 int options,
161 md_error_t *ep
162 )
163 {
164 return (meta_get_names(MD_STRIPE, sp, nlpp, options, ep));
165 }
166
167 /*
168 * free stripe
169 */
170 void
meta_free_stripe(md_stripe_t * stripep)171 meta_free_stripe(
172 md_stripe_t *stripep
173 )
174 {
175 uint_t row;
176
177 for (row = 0; (row < stripep->rows.rows_len); ++row) {
178 md_row_t *rp = &stripep->rows.rows_val[row];
179
180 if (rp->comps.comps_val != NULL) {
181 assert(rp->comps.comps_len > 0);
182 Free(rp->comps.comps_val);
183 }
184 }
185 if (stripep->rows.rows_val != NULL) {
186 assert(stripep->rows.rows_len > 0);
187 Free(stripep->rows.rows_val);
188 }
189 Free(stripep);
190 }
191
192
193 /*
194 * get stripe (common)
195 */
196 md_stripe_t *
meta_get_stripe_common(mdsetname_t * sp,mdname_t * stripenp,int fast,md_error_t * ep)197 meta_get_stripe_common(
198 mdsetname_t *sp,
199 mdname_t *stripenp,
200 int fast,
201 md_error_t *ep
202 )
203 {
204 mddrivename_t *dnp = stripenp->drivenamep;
205 char *miscname;
206 ms_unit_t *ms;
207 md_stripe_t *stripep;
208 uint_t row;
209
210 /* must have set */
211 assert(sp != NULL);
212 assert(sp->setno == MD_MIN2SET(meta_getminor(stripenp->dev)));
213
214 /* short circuit */
215 if (dnp->unitp != NULL) {
216 assert(dnp->unitp->type == MD_DEVICE);
217 return ((md_stripe_t *)dnp->unitp);
218 }
219
220 /* get miscname and unit */
221 if ((miscname = metagetmiscname(stripenp, ep)) == NULL)
222 return (NULL);
223 if (strcmp(miscname, MD_STRIPE) != 0) {
224 (void) mdmderror(ep, MDE_NOT_STRIPE,
225 meta_getminor(stripenp->dev), stripenp->cname);
226 return (NULL);
227 }
228 if ((ms = (ms_unit_t *)meta_get_mdunit(sp, stripenp, ep)) == NULL)
229 return (NULL);
230 assert(ms->c.un_type == MD_DEVICE);
231
232 /* allocate stripe */
233 stripep = Zalloc(sizeof (*stripep));
234
235 /* allocate rows */
236 assert(ms->un_nrows > 0);
237 stripep->rows.rows_len = ms->un_nrows;
238 stripep->rows.rows_val = Zalloc(stripep->rows.rows_len *
239 sizeof (*stripep->rows.rows_val));
240
241 /* get common info */
242 stripep->common.namep = stripenp;
243 stripep->common.type = ms->c.un_type;
244 stripep->common.state = ms->c.un_status;
245 stripep->common.capabilities = ms->c.un_capabilities;
246 stripep->common.parent = ms->c.un_parent;
247 stripep->common.size = ms->c.un_total_blocks;
248 stripep->common.user_flags = ms->c.un_user_flags;
249 stripep->common.revision = ms->c.un_revision;
250
251 /* get options */
252 if ((ms->un_hsp_id != MD_HSP_NONE) &&
253 ((stripep->hspnamep = metahsphspname(&sp, ms->un_hsp_id,
254 ep)) == NULL)) {
255 goto out;
256 }
257
258 /* get rows */
259 for (row = 0; (row < ms->un_nrows); ++row) {
260 struct ms_row *mdr = &ms->un_row[row];
261 struct ms_comp *mdcomp = (void *)&((char *)ms)[ms->un_ocomp];
262 md_row_t *rp = &stripep->rows.rows_val[row];
263 uint_t comp, c;
264
265 /* get interlace */
266 rp->interlace = mdr->un_interlace;
267
268 /* allocate comps */
269 assert(mdr->un_ncomp > 0);
270 rp->comps.comps_len = mdr->un_ncomp;
271 rp->comps.comps_val = Zalloc(rp->comps.comps_len *
272 sizeof (*rp->comps.comps_val));
273
274 /* get components */
275 for (comp = 0, c = mdr->un_icomp; (comp < mdr->un_ncomp);
276 ++comp, ++c) {
277 struct ms_comp *mdc = &mdcomp[c];
278 diskaddr_t comp_start_blk = mdc->un_start_block;
279 md_comp_t *cp = &rp->comps.comps_val[comp];
280
281 /* get the component name */
282 cp->compnamep = metakeyname(&sp, mdc->un_key, fast, ep);
283 if (cp->compnamep == NULL)
284 goto out;
285
286 /* if hotspared */
287 if (mdc->un_mirror.ms_hs_id != 0) {
288 diskaddr_t hs_start_blk = mdc->un_start_block;
289
290 /* get the hotspare name */
291 cp->hsnamep = metakeyname(&sp,
292 mdc->un_mirror.ms_hs_key, fast, ep);
293 if (cp->hsnamep == NULL)
294 goto out;
295
296 if (getenv("META_DEBUG_START_BLK") != NULL) {
297 if (metagetstart(sp, cp->hsnamep,
298 ep) == MD_DISKADDR_ERROR)
299 mdclrerror(ep);
300
301 if ((cp->hsnamep->start_blk == 0) &&
302 (hs_start_blk != 0))
303 md_eprintf(dgettext(TEXT_DOMAIN,
304 "%s: suspected bad"
305 "start block,"
306 " seems labelled"
307 "[stripe/hs]\n"),
308 cp->hsnamep->cname);
309
310 if ((cp->hsnamep->start_blk > 0) &&
311 (hs_start_blk == 0) &&
312 ! ((row == 0) && (comp == 0)))
313 md_eprintf(dgettext(TEXT_DOMAIN,
314 "%s: suspected bad"
315 "start block, "
316 "seems unlabelled"
317 "[stripe/hs]\n"),
318 cp->hsnamep->cname);
319 }
320 /* override any start_blk */
321 cp->hsnamep->start_blk = hs_start_blk;
322
323 /* get the right component start_blk */
324 comp_start_blk = mdc->un_mirror.ms_orig_blk;
325 } else {
326 if (getenv("META_DEBUG_START_BLK") != NULL) {
327 if (metagetstart(sp, cp->compnamep,
328 ep) == MD_DISKADDR_ERROR)
329 mdclrerror(ep);
330
331 if ((cp->compnamep->start_blk == 0) &&
332 (comp_start_blk != 0))
333 md_eprintf(dgettext(TEXT_DOMAIN,
334 "%s: suspected bad"
335 "start block,"
336 " seems labelled"
337 "[stripe]"),
338 cp->compnamep->cname);
339
340 if ((cp->compnamep->start_blk > 0) &&
341 (comp_start_blk == 0) &&
342 ! ((row == 0) && (comp == 0)))
343 md_eprintf(dgettext(TEXT_DOMAIN,
344 "%s: suspected bad"
345 "start block, "
346 "seems unlabelled"
347 "[stripe]"),
348 cp->compnamep->cname);
349 }
350 }
351
352 /* override any start_blk */
353 cp->compnamep->start_blk = comp_start_blk;
354
355 /* get state */
356 cp->state = mdc->un_mirror.ms_state;
357
358 /* get time of last state change */
359 cp->timestamp = mdc->un_mirror.ms_timestamp;
360
361 /* get lasterr count */
362 cp->lasterrcnt = mdc->un_mirror.ms_lasterrcnt;
363 }
364 }
365
366 /* cleanup, return success */
367 Free(ms);
368 dnp->unitp = (md_common_t *)stripep;
369 return (stripep);
370
371 /* cleanup, return error */
372 out:
373 Free(ms);
374 meta_free_stripe(stripep);
375 return (NULL);
376 }
377
378 /*
379 * get stripe
380 */
381 md_stripe_t *
meta_get_stripe(mdsetname_t * sp,mdname_t * stripenp,md_error_t * ep)382 meta_get_stripe(
383 mdsetname_t *sp,
384 mdname_t *stripenp,
385 md_error_t *ep
386 )
387 {
388 return (meta_get_stripe_common(sp, stripenp, 0, ep));
389 }
390
391 /*
392 * check stripe for dev
393 */
394 static int
in_stripe(mdsetname_t * sp,mdname_t * stripenp,mdname_t * np,diskaddr_t slblk,diskaddr_t nblks,md_error_t * ep)395 in_stripe(
396 mdsetname_t *sp,
397 mdname_t *stripenp,
398 mdname_t *np,
399 diskaddr_t slblk,
400 diskaddr_t nblks,
401 md_error_t *ep
402 )
403 {
404 md_stripe_t *stripep;
405 uint_t row;
406
407 /* should be in the same set */
408 assert(sp != NULL);
409
410 /* get unit */
411 if ((stripep = meta_get_stripe(sp, stripenp, ep)) == NULL)
412 return (-1);
413
414 /* look in rows */
415 for (row = 0; (row < stripep->rows.rows_len); ++row) {
416 md_row_t *rp = &stripep->rows.rows_val[row];
417 uint_t comp;
418
419 /* look in columns */
420 for (comp = 0; (comp < rp->comps.comps_len); ++comp) {
421 md_comp_t *cp = &rp->comps.comps_val[comp];
422 mdname_t *compnp = cp->compnamep;
423 diskaddr_t comp_sblk;
424 int err;
425
426 /* check same drive since metagetstart() can fail */
427 if ((err = meta_check_samedrive(np, compnp, ep)) < 0)
428 return (-1);
429 else if (err == 0)
430 continue;
431
432 /* check overlap */
433 if ((comp_sblk = metagetstart(sp, compnp, ep)) ==
434 MD_DISKADDR_ERROR)
435 return (-1);
436 if (meta_check_overlap(stripenp->cname, np,
437 slblk, nblks, compnp, comp_sblk, -1,
438 ep) != 0) {
439 return (-1);
440 }
441 }
442 }
443
444 /* return success */
445 return (0);
446 }
447
448 /*
449 * check to see if we're in a stripe
450 */
451 int
meta_check_instripe(mdsetname_t * sp,mdname_t * np,diskaddr_t slblk,diskaddr_t nblks,md_error_t * ep)452 meta_check_instripe(
453 mdsetname_t *sp,
454 mdname_t *np,
455 diskaddr_t slblk,
456 diskaddr_t nblks,
457 md_error_t *ep
458 )
459 {
460 mdnamelist_t *stripenlp = NULL;
461 mdnamelist_t *p;
462 int rval = 0;
463
464 /* should have a set */
465 assert(sp != NULL);
466
467 /* for each stripe */
468 if (meta_get_stripe_names(sp, &stripenlp, 0, ep) < 0)
469 return (-1);
470 for (p = stripenlp; (p != NULL); p = p->next) {
471 mdname_t *stripenp = p->namep;
472
473 /* check stripe */
474 if (in_stripe(sp, stripenp, np, slblk, nblks, ep) != 0) {
475 rval = -1;
476 break;
477 }
478 }
479
480 /* cleanup, return success */
481 metafreenamelist(stripenlp);
482 return (rval);
483 }
484
485 /*
486 * check component
487 */
488 int
meta_check_component(mdsetname_t * sp,mdname_t * np,int force,md_error_t * ep)489 meta_check_component(
490 mdsetname_t *sp,
491 mdname_t *np,
492 int force,
493 md_error_t *ep
494 )
495 {
496 mdchkopts_t options = (MDCHK_ALLOW_MDDB);
497 md_common_t *mdp;
498
499 /*
500 * See if we are a soft partition: meta_sp_issp() returns 0 if
501 * np points to a soft partition, so the if and else clauses
502 * here represent "not a soft partition" and "soft partition,"
503 * respectively.
504 */
505 if (meta_sp_issp(sp, np, ep) != 0) {
506 /* make sure we have a disk */
507 if (metachkcomp(np, ep) != 0)
508 return (-1);
509 } else {
510 /* make sure soft partition can parent & doesn't have parent */
511 if ((mdp = meta_get_unit(sp, np, ep)) == NULL)
512 return (mdmderror(ep, MDE_INVAL_UNIT, NULL,
513 np->cname));
514 if (mdp->capabilities == MD_CANT_PARENT)
515 return (mdmderror(ep, MDE_INVAL_UNIT, NULL,
516 np->cname));
517 if (MD_HAS_PARENT(mdp->parent)) {
518 mdname_t *pnp;
519
520 pnp = metamnumname(&sp, mdp->parent, 0, ep);
521 if (pnp == NULL) {
522 return (-1);
523 }
524
525 return (mduseerror(ep, MDE_ALREADY, np->dev,
526 pnp->cname, np->cname));
527 }
528 }
529
530 /* check to ensure that it is not already in use */
531 if ((! force) &&
532 (meta_check_inuse(sp, np, MDCHK_INUSE, ep) != 0)) {
533 return (-1);
534 }
535
536 /* make sure it is in the set */
537 if (meta_check_inset(sp, np, ep) != 0)
538 return (-1);
539
540 /* make sure its not in a metadevice */
541 if (meta_check_inmeta(sp, np, options, 0, -1, ep) != 0)
542 return (-1);
543
544 /* return success */
545 return (0);
546 }
547
548 /*
549 * print stripe
550 */
551 static int
stripe_print(md_stripe_t * stripep,char * fname,FILE * fp,mdprtopts_t options,md_error_t * ep)552 stripe_print(
553 md_stripe_t *stripep,
554 char *fname,
555 FILE *fp,
556 mdprtopts_t options,
557 md_error_t *ep
558 )
559 {
560 uint_t row;
561 int rval = -1;
562
563 if (options & PRINT_LARGEDEVICES) {
564 if (stripep->common.revision != MD_64BIT_META_DEV) {
565 rval = 0;
566 goto out;
567 }
568 }
569
570 if (options & PRINT_FN) {
571 if (stripep->common.revision != MD_FN_META_DEV) {
572 rval = 0;
573 goto out;
574 }
575 }
576
577 /* print name and num rows */
578 if (fprintf(fp, "%s %u",
579 stripep->common.namep->cname, stripep->rows.rows_len) == EOF)
580 goto out;
581
582 /* print rows */
583 for (row = 0; (row < stripep->rows.rows_len); ++row) {
584 md_row_t *rp = &stripep->rows.rows_val[row];
585 uint_t comp;
586
587 /* print num components */
588 if (fprintf(fp, " %u", rp->comps.comps_len) == EOF)
589 goto out;
590
591 /*
592 * Print components. Always print the full path name.
593 */
594 for (comp = 0; (comp < rp->comps.comps_len); ++comp) {
595 md_comp_t *cp = &rp->comps.comps_val[comp];
596
597 if (fprintf(fp, " %s", cp->compnamep->rname) == EOF)
598 goto out;
599 }
600
601 /* print interlace */
602 if (rp->comps.comps_len > 1)
603 if (fprintf(fp, " -i %lldb", rp->interlace) == EOF)
604 goto out;
605
606 /* print continuation */
607 if (row != (stripep->rows.rows_len - 1))
608 if (fprintf(fp, " \\\n\t") == EOF)
609 goto out;
610 }
611
612 /* print hotspare name */
613 if (stripep->hspnamep != NULL)
614 if (fprintf(fp, " -h %s", stripep->hspnamep->hspname) == EOF)
615 goto out;
616
617 /* terminate last line */
618 if (fprintf(fp, "\n") == EOF)
619 goto out;
620
621 /* success */
622 rval = 0;
623
624 /* cleanup, return error */
625 out:
626 if (rval != 0)
627 (void) mdsyserror(ep, errno, fname);
628 return (rval);
629 }
630
631 /*
632 * convert component state to name
633 */
634 char *
comp_state_to_name(md_comp_t * mdcp,md_timeval32_t * tvp,uint_t tstate)635 comp_state_to_name(
636 md_comp_t *mdcp,
637 md_timeval32_t *tvp,
638 uint_t tstate /* Errored tstate flags */
639 )
640 {
641 comp_state_t state = mdcp->state;
642
643 /* grab time */
644 if (tvp != NULL)
645 *tvp = mdcp->timestamp;
646
647 if (tstate != 0) {
648 return (dgettext(TEXT_DOMAIN, "Unavailable"));
649 }
650
651 /* return state */
652 switch (state) {
653 case CS_OKAY:
654 return (dgettext(TEXT_DOMAIN, "Okay"));
655 case CS_ERRED:
656 return (dgettext(TEXT_DOMAIN, "Maintenance"));
657 case CS_LAST_ERRED:
658 return (dgettext(TEXT_DOMAIN, "Last Erred"));
659 case CS_RESYNC:
660 return (dgettext(TEXT_DOMAIN, "Resyncing"));
661 default:
662 return (dgettext(TEXT_DOMAIN, "invalid"));
663 }
664 }
665
666 /*
667 * print subdevice stripe row
668 */
669 static int
subdev_row_report(mdsetname_t * sp,md_row_t * rp,char * fname,FILE * fp,mdprtopts_t options,uint_t top_tstate,md_error_t * ep)670 subdev_row_report(
671 mdsetname_t *sp,
672 md_row_t *rp,
673 char *fname,
674 FILE *fp,
675 mdprtopts_t options,
676 uint_t top_tstate, /* Errored tstate flags */
677 md_error_t *ep
678 )
679 {
680 uint_t comp;
681 int rval = -1;
682 ddi_devid_t dtp;
683 int len = 0;
684
685
686 /*
687 * building a format string on the fly that will be used
688 * in fprintf. This is to allow really really long ctd names
689 */
690 for (comp = 0; (comp < rp->comps.comps_len); ++comp) {
691 md_comp_t *cp = &rp->comps.comps_val[comp];
692 char *cname = cp->compnamep->cname;
693
694 len = max(len, strlen(cname));
695 }
696
697 len = max(len, strlen(dgettext(TEXT_DOMAIN, "Device")));
698 len += 2;
699 /* print header */
700 if (! (options & PRINT_TIMES)) {
701 if (fprintf(fp,
702 "\t%-*.*s %-12.12s %5.5s %12.12s %5.5s %s\n",
703 len, len,
704 dgettext(TEXT_DOMAIN, "Device"),
705 dgettext(TEXT_DOMAIN, "Start Block"),
706 dgettext(TEXT_DOMAIN, "Dbase"),
707 dgettext(TEXT_DOMAIN, "State"),
708 dgettext(TEXT_DOMAIN, "Reloc"),
709 dgettext(TEXT_DOMAIN, "Hot Spare")) == EOF) {
710 goto out;
711 }
712 } else {
713 if (fprintf(fp,
714 "\t%-*s %5s %5s %-11s %-5s %-9s %s\n",
715 len,
716 dgettext(TEXT_DOMAIN, "Device"),
717 dgettext(TEXT_DOMAIN, "Start"),
718 dgettext(TEXT_DOMAIN, "Dbase"),
719 dgettext(TEXT_DOMAIN, "State"),
720 dgettext(TEXT_DOMAIN, "Reloc"),
721 dgettext(TEXT_DOMAIN, "Hot Spare"),
722 dgettext(TEXT_DOMAIN, "Time")) == EOF) {
723 goto out;
724 }
725 }
726
727
728 /* print components */
729 for (comp = 0; (comp < rp->comps.comps_len); ++comp) {
730 md_comp_t *cp = &rp->comps.comps_val[comp];
731 mdname_t *namep = cp->compnamep;
732 char *cname = namep->cname;
733 diskaddr_t start_blk;
734 int has_mddb;
735 char *has_mddb_str;
736 char *comp_state;
737 md_timeval32_t tv;
738 char *hsname = ((cp->hsnamep != NULL) ?
739 cp->hsnamep->cname : "");
740 char *devid = " ";
741 mdname_t *didnp = NULL;
742 uint_t tstate = 0;
743
744 /* get info */
745 if ((start_blk = metagetstart(sp, namep, ep)) ==
746 MD_DISKADDR_ERROR) {
747 return (-1);
748 }
749 if ((has_mddb = metahasmddb(sp, namep, ep)) < 0) {
750 return (-1);
751 }
752 if (has_mddb)
753 has_mddb_str = dgettext(TEXT_DOMAIN, "Yes");
754 else
755 has_mddb_str = dgettext(TEXT_DOMAIN, "No");
756
757 /*
758 * If the component is a metadevice, print out either
759 * unavailable or the state of the metadevice, if not
760 * a metadevice, print nothing if the state of the
761 * stripe is unavailable
762 */
763 if (metaismeta(namep)) {
764 if (meta_get_tstate(namep->dev, &tstate, ep) != 0)
765 return (-1);
766 comp_state = comp_state_to_name(cp, &tv, tstate &
767 MD_DEV_ERRORED);
768 } else {
769 /*
770 * if top_tstate is set, that implies that you have
771 * a ctd type device with an unavailable metadevice
772 * on top of it. If so, print a - for it's state
773 */
774 if (top_tstate != 0)
775 comp_state = "-";
776 else
777 comp_state = comp_state_to_name(cp, &tv,
778 tstate & MD_DEV_ERRORED);
779 }
780
781 /* populate the key in the name_p structure */
782 if ((didnp = metadevname(&sp, namep->dev, ep))
783 == NULL) {
784 return (-1);
785 }
786
787 /* determine if devid does NOT exist */
788 if (options & PRINT_DEVID) {
789 if ((dtp = meta_getdidbykey(sp->setno,
790 getmyside(sp, ep), didnp->key, ep)) == NULL)
791 devid = dgettext(TEXT_DOMAIN, "No ");
792 else {
793 devid = dgettext(TEXT_DOMAIN, "Yes");
794 free(dtp);
795 }
796 }
797 /* print info */
798 /*
799 * building a format string on the fly that will be used
800 * in fprintf. This is to allow really really long ctd names
801 */
802 if (! (options & PRINT_TIMES)) {
803 if (fprintf(fp,
804 "\t%-*s %8lld %-5.5s %12.12s %5.5s %s\n",
805 len, cname, start_blk,
806 has_mddb_str, comp_state, devid, hsname) == EOF) {
807 goto out;
808 }
809 } else {
810 char *timep = meta_print_time(&tv);
811
812 if (fprintf(fp,
813 "\t%-*s %5lld %-5s %-11s %-5s %-9s %s\n",
814 len, cname, start_blk,
815 has_mddb_str, comp_state, devid, hsname,
816 timep) == EOF) {
817 goto out;
818 }
819 }
820 }
821
822 /* success */
823 rval = 0;
824
825 /* cleanup, return error */
826 out:
827 if (rval != 0)
828 (void) mdsyserror(ep, errno, fname);
829 return (rval);
830 }
831
832 /*
833 * print toplevel stripe row
834 */
835 /*ARGSUSED4*/
836 static int
toplev_row_report(mdsetname_t * sp,md_row_t * rp,char * fname,FILE * fp,mdprtopts_t options,md_error_t * ep)837 toplev_row_report(
838 mdsetname_t *sp,
839 md_row_t *rp,
840 char *fname,
841 FILE *fp,
842 mdprtopts_t options,
843 md_error_t *ep
844 )
845 {
846 uint_t comp;
847 int rval = -1;
848 char *devid = " ";
849 mdname_t *didnp = NULL;
850 int len = 0;
851
852 /*
853 * building a format string on the fly that will be used
854 * in fprintf. This is to allow really really long ctd names
855 */
856 for (comp = 0; (comp < rp->comps.comps_len); ++comp) {
857 len = max(len,
858 strlen(rp->comps.comps_val[comp].compnamep->cname));
859 }
860
861 len = max(len, strlen(dgettext(TEXT_DOMAIN, "Device")));
862 len += 2;
863 /* print header */
864 if (fprintf(fp,
865 "\t%-*.*s %-12.12s %-5.5s\t%s\n",
866 len, len,
867 dgettext(TEXT_DOMAIN, "Device"),
868 dgettext(TEXT_DOMAIN, "Start Block"),
869 dgettext(TEXT_DOMAIN, "Dbase"),
870 dgettext(TEXT_DOMAIN, "Reloc")) == EOF) {
871 goto out;
872 }
873
874 /* print components */
875 for (comp = 0; (comp < rp->comps.comps_len); ++comp) {
876 md_comp_t *cp = &rp->comps.comps_val[comp];
877 mdname_t *namep = cp->compnamep;
878 char *cname = namep->cname;
879 diskaddr_t start_blk;
880 int has_mddb;
881 char *has_mddb_str;
882 ddi_devid_t dtp;
883
884 /* get info */
885 if ((start_blk = metagetstart(sp, namep, ep)) ==
886 MD_DISKADDR_ERROR) {
887 return (-1);
888 }
889 if ((has_mddb = metahasmddb(sp, namep, ep)) < 0) {
890 return (-1);
891 }
892 if (has_mddb)
893 has_mddb_str = dgettext(TEXT_DOMAIN, "Yes");
894 else
895 has_mddb_str = dgettext(TEXT_DOMAIN, "No");
896
897 /* populate the key in the name_p structure */
898 if ((didnp = metadevname(&sp, namep->dev, ep))
899 == NULL) {
900 return (-1);
901 }
902
903 /* determine if devid does NOT exist */
904 if (options & PRINT_DEVID) {
905 if ((dtp = meta_getdidbykey(sp->setno,
906 getmyside(sp, ep), didnp->key, ep)) == NULL) {
907 devid = dgettext(TEXT_DOMAIN, "No ");
908 } else {
909 devid = dgettext(TEXT_DOMAIN, "Yes");
910 free(dtp);
911 }
912 }
913 /* print info */
914 /*
915 * building a format string on the fly that will be used
916 * in fprintf. This is to allow really really long ctd names
917 */
918 if (fprintf(fp,
919 "\t%-*s %8lld %-5.5s\t%s\n", len,
920 cname, start_blk, has_mddb_str, devid) == EOF) {
921 goto out;
922 }
923 }
924
925 /* success */
926 rval = 0;
927
928 /* cleanup, return error */
929 out:
930 if (rval != 0)
931 (void) mdsyserror(ep, errno, fname);
932 return (rval);
933 }
934
935 /*
936 * print stripe options
937 */
938 int
meta_print_stripe_options(mdhspname_t * hspnamep,char * fname,FILE * fp,md_error_t * ep)939 meta_print_stripe_options(
940 mdhspname_t *hspnamep,
941 char *fname,
942 FILE *fp,
943 md_error_t *ep
944 )
945 {
946 char *hspname = ((hspnamep != NULL) ? hspnamep->hspname :
947 dgettext(TEXT_DOMAIN, "none"));
948 int rval = -1;
949
950 /* print options */
951 if (fprintf(fp, dgettext(TEXT_DOMAIN,
952 " Hot spare pool: %s\n"), hspname) == EOF) {
953 goto out;
954 }
955
956 /* success */
957 rval = 0;
958
959 /* cleanup, return error */
960 out:
961 if (rval != 0)
962 (void) mdsyserror(ep, errno, fname);
963 return (rval);
964 }
965
966 /*
967 * report stripe
968 */
969 static int
stripe_report(mdsetname_t * sp,md_stripe_t * stripep,mdnamelist_t ** nlpp,char * fname,FILE * fp,mdprtopts_t options,md_error_t * ep)970 stripe_report(
971 mdsetname_t *sp,
972 md_stripe_t *stripep,
973 mdnamelist_t **nlpp,
974 char *fname,
975 FILE *fp,
976 mdprtopts_t options,
977 md_error_t *ep
978 )
979 {
980 uint_t row;
981 int rval = -1;
982 uint_t tstate = 0;
983
984 /*
985 * if the -B option has been specified check to see if the
986 * metadevice is s "big" one and print if so, also if a
987 * big device we need to store the ctd involved for use in
988 * printing out the relocation information.
989 */
990 if (options & PRINT_LARGEDEVICES) {
991 if ((stripep->common.revision & MD_64BIT_META_DEV) == 0) {
992 rval = 0;
993 goto out;
994 } else {
995 if (meta_getdevs(sp, stripep->common.namep,
996 nlpp, ep) != 0)
997 goto out;
998 }
999 }
1000
1001 /*
1002 * if the -D option has been specified check to see if the
1003 * metadevice has a descriptive name and print if so, also if a
1004 * descriptive device name we need to store the ctd involved
1005 * for use in printing out the relocation information.
1006 */
1007 if (options & PRINT_FN) {
1008 if ((stripep->common.revision & MD_FN_META_DEV) == 0) {
1009 rval = 0;
1010 goto out;
1011 } else {
1012 if (meta_getdevs(sp, stripep->common.namep,
1013 nlpp, ep) != 0)
1014 goto out;
1015 }
1016 }
1017
1018 /* print header */
1019 if (options & PRINT_HEADER) {
1020 if (fprintf(fp, "%s: Concat/Stripe\n",
1021 stripep->common.namep->cname) == EOF) {
1022 goto out;
1023 }
1024
1025 }
1026
1027 /* print hotspare pool */
1028 if (stripep->hspnamep != NULL) {
1029 if (meta_print_stripe_options(stripep->hspnamep,
1030 fname, fp, ep) != 0) {
1031 return (-1);
1032 }
1033 }
1034
1035 if (metaismeta(stripep->common.namep)) {
1036 if (meta_get_tstate(stripep->common.namep->dev, &tstate, ep)
1037 != 0)
1038 return (-1);
1039 }
1040 if ((tstate & MD_DEV_ERRORED) != 0) {
1041 if (fprintf(fp, dgettext(TEXT_DOMAIN,
1042 " State: Unavailable\n"
1043 " Reconnect disk and invoke: metastat -i\n")) == EOF) {
1044 goto out;
1045 }
1046 }
1047
1048 /* print size */
1049 if (fprintf(fp, dgettext(TEXT_DOMAIN, " Size: %lld blocks (%s)\n"),
1050 stripep->common.size,
1051 meta_number_to_string(stripep->common.size, DEV_BSIZE))
1052 == EOF) {
1053 goto out;
1054 }
1055
1056 /* print rows */
1057 for (row = 0; (row < stripep->rows.rows_len); ++row) {
1058 md_row_t *rp = &stripep->rows.rows_val[row];
1059
1060 /* print stripe and interlace */
1061 if (rp->comps.comps_len > 1) {
1062 if (fprintf(fp, dgettext(TEXT_DOMAIN,
1063 " Stripe %u: (interlace: %lld blocks)\n"),
1064 row, rp->interlace) == EOF) {
1065 goto out;
1066 }
1067 } else {
1068 if (fprintf(fp, dgettext(TEXT_DOMAIN,
1069 " Stripe %u:\n"),
1070 row) == EOF) {
1071 goto out;
1072 }
1073 }
1074
1075 /* print components appropriately */
1076 if (MD_HAS_PARENT(stripep->common.parent)) {
1077 if (subdev_row_report(sp, rp, fname, fp, options,
1078 tstate & MD_DEV_ERRORED, ep) != 0) {
1079 return (-1);
1080 }
1081 } else {
1082 if (toplev_row_report(sp, rp, fname, fp, options,
1083 ep) != 0) {
1084 return (-1);
1085 }
1086 }
1087 }
1088
1089 /* add extra line */
1090 if (fprintf(fp, "\n") == EOF)
1091 goto out;
1092
1093 /* success */
1094 rval = 0;
1095
1096 /* cleanup, return error */
1097 out:
1098 if (rval != 0)
1099 (void) mdsyserror(ep, errno, fname);
1100 return (rval);
1101 }
1102
1103 /*
1104 * print/report stripe
1105 */
1106 int
meta_stripe_print(mdsetname_t * sp,mdname_t * stripenp,mdnamelist_t ** nlpp,char * fname,FILE * fp,mdprtopts_t options,md_error_t * ep)1107 meta_stripe_print(
1108 mdsetname_t *sp,
1109 mdname_t *stripenp,
1110 mdnamelist_t **nlpp,
1111 char *fname,
1112 FILE *fp,
1113 mdprtopts_t options,
1114 md_error_t *ep
1115 )
1116 {
1117 md_stripe_t *stripep;
1118 int row, comp;
1119
1120 /* should have same set */
1121 assert(sp != NULL);
1122 assert((stripenp == NULL) ||
1123 (sp->setno == MD_MIN2SET(meta_getminor(stripenp->dev))));
1124
1125 /* print all stripes */
1126 if (stripenp == NULL) {
1127 mdnamelist_t *nlp = NULL;
1128 mdnamelist_t *p;
1129 int cnt;
1130 int rval = 0;
1131
1132 /* get list */
1133 if ((cnt = meta_get_stripe_names(sp, &nlp, options, ep)) < 0)
1134 return (-1);
1135 else if (cnt == 0)
1136 return (0);
1137
1138 /* recurse */
1139 for (p = nlp; (p != NULL); p = p->next) {
1140 mdname_t *np = p->namep;
1141
1142 if (meta_stripe_print(sp, np, nlpp, fname, fp,
1143 options, ep) != 0)
1144 rval = -1;
1145 }
1146
1147 /* cleanup, return success */
1148 metafreenamelist(nlp);
1149 return (rval);
1150 }
1151
1152 /* get unit structure */
1153 if ((stripep = meta_get_stripe_common(sp, stripenp,
1154 ((options & PRINT_FAST) ? 1 : 0), ep)) == NULL)
1155 return (-1);
1156
1157 /* check for parented */
1158 if ((! (options & PRINT_SUBDEVS)) &&
1159 (MD_HAS_PARENT(stripep->common.parent))) {
1160 return (0);
1161 }
1162
1163 /* print appropriate detail */
1164 if (options & PRINT_SHORT) {
1165 if (stripe_print(stripep, fname, fp, options, ep) != 0)
1166 return (-1);
1167 } else {
1168 if (stripe_report(sp, stripep, nlpp, fname, fp, options,
1169 ep) != 0)
1170 return (-1);
1171 }
1172
1173 /* Recurse on components that are metadevices */
1174 for (row = 0; (row < stripep->rows.rows_len); ++row) {
1175 md_row_t *rp = &stripep->rows.rows_val[row];
1176
1177 /* look for components that are metadevices */
1178 for (comp = 0; (comp < rp->comps.comps_len); ++comp) {
1179 md_comp_t *cp = &rp->comps.comps_val[comp];
1180 mdname_t *namep = cp->compnamep;
1181
1182 if ((metaismeta(namep)) &&
1183 (meta_print_name(sp, namep, nlpp, fname, fp,
1184 (options | PRINT_HEADER | PRINT_SUBDEVS),
1185 NULL, ep) != 0)) {
1186 return (-1);
1187 }
1188 }
1189 }
1190 return (0);
1191 }
1192
1193 /*
1194 * find stripe component to replace
1195 */
1196 int
meta_find_erred_comp(mdsetname_t * sp,mdname_t * stripenp,mdname_t ** compnpp,comp_state_t * compstate,md_error_t * ep)1197 meta_find_erred_comp(
1198 mdsetname_t *sp,
1199 mdname_t *stripenp,
1200 mdname_t **compnpp,
1201 comp_state_t *compstate,
1202 md_error_t *ep
1203 )
1204 {
1205 md_stripe_t *stripep;
1206 md_comp_t *compp = NULL;
1207 uint_t lasterrcnt = 0;
1208 uint_t row;
1209
1210 /* get stripe */
1211 *compnpp = NULL;
1212 if ((stripep = meta_get_stripe_common(sp, stripenp, 1, ep)) == NULL)
1213 return (-1);
1214
1215 /*
1216 * Try to find the first erred component.
1217 * If there is not one, then look for the
1218 * first last_erred component.
1219 */
1220 for (row = 0; (row < stripep->rows.rows_len); ++row) {
1221 md_row_t *rp = &stripep->rows.rows_val[row];
1222 uint_t comp;
1223
1224 for (comp = 0; (comp < rp->comps.comps_len); ++comp) {
1225 md_comp_t *cp = &rp->comps.comps_val[comp];
1226
1227 if ((cp->state == CS_ERRED) && ((compp == NULL) ||
1228 (cp->lasterrcnt < lasterrcnt))) {
1229 compp = cp;
1230 lasterrcnt = cp->lasterrcnt;
1231 }
1232 }
1233 }
1234 for (row = 0; (row < stripep->rows.rows_len); ++row) {
1235 md_row_t *rp = &stripep->rows.rows_val[row];
1236 uint_t comp;
1237
1238 for (comp = 0; (comp < rp->comps.comps_len); ++comp) {
1239 md_comp_t *cp = &rp->comps.comps_val[comp];
1240
1241 if ((cp->state == CS_LAST_ERRED) && ((compp == NULL) ||
1242 (cp->lasterrcnt < lasterrcnt))) {
1243 compp = cp;
1244 lasterrcnt = cp->lasterrcnt;
1245 }
1246 }
1247 }
1248
1249 /* return component */
1250 if (compp != NULL) {
1251 *compnpp = compp->compnamep;
1252 *compstate = compp->state;
1253 }
1254
1255 /* return success */
1256 return (0);
1257 }
1258
1259 /*
1260 * invalidate component names
1261 */
1262 static int
invalidate_components(mdsetname_t * sp,mdname_t * stripenp,md_error_t * ep)1263 invalidate_components(
1264 mdsetname_t *sp,
1265 mdname_t *stripenp,
1266 md_error_t *ep
1267 )
1268 {
1269 md_stripe_t *stripep;
1270 uint_t row;
1271
1272 if ((stripep = meta_get_stripe(sp, stripenp, ep)) == NULL)
1273 return (-1);
1274 for (row = 0; (row < stripep->rows.rows_len); ++row) {
1275 md_row_t *rp = &stripep->rows.rows_val[row];
1276 uint_t comp;
1277
1278 for (comp = 0; (comp < rp->comps.comps_len); ++comp) {
1279 md_comp_t *cp = &rp->comps.comps_val[comp];
1280 mdname_t *compnp = cp->compnamep;
1281
1282 meta_invalidate_name(compnp);
1283 }
1284 }
1285 return (0);
1286 }
1287
1288 /*
1289 * attach components to stripe
1290 */
1291 int
meta_stripe_attach(mdsetname_t * sp,mdname_t * stripenp,mdnamelist_t * nlp,diskaddr_t interlace,mdcmdopts_t options,md_error_t * ep)1292 meta_stripe_attach(
1293 mdsetname_t *sp,
1294 mdname_t *stripenp,
1295 mdnamelist_t *nlp,
1296 diskaddr_t interlace,
1297 mdcmdopts_t options,
1298 md_error_t *ep
1299 )
1300 {
1301 mdnamelist_t *lp;
1302 ms_unit_t *old_un, *new_un;
1303 struct ms_row *mdr, *new_mdr;
1304 uint_t newcomps, ncomps, icomp;
1305 uint_t row;
1306 size_t mdsize, first_comp;
1307 diskaddr_t new_blks;
1308 diskaddr_t limit;
1309 diskaddr_t disk_size = 0;
1310 ms_comp_t *mdcomp, *new_comp;
1311 uint_t write_reinstruct = 0;
1312 uint_t read_reinstruct = 0;
1313 mdnamelist_t *keynlp = NULL;
1314 uint_t round_cyl = 1;
1315 minor_t parent;
1316 md_grow_params_t mgp;
1317 int rval = -1;
1318 md_timeval32_t creation_time;
1319 int create_flag = MD_CRO_32BIT;
1320
1321 /* should have a set */
1322 assert(sp != NULL);
1323 assert(sp->setno == MD_MIN2SET(meta_getminor(stripenp->dev)));
1324
1325 /* check type */
1326 if (metachkmeta(stripenp, ep) != 0)
1327 return (-1);
1328
1329 /* check and count components */
1330 assert(nlp != NULL);
1331 newcomps = 0;
1332 for (lp = nlp; (lp != NULL); lp = lp->next) {
1333 mdname_t *np = lp->namep;
1334 mdnamelist_t *p;
1335
1336 /* check against existing devices */
1337 if (meta_check_component(sp, np, 0, ep) != 0)
1338 return (-1);
1339
1340 /* check against ourselves */
1341 for (p = lp->next; (p != NULL); p = p->next) {
1342 if (meta_check_overlap(np->cname, np, 0, -1,
1343 p->namep, 0, -1, ep) != 0) {
1344 return (-1);
1345 }
1346 }
1347
1348 /* count */
1349 ++newcomps;
1350 }
1351
1352 /* get old unit */
1353 if ((old_un = (ms_unit_t *)meta_get_mdunit(sp, stripenp, ep)) == NULL)
1354 return (-1);
1355
1356 /* if zero, inherit the last rows interlace value */
1357 if (interlace == 0) {
1358 mdr = &old_un->un_row[old_un->un_nrows - 1];
1359 interlace = mdr->un_interlace;
1360 }
1361
1362 /*
1363 * calculate size of new unit structure
1364 */
1365
1366 /* unit + rows */
1367 mdsize = sizeof (ms_unit_t) - sizeof (struct ms_row);
1368 mdsize += sizeof (struct ms_row) * (old_un->un_nrows + 1);
1369
1370 /* number of new components being added */
1371 ncomps = newcomps;
1372
1373 /* count the # of components in the old unit */
1374 mdr = &old_un->un_row[0];
1375 for (row = 0; (row < old_un->un_nrows); row++)
1376 ncomps += mdr[row].un_ncomp;
1377 first_comp = roundup(mdsize, sizeof (long long));
1378 mdsize += sizeof (ms_comp_t) * ncomps + (first_comp - mdsize);
1379
1380 /* allocate new unit */
1381 new_un = Zalloc(mdsize);
1382 new_un->un_ocomp = first_comp;
1383
1384 /* compute new data */
1385 new_mdr = &new_un->un_row[old_un->un_nrows];
1386 new_mdr->un_icomp = ncomps - newcomps;
1387 new_mdr->un_ncomp = newcomps;
1388 new_mdr->un_blocks = 0;
1389 new_mdr->un_cum_blocks =
1390 old_un->un_row[old_un->un_nrows - 1].un_cum_blocks;
1391 new_mdr->un_interlace = interlace;
1392
1393 /* for each new device */
1394 mdcomp = (struct ms_comp *)(void *)&((char *)new_un)[new_un->un_ocomp];
1395 icomp = new_mdr->un_icomp;
1396 if (meta_gettimeofday(&creation_time) == -1)
1397 return (mdsyserror(ep, errno, NULL));
1398 for (lp = nlp; (lp != NULL); lp = lp->next) {
1399 mdname_t *np = lp->namep;
1400 diskaddr_t size, start_blk;
1401 mdgeom_t *geomp;
1402
1403 /* figure out how big */
1404 if ((size = metagetsize(np, ep)) == MD_DISKADDR_ERROR)
1405 goto out;
1406 if ((start_blk = metagetstart(sp, np, ep)) ==
1407 MD_DISKADDR_ERROR)
1408 goto out;
1409 if (start_blk >= size) {
1410 (void) mdsyserror(ep, ENOSPC, np->cname);
1411 goto out;
1412 }
1413 size -= start_blk;
1414 if (newcomps > 1)
1415 size = rounddown(size, interlace);
1416
1417 /* adjust for smallest disk */
1418 if (disk_size == 0) {
1419 disk_size = size;
1420 } else if (size < disk_size) {
1421 disk_size = size;
1422 }
1423
1424 /* get worst reinstructs */
1425 if ((geomp = metagetgeom(np, ep)) == NULL)
1426 goto out;
1427 if (geomp->write_reinstruct > write_reinstruct)
1428 write_reinstruct = geomp->write_reinstruct;
1429 if (geomp->read_reinstruct > read_reinstruct)
1430 read_reinstruct = geomp->read_reinstruct;
1431
1432 /* In dryrun mode (DOIT not set) we must not alter the mddb */
1433 if (options & MDCMD_DOIT) {
1434 /* store name in namespace */
1435 if (add_key_name(sp, np, &keynlp, ep) != 0)
1436 goto out;
1437 }
1438
1439 /* build new component */
1440 new_comp = &mdcomp[icomp++];
1441 new_comp->un_key = np->key;
1442 new_comp->un_dev = np->dev;
1443 new_comp->un_start_block = start_blk;
1444 new_comp->un_mirror.ms_state = CS_OKAY;
1445 new_comp->un_mirror.ms_timestamp = creation_time;
1446 }
1447
1448 limit = LLONG_MAX;
1449
1450 /* compute new size */
1451 new_mdr->un_blocks = new_mdr->un_ncomp * disk_size;
1452 new_blks = new_mdr->un_cum_blocks + new_mdr->un_blocks;
1453 if (new_blks > limit) {
1454 new_mdr->un_cum_blocks = limit;
1455 new_blks = limit;
1456 md_eprintf(dgettext(TEXT_DOMAIN,
1457 "unit size overflow, limit is %lld blocks\n"),
1458 limit);
1459 } else {
1460 new_mdr->un_cum_blocks += new_mdr->un_blocks;
1461 }
1462 new_un->c.un_actual_tb = new_mdr->un_cum_blocks;
1463 new_un->un_nrows = old_un->un_nrows + 1;
1464
1465 /* adjust geometry */
1466 new_un->c.un_nhead = old_un->c.un_nhead;
1467 new_un->c.un_nsect = old_un->c.un_nsect;
1468 new_un->c.un_rpm = old_un->c.un_rpm;
1469 new_un->c.un_wr_reinstruct = old_un->c.un_wr_reinstruct;
1470 new_un->c.un_rd_reinstruct = old_un->c.un_rd_reinstruct;
1471 if (meta_adjust_geom((md_unit_t *)new_un, stripenp,
1472 write_reinstruct, read_reinstruct, round_cyl, ep) != 0)
1473 goto out;
1474
1475 /* if in dryrun mode, we are done here. */
1476 if ((options & MDCMD_DOIT) == 0) {
1477 if (options & MDCMD_PRINT) {
1478 if (newcomps == 1) {
1479 (void) printf(dgettext(TEXT_DOMAIN,
1480 "%s: attaching component would suceed\n"),
1481 stripenp->cname);
1482 } else {
1483 (void) printf(dgettext(TEXT_DOMAIN,
1484 "%s: attaching components would suceed\n"),
1485 stripenp->cname);
1486 }
1487 }
1488 rval = 0; /* success */
1489 goto out;
1490 }
1491
1492 create_flag = meta_check_devicesize(new_un->c.un_total_blocks);
1493
1494 /* grow stripe */
1495 (void) memset(&mgp, 0, sizeof (mgp));
1496 mgp.mnum = MD_SID(old_un);
1497 MD_SETDRIVERNAME(&mgp, MD_STRIPE, sp->setno);
1498 mgp.size = mdsize;
1499 mgp.mdp = (uintptr_t)new_un;
1500 mgp.nrows = old_un->un_nrows;
1501 if (create_flag == MD_CRO_32BIT) {
1502 mgp.options = MD_CRO_32BIT;
1503 new_un->c.un_revision &= ~MD_64BIT_META_DEV;
1504 } else {
1505 mgp.options = MD_CRO_64BIT;
1506 new_un->c.un_revision |= MD_64BIT_META_DEV;
1507 }
1508
1509 if ((MD_HAS_PARENT(old_un->c.un_parent)) &&
1510 (old_un->c.un_parent != MD_MULTI_PARENT)) {
1511 mgp.npar = 1;
1512 parent = old_un->c.un_parent;
1513 mgp.par = (uintptr_t)(&parent);
1514 }
1515
1516 if (metaioctl(MD_IOCGROW, &mgp, &mgp.mde, NULL) != 0) {
1517 (void) mdstealerror(ep, &mgp.mde);
1518 goto out;
1519 }
1520
1521 /* clear cache */
1522 if (invalidate_components(sp, stripenp, ep) != 0)
1523 goto out;
1524 meta_invalidate_name(stripenp);
1525
1526 /* let em know */
1527 if (options & MDCMD_PRINT) {
1528 if (newcomps == 1) {
1529 (void) printf(dgettext(TEXT_DOMAIN,
1530 "%s: component is attached\n"), stripenp->cname);
1531 } else {
1532 (void) printf(dgettext(TEXT_DOMAIN,
1533 "%s: components are attached\n"), stripenp->cname);
1534 }
1535 (void) fflush(stdout);
1536 }
1537
1538 /* grow any parents */
1539 if (meta_concat_parent(sp, stripenp, ep) != 0)
1540 return (-1);
1541
1542 rval = 0; /* success */
1543
1544 /* cleanup, return error */
1545 out:
1546 Free(old_un);
1547 Free(new_un);
1548 if (options & MDCMD_DOIT) {
1549 if (rval != 0)
1550 (void) del_key_names(sp, keynlp, NULL);
1551 metafreenamelist(keynlp);
1552 }
1553 return (rval);
1554 }
1555
1556 /*
1557 * get stripe parameters
1558 */
1559 int
meta_stripe_get_params(mdsetname_t * sp,mdname_t * stripenp,ms_params_t * paramsp,md_error_t * ep)1560 meta_stripe_get_params(
1561 mdsetname_t *sp,
1562 mdname_t *stripenp,
1563 ms_params_t *paramsp,
1564 md_error_t *ep
1565 )
1566 {
1567 md_stripe_t *stripep;
1568
1569 /* should have a set */
1570 assert(sp != NULL);
1571 assert(sp->setno == MD_MIN2SET(meta_getminor(stripenp->dev)));
1572
1573 /* check name */
1574 if (metachkmeta(stripenp, ep) != 0)
1575 return (-1);
1576
1577 /* get unit */
1578 if ((stripep = meta_get_stripe(sp, stripenp, ep)) == NULL)
1579 return (-1);
1580
1581 /* return parameters */
1582 (void) memset(paramsp, 0, sizeof (*paramsp));
1583 if (stripep->hspnamep == NULL)
1584 paramsp->hsp_id = MD_HSP_NONE;
1585 else
1586 paramsp->hsp_id = stripep->hspnamep->hsp;
1587 return (0);
1588 }
1589
1590 /*
1591 * set stripe parameters
1592 */
1593 int
meta_stripe_set_params(mdsetname_t * sp,mdname_t * stripenp,ms_params_t * paramsp,md_error_t * ep)1594 meta_stripe_set_params(
1595 mdsetname_t *sp,
1596 mdname_t *stripenp,
1597 ms_params_t *paramsp,
1598 md_error_t *ep
1599 )
1600 {
1601 md_stripe_params_t msp;
1602
1603 /* should have a set */
1604 assert(sp != NULL);
1605 assert(sp->setno == MD_MIN2SET(meta_getminor(stripenp->dev)));
1606
1607 /* check name */
1608 if (metachkmeta(stripenp, ep) != 0)
1609 return (-1);
1610
1611 /* set parameters */
1612 (void) memset(&msp, 0, sizeof (msp));
1613 MD_SETDRIVERNAME(&msp, MD_STRIPE, sp->setno);
1614 msp.mnum = meta_getminor(stripenp->dev);
1615 msp.params = *paramsp;
1616 if (metaioctl(MD_IOCCHANGE, &msp, &msp.mde, stripenp->cname) != 0)
1617 return (mdstealerror(ep, &msp.mde));
1618
1619 /* clear cache */
1620 meta_invalidate_name(stripenp);
1621
1622 /* return success */
1623 return (0);
1624 }
1625
1626 /*
1627 * check for dups in the stripe itself
1628 */
1629 static int
check_twice(md_stripe_t * stripep,uint_t row,uint_t comp,md_error_t * ep)1630 check_twice(
1631 md_stripe_t *stripep,
1632 uint_t row,
1633 uint_t comp,
1634 md_error_t *ep
1635 )
1636 {
1637 mdname_t *stripenp = stripep->common.namep;
1638 mdname_t *thisnp;
1639 uint_t r;
1640
1641 thisnp = stripep->rows.rows_val[row].comps.comps_val[comp].compnamep;
1642 for (r = 0; (r <= row); ++r) {
1643 md_row_t *rp = &stripep->rows.rows_val[r];
1644 uint_t e = ((r == row) ? comp : rp->comps.comps_len);
1645 uint_t c;
1646
1647 for (c = 0; (c < e); ++c) {
1648 md_comp_t *cp = &rp->comps.comps_val[c];
1649 mdname_t *compnp = cp->compnamep;
1650
1651 if (meta_check_overlap(stripenp->cname, thisnp, 0, -1,
1652 compnp, 0, -1, ep) != 0) {
1653 return (-1);
1654 }
1655 }
1656 }
1657 return (0);
1658 }
1659
1660 /*
1661 * default stripe interlace
1662 */
1663 diskaddr_t
meta_default_stripe_interlace(void)1664 meta_default_stripe_interlace(void)
1665 {
1666 diskaddr_t interlace;
1667
1668 /* default to 512k, round up if necessary */
1669 interlace = btodb(512 * 1024);
1670 if (interlace < btodb(MININTERLACE))
1671 interlace = roundup(MININTERLACE, interlace);
1672 return (interlace);
1673 }
1674
1675 /*
1676 * convert interlaces
1677 */
1678 int
meta_stripe_check_interlace(diskaddr_t interlace,char * uname,md_error_t * ep)1679 meta_stripe_check_interlace(
1680 diskaddr_t interlace,
1681 char *uname,
1682 md_error_t *ep
1683 )
1684 {
1685 if ((interlace < btodb(MININTERLACE)) ||
1686 (interlace > btodb(MAXINTERLACE))) {
1687 return (mderror(ep, MDE_BAD_INTERLACE, uname));
1688 }
1689 return (0);
1690 }
1691
1692
1693 /*
1694 * check stripe
1695 */
1696 int
meta_check_stripe(mdsetname_t * sp,md_stripe_t * stripep,mdcmdopts_t options,md_error_t * ep)1697 meta_check_stripe(
1698 mdsetname_t *sp,
1699 md_stripe_t *stripep,
1700 mdcmdopts_t options,
1701 md_error_t *ep
1702 )
1703 {
1704 mdname_t *stripenp = stripep->common.namep;
1705 int force = ((options & MDCMD_FORCE) ? 1 : 0);
1706 int doit = ((options & MDCMD_DOIT) ? 1 : 0);
1707 int updateit = ((options & MDCMD_UPDATE) ? 1 : 0);
1708 uint_t row;
1709
1710 /* check rows */
1711 if (stripep->rows.rows_len < 1) {
1712 return (mdmderror(ep, MDE_BAD_STRIPE,
1713 meta_getminor(stripenp->dev), stripenp->cname));
1714 }
1715 for (row = 0; (row < stripep->rows.rows_len); ++row) {
1716 md_row_t *rp = &stripep->rows.rows_val[row];
1717 uint_t comp;
1718
1719 /* check number */
1720 if (rp->comps.comps_len < 1) {
1721 return (mdmderror(ep, MDE_BAD_STRIPE,
1722 meta_getminor(stripenp->dev), stripenp->cname));
1723 }
1724
1725 /* compute default interlace */
1726 if (rp->interlace == 0) {
1727 rp->interlace = meta_default_stripe_interlace();
1728 }
1729
1730 /* check interlace */
1731 if (meta_stripe_check_interlace(rp->interlace, stripenp->cname,
1732 ep) != 0) {
1733 return (-1);
1734 }
1735
1736 /* check components */
1737 for (comp = 0; (comp < rp->comps.comps_len); ++comp) {
1738 md_comp_t *cp = &rp->comps.comps_val[comp];
1739 mdname_t *compnp = cp->compnamep;
1740 diskaddr_t start_blk, size;
1741
1742 /* check component */
1743 if (!updateit) {
1744 if (meta_check_component(sp, compnp,
1745 force, ep) != 0)
1746 return (-1);
1747 if (((start_blk = metagetstart(sp, compnp,
1748 ep)) == MD_DISKADDR_ERROR) ||
1749 ((size = metagetsize(compnp, ep)) ==
1750 MD_DISKADDR_ERROR)) {
1751 return (-1);
1752 }
1753 if (start_blk >= size)
1754 return (mdsyserror(ep, ENOSPC,
1755 compnp->cname));
1756 size -= start_blk;
1757 size = rounddown(size, rp->interlace);
1758 if (size == 0)
1759 return (mdsyserror(ep, ENOSPC,
1760 compnp->cname));
1761 }
1762
1763 /* check this stripe too */
1764 if (check_twice(stripep, row, comp, ep) != 0)
1765 return (-1);
1766 }
1767 }
1768
1769 /* check hotspare pool name */
1770 if (doit) {
1771 if ((stripep->hspnamep != NULL) &&
1772 (metachkhsp(sp, stripep->hspnamep, ep) != 0)) {
1773 return (-1);
1774 }
1775 }
1776
1777 /* return success */
1778 return (0);
1779 }
1780
1781 /*
1782 * setup stripe geometry
1783 */
1784 static int
stripe_geom(md_stripe_t * stripep,ms_unit_t * ms,md_error_t * ep)1785 stripe_geom(
1786 md_stripe_t *stripep,
1787 ms_unit_t *ms,
1788 md_error_t *ep
1789 )
1790 {
1791 uint_t nrow = stripep->rows.rows_len;
1792 uint_t write_reinstruct = 0;
1793 uint_t read_reinstruct = 0;
1794 uint_t round_cyl = 1;
1795 uint_t row;
1796 mdgeom_t *geomp;
1797 diskaddr_t first_row_size = 0;
1798 char *miscname;
1799 int is_sp = 0;
1800
1801 /* get worst reinstructs */
1802 for (row = 0; (row < nrow); ++row) {
1803 md_row_t *rp = &stripep->rows.rows_val[row];
1804 uint_t ncomp = rp->comps.comps_len;
1805 uint_t comp;
1806
1807 for (comp = 0; (comp < ncomp); ++comp) {
1808 md_comp_t *cp = &rp->comps.comps_val[comp];
1809 mdname_t *compnp = cp->compnamep;
1810
1811 if ((geomp = metagetgeom(compnp, ep)) == NULL)
1812 return (-1);
1813 if (geomp->write_reinstruct > write_reinstruct)
1814 write_reinstruct = geomp->write_reinstruct;
1815 if (geomp->read_reinstruct > read_reinstruct)
1816 read_reinstruct = geomp->read_reinstruct;
1817 }
1818 }
1819
1820 if ((geomp = metagetgeom(
1821 stripep->rows.rows_val[0].comps.comps_val[0].compnamep,
1822 ep)) == NULL) {
1823 return (-1);
1824 }
1825 /*
1826 * Figure out if the first component is a softpartition as the
1827 * truncation check only occurs on them.
1828 */
1829 if ((miscname = metagetmiscname(
1830 stripep->rows.rows_val[0].comps.comps_val[0].compnamep,
1831 ep)) == NULL) {
1832 if (!mdisdeverror(ep, MDE_NOT_META))
1833 return (-1);
1834 } else if (strcmp(miscname, MD_SP) == 0) {
1835 is_sp = 1;
1836 }
1837
1838 /*
1839 * If the stripe is to be multi-terabyte we should
1840 * use EFI geometries, else we can get rounding errors
1841 * in meta_setup_geom().
1842 */
1843
1844 if (ms->c.un_actual_tb > MD_MAX_BLKS_FOR_SMALL_DEVS) {
1845 geomp->nhead = MD_EFI_FG_HEADS;
1846 geomp->nsect = MD_EFI_FG_SECTORS;
1847 geomp->rpm = MD_EFI_FG_RPM;
1848 }
1849
1850 /* setup geometry from first device */
1851 if (meta_setup_geom((md_unit_t *)ms, stripep->common.namep, geomp,
1852 write_reinstruct, read_reinstruct, round_cyl, ep) != 0)
1853 return (-1);
1854
1855 /*
1856 * Here we want to make sure that any truncation did not
1857 * result in lost data (or, more appropriately, inaccessible
1858 * data).
1859 *
1860 * This is mainly a danger for (1, 1) concats, but it is
1861 * mathematically possible for other somewhat contrived
1862 * arrangements where in the sum of the lengths of each row
1863 * beyond the first is smaller than the cylinder size of the
1864 * only component in the first row.
1865 *
1866 * It is tempting to simply test for truncation here, by
1867 * (md->c.un_total_blocks < md->c.un_actual_tb). That does
1868 * not tell us, however, if rounding resulted in data loss,
1869 * rather only that it occurred. The somewhat less obvious
1870 * test below covers both the obvious (1, 1) case and the
1871 * aforementioned corner case.
1872 */
1873 first_row_size = ms->un_row[0].un_blocks;
1874 if (is_sp == 1) {
1875 md_unit_t *md = (md_unit_t *)ms;
1876
1877 if (md->c.un_total_blocks < first_row_size) {
1878 char buf[] = VAL2STR(ULLONG_MAX);
1879
1880 /*
1881 * The only difference here is the text of the error
1882 * message, since the remediation is slightly
1883 * different in the one-component versus
1884 * multiple-component cases.
1885 */
1886 if (nrow == 1) {
1887 (void) mderror(ep, MDE_STRIPE_TRUNC_SINGLE,
1888 stripep->common.namep->cname);
1889 } else {
1890 (void) mderror(ep, MDE_STRIPE_TRUNC_MULTIPLE,
1891 stripep->common.namep->cname);
1892 }
1893
1894 /*
1895 * By the size comparison above and the initialization
1896 * of buf[] in terms of ULLONG_MAX, we guarantee that
1897 * the value arg is non-negative and that we won't
1898 * overflow the container.
1899 */
1900 mderrorextra(ep, ulltostr((md->c.un_total_blocks +
1901 (geomp->nhead * geomp->nsect))
1902 - first_row_size, &buf[sizeof (buf) - 1]));
1903
1904 return (-1);
1905 }
1906 }
1907
1908 /* return success */
1909 return (0);
1910 }
1911
1912 /*
1913 * create stripe
1914 */
1915 int
meta_create_stripe(mdsetname_t * sp,md_stripe_t * stripep,mdcmdopts_t options,md_error_t * ep)1916 meta_create_stripe(
1917 mdsetname_t *sp,
1918 md_stripe_t *stripep,
1919 mdcmdopts_t options,
1920 md_error_t *ep
1921 )
1922 {
1923 mdname_t *stripenp = stripep->common.namep;
1924 int force = ((options & MDCMD_FORCE) ? 1 : 0);
1925 int doall = ((options & MDCMD_ALLOPTION) ? 1 : 0);
1926 uint_t nrow = stripep->rows.rows_len;
1927 uint_t ncomp = 0;
1928 uint_t icomp = 0;
1929 diskaddr_t cum_blocks = 0;
1930 diskaddr_t limit;
1931 size_t mdsize, first_comp;
1932 uint_t row;
1933 ms_unit_t *ms;
1934 ms_comp_t *mdcomp;
1935 mdnamelist_t *keynlp = NULL;
1936 md_set_params_t set_params;
1937 int rval = -1;
1938 md_timeval32_t creation_time;
1939 int create_flag = MD_CRO_32BIT;
1940
1941 /* validate stripe */
1942 if (meta_check_stripe(sp, stripep, options, ep) != 0)
1943 return (-1);
1944
1945 /* allocate stripe unit */
1946 mdsize = sizeof (*ms) - sizeof (ms->un_row[0]);
1947 mdsize += sizeof (ms->un_row) * nrow;
1948 for (row = 0; (row < nrow); ++row) {
1949 md_row_t *rp = &stripep->rows.rows_val[row];
1950
1951 ncomp += rp->comps.comps_len;
1952 }
1953 first_comp = roundup(mdsize, sizeof (long long));
1954 mdsize += (first_comp - mdsize) + (ncomp * sizeof (ms_comp_t));
1955 ms = Zalloc(mdsize);
1956 ms->un_ocomp = first_comp;
1957 if (meta_gettimeofday(&creation_time) == -1)
1958 return (mdsyserror(ep, errno, NULL));
1959
1960 /* do rows */
1961 mdcomp = (ms_comp_t *)(void *)&((char *)ms)[ms->un_ocomp];
1962 for (row = 0; (row < nrow); ++row) {
1963 md_row_t *rp = &stripep->rows.rows_val[row];
1964 uint_t ncomp = rp->comps.comps_len;
1965 struct ms_row *mdr = &ms->un_row[row];
1966 diskaddr_t disk_size = 0;
1967 uint_t comp;
1968
1969 /* setup component count and offfset */
1970 mdr->un_icomp = icomp;
1971 mdr->un_ncomp = ncomp;
1972
1973 /* do components */
1974 for (comp = 0; (comp < ncomp); ++comp) {
1975 md_comp_t *cp = &rp->comps.comps_val[comp];
1976 mdname_t *compnp = cp->compnamep;
1977 ms_comp_t *mdc = &mdcomp[icomp++];
1978 diskaddr_t size, start_blk;
1979
1980 /*
1981 * get start and size
1982 * if first component is labelled, include label
1983 */
1984 if ((size = metagetsize(compnp, ep)) ==
1985 MD_DISKADDR_ERROR)
1986 goto out;
1987 if ((start_blk = metagetstart(sp, compnp, ep)) ==
1988 MD_DISKADDR_ERROR)
1989 goto out;
1990 if ((row == 0) && (comp == 0)) {
1991 diskaddr_t label;
1992 int has_db;
1993
1994 if ((has_db = metahasmddb(sp, compnp, ep)) < 0)
1995 goto out;
1996 if ((label = metagetlabel(compnp, ep)) ==
1997 MD_DISKADDR_ERROR)
1998 goto out;
1999 if ((has_db == 0) && (label != 0)) {
2000 ms->c.un_flag |= MD_LABELED;
2001 start_blk = compnp->start_blk = 0;
2002 }
2003 }
2004 /* make sure we still have something left */
2005 if (start_blk >= size) {
2006 (void) mdsyserror(ep, ENOSPC, compnp->cname);
2007 goto out;
2008 }
2009 size -= start_blk;
2010
2011 /*
2012 * round down by interlace: this only applies
2013 * if this row is a stripe, as indicated by
2014 * (ncomp > 1)
2015 */
2016 if (ncomp > 1)
2017 size = rounddown(size, rp->interlace);
2018
2019 if (size == 0) {
2020 (void) mdsyserror(ep, ENOSPC, compnp->cname);
2021 goto out;
2022 }
2023
2024 /*
2025 * adjust for smallest disk: for a concat (any
2026 * row with only one component), this will
2027 * never hit the second conditional.
2028 */
2029 if (disk_size == 0) {
2030 disk_size = size;
2031 } else if (size < disk_size) {
2032 disk_size = size;
2033 }
2034
2035 if (options & MDCMD_DOIT) {
2036 /* store name in namespace */
2037 if (add_key_name(sp, compnp, &keynlp, ep) != 0)
2038 goto out;
2039 }
2040
2041 /* setup component */
2042 mdc->un_key = compnp->key;
2043 mdc->un_dev = compnp->dev;
2044 mdc->un_start_block = start_blk;
2045 mdc->un_mirror.ms_state = CS_OKAY;
2046 mdc->un_mirror.ms_timestamp = creation_time;
2047 }
2048 limit = LLONG_MAX;
2049
2050 /* setup row */
2051 mdr->un_blocks = mdr->un_ncomp * disk_size;
2052 cum_blocks += mdr->un_blocks;
2053 if (cum_blocks > limit) {
2054 cum_blocks = limit;
2055 md_eprintf(dgettext(TEXT_DOMAIN,
2056 "unit size overflow, limit is %lld blocks\n"),
2057 limit);
2058 }
2059 mdr->un_cum_blocks = cum_blocks;
2060 mdr->un_interlace = rp->interlace;
2061 }
2062
2063 /* setup unit */
2064 ms->c.un_type = MD_DEVICE;
2065 MD_SID(ms) = meta_getminor(stripenp->dev);
2066 ms->c.un_actual_tb = cum_blocks;
2067 ms->c.un_size = mdsize;
2068 if (stripep->hspnamep != NULL)
2069 ms->un_hsp_id = stripep->hspnamep->hsp;
2070 else
2071 ms->un_hsp_id = MD_HSP_NONE;
2072 ms->un_nrows = nrow;
2073
2074 /* fill in the size of the stripe */
2075 if (options & MDCMD_UPDATE) {
2076 stripep->common.size = ms->c.un_total_blocks;
2077 for (row = 0; (row < nrow); ++row) {
2078 stripep->rows.rows_val[row].row_size =
2079 ms->un_row[row].un_blocks;
2080 }
2081 }
2082
2083 if (stripe_geom(stripep, ms, ep) != 0) {
2084 /*
2085 * If the device is being truncated then only allow this
2086 * if the user is aware (using the -f option) or they
2087 * are in a recovery/complete build situation (using the -a
2088 * option).
2089 */
2090 if ((mdiserror(ep, MDE_STRIPE_TRUNC_SINGLE) ||
2091 mdiserror(ep, MDE_STRIPE_TRUNC_MULTIPLE)) &&
2092 (force || doall)) {
2093 md_eprintf(dgettext(TEXT_DOMAIN,
2094 "%s: WARNING: This form of metainit is not recommended.\n"
2095 "The stripe is truncating the size of the underlying device.\n"
2096 "Please see ERRORS in metainit(1M) for additional information.\n"),
2097 stripenp->cname);
2098 mdclrerror(ep);
2099 } else {
2100 goto out;
2101 }
2102 }
2103
2104 create_flag = meta_check_devicesize(ms->c.un_total_blocks);
2105
2106 /* if we're not doing anything, return success */
2107 if (! (options & MDCMD_DOIT)) {
2108 rval = 0; /* success */
2109 goto out;
2110 }
2111
2112 /* create stripe */
2113 (void) memset(&set_params, 0, sizeof (set_params));
2114
2115 /* did the user tell us to generate a large device? */
2116 if (create_flag == MD_CRO_64BIT) {
2117 ms->c.un_revision |= MD_64BIT_META_DEV;
2118 set_params.options = MD_CRO_64BIT;
2119 } else {
2120 ms->c.un_revision &= ~MD_64BIT_META_DEV;
2121 set_params.options = MD_CRO_32BIT;
2122 }
2123
2124 set_params.mnum = MD_SID(ms);
2125 set_params.size = ms->c.un_size;
2126 set_params.mdp = (uintptr_t)ms;
2127 MD_SETDRIVERNAME(&set_params, MD_STRIPE, MD_MIN2SET(set_params.mnum));
2128 if (metaioctl(MD_IOCSET, &set_params, &set_params.mde,
2129 stripenp->cname) != 0) {
2130 (void) mdstealerror(ep, &set_params.mde);
2131 goto out;
2132 }
2133 rval = 0; /* success */
2134
2135 /* cleanup, return success */
2136 out:
2137 Free(ms);
2138 if (rval != 0) {
2139 (void) del_key_names(sp, keynlp, NULL);
2140 }
2141
2142 metafreenamelist(keynlp);
2143 if ((rval == 0) && (options & MDCMD_DOIT)) {
2144 if (invalidate_components(sp, stripenp, ep) != 0)
2145 rval = -1;
2146 meta_invalidate_name(stripenp);
2147 }
2148 return (rval);
2149 }
2150
2151 /*
2152 * initialize stripe
2153 * NOTE: this functions is metainit(1m)'s command line parser!
2154 */
2155 int
meta_init_stripe(mdsetname_t ** spp,int argc,char * argv[],mdcmdopts_t options,md_error_t * ep)2156 meta_init_stripe(
2157 mdsetname_t **spp,
2158 int argc,
2159 char *argv[],
2160 mdcmdopts_t options,
2161 md_error_t *ep
2162 )
2163 {
2164 char *uname = argv[0];
2165 mdname_t *stripenp = NULL;
2166 int old_optind;
2167 int c;
2168 md_stripe_t *stripep = NULL;
2169 uint_t nrow, row;
2170 int rval = -1;
2171
2172 /* get stripe name */
2173 assert(argc > 0);
2174 if (argc < 1)
2175 goto syntax;
2176
2177 if ((stripenp = metaname(spp, uname, META_DEVICE, ep)) == NULL)
2178 goto out;
2179 assert(*spp != NULL);
2180 uname = stripenp->cname;
2181 if (metachkmeta(stripenp, ep) != 0)
2182 goto out;
2183
2184 if (!(options & MDCMD_NOLOCK)) {
2185 /* grab set lock */
2186 if (meta_lock(*spp, TRUE, ep))
2187 goto out;
2188
2189 if (meta_check_ownership(*spp, ep) != 0)
2190 goto out;
2191 }
2192
2193 /* see if it exists already */
2194 if (metagetmiscname(stripenp, ep) != NULL) {
2195 (void) mdmderror(ep, MDE_UNIT_ALREADY_SETUP,
2196 meta_getminor(stripenp->dev), uname);
2197 goto out;
2198 } else if (! mdismderror(ep, MDE_UNIT_NOT_SETUP)) {
2199 goto out;
2200 } else {
2201 mdclrerror(ep);
2202 }
2203 --argc, ++argv;
2204
2205 /* parse general options */
2206 optind = 0;
2207 opterr = 0;
2208 if (getopt(argc, argv, "") != -1)
2209 goto options;
2210
2211 /* allocate stripe */
2212 stripep = Zalloc(sizeof (*stripep));
2213
2214 /* setup common */
2215 stripep->common.namep = stripenp;
2216 stripep->common.type = MD_DEVICE;
2217
2218 /* allocate and parse rows */
2219 if (argc < 1) {
2220 (void) mdmderror(ep, MDE_NROWS, meta_getminor(stripenp->dev),
2221 uname);
2222 goto out;
2223 } else if ((sscanf(argv[0], "%u", &nrow) != 1) || ((int)nrow < 0)) {
2224 goto syntax;
2225 } else if (nrow < 1) {
2226 (void) mdmderror(ep, MDE_NROWS, meta_getminor(stripenp->dev),
2227 uname);
2228 goto out;
2229 }
2230 --argc, ++argv;
2231 stripep->rows.rows_len = nrow;
2232 stripep->rows.rows_val =
2233 Zalloc(nrow * sizeof (*stripep->rows.rows_val));
2234 for (row = 0; (row < nrow); ++row) {
2235 md_row_t *mdr = &stripep->rows.rows_val[row];
2236 uint_t ncomp, comp;
2237
2238 /* allocate and parse components */
2239 if (argc < 1) {
2240 (void) mdmderror(ep, MDE_NROWS,
2241 meta_getminor(stripenp->dev), uname);
2242 goto out;
2243 } else if ((sscanf(argv[0], "%u", &ncomp) != 1) ||
2244 ((int)ncomp < 0)) {
2245 goto syntax;
2246 } else if (ncomp < 1) {
2247 (void) mdmderror(ep, MDE_NCOMPS,
2248 meta_getminor(stripenp->dev), uname);
2249 goto out;
2250 }
2251 --argc, ++argv;
2252 mdr->comps.comps_len = ncomp;
2253 mdr->comps.comps_val =
2254 Zalloc(ncomp * sizeof (*mdr->comps.comps_val));
2255 for (comp = 0; (comp < ncomp); ++comp) {
2256 md_comp_t *mdc = &mdr->comps.comps_val[comp];
2257 mdname_t *compnp;
2258
2259 /* parse component name */
2260 if (argc < 1) {
2261 (void) mdmderror(ep, MDE_NCOMPS,
2262 meta_getminor(stripenp->dev), uname);
2263 goto out;
2264 }
2265 if ((compnp = metaname(spp, argv[0], UNKNOWN,
2266 ep)) == NULL) {
2267 goto out;
2268 }
2269 /* check for soft partition */
2270 if (meta_sp_issp(*spp, compnp, ep) != 0) {
2271 /* check disk */
2272 if (metachkcomp(compnp, ep) != 0) {
2273 goto out;
2274 }
2275 }
2276 mdc->compnamep = compnp;
2277 --argc, ++argv;
2278 }
2279
2280 /* parse row options */
2281 old_optind = optind = 0;
2282 opterr = 0;
2283 while ((c = getopt(argc, argv, "i:")) != -1) {
2284 switch (c) {
2285 case 'i':
2286 if (parse_interlace(uname, optarg,
2287 &mdr->interlace, ep) != 0) {
2288 goto out;
2289 }
2290 if (meta_stripe_check_interlace(mdr->interlace,
2291 uname, ep))
2292 goto out;
2293 break;
2294
2295 default:
2296 optind = old_optind; /* bomb out later */
2297 goto done_row_opts;
2298 }
2299 old_optind = optind;
2300 }
2301 done_row_opts:
2302 argc -= optind;
2303 argv += optind;
2304 }
2305
2306 /* parse stripe options */
2307 old_optind = optind = 0;
2308 opterr = 0;
2309 while ((c = getopt(argc, argv, "h:")) != -1) {
2310 switch (c) {
2311 case 'h':
2312 if ((stripep->hspnamep = metahspname(spp, optarg,
2313 ep)) == NULL) {
2314 goto out;
2315 }
2316
2317 /*
2318 * Get out if the specified hotspare pool really
2319 * doesn't exist.
2320 */
2321 if (stripep->hspnamep->hsp == MD_HSP_NONE) {
2322 (void) mdhsperror(ep, MDE_INVAL_HSP,
2323 stripep->hspnamep->hsp, optarg);
2324 goto out;
2325 }
2326 break;
2327
2328 default:
2329 argc += old_optind;
2330 argv += old_optind;
2331 goto options;
2332 }
2333 old_optind = optind;
2334 }
2335 argc -= optind;
2336 argv += optind;
2337
2338 /* we should be at the end */
2339 if (argc != 0)
2340 goto syntax;
2341
2342 /* create stripe */
2343 if (meta_create_stripe(*spp, stripep, options, ep) != 0)
2344 goto out;
2345 rval = 0; /* success */
2346
2347 /* let em know */
2348 if (options & MDCMD_PRINT) {
2349 (void) printf(dgettext(TEXT_DOMAIN,
2350 "%s: Concat/Stripe is setup\n"),
2351 uname);
2352 (void) fflush(stdout);
2353 }
2354 goto out;
2355
2356 /* syntax error */
2357 syntax:
2358 rval = meta_cook_syntax(ep, MDE_SYNTAX, uname, argc, argv);
2359 goto out;
2360
2361 /* options error */
2362 options:
2363 rval = meta_cook_syntax(ep, MDE_OPTION, uname, argc, argv);
2364 goto out;
2365
2366 /* cleanup, return error */
2367 out:
2368 if (stripep != NULL)
2369 meta_free_stripe(stripep);
2370 return (rval);
2371 }
2372
2373 /*
2374 * reset stripes
2375 */
2376 int
meta_stripe_reset(mdsetname_t * sp,mdname_t * stripenp,mdcmdopts_t options,md_error_t * ep)2377 meta_stripe_reset(
2378 mdsetname_t *sp,
2379 mdname_t *stripenp,
2380 mdcmdopts_t options,
2381 md_error_t *ep
2382 )
2383 {
2384 md_stripe_t *stripep;
2385 int rval = -1;
2386 int row, comp;
2387
2388 /* should have same set */
2389 assert(sp != NULL);
2390 assert((stripenp == NULL) ||
2391 (sp->setno == MD_MIN2SET(meta_getminor(stripenp->dev))));
2392
2393 /* reset all stripes */
2394 if (stripenp == NULL) {
2395 mdnamelist_t *stripenlp = NULL;
2396 mdnamelist_t *p;
2397
2398 /* for each stripe */
2399 rval = 0;
2400 if (meta_get_stripe_names(sp, &stripenlp, 0, ep) < 0)
2401 return (-1);
2402 for (p = stripenlp; (p != NULL); p = p->next) {
2403 /* reset stripe */
2404 stripenp = p->namep;
2405
2406 /*
2407 * If this is a multi-node set, we send a series
2408 * of individual metaclear commands.
2409 */
2410 if (meta_is_mn_set(sp, ep)) {
2411 if (meta_mn_send_metaclear_command(sp,
2412 stripenp->cname, options, 0, ep) != 0) {
2413 rval = -1;
2414 break;
2415 }
2416 } else {
2417 if (meta_stripe_reset(sp, stripenp,
2418 options, ep) != 0) {
2419 rval = -1;
2420 break;
2421 }
2422 }
2423 }
2424
2425 /* cleanup, return success */
2426 metafreenamelist(stripenlp);
2427 return (rval);
2428 }
2429
2430 /* check name */
2431 if (metachkmeta(stripenp, ep) != 0)
2432 return (-1);
2433
2434 /* get unit structure */
2435 if ((stripep = meta_get_stripe(sp, stripenp, ep)) == NULL)
2436 return (-1);
2437
2438 /* make sure nobody owns us */
2439 if (MD_HAS_PARENT(stripep->common.parent)) {
2440 return (mdmderror(ep, MDE_IN_USE, meta_getminor(stripenp->dev),
2441 stripenp->cname));
2442 }
2443
2444 /* clear subdevices cache */
2445 if (invalidate_components(sp, stripenp, ep) != 0)
2446 return (-1);
2447
2448 /* clear metadevice */
2449 if (meta_reset(sp, stripenp, options, ep) != 0)
2450 goto out;
2451 rval = 0; /* success */
2452
2453 /* let em know */
2454 if (options & MDCMD_PRINT) {
2455 (void) printf(dgettext(TEXT_DOMAIN,
2456 "%s: Concat/Stripe is cleared\n"),
2457 stripenp->cname);
2458 (void) fflush(stdout);
2459 }
2460
2461 /* clear subdevices */
2462 if (! (options & MDCMD_RECURSE))
2463 goto out;
2464
2465 for (row = 0; (row < stripep->rows.rows_len); ++row) {
2466 md_row_t *rp = &stripep->rows.rows_val[row];
2467 for (comp = 0; (comp < rp->comps.comps_len); ++comp) {
2468 md_comp_t *cp = &rp->comps.comps_val[comp];
2469 mdname_t *compnp = cp->compnamep;
2470
2471 /* only recurse on metadevices */
2472 if (! metaismeta(compnp))
2473 continue;
2474
2475 if (meta_reset_by_name(sp, compnp, options, ep) != 0)
2476 rval = -1;
2477 }
2478 }
2479
2480 /* cleanup, return success */
2481 out:
2482 meta_invalidate_name(stripenp);
2483 return (rval);
2484 }
2485
2486 /*
2487 * reports TRUE if any stripe component is in error
2488 */
2489 int
meta_stripe_anycomp_is_err(mdsetname_t * sp,mdnamelist_t * stripe_names)2490 meta_stripe_anycomp_is_err(mdsetname_t *sp, mdnamelist_t *stripe_names)
2491 {
2492 mdnamelist_t *nlp;
2493 md_error_t status = mdnullerror;
2494 md_error_t *ep = &status;
2495 int any_errs = FALSE;
2496
2497 for (nlp = stripe_names; nlp; nlp = nlp->next) {
2498 md_stripe_t *stripep;
2499 int row;
2500
2501 if ((stripep = meta_get_stripe(sp, nlp->namep, ep)) == NULL) {
2502 any_errs |= TRUE;
2503 goto out;
2504 }
2505
2506 for (row = 0; row < stripep->rows.rows_len; ++row) {
2507 md_row_t *rp = &stripep->rows.rows_val[row];
2508 uint_t comp;
2509
2510 for (comp = 0; comp < rp->comps.comps_len; ++comp) {
2511 md_comp_t *cp = &rp->comps.comps_val[comp];
2512
2513 if (cp->state != CS_OKAY) {
2514 any_errs |= TRUE;
2515 goto out;
2516 }
2517 }
2518 }
2519 }
2520 out:
2521 if (!mdisok(ep))
2522 mdclrerror(ep);
2523
2524 return (any_errs);
2525 }
2526
2527 int
meta_stripe_check_component(mdsetname_t * sp,mdname_t * np,md_dev64_t mydevs,md_error_t * ep)2528 meta_stripe_check_component(
2529 mdsetname_t *sp,
2530 mdname_t *np,
2531 md_dev64_t mydevs,
2532 md_error_t *ep
2533 )
2534 {
2535 md_stripe_t *stripe;
2536 mdnm_params_t nm;
2537 md_getdevs_params_t mgd;
2538 side_t sideno;
2539 char *miscname;
2540 md_dev64_t *mydev = NULL;
2541 mdkey_t key;
2542 char *pname = NULL, *t;
2543 char *ctd_name = NULL;
2544 char *devname = NULL;
2545 int len;
2546 int cnt, i;
2547 int rval = -1;
2548
2549 (void) memset(&nm, '\0', sizeof (nm));
2550 if ((stripe = meta_get_stripe_common(sp, np, 0, ep)) == NULL)
2551 return (-1);
2552
2553 if ((miscname = metagetmiscname(np, ep)) == NULL)
2554 return (-1);
2555
2556 sideno = getmyside(sp, ep);
2557
2558
2559 /* get count of underlying devices */
2560
2561 (void) memset(&mgd, '\0', sizeof (mgd));
2562 MD_SETDRIVERNAME(&mgd, miscname, sp->setno);
2563 mgd.mnum = meta_getminor(np->dev);
2564 mgd.cnt = 0;
2565 mgd.devs = NULL;
2566 if (metaioctl(MD_IOCGET_DEVS, &mgd, &mgd.mde, np->cname) != 0) {
2567 (void) mdstealerror(ep, &mgd.mde);
2568 rval = 0;
2569 goto out;
2570 } else if (mgd.cnt <= 0) {
2571 assert(mgd.cnt >= 0);
2572 rval = 0;
2573 goto out;
2574 }
2575
2576 /*
2577 * Now get the data from the unit structure.
2578 * The compnamep stuff contains the data from
2579 * the namespace and we need the un_dev
2580 * from the unit structure.
2581 */
2582 mydev = Zalloc(sizeof (*mydev) * mgd.cnt);
2583 mgd.devs = (uintptr_t)mydev;
2584 if (metaioctl(MD_IOCGET_DEVS, &mgd, &mgd.mde, np->cname) != 0) {
2585 (void) mdstealerror(ep, &mgd.mde);
2586 rval = 0;
2587 goto out;
2588 } else if (mgd.cnt <= 0) {
2589 assert(mgd.cnt >= 0);
2590 rval = 0;
2591 goto out;
2592 }
2593
2594 for (cnt = 0, i = 0; i < stripe->rows.rows_len; i++) {
2595 md_row_t *rp = &stripe->rows.rows_val[i];
2596 uint_t comp;
2597 for (comp = 0; (comp < rp->comps.comps_len); ++comp) {
2598 md_comp_t *cp = &rp->comps.comps_val[comp];
2599 mdname_t *compnp = cp->compnamep;
2600
2601 if (mydevs == mydev[cnt]) {
2602 /* Get the devname from the name space. */
2603 if ((devname = meta_getnmentbydev(sp->setno,
2604 sideno, compnp->dev, NULL, NULL,
2605 &key, ep)) == NULL) {
2606 goto out;
2607 }
2608
2609 if (compnp->dev != meta_getminor(mydev[cnt])) {
2610 /*
2611 * The minor numbers are different.
2612 * Update the namespace with the
2613 * information from the component.
2614 */
2615
2616 t = strrchr(devname, '/');
2617 t++;
2618 ctd_name = Strdup(t);
2619
2620 len = strlen(devname);
2621 t = strrchr(devname, '/');
2622 t++;
2623 pname = Zalloc((len - strlen(t)) + 1);
2624 (void) strncpy(pname, devname,
2625 (len - strlen(t)));
2626
2627 if (meta_update_namespace(sp->setno,
2628 sideno, ctd_name, mydev[i],
2629 key, pname, ep) != 0) {
2630 goto out;
2631 }
2632 }
2633 rval = 0;
2634 break;
2635 } /* End of if (mydevs == mydev[i]) */
2636 cnt++;
2637 } /* End of second for loop */
2638 } /* End of first for loop */
2639 out:
2640 if (pname != NULL)
2641 Free(pname);
2642 if (ctd_name != NULL)
2643 Free(ctd_name);
2644 if (devname != NULL)
2645 Free(devname);
2646 if (mydev != NULL)
2647 Free(mydev);
2648 return (rval);
2649 }
2650