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 * RAID operations
36 */
37
38 #include <stdlib.h>
39 #include <meta.h>
40 #include <sys/lvm/md_raid.h>
41 #include <sys/lvm/mdvar.h>
42 #include <sys/lvm/md_convert.h>
43 #include <stddef.h>
44
45 /*
46 * FUNCTION: meta_get_raid_names()
47 * INPUT: sp - the set name to get raid from
48 * options - options from the command line
49 * OUTPUT: nlpp - list of all raid names
50 * ep - return error pointer
51 * RETURNS: int - -1 if error, 0 success
52 * PURPOSE: returns a list of all raid in the metadb
53 * for all devices in the specified set
54 */
55 int
meta_get_raid_names(mdsetname_t * sp,mdnamelist_t ** nlpp,int options,md_error_t * ep)56 meta_get_raid_names(
57 mdsetname_t *sp,
58 mdnamelist_t **nlpp,
59 int options,
60 md_error_t *ep
61 )
62 {
63 return (meta_get_names(MD_RAID, sp, nlpp, options, ep));
64 }
65
66 /*
67 * free raid unit
68 */
69 void
meta_free_raid(md_raid_t * raidp)70 meta_free_raid(
71 md_raid_t *raidp
72 )
73 {
74 if (raidp->cols.cols_val != NULL) {
75 assert(raidp->cols.cols_len > 0);
76 Free(raidp->cols.cols_val);
77 }
78 Free(raidp);
79 }
80
81 /*
82 * get raid (common)
83 */
84 md_raid_t *
meta_get_raid_common(mdsetname_t * sp,mdname_t * raidnp,int fast,md_error_t * ep)85 meta_get_raid_common(
86 mdsetname_t *sp,
87 mdname_t *raidnp,
88 int fast,
89 md_error_t *ep
90 )
91 {
92 mddrivename_t *dnp = raidnp->drivenamep;
93 char *miscname;
94 mr_unit_t *mr;
95 md_raid_t *raidp;
96 uint_t ncol;
97 uint_t col;
98 md_resync_ioctl_t ri;
99
100 /* must have set */
101 assert(sp != NULL);
102 assert(sp->setno == MD_MIN2SET(meta_getminor(raidnp->dev)));
103
104 /* short circuit */
105 if (dnp->unitp != NULL) {
106 assert(dnp->unitp->type == MD_METARAID);
107 return ((md_raid_t *)dnp->unitp);
108 }
109
110 /* get miscname and unit */
111 if ((miscname = metagetmiscname(raidnp, ep)) == NULL)
112 return (NULL);
113 if (strcmp(miscname, MD_RAID) != 0) {
114 (void) mdmderror(ep, MDE_NOT_RAID, meta_getminor(raidnp->dev),
115 raidnp->cname);
116 return (NULL);
117 }
118 if ((mr = (mr_unit_t *)meta_get_mdunit(sp, raidnp, ep)) == NULL)
119 return (NULL);
120 assert(mr->c.un_type == MD_METARAID);
121
122 /* allocate raid */
123 raidp = Zalloc(sizeof (*raidp));
124
125 /* allocate columns */
126 ncol = mr->un_totalcolumncnt;
127 assert(ncol >= MD_RAID_MIN);
128 raidp->cols.cols_len = ncol;
129 raidp->cols.cols_val = Zalloc(raidp->cols.cols_len *
130 sizeof (*raidp->cols.cols_val));
131
132 /* get common info */
133 raidp->common.namep = raidnp;
134 raidp->common.type = mr->c.un_type;
135 raidp->common.state = mr->c.un_status;
136 raidp->common.capabilities = mr->c.un_capabilities;
137 raidp->common.parent = mr->c.un_parent;
138 raidp->common.size = mr->c.un_total_blocks;
139 raidp->common.user_flags = mr->c.un_user_flags;
140 raidp->common.revision = mr->c.un_revision;
141
142 /* get options */
143 raidp->state = mr->un_state;
144 raidp->timestamp = mr->un_timestamp;
145 raidp->interlace = mr->un_segsize;
146 raidp->orig_ncol = mr->un_origcolumncnt;
147 raidp->column_size = mr->un_segsize * mr->un_segsincolumn;
148 raidp->pw_count = mr->un_pwcnt;
149 assert(raidp->orig_ncol <= ncol);
150 if ((mr->un_hsp_id != MD_HSP_NONE) &&
151 ((raidp->hspnamep = metahsphspname(&sp, mr->un_hsp_id,
152 ep)) == NULL)) {
153 goto out;
154 }
155
156 /* get columns, update unit state */
157 for (col = 0; (col < ncol); ++col) {
158 mr_column_t *rcp = &mr->un_column[col];
159 md_raidcol_t *mdrcp = &raidp->cols.cols_val[col];
160
161 /* get column name */
162 mdrcp->colnamep = metakeyname(&sp, rcp->un_orig_key, fast, ep);
163 if (mdrcp->colnamep == NULL)
164 goto out;
165
166 /* override any start_blk */
167 #ifdef DEBUG
168 if (metagetstart(sp, mdrcp->colnamep, ep) !=
169 MD_DISKADDR_ERROR) {
170 assert(mdrcp->colnamep->start_blk <=
171 rcp->un_orig_devstart);
172 } else {
173 mdclrerror(ep);
174 }
175 #endif /* DEBUG */
176 mdrcp->colnamep->start_blk = rcp->un_orig_devstart;
177
178 /* if hotspared */
179 if (HOTSPARED(mr, col)) {
180 /* get hotspare name */
181 mdrcp->hsnamep = metakeyname(&sp, rcp->un_hs_key,
182 fast, ep);
183 if (mdrcp->hsnamep == NULL)
184 goto out;
185
186 if (getenv("META_DEBUG_START_BLK") != NULL) {
187 if (metagetstart(sp, mdrcp->hsnamep, ep) ==
188 MD_DISKADDR_ERROR)
189 mdclrerror(ep);
190
191 if ((mdrcp->hsnamep->start_blk == 0) &&
192 (rcp->un_hs_pwstart != 0))
193 md_eprintf(dgettext(TEXT_DOMAIN,
194 "%s: suspected bad start block,"
195 " seems labelled [raid]\n"),
196 mdrcp->hsnamep->cname);
197
198 if ((mdrcp->hsnamep->start_blk > 0) &&
199 (rcp->un_hs_pwstart == 0))
200 md_eprintf(dgettext(TEXT_DOMAIN,
201 "%s: suspected bad start block, "
202 " seems unlabelled [raid]\n"),
203 mdrcp->hsnamep->cname);
204 }
205
206 /* override any start_blk */
207 mdrcp->hsnamep->start_blk = rcp->un_hs_devstart;
208 }
209
210 /* get state, flags, and timestamp */
211 mdrcp->state = rcp->un_devstate;
212 mdrcp->flags = rcp->un_devflags;
213 mdrcp->timestamp = rcp->un_devtimestamp;
214 }
215
216 /* get resync info */
217 (void) memset(&ri, 0, sizeof (ri));
218 ri.ri_mnum = meta_getminor(raidnp->dev);
219 MD_SETDRIVERNAME(&ri, MD_RAID, sp->setno);
220 if (metaioctl(MD_IOCGETSYNC, &ri, &ri.mde, raidnp->cname) != 0) {
221 (void) mdstealerror(ep, &ri.mde);
222 goto out;
223 }
224 raidp->resync_flags = ri.ri_flags;
225 raidp->percent_dirty = ri.ri_percent_dirty;
226 raidp->percent_done = ri.ri_percent_done;
227
228 /* cleanup, return success */
229 Free(mr);
230 dnp->unitp = (md_common_t *)raidp;
231 return (raidp);
232
233 /* cleanup, return error */
234 out:
235 Free(mr);
236 meta_free_raid(raidp);
237 return (NULL);
238 }
239
240 /*
241 * get raid
242 */
243 md_raid_t *
meta_get_raid(mdsetname_t * sp,mdname_t * raidnp,md_error_t * ep)244 meta_get_raid(
245 mdsetname_t *sp,
246 mdname_t *raidnp,
247 md_error_t *ep
248 )
249 {
250 return (meta_get_raid_common(sp, raidnp, 0, ep));
251 }
252
253 /*
254 * check raid for dev
255 */
256 static int
in_raid(mdsetname_t * sp,mdname_t * raidnp,mdname_t * np,diskaddr_t slblk,diskaddr_t nblks,md_error_t * ep)257 in_raid(
258 mdsetname_t *sp,
259 mdname_t *raidnp,
260 mdname_t *np,
261 diskaddr_t slblk,
262 diskaddr_t nblks,
263 md_error_t *ep
264 )
265 {
266 md_raid_t *raidp;
267 uint_t col;
268
269 /* should be in the same set */
270 assert(sp != NULL);
271 assert(sp->setno == MD_MIN2SET(meta_getminor(raidnp->dev)));
272
273 /* get unit */
274 if ((raidp = meta_get_raid(sp, raidnp, ep)) == NULL)
275 return (-1);
276
277 /* look in columns */
278 for (col = 0; (col < raidp->cols.cols_len); ++col) {
279 md_raidcol_t *cp = &raidp->cols.cols_val[col];
280 mdname_t *colnp = cp->colnamep;
281 diskaddr_t col_sblk;
282 int err;
283
284 /* check same drive since metagetstart() can fail */
285 if ((err = meta_check_samedrive(np, colnp, ep)) < 0)
286 return (-1);
287 else if (err == 0)
288 continue;
289
290 /* check overlap */
291 if ((col_sblk = metagetstart(sp, colnp, ep)) ==
292 MD_DISKADDR_ERROR)
293 return (-1);
294 if (meta_check_overlap(raidnp->cname, np, slblk, nblks,
295 colnp, col_sblk, -1, ep) != 0) {
296 return (-1);
297 }
298 }
299
300 /* return success */
301 return (0);
302 }
303
304 /*
305 * check to see if we're in a raid
306 */
307 int
meta_check_inraid(mdsetname_t * sp,mdname_t * np,diskaddr_t slblk,diskaddr_t nblks,md_error_t * ep)308 meta_check_inraid(
309 mdsetname_t *sp,
310 mdname_t *np,
311 diskaddr_t slblk,
312 diskaddr_t nblks,
313 md_error_t *ep
314 )
315 {
316 mdnamelist_t *raidnlp = NULL;
317 mdnamelist_t *p;
318 int rval = 0;
319
320 /* should have a set */
321 assert(sp != NULL);
322
323 /* for each raid */
324 if (meta_get_raid_names(sp, &raidnlp, 0, ep) < 0)
325 return (-1);
326 for (p = raidnlp; (p != NULL); p = p->next) {
327 mdname_t *raidnp = p->namep;
328
329 /* check raid */
330 if (in_raid(sp, raidnp, np, slblk, nblks, ep) != 0) {
331 rval = -1;
332 break;
333 }
334 }
335
336 /* cleanup, return success */
337 metafreenamelist(raidnlp);
338 return (rval);
339 }
340
341 /*
342 * check column
343 */
344 int
meta_check_column(mdsetname_t * sp,mdname_t * np,md_error_t * ep)345 meta_check_column(
346 mdsetname_t *sp,
347 mdname_t *np,
348 md_error_t *ep
349 )
350 {
351 mdchkopts_t options = (MDCHK_ALLOW_MDDB);
352
353 /* check for soft partitions */
354 if (meta_sp_issp(sp, np, ep) != 0) {
355 /* make sure we have a disk */
356 if (metachkcomp(np, ep) != 0)
357 return (-1);
358 }
359
360 /* check to ensure that it is not already in use */
361 if (meta_check_inuse(sp, np, MDCHK_INUSE, ep) != 0) {
362 return (-1);
363 }
364
365 /* make sure it is in the set */
366 if (meta_check_inset(sp, np, ep) != 0)
367 return (-1);
368
369 /* make sure its not in a metadevice */
370 if (meta_check_inmeta(sp, np, options, 0, -1, ep) != 0)
371 return (-1);
372
373 /* return success */
374 return (0);
375 }
376
377 /*
378 * print raid
379 */
380 static int
raid_print(md_raid_t * raidp,char * fname,FILE * fp,mdprtopts_t options,md_error_t * ep)381 raid_print(
382 md_raid_t *raidp,
383 char *fname,
384 FILE *fp,
385 mdprtopts_t options,
386 md_error_t *ep
387 )
388 {
389 uint_t col;
390 int rval = -1;
391
392
393 if (options & PRINT_LARGEDEVICES) {
394 if ((raidp->common.revision & MD_64BIT_META_DEV) == 0) {
395 rval = 0;
396 goto out;
397 }
398 }
399
400 if (options & PRINT_FN) {
401 if ((raidp->common.revision & MD_FN_META_DEV) == 0) {
402 rval = 0;
403 goto out;
404 }
405 }
406
407 /* print name and -r */
408 if (fprintf(fp, "%s -r", raidp->common.namep->cname) == EOF)
409 goto out;
410
411 /*
412 * Print columns. Always print the full path.
413 */
414 for (col = 0; (col < raidp->cols.cols_len); ++col) {
415 md_raidcol_t *mdrcp = &raidp->cols.cols_val[col];
416
417 if (fprintf(fp, " %s", mdrcp->colnamep->rname) == EOF)
418 goto out;
419 }
420
421 if (fprintf(fp, " -k") == EOF)
422 goto out;
423
424 /* print options */
425 if (fprintf(fp, " -i %lldb", raidp->interlace) == EOF)
426 goto out;
427
428 if (raidp->pw_count != PWCNT_MIN)
429 if (fprintf(fp, " -w %d", raidp->pw_count) == EOF)
430 goto out;
431
432 if (raidp->hspnamep != NULL) {
433 if (fprintf(fp, " -h %s", raidp->hspnamep->hspname) == EOF)
434 goto out;
435 }
436 if (raidp->orig_ncol != raidp->cols.cols_len) {
437 assert(raidp->orig_ncol < raidp->cols.cols_len);
438 if (fprintf(fp, " -o %u", raidp->orig_ncol) == EOF)
439 goto out;
440 }
441
442 /* terminate last line */
443 if (fprintf(fp, "\n") == EOF)
444 goto out;
445
446 /* success */
447 rval = 0;
448
449 /* cleanup, return error */
450 out:
451 if (rval != 0)
452 (void) mdsyserror(ep, errno, fname);
453 return (rval);
454 }
455
456 static int
find_resyncing_column(md_raid_t * raidp)457 find_resyncing_column(
458 md_raid_t *raidp
459 )
460 {
461 int col;
462
463 for (col = 0; (col < raidp->cols.cols_len); ++col) {
464 md_raidcol_t *cp = &raidp->cols.cols_val[col];
465 if (cp->state & RCS_RESYNC)
466 return (col);
467 }
468
469 /* No resyncing columns */
470 return (-1);
471 }
472
473 /*
474 * convert raid state to name
475 */
476 char *
raid_state_to_name(md_raid_t * raidp,md_timeval32_t * tvp,uint_t tstate)477 raid_state_to_name(
478 md_raid_t *raidp,
479 md_timeval32_t *tvp,
480 uint_t tstate /* Errored tstate flags */
481 )
482 {
483
484 /* grab time */
485 if (tvp != NULL)
486 *tvp = raidp->timestamp;
487
488 /*
489 * If the device has a transient error state (due to it being DR'ed or
490 * failed) and there has been no I/O to it (the actual device is still
491 * marked as 'Okay') then we cannot know what the state is or what
492 * action to take on it. Therefore report the device as 'Unavailable'.
493 * A subsequent I/O to the device will cause the 'Okay' status to
494 * disappear if the device is actually gone and then we will print out
495 * the appropriate status. The MD_INACCESSIBLE state is only set
496 * on the raid when we open it or probe it. One the raid is open
497 * then we will just have regular error status on the device.
498 */
499 if (tstate & MD_INACCESSIBLE) {
500 return (dgettext(TEXT_DOMAIN, "Unavailable"));
501 }
502
503 /* resyncing */
504 if (find_resyncing_column(raidp) >= 0)
505 return (dgettext(TEXT_DOMAIN, "Resyncing"));
506
507 /* everything else */
508 switch (raidp->state) {
509 case RUS_INIT :
510 return (dgettext(TEXT_DOMAIN, "Initializing"));
511 case RUS_OKAY :
512 return (dgettext(TEXT_DOMAIN, "Okay"));
513 case RUS_ERRED :
514 /*FALLTHROUGH*/
515 case RUS_LAST_ERRED :
516 return (dgettext(TEXT_DOMAIN, "Needs Maintenance"));
517 case RUS_DOI :
518 return (dgettext(TEXT_DOMAIN, "Initialization Failed"));
519 case RUS_REGEN :
520 return (dgettext(TEXT_DOMAIN, "Regen"));
521 default :
522 return (dgettext(TEXT_DOMAIN, "invalid"));
523 } /* switch */
524 }
525
526 static int
find_erred_column(md_raid_t * raidp,rcs_state_t state)527 find_erred_column(md_raid_t *raidp, rcs_state_t state)
528 {
529 int col;
530
531 for (col = 0; (col < raidp->cols.cols_len); ++col) {
532 md_raidcol_t *cp = &raidp->cols.cols_val[col];
533 if (cp->state & state)
534 return (col);
535 }
536
537 /* No erred columns */
538 return (-1);
539 }
540
541 /*
542 * convert raid state to repair action
543 */
544 char *
raid_state_to_action(md_raid_t * raidp)545 raid_state_to_action(md_raid_t *raidp)
546 {
547 static char emsg[1024];
548 mdname_t *raidnp = raidp->common.namep;
549 int err_col;
550
551 /* first check for full init failure */
552 if (raidp->state & RUS_DOI) {
553 (void) snprintf(emsg, sizeof (emsg),
554 "metaclear -f %s", raidnp->cname);
555 return (emsg);
556 }
557
558 /* replace errored or init errored raid column */
559 if ((err_col = find_erred_column(raidp,
560 (RCS_ERRED | RCS_INIT_ERRED))) >= 0) {
561 mdname_t *colnp;
562
563 /* get column with error */
564 assert(err_col < raidp->cols.cols_len);
565 colnp = raidp->cols.cols_val[err_col].colnamep;
566 (void) snprintf(emsg, sizeof (emsg),
567 "metareplace %s%s %s <%s>",
568 ((raidp->state == RUS_LAST_ERRED) ? "-f " : ""),
569 raidnp->cname, colnp->cname,
570 dgettext(TEXT_DOMAIN, "new device"));
571 return (emsg);
572 }
573
574
575 /* replace last errored raid column */
576 if ((err_col = find_erred_column(raidp, RCS_LAST_ERRED)) >= 0) {
577 mdname_t *colnp;
578
579 assert(err_col < raidp->cols.cols_len);
580 colnp = raidp->cols.cols_val[err_col].colnamep;
581 (void) snprintf(emsg, sizeof (emsg),
582 "metareplace %s %s %s <%s>",
583 ((raidp->state == RUS_LAST_ERRED) ? "-f " : ""),
584 raidnp->cname, colnp->cname,
585 dgettext(TEXT_DOMAIN, "new device"));
586 return (emsg);
587 }
588
589 /* OK */
590 return (NULL);
591 }
592
593 /*
594 * get printable raid column state
595 */
596 char *
raid_col_state_to_name(md_raidcol_t * colp,md_timeval32_t * tvp,uint_t tstate)597 raid_col_state_to_name(
598 md_raidcol_t *colp,
599 md_timeval32_t *tvp,
600 uint_t tstate
601 )
602 {
603 /* grab time */
604 if (tvp != NULL)
605 *tvp = colp->timestamp;
606
607 if (tstate != 0) {
608 return (dgettext(TEXT_DOMAIN, "Unavailable"));
609 }
610
611 /* everything else */
612 switch (colp->state) {
613 case RCS_INIT:
614 return (dgettext(TEXT_DOMAIN, "Initializing"));
615
616 case RCS_OKAY:
617 return (dgettext(TEXT_DOMAIN, "Okay"));
618
619 case RCS_INIT_ERRED:
620 /*FALLTHROUGH*/
621 case RCS_ERRED:
622 return (dgettext(TEXT_DOMAIN, "Maintenance"));
623
624 case RCS_LAST_ERRED:
625 return (dgettext(TEXT_DOMAIN, "Last Erred"));
626
627 case RCS_RESYNC:
628 return (dgettext(TEXT_DOMAIN, "Resyncing"));
629
630 default:
631 return (dgettext(TEXT_DOMAIN, "Unknown"));
632 }
633 }
634
635 /*
636 * print raid column
637 */
638 static int
display_raid_device_info(mdsetname_t * sp,md_raidcol_t * colp,char * fname,FILE * fp,mdprtopts_t options,int print_len,uint_t top_tstate,md_error_t * ep)639 display_raid_device_info(
640 mdsetname_t *sp,
641 md_raidcol_t *colp,
642 char *fname,
643 FILE *fp,
644 mdprtopts_t options,
645 int print_len,
646 uint_t top_tstate, /* Errored tstate flags */
647 md_error_t *ep
648 )
649 {
650 mdname_t *namep = ((colp->hsnamep != NULL) ?
651 colp->hsnamep : colp->colnamep);
652 char *devid = "";
653 char *cname = colp->colnamep->cname;
654 diskaddr_t start_blk;
655 int has_mddb;
656 char *has_mddb_str;
657 char *col_state;
658 md_timeval32_t tv;
659 char *hsname = ((colp->hsnamep != NULL) ?
660 colp->hsnamep->cname : "");
661 int rval = -1;
662 mdname_t *didnp = NULL;
663 ddi_devid_t dtp;
664 uint_t tstate = 0;
665
666 /* get info */
667 if ((start_blk = metagetstart(sp, namep, ep)) == MD_DISKADDR_ERROR)
668 return (-1);
669 if ((has_mddb = metahasmddb(sp, namep, ep)) < 0)
670 return (-1);
671 if (has_mddb)
672 has_mddb_str = dgettext(TEXT_DOMAIN, "Yes");
673 else
674 has_mddb_str = dgettext(TEXT_DOMAIN, "No");
675
676 if (metaismeta(namep)) {
677 if (meta_get_tstate(namep->dev, &tstate, ep) != 0)
678 return (-1);
679 col_state = raid_col_state_to_name(colp, &tv,
680 tstate & MD_DEV_ERRORED);
681 } else {
682 /*
683 * if top_tstate is set, that implies that you have
684 * a ctd type device with an unavailable metadevice
685 * on top of it. If so, print a - for it's state
686 */
687 if (top_tstate != 0)
688 col_state = "-";
689 else
690 col_state = raid_col_state_to_name(colp, &tv, tstate);
691 }
692
693 /* populate the key in the name_p structure */
694 if ((didnp = metadevname(&sp, namep->dev, ep)) == NULL)
695 return (-1);
696
697 /* determine if devid does NOT exist */
698 if (options & PRINT_DEVID) {
699 if ((dtp = meta_getdidbykey(sp->setno, getmyside(sp, ep),
700 didnp->key, ep)) == NULL)
701 devid = dgettext(TEXT_DOMAIN, "No ");
702 else {
703 devid = dgettext(TEXT_DOMAIN, "Yes");
704 free(dtp);
705 }
706 }
707 /* print column */
708 /*
709 * Building a format string on the fly that will
710 * be used in (f)printf. This allows the length
711 * of the ctd to vary from small to large without
712 * looking horrible.
713 */
714 if (! (options & PRINT_TIMES)) {
715 if (fprintf(fp,
716 "\t%-*.*s %8lld %5.5s %12.12s %5.5s %s\n",
717 print_len, print_len, cname, start_blk, has_mddb_str,
718 col_state, devid, hsname) == EOF) {
719 goto out;
720 }
721 } else {
722 char *timep = meta_print_time(&tv);
723
724 if (fprintf(fp,
725 "\t%-*s %5lld %-5s %-11s %-5s %-9s %s\n",
726 print_len, cname, start_blk, has_mddb_str,
727 col_state, devid, hsname, timep) == EOF) {
728 goto out;
729 }
730 }
731
732 /* success */
733 rval = 0;
734
735 /* cleanup, return error */
736 out:
737 if (rval != 0)
738 (void) mdsyserror(ep, errno, fname);
739
740 return (rval);
741 }
742
743 /*
744 * print raid options
745 */
746 int
meta_print_raid_options(mdhspname_t * hspnamep,char * fname,FILE * fp,md_error_t * ep)747 meta_print_raid_options(
748 mdhspname_t *hspnamep,
749 char *fname,
750 FILE *fp,
751 md_error_t *ep
752 )
753 {
754 char *hspname = ((hspnamep != NULL) ? hspnamep->hspname :
755 dgettext(TEXT_DOMAIN, "none"));
756 int rval = -1;
757
758 /* print options */
759 if (fprintf(fp, dgettext(TEXT_DOMAIN,
760 " Hot spare pool: %s\n"), hspname) == EOF) {
761 goto out;
762 }
763
764 /* success */
765 rval = 0;
766
767 /* cleanup, return error */
768 out:
769 if (rval != 0)
770 (void) mdsyserror(ep, errno, fname);
771 return (rval);
772 }
773
774 /*
775 * report raid
776 */
777 static int
raid_report(mdsetname_t * sp,md_raid_t * raidp,char * fname,FILE * fp,mdprtopts_t options,md_error_t * ep)778 raid_report(
779 mdsetname_t *sp,
780 md_raid_t *raidp,
781 char *fname,
782 FILE *fp,
783 mdprtopts_t options,
784 md_error_t *ep
785 )
786 {
787 char *p;
788 uint_t ncol = raidp->cols.cols_len;
789 uint_t orig_ncol = raidp->orig_ncol;
790 diskaddr_t column_size = raidp->column_size;
791 char *raid_state;
792 md_timeval32_t tv;
793 char *timep;
794 uint_t col;
795 int rval = -1;
796 int len = 0;
797 uint_t tstate = 0;
798
799 if (options & PRINT_LARGEDEVICES) {
800 if ((raidp->common.revision & MD_64BIT_META_DEV) == 0) {
801 rval = 0;
802 goto out;
803 }
804 }
805
806 if (options & PRINT_FN) {
807 if ((raidp->common.revision & MD_FN_META_DEV) == 0) {
808 rval = 0;
809 goto out;
810 }
811 }
812
813 /* print header */
814 if (options & PRINT_HEADER) {
815 if (fprintf(fp, dgettext(TEXT_DOMAIN, "%s: RAID\n"),
816 raidp->common.namep->cname) == EOF) {
817 goto out;
818 }
819
820 }
821
822 /* print state */
823 if (metaismeta(raidp->common.namep)) {
824 if (meta_get_tstate(raidp->common.namep->dev, &tstate, ep) != 0)
825 return (-1);
826 }
827 tstate &= MD_DEV_ERRORED; /* extract the errored tstate bits */
828 raid_state = raid_state_to_name(raidp, &tv, tstate);
829 if (options & PRINT_TIMES) {
830 timep = meta_print_time(&tv);
831 } else {
832 timep = "";
833 }
834
835 if (fprintf(fp, dgettext(TEXT_DOMAIN, " State: %-12s %s\n"),
836 raid_state, timep) == EOF) {
837 goto out;
838 }
839
840 /*
841 * Display recovery action if we're marked in the Unavailable state.
842 */
843 if ((tstate == 0) || (tstate & MD_INACCESSIBLE)) {
844 /* print what to do */
845 if (tstate & MD_INACCESSIBLE) {
846 char sname[MD_MAX_SETNAME + 3]; /* 3 = sizeof("-s ") */
847
848 if (metaislocalset(sp)) {
849 sname[0] = '\0';
850 } else {
851 (void) snprintf(sname, MD_MAX_SETNAME + 3,
852 "-s %s", sp->setname);
853 }
854 if (fprintf(fp, dgettext(TEXT_DOMAIN,
855 " Invoke: metastat -i %s\n"), sname) == EOF) {
856 goto out;
857 }
858 } else if ((p = raid_state_to_action(raidp)) != NULL) {
859 if (fprintf(fp, dgettext(TEXT_DOMAIN,
860 " Invoke: %s\n"), p) == EOF) {
861 goto out;
862 }
863 }
864
865 /* resync status */
866 if (raidp->resync_flags & MD_RI_INPROGRESS) {
867 if (fprintf(fp, dgettext(TEXT_DOMAIN,
868 " Resync in progress: %2d.%1d%% done\n"),
869 raidp->percent_done/10,
870 raidp->percent_done % 10) == EOF) {
871 goto out;
872 }
873 } else if (raidp->resync_flags & MD_GROW_INPROGRESS) {
874 if (fprintf(fp, dgettext(TEXT_DOMAIN,
875 " Initialization in progress: %2d.%1d%% "
876 "done\n"),
877 raidp->percent_done/10,
878 raidp->percent_done % 10) == EOF) {
879 goto out;
880 }
881 } else if (raidp->state & RUS_REGEN) {
882 if (fprintf(fp, dgettext(TEXT_DOMAIN,
883 " Parity regeneration in progress: %2d.%1d%% "
884 "done\n"),
885 raidp->percent_done/10,
886 raidp->percent_done % 10) == EOF) {
887 goto out;
888 }
889 }
890 }
891
892 /* print hotspare pool */
893 if (raidp->hspnamep != NULL) {
894 if (meta_print_raid_options(raidp->hspnamep,
895 fname, fp, ep) != 0) {
896 return (-1);
897 }
898 }
899
900 /* print interlace */
901 if (fprintf(fp, dgettext(TEXT_DOMAIN, " Interlace: %lld blocks\n"),
902 raidp->interlace) == EOF) {
903 goto out;
904 }
905
906 /* print size */
907 if (fprintf(fp, dgettext(TEXT_DOMAIN, " Size: %lld blocks (%s)\n"),
908 raidp->common.size,
909 meta_number_to_string(raidp->common.size, DEV_BSIZE)) == EOF) {
910 goto out;
911 }
912
913 /* MD_DEBUG stuff */
914 if (options & PRINT_DEBUG) {
915 mdname_t *raidnp = raidp->common.namep;
916 mr_unit_t *mr;
917
918 /* get additional info */
919 if ((mr = (mr_unit_t *)meta_get_mdunit(sp, raidnp, ep)) == NULL)
920 return (-1);
921 assert(mr->c.un_type == MD_METARAID);
922
923 /* print prewrite count and size */
924 if (fprintf(fp, dgettext(TEXT_DOMAIN,
925 " Prewrite Count: %u slots\n"),
926 mr->un_pwcnt) == EOF) {
927 Free(mr);
928 goto out;
929 }
930 if (fprintf(fp, dgettext(TEXT_DOMAIN,
931 " Prewrite Slot Size: %u blocks\n"),
932 (mr->un_pwsize / mr->un_pwcnt)) == EOF) {
933 Free(mr);
934 goto out;
935 }
936 if (fprintf(fp, dgettext(TEXT_DOMAIN,
937 " Prewrite Total Size: %u blocks\n"),
938 mr->un_pwsize) == EOF) {
939 Free(mr);
940 goto out;
941 }
942 Free(mr);
943 }
944
945 /* print original devices */
946 if (fprintf(fp, dgettext(TEXT_DOMAIN, "Original device:\n")) == EOF)
947 goto out;
948 if (fprintf(fp, dgettext(TEXT_DOMAIN, " Size: %lld blocks (%s)\n"),
949 column_size * (orig_ncol - 1),
950 meta_number_to_string(column_size * (orig_ncol - 1), DEV_BSIZE))
951 == EOF) {
952 goto out;
953 }
954 /*
955 * Building a format string on the fly that will
956 * be used in (f)printf. This allows the length
957 * of the ctd to vary from small to large without
958 * looking horrible.
959 */
960 for (col = 0; (col < orig_ncol); ++col) {
961 len = max(len,
962 strlen(raidp->cols.cols_val[col].colnamep->cname));
963 }
964
965 len = max(len, strlen(dgettext(TEXT_DOMAIN, "Device")));
966 len += 2;
967
968 if (! (options & PRINT_TIMES)) {
969 if (fprintf(fp,
970 "\t%-*.*s %-12.12s %-5.5s %12.12s %-5.5s %s\n",
971 len, len,
972 dgettext(TEXT_DOMAIN, "Device"),
973 dgettext(TEXT_DOMAIN, "Start Block"),
974 dgettext(TEXT_DOMAIN, "Dbase"),
975 dgettext(TEXT_DOMAIN, "State"),
976 dgettext(TEXT_DOMAIN, "Reloc"),
977 dgettext(TEXT_DOMAIN, "Hot Spare")) == EOF) {
978 goto out;
979 }
980 } else {
981 if (fprintf(fp,
982 "\t%-*s %5s %-5s %-11s %-5s %-9s %s\n",
983 len,
984 dgettext(TEXT_DOMAIN, "Device"),
985 dgettext(TEXT_DOMAIN, "Start"),
986 dgettext(TEXT_DOMAIN, "Dbase"),
987 dgettext(TEXT_DOMAIN, "State"),
988 dgettext(TEXT_DOMAIN, "Reloc"),
989 dgettext(TEXT_DOMAIN, "Hot Spare"),
990 dgettext(TEXT_DOMAIN, "Time")) == EOF) {
991 goto out;
992 }
993 }
994 for (col = 0; (col < orig_ncol); ++col) {
995 md_raidcol_t *mdrcp = &raidp->cols.cols_val[col];
996
997 if (display_raid_device_info(sp, mdrcp, fname, fp, options,
998 len, tstate, ep) != 0) {
999 return (-1);
1000 }
1001 }
1002
1003 /* print concatenated devices */
1004 if (col < ncol) {
1005 if (fprintf(fp, dgettext(TEXT_DOMAIN,
1006 "Concatenated Devices:\n")) == EOF) {
1007 goto out;
1008 }
1009 if (fprintf(fp, dgettext(TEXT_DOMAIN,
1010 " Size: %lld blocks (%s)\n"),
1011 column_size * (ncol - orig_ncol),
1012 meta_number_to_string(column_size * (ncol - orig_ncol),
1013 DEV_BSIZE))
1014 == EOF) {
1015 goto out;
1016 }
1017 /*
1018 * This allows the length
1019 * of the ctd to vary from small to large without
1020 * looking horrible.
1021 */
1022 if (! (options & PRINT_TIMES)) {
1023 if (fprintf(fp,
1024 "\t%-*.*s %-12.12s %-5.5s %-12.12s %5.5s %s\n",
1025 len, len,
1026 dgettext(TEXT_DOMAIN, "Device"),
1027 dgettext(TEXT_DOMAIN, "Start Block"),
1028 dgettext(TEXT_DOMAIN, "Dbase"),
1029 dgettext(TEXT_DOMAIN, "State"),
1030 dgettext(TEXT_DOMAIN, "Reloc"),
1031 dgettext(TEXT_DOMAIN, "Hot Spare")) == EOF) {
1032 goto out;
1033 }
1034 } else {
1035 if (fprintf(fp,
1036 "\t%-*s %5s %-5s %-11s %-9s %s\t%s\n",
1037 len,
1038 dgettext(TEXT_DOMAIN, "Device"),
1039 dgettext(TEXT_DOMAIN, "Start"),
1040 dgettext(TEXT_DOMAIN, "Dbase"),
1041 dgettext(TEXT_DOMAIN, "State"),
1042 dgettext(TEXT_DOMAIN, "Reloc"),
1043 dgettext(TEXT_DOMAIN, "Hot Spare"),
1044 dgettext(TEXT_DOMAIN, "Time")) == EOF) {
1045 goto out;
1046 }
1047 }
1048 assert(col == orig_ncol);
1049 for (/* void */; (col < ncol); col++) {
1050 md_raidcol_t *mdrcp = &raidp->cols.cols_val[col];
1051
1052 if (display_raid_device_info(sp, mdrcp, fname, fp,
1053 options, len, tstate, ep) != 0) {
1054 return (-1);
1055 }
1056 }
1057 }
1058
1059 /* add extra line */
1060 if (fprintf(fp, "\n") == EOF)
1061 goto out;
1062
1063 /* success */
1064 rval = 0;
1065
1066 /* cleanup, return error */
1067 out:
1068 if (rval != 0)
1069 (void) mdsyserror(ep, errno, fname);
1070 return (rval);
1071 }
1072
1073 /*
1074 * print/report raid
1075 */
1076 int
meta_raid_print(mdsetname_t * sp,mdname_t * raidnp,mdnamelist_t ** nlpp,char * fname,FILE * fp,mdprtopts_t options,md_error_t * ep)1077 meta_raid_print(
1078 mdsetname_t *sp,
1079 mdname_t *raidnp,
1080 mdnamelist_t **nlpp,
1081 char *fname,
1082 FILE *fp,
1083 mdprtopts_t options,
1084 md_error_t *ep
1085 )
1086 {
1087 md_raid_t *raidp;
1088 int col;
1089
1090 /* should have same set */
1091 assert(sp != NULL);
1092 assert((raidnp == NULL) ||
1093 (sp->setno == MD_MIN2SET(meta_getminor(raidnp->dev))));
1094
1095 /* print all raids */
1096 if (raidnp == NULL) {
1097 mdnamelist_t *nlp = NULL;
1098 mdnamelist_t *p;
1099 int cnt;
1100 int rval = 0;
1101
1102 /* get list */
1103 if ((cnt = meta_get_raid_names(sp, &nlp, options, ep)) < 0)
1104 return (-1);
1105 else if (cnt == 0)
1106 return (0);
1107
1108 /* recurse */
1109 for (p = nlp; (p != NULL); p = p->next) {
1110 mdname_t *np = p->namep;
1111
1112 if (meta_raid_print(sp, np, nlpp, fname, fp,
1113 options, ep) != 0)
1114 rval = -1;
1115 }
1116
1117 /* cleanup, return success */
1118 metafreenamelist(nlp);
1119 return (rval);
1120 }
1121
1122 /* get unit structure */
1123 if ((raidp = meta_get_raid_common(sp, raidnp,
1124 ((options & PRINT_FAST) ? 1 : 0), ep)) == NULL)
1125 return (-1);
1126
1127 /* check for parented */
1128 if ((! (options & PRINT_SUBDEVS)) &&
1129 (MD_HAS_PARENT(raidp->common.parent))) {
1130 return (0);
1131 }
1132
1133 /* print appropriate detail */
1134 if (options & PRINT_SHORT) {
1135 if (raid_print(raidp, fname, fp, options, ep) != 0)
1136 return (-1);
1137 } else {
1138 if (raid_report(sp, raidp, fname, fp, options, ep) != 0)
1139 return (-1);
1140 }
1141
1142 /* Recurse on components that are metadevices */
1143 for (col = 0; col < raidp->cols.cols_len; ++col) {
1144 md_raidcol_t *colp = &raidp->cols.cols_val[col];
1145 mdname_t *namep = colp->colnamep;
1146
1147 if ((metaismeta(namep)) &&
1148 (meta_print_name(sp, namep, nlpp, fname, fp,
1149 (options | PRINT_HEADER | PRINT_SUBDEVS),
1150 NULL, ep) != 0)) {
1151 return (-1);
1152 }
1153 }
1154
1155 return (0);
1156 }
1157
1158 /*
1159 * adjust raid geometry
1160 */
1161 static int
adjust_geom(mdname_t * raidnp,mdname_t * colnp,mr_unit_t * mr,md_error_t * ep)1162 adjust_geom(
1163 mdname_t *raidnp,
1164 mdname_t *colnp,
1165 mr_unit_t *mr,
1166 md_error_t *ep
1167 )
1168 {
1169 uint_t round_cyl = 1;
1170 mdgeom_t *geomp;
1171
1172 /* get reinstructs */
1173 if ((geomp = metagetgeom(colnp, ep)) == NULL)
1174 return (-1);
1175
1176 /* adjust geometry */
1177 if (meta_adjust_geom((md_unit_t *)mr, raidnp, geomp->write_reinstruct,
1178 geomp->read_reinstruct, round_cyl, ep) != 0)
1179 return (-1);
1180
1181 /* return success */
1182 return (0);
1183 }
1184
1185 /*
1186 * add another column to the raid unit structure
1187 */
1188 static int
attach_raid_col(mdsetname_t * sp,mdname_t * raidnp,mr_unit_t * mr,mr_column_t * mdc,mdname_t * colnp,rcs_state_t state,mdnamelist_t ** keynlpp,mdcmdopts_t options,md_error_t * ep)1189 attach_raid_col(
1190 mdsetname_t *sp,
1191 mdname_t *raidnp,
1192 mr_unit_t *mr,
1193 mr_column_t *mdc,
1194 mdname_t *colnp,
1195 rcs_state_t state,
1196 mdnamelist_t **keynlpp,
1197 mdcmdopts_t options,
1198 md_error_t *ep
1199 )
1200 {
1201 diskaddr_t column_size = mr->un_segsize * mr->un_segsincolumn;
1202 diskaddr_t size;
1203 uint_t maxio;
1204 mdcinfo_t *cinfop;
1205 md_timeval32_t tmp_time;
1206
1207 /* setup state and timestamp */
1208 mdc->un_devstate = state;
1209 if (meta_gettimeofday(&tmp_time) == -1)
1210 return (mdsyserror(ep, errno, NULL));
1211
1212 mdc->un_devtimestamp = tmp_time;
1213 /* get start, size, and maxio */
1214 if ((mdc->un_orig_devstart = metagetstart(sp, colnp, ep)) ==
1215 MD_DISKADDR_ERROR)
1216 return (-1);
1217 if ((size = metagetsize(colnp, ep)) == MD_DISKADDR_ERROR)
1218 return (-1);
1219 if ((cinfop = metagetcinfo(colnp, ep)) == NULL)
1220 return (-1);
1221 maxio = cinfop->maxtransfer;
1222
1223 /* adjust start and size by prewrite */
1224 mdc->un_orig_pwstart = mdc->un_orig_devstart;
1225 mdc->un_orig_devstart += mr->un_pwsize;
1226
1227 /* make sure we still have something left */
1228 if ((mdc->un_orig_devstart >= size) ||
1229 ((size - mdc->un_orig_devstart) < column_size)) {
1230 return (mdsyserror(ep, ENOSPC, colnp->cname));
1231 }
1232 size -= mdc->un_orig_devstart;
1233 if (maxio < mr->un_maxio) {
1234 return (mdcomperror(ep, MDE_MAXIO,
1235 meta_getminor(raidnp->dev), colnp->dev, colnp->cname));
1236 }
1237
1238 if (options & MDCMD_DOIT) {
1239 /* store name in namespace */
1240 if (add_key_name(sp, colnp, keynlpp, ep) != 0)
1241 return (-1);
1242 }
1243
1244 /* setup column */
1245 mdc->un_orig_dev = colnp->dev;
1246 mdc->un_orig_key = colnp->key;
1247 mdc->un_dev = colnp->dev;
1248 mdc->un_pwstart = mdc->un_orig_pwstart;
1249 mdc->un_devstart = mdc->un_orig_devstart;
1250 mdc->un_alt_dev = NODEV64;
1251 mdc->un_alt_pwstart = 0;
1252 mdc->un_alt_devstart = 0;
1253 mdc->un_hs_id = 0;
1254
1255 /* add the size (we use) of the device to the total */
1256 mr->c.un_actual_tb += column_size;
1257
1258 /* adjust geometry */
1259 if (adjust_geom(raidnp, colnp, mr, ep) != 0)
1260 return (-1);
1261
1262 /* count column */
1263 mr->un_totalcolumncnt++;
1264
1265 /* return success */
1266 return (0);
1267 }
1268
1269 /*
1270 * invalidate column names
1271 */
1272 static int
invalidate_columns(mdsetname_t * sp,mdname_t * raidnp,md_error_t * ep)1273 invalidate_columns(
1274 mdsetname_t *sp,
1275 mdname_t *raidnp,
1276 md_error_t *ep
1277 )
1278 {
1279 md_raid_t *raidp;
1280 uint_t col;
1281
1282 if ((raidp = meta_get_raid(sp, raidnp, ep)) == NULL)
1283 return (-1);
1284 for (col = 0; (col < raidp->cols.cols_len); ++col) {
1285 md_raidcol_t *cp = &raidp->cols.cols_val[col];
1286 mdname_t *colnp = cp->colnamep;
1287
1288 meta_invalidate_name(colnp);
1289 }
1290 return (0);
1291 }
1292
1293 /*
1294 * attach columns to raid
1295 */
1296 int
meta_raid_attach(mdsetname_t * sp,mdname_t * raidnp,mdnamelist_t * colnlp,mdcmdopts_t options,md_error_t * ep)1297 meta_raid_attach(
1298 mdsetname_t *sp,
1299 mdname_t *raidnp,
1300 mdnamelist_t *colnlp,
1301 mdcmdopts_t options,
1302 md_error_t *ep
1303 )
1304 {
1305 uint_t concat_cnt = 0;
1306 mdnamelist_t *p;
1307 mr_unit_t *old_mr;
1308 mr_unit_t *new_mr;
1309 size_t old_rusize;
1310 size_t new_rusize;
1311 mdnamelist_t *keynlp = NULL;
1312 md_grow_params_t mgp;
1313 int rval = -1;
1314 int create_flag = MD_CRO_32BIT;
1315
1316 /* should have a set */
1317 assert(sp != NULL);
1318 assert(sp->setno == MD_MIN2SET(meta_getminor(raidnp->dev)));
1319
1320 /* check type */
1321 if (metachkmeta(raidnp, ep) != 0)
1322 return (-1);
1323
1324 /* check and count new columns */
1325 for (p = colnlp; (p != NULL); p = p->next) {
1326 mdname_t *np = p->namep;
1327 mdnamelist_t *p2;
1328
1329 /* check against existing devices */
1330 if (meta_check_column(sp, np, ep) != 0)
1331 return (-1);
1332
1333 /* check against ourselves */
1334 for (p2 = p->next; (p2 != NULL); p2 = p2->next) {
1335 if (meta_check_overlap(np->cname, np, 0, -1,
1336 p2->namep, 0, -1, ep) != 0) {
1337 return (-1);
1338 }
1339 }
1340
1341 /* count */
1342 ++concat_cnt;
1343 }
1344
1345 /* get old unit */
1346 if ((old_mr = (mr_unit_t *)meta_get_mdunit(sp, raidnp, ep)) == NULL)
1347 return (-1);
1348
1349 /*
1350 * calculate the size needed for the new raid unit and allocate
1351 * the appropriate structure. allocate new unit.
1352 */
1353 old_rusize = sizeof (*old_mr) - sizeof (old_mr->un_column[0]);
1354 old_rusize += old_mr->un_totalcolumncnt * sizeof (old_mr->un_column[0]);
1355 new_rusize = sizeof (*new_mr) - sizeof (new_mr->un_column[0]);
1356 new_rusize += (old_mr->un_totalcolumncnt + concat_cnt)
1357 * sizeof (new_mr->un_column[0]);
1358 new_mr = Zalloc(new_rusize);
1359 (void) memcpy(new_mr, old_mr, old_rusize);
1360
1361 /* We always want a do-it, this is for attach_raid_col below */
1362 options |= MDCMD_DOIT;
1363
1364 /* build new unit structure */
1365 for (p = colnlp; (p != NULL); p = p->next) {
1366 mdname_t *colnp = p->namep;
1367 mr_column_t *mdc;
1368
1369 /* attach column */
1370 mdc = &new_mr->un_column[new_mr->un_totalcolumncnt];
1371 if (attach_raid_col(sp, raidnp, new_mr, mdc, colnp,
1372 RCS_INIT, &keynlp, options, ep) != 0) {
1373 goto out;
1374 }
1375 }
1376 assert(new_mr->un_totalcolumncnt
1377 == (old_mr->un_totalcolumncnt + concat_cnt));
1378
1379
1380 create_flag = meta_check_devicesize(new_mr->c.un_total_blocks);
1381
1382 /* grow raid */
1383 (void) memset(&mgp, 0, sizeof (mgp));
1384 mgp.mnum = MD_SID(new_mr);
1385 MD_SETDRIVERNAME(&mgp, MD_RAID, sp->setno);
1386 mgp.size = new_rusize;
1387 mgp.mdp = (uintptr_t)new_mr;
1388
1389 if (create_flag == MD_CRO_32BIT) {
1390 mgp.options = MD_CRO_32BIT;
1391 new_mr->c.un_revision &= ~MD_64BIT_META_DEV;
1392 } else {
1393 mgp.options = MD_CRO_64BIT;
1394 new_mr->c.un_revision |= MD_64BIT_META_DEV;
1395 }
1396 if (metaioctl(MD_IOCGROW, &mgp, &mgp.mde, NULL) != 0) {
1397 (void) mdstealerror(ep, &mgp.mde);
1398 goto out;
1399 }
1400
1401 /* clear cache */
1402 if (invalidate_columns(sp, raidnp, ep) != 0)
1403 goto out;
1404 meta_invalidate_name(raidnp);
1405
1406 /* let em know */
1407 if (options & MDCMD_PRINT) {
1408 if (concat_cnt == 1) {
1409 (void) printf(dgettext(TEXT_DOMAIN,
1410 "%s: component is attached\n"),
1411 raidnp->cname);
1412 } else {
1413 (void) printf(dgettext(TEXT_DOMAIN,
1414 "%s: components are attached\n"),
1415 raidnp->cname);
1416 }
1417 (void) fflush(stdout);
1418 }
1419
1420
1421 /* grow any parents */
1422 if (meta_concat_parent(sp, raidnp, ep) != 0)
1423 goto out;
1424 rval = 0; /* success */
1425
1426 /* cleanup, return error */
1427 out:
1428 Free(old_mr);
1429 Free(new_mr);
1430 if (rval != 0)
1431 (void) del_key_names(sp, keynlp, NULL);
1432 metafreenamelist(keynlp);
1433 return (rval);
1434 }
1435
1436 /*
1437 * get raid parameters
1438 */
1439 int
meta_raid_get_params(mdsetname_t * sp,mdname_t * raidnp,mr_params_t * paramsp,md_error_t * ep)1440 meta_raid_get_params(
1441 mdsetname_t *sp,
1442 mdname_t *raidnp,
1443 mr_params_t *paramsp,
1444 md_error_t *ep
1445 )
1446 {
1447 md_raid_t *raidp;
1448
1449 /* should have a set */
1450 assert(sp != NULL);
1451 assert(sp->setno == MD_MIN2SET(meta_getminor(raidnp->dev)));
1452
1453 /* check name */
1454 if (metachkmeta(raidnp, ep) != 0)
1455 return (-1);
1456
1457 /* get unit */
1458 if ((raidp = meta_get_raid(sp, raidnp, ep)) == NULL)
1459 return (-1);
1460
1461 /* return parameters */
1462 (void) memset(paramsp, 0, sizeof (*paramsp));
1463 if (raidp->hspnamep == NULL)
1464 paramsp->hsp_id = MD_HSP_NONE;
1465 else
1466 paramsp->hsp_id = raidp->hspnamep->hsp;
1467 return (0);
1468 }
1469
1470 /*
1471 * set raid parameters
1472 */
1473 int
meta_raid_set_params(mdsetname_t * sp,mdname_t * raidnp,mr_params_t * paramsp,md_error_t * ep)1474 meta_raid_set_params(
1475 mdsetname_t *sp,
1476 mdname_t *raidnp,
1477 mr_params_t *paramsp,
1478 md_error_t *ep
1479 )
1480 {
1481 md_raid_params_t msp;
1482
1483 /* should have a set */
1484 assert(sp != NULL);
1485 assert(sp->setno == MD_MIN2SET(meta_getminor(raidnp->dev)));
1486
1487 /* check name */
1488 if (metachkmeta(raidnp, ep) != 0)
1489 return (-1);
1490
1491 /* set parameters */
1492 (void) memset(&msp, 0, sizeof (msp));
1493 MD_SETDRIVERNAME(&msp, MD_RAID, sp->setno);
1494 msp.mnum = meta_getminor(raidnp->dev);
1495 msp.params = *paramsp;
1496 if (metaioctl(MD_IOCCHANGE, &msp, &msp.mde, raidnp->cname) != 0)
1497 return (mdstealerror(ep, &msp.mde));
1498
1499 /* clear cache */
1500 meta_invalidate_name(raidnp);
1501
1502 /* return success */
1503 return (0);
1504 }
1505
1506 /*
1507 * validate raid replace column
1508 */
1509 static int
validate_new_raid(mdsetname_t * sp,mdname_t * raidnp,mdname_t * colnp,replace_params_t * paramsp,int dup_ok,md_error_t * ep)1510 validate_new_raid(
1511 mdsetname_t *sp,
1512 mdname_t *raidnp,
1513 mdname_t *colnp,
1514 replace_params_t *paramsp,
1515 int dup_ok,
1516 md_error_t *ep
1517 )
1518 {
1519 mr_unit_t *mr;
1520 diskaddr_t column_size;
1521 diskaddr_t label;
1522 mdcinfo_t *cinfop;
1523 int rval = -1;
1524
1525 /* get raid unit */
1526 if ((mr = (mr_unit_t *)meta_get_mdunit(sp, raidnp, ep)) == NULL)
1527 return (-1);
1528 column_size = mr->un_segsize * mr->un_segsincolumn;
1529
1530 /* check it out */
1531 if (meta_check_column(sp, colnp, ep) != 0) {
1532 if ((! dup_ok) || (! mdisuseerror(ep, MDE_ALREADY)))
1533 goto out;
1534 mdclrerror(ep);
1535 }
1536 if ((paramsp->number_blks = metagetsize(colnp, ep)) ==
1537 MD_DISKADDR_ERROR)
1538 goto out;
1539 if ((label = metagetlabel(colnp, ep)) == MD_DISKADDR_ERROR)
1540 goto out;
1541 paramsp->has_label = ((label > 0) ? 1 : 0);
1542 if ((paramsp->start_blk = metagetstart(sp, colnp, ep)) ==
1543 MD_DISKADDR_ERROR)
1544 goto out;
1545 if ((paramsp->number_blks - paramsp->start_blk) < column_size) {
1546 (void) mdsyserror(ep, ENOSPC, colnp->cname);
1547 goto out;
1548 }
1549 if ((cinfop = metagetcinfo(colnp, ep)) == NULL)
1550 goto out;
1551 if (cinfop->maxtransfer < mr->un_maxio) {
1552 (void) mdcomperror(ep, MDE_MAXIO, meta_getminor(raidnp->dev),
1553 colnp->dev, colnp->cname);
1554 goto out;
1555 }
1556
1557 /* success */
1558 rval = 0;
1559
1560 /* cleanup, return error */
1561 out:
1562 Free(mr);
1563 return (rval);
1564 }
1565
1566 /*
1567 * replace raid column
1568 */
1569 int
meta_raid_replace(mdsetname_t * sp,mdname_t * raidnp,mdname_t * oldnp,mdname_t * newnp,mdcmdopts_t options,md_error_t * ep)1570 meta_raid_replace(
1571 mdsetname_t *sp,
1572 mdname_t *raidnp,
1573 mdname_t *oldnp,
1574 mdname_t *newnp,
1575 mdcmdopts_t options,
1576 md_error_t *ep
1577 )
1578 {
1579 int force = ((options & MDCMD_FORCE) ? 1 : 0);
1580 replace_params_t params;
1581 md_dev64_t old_dev, new_dev;
1582 diskaddr_t new_start_blk, new_end_blk;
1583 int rebind;
1584 char *new_devidp = NULL;
1585 md_error_t xep = mdnullerror;
1586 int ret;
1587 md_set_desc *sd;
1588 uint_t tstate;
1589
1590 /* should have same set */
1591 assert(sp != NULL);
1592 assert(sp->setno == MD_MIN2SET(meta_getminor(raidnp->dev)));
1593
1594 /* check name */
1595 if (metachkmeta(raidnp, ep) != 0)
1596 return (-1);
1597
1598 /* save new binding incase this is a rebind where oldnp==newnp */
1599 new_dev = newnp->dev;
1600 new_start_blk = newnp->start_blk;
1601 new_end_blk = newnp->end_blk;
1602
1603 /* invalidate, then get the raid (fill in oldnp from metadb) */
1604 meta_invalidate_name(raidnp);
1605 if (meta_get_raid(sp, raidnp, ep) == NULL)
1606 return (-1);
1607
1608 /* can't replace a component if the raid inaccessible */
1609 if (meta_get_tstate(raidnp->dev, &tstate, ep) != 0) {
1610 return (-1);
1611 }
1612 if (tstate & MD_INACCESSIBLE) {
1613 return (mdmderror(ep, MDE_IN_UNAVAIL_STATE,
1614 meta_getminor(raidnp->dev), raidnp->cname));
1615 }
1616
1617 /* the old device binding is now established */
1618 if ((old_dev = oldnp->dev) == NODEV64)
1619 return (mdsyserror(ep, ENODEV, oldnp->cname));
1620
1621
1622 /* setup raid info */
1623 (void) memset(¶ms, 0, sizeof (params));
1624 params.mnum = meta_getminor(raidnp->dev);
1625 MD_SETDRIVERNAME(¶ms, MD_RAID, sp->setno);
1626 params.old_dev = old_dev;
1627 params.cmd = force ? FORCE_REPLACE_COMP : REPLACE_COMP;
1628
1629 if ((strcmp(oldnp->rname, newnp->rname) == 0) &&
1630 (old_dev != new_dev)) {
1631 rebind = 1;
1632 } else {
1633 rebind = 0;
1634 }
1635 if (rebind) {
1636 newnp->dev = new_dev;
1637 newnp->start_blk = new_start_blk;
1638 newnp->end_blk = new_end_blk;
1639 }
1640
1641 /*
1642 * Save a copy of the devid associated with the new disk, the
1643 * reason is that the checks for the column (meta_check_column)
1644 * via validate_new_raid(), could cause the disk's devid to be
1645 * changed to that of the devid that is currently stored in the
1646 * replica namespace for the disk in question. This devid could
1647 * be stale if we are replacing the disk. The actual function
1648 * that overwrites the devid is dr2drivedesc().
1649 */
1650
1651 /* don't setup new_devid if no devid's or MN diskset */
1652 if (newnp->drivenamep->devid != NULL)
1653 new_devidp = Strdup(newnp->drivenamep->devid);
1654
1655 if (!metaislocalset(sp)) {
1656 if ((sd = metaget_setdesc(sp, ep)) == NULL)
1657 return (-1);
1658 if (MD_MNSET_DESC(sd))
1659 new_devidp = NULL;
1660 }
1661
1662 /* check out new (sets up start_blk, has_label, number_blks) */
1663 if (validate_new_raid(sp, raidnp, newnp, ¶ms, rebind,
1664 ep) != 0) {
1665 Free(new_devidp);
1666 return (-1);
1667 }
1668
1669 /*
1670 * Copy back the saved devid.
1671 */
1672 Free(newnp->drivenamep->devid);
1673 if (new_devidp) {
1674 newnp->drivenamep->devid = Strdup(new_devidp);
1675 Free(new_devidp);
1676 }
1677
1678 /* store name in namespace, allocate new key */
1679 if (add_key_name(sp, newnp, NULL, ep) != 0)
1680 return (-1);
1681
1682 if (rebind && !metaislocalset(sp)) {
1683 /*
1684 * We are 'rebind'ing a disk that is in a diskset so as well
1685 * as updating the diskset's namespace the local set needs
1686 * to be updated because it also contains a reference to the
1687 * disk in question.
1688 */
1689 ret = meta_fixdevid(sp, DEV_UPDATE|DEV_LOCAL_SET,
1690 newnp->cname, ep);
1691
1692 if (ret != METADEVADM_SUCCESS) {
1693 (void) del_key_name(sp, newnp, &xep);
1694 return (-1);
1695 }
1696 }
1697
1698 /* replace column */
1699 params.new_dev = new_dev;
1700 params.new_key = newnp->key;
1701 if (metaioctl(MD_IOCREPLACE, ¶ms, ¶ms.mde, NULL) != 0) {
1702 (void) del_key_name(sp, newnp, ep);
1703 return (mdstealerror(ep, ¶ms.mde));
1704 }
1705
1706 /* clear cache */
1707 meta_invalidate_name(oldnp);
1708 meta_invalidate_name(newnp);
1709 meta_invalidate_name(raidnp);
1710
1711 /* let em know */
1712 if (options & MDCMD_PRINT) {
1713 (void) printf(dgettext(TEXT_DOMAIN,
1714 "%s: device %s is replaced with %s\n"),
1715 raidnp->cname, oldnp->cname, newnp->cname);
1716 (void) fflush(stdout);
1717 }
1718
1719 /* return success */
1720 return (0);
1721 }
1722
1723 /*
1724 * enable raid column
1725 */
1726 int
meta_raid_enable(mdsetname_t * sp,mdname_t * raidnp,mdname_t * colnp,mdcmdopts_t options,md_error_t * ep)1727 meta_raid_enable(
1728 mdsetname_t *sp,
1729 mdname_t *raidnp,
1730 mdname_t *colnp,
1731 mdcmdopts_t options,
1732 md_error_t *ep
1733 )
1734 {
1735 int force = ((options & MDCMD_FORCE) ? 1 : 0);
1736 replace_params_t params;
1737 md_dev64_t fs_dev, del_dev;
1738 int err = 0;
1739 char *devnm;
1740 int ret;
1741 uint_t tstate;
1742
1743 /* should have same set */
1744 assert(sp != NULL);
1745 assert(sp->setno == MD_MIN2SET(meta_getminor(raidnp->dev)));
1746
1747 /* check name */
1748 if (metachkmeta(raidnp, ep) != 0)
1749 return (-1);
1750
1751 /* get the file_system dev binding */
1752 if (meta_getdev(sp, colnp, ep) != 0)
1753 return (-1);
1754 fs_dev = colnp->dev;
1755
1756 /* get the raid unit (fill in colnp->dev with metadb version) */
1757 meta_invalidate_name(raidnp);
1758 if (meta_get_raid(sp, raidnp, ep) == NULL)
1759 return (-1);
1760
1761 /* enabling a component can't work if the raid inaccessible */
1762 if (meta_get_tstate(raidnp->dev, &tstate, ep) != 0) {
1763 return (-1);
1764 }
1765 if (tstate & MD_INACCESSIBLE) {
1766 return (mdmderror(ep, MDE_IN_UNAVAIL_STATE,
1767 meta_getminor(raidnp->dev), raidnp->cname));
1768 }
1769
1770 /* the metadb device binding is now established */
1771 if (colnp->dev == NODEV64)
1772 return (mdsyserror(ep, ENODEV, colnp->cname));
1773
1774 /*
1775 * check for the case where the dev_t has changed between the
1776 * filesystem and the metadb. This is called a rebind, and
1777 * is handled by meta_raid_replace.
1778 */
1779 if (fs_dev != colnp->dev) {
1780 /*
1781 * Save the devt of mddb version
1782 */
1783 del_dev = colnp->dev;
1784
1785 /* establish file system binding with invalid start/end */
1786 colnp->dev = fs_dev;
1787 colnp->start_blk = -1;
1788 colnp->end_blk = -1;
1789 err = meta_raid_replace(sp, raidnp, colnp, colnp, options, ep);
1790
1791 /*
1792 * Don't do it if meta_raid_replace returns an error
1793 */
1794 if (!err && (devnm = meta_getnmentbydev(sp->setno, MD_SIDEWILD,
1795 del_dev, NULL, NULL, &colnp->key, ep)) != NULL) {
1796 (void) del_key_name(sp, colnp, ep);
1797 Free(devnm);
1798 }
1799 return (err);
1800 }
1801
1802 /* setup raid info */
1803 (void) memset(¶ms, 0, sizeof (params));
1804 params.mnum = meta_getminor(raidnp->dev);
1805 MD_SETDRIVERNAME(¶ms, MD_RAID, sp->setno);
1806 params.old_dev = params.new_dev = colnp->dev;
1807 if (force)
1808 params.cmd = FORCE_ENABLE_COMP;
1809 else
1810 params.cmd = ENABLE_COMP;
1811
1812 /* check it out */
1813 if (validate_new_raid(sp, raidnp, colnp, ¶ms, 1, ep) != 0)
1814 return (-1);
1815
1816 /* enable column */
1817 if (metaioctl(MD_IOCREPLACE, ¶ms, ¶ms.mde, NULL) != 0)
1818 return (mdstealerror(ep, ¶ms.mde));
1819
1820 /*
1821 * are we dealing with a non-local set? If so need to update the
1822 * local namespace so that the disk record has the correct devid.
1823 */
1824 if (!metaislocalset(sp)) {
1825 ret = meta_fixdevid(sp, DEV_UPDATE|DEV_LOCAL_SET, colnp->cname,
1826 ep);
1827
1828 if (ret != METADEVADM_SUCCESS) {
1829 /*
1830 * Failed to update the local set. Nothing to do here
1831 * apart from report the error. The namespace is
1832 * most likely broken and some form of remedial
1833 * recovery is going to be required.
1834 */
1835 mde_perror(ep, "");
1836 mdclrerror(ep);
1837 }
1838 }
1839
1840 /* clear cache */
1841 meta_invalidate_name(colnp);
1842 meta_invalidate_name(raidnp);
1843
1844 /* let em know */
1845 if (options & MDCMD_PRINT) {
1846 (void) printf(dgettext(TEXT_DOMAIN,
1847 "%s: device %s is enabled\n"),
1848 raidnp->cname, colnp->cname);
1849 (void) fflush(stdout);
1850 }
1851
1852 /* return success */
1853 return (0);
1854 }
1855
1856 /*
1857 * check for dups in the raid itself
1858 */
1859 static int
check_twice(md_raid_t * raidp,uint_t col,md_error_t * ep)1860 check_twice(
1861 md_raid_t *raidp,
1862 uint_t col,
1863 md_error_t *ep
1864 )
1865 {
1866 mdname_t *raidnp = raidp->common.namep;
1867 mdname_t *thisnp;
1868 uint_t c;
1869
1870 thisnp = raidp->cols.cols_val[col].colnamep;
1871 for (c = 0; (c < col); ++c) {
1872 md_raidcol_t *mdcp = &raidp->cols.cols_val[c];
1873 mdname_t *colnp = mdcp->colnamep;
1874
1875 if (meta_check_overlap(raidnp->cname, thisnp, 0, -1,
1876 colnp, 0, -1, ep) != 0) {
1877 return (-1);
1878 }
1879 }
1880 return (0);
1881 }
1882
1883 /*
1884 * default raid interlace
1885 */
1886 diskaddr_t
meta_default_raid_interlace(void)1887 meta_default_raid_interlace(void)
1888 {
1889 diskaddr_t interlace;
1890
1891 /* default to 512k, round up if necessary */
1892 interlace = btodb(512 * 1024);
1893 if (interlace < lbtodb(MININTERLACE))
1894 interlace = roundup(MININTERLACE, interlace);
1895 return (interlace);
1896 }
1897
1898 /*
1899 * convert interlaces
1900 */
1901 int
meta_raid_check_interlace(diskaddr_t interlace,char * uname,md_error_t * ep)1902 meta_raid_check_interlace(
1903 diskaddr_t interlace,
1904 char *uname,
1905 md_error_t *ep
1906 )
1907 {
1908 if ((interlace < btodb(RAID_MIN_INTERLACE)) ||
1909 (interlace > btodb(MAXINTERLACE))) {
1910 return (mderror(ep, MDE_BAD_INTERLACE, uname));
1911 }
1912 return (0);
1913 }
1914
1915 /*
1916 * check raid
1917 */
1918 int
meta_check_raid(mdsetname_t * sp,md_raid_t * raidp,mdcmdopts_t options,md_error_t * ep)1919 meta_check_raid(
1920 mdsetname_t *sp,
1921 md_raid_t *raidp,
1922 mdcmdopts_t options,
1923 md_error_t *ep
1924 )
1925 {
1926 mdname_t *raidnp = raidp->common.namep;
1927 int doit = ((options & MDCMD_DOIT) ? 1 : 0);
1928 int updateit = ((options & MDCMD_UPDATE) ? 1 : 0);
1929 uint_t ncol;
1930 uint_t col;
1931 minor_t mnum = meta_getminor(raidnp->dev);
1932
1933 /* check number */
1934 if (((ncol = raidp->cols.cols_len) < MD_RAID_MIN) ||
1935 (raidp->orig_ncol > ncol)) {
1936 return (mdmderror(ep, MDE_BAD_RAID, mnum, raidnp->cname));
1937 }
1938
1939 /* compute default interlace */
1940 if (raidp->interlace == 0) {
1941 raidp->interlace = meta_default_raid_interlace();
1942 }
1943
1944 /* check state */
1945 switch (raidp->state) {
1946 case RUS_INIT:
1947 case RUS_OKAY:
1948 break;
1949
1950 default:
1951 return (mdmderror(ep, MDE_BAD_RAID, mnum, raidnp->cname));
1952 }
1953
1954 /* check interlace */
1955 if (meta_raid_check_interlace(raidp->interlace, raidnp->cname, ep) != 0)
1956 return (-1);
1957
1958 /* check hotspare pool name */
1959 if (doit) {
1960 if ((raidp->hspnamep != NULL) &&
1961 (metachkhsp(sp, raidp->hspnamep, ep) != 0)) {
1962 return (-1);
1963 }
1964 }
1965
1966 /* check columns */
1967 for (col = 0; (col < ncol); ++col) {
1968 md_raidcol_t *mdcp = &raidp->cols.cols_val[col];
1969 mdname_t *colnp = mdcp->colnamep;
1970 diskaddr_t start_blk, size;
1971
1972 /* setup column */
1973 if (raidp->state == RUS_INIT)
1974 mdcp->state = RCS_INIT;
1975 else
1976 mdcp->state = RCS_OKAY;
1977
1978 /* check column */
1979 if (!updateit) {
1980 if (meta_check_column(sp, colnp, ep) != 0)
1981 return (-1);
1982 if (((start_blk = metagetstart(sp, colnp, ep)) ==
1983 MD_DISKADDR_ERROR) || ((size = metagetsize(colnp,
1984 ep)) == MD_DISKADDR_ERROR)) {
1985 return (-1);
1986 }
1987 if (start_blk >= size)
1988 return (mdsyserror(ep, ENOSPC, colnp->cname));
1989 size -= start_blk;
1990 size = rounddown(size, raidp->interlace);
1991 if (size == 0)
1992 return (mdsyserror(ep, ENOSPC, colnp->cname));
1993 }
1994
1995 /* check this raid too */
1996 if (check_twice(raidp, col, ep) != 0)
1997 return (-1);
1998 }
1999
2000 /* return success */
2001 return (0);
2002 }
2003
2004 /*
2005 * setup raid geometry
2006 */
2007 static int
raid_geom(md_raid_t * raidp,mr_unit_t * mr,md_error_t * ep)2008 raid_geom(
2009 md_raid_t *raidp,
2010 mr_unit_t *mr,
2011 md_error_t *ep
2012 )
2013 {
2014 uint_t write_reinstruct = 0;
2015 uint_t read_reinstruct = 0;
2016 uint_t round_cyl = 1;
2017 uint_t col;
2018 mdgeom_t *geomp;
2019
2020 /* get worst reinstructs */
2021 for (col = 0; (col < raidp->cols.cols_len); ++col) {
2022 md_raidcol_t *mdcp = &raidp->cols.cols_val[col];
2023 mdname_t *colnp = mdcp->colnamep;
2024
2025 if ((geomp = metagetgeom(colnp, ep)) == NULL)
2026 return (-1);
2027 if (geomp->write_reinstruct > write_reinstruct)
2028 write_reinstruct = geomp->write_reinstruct;
2029 if (geomp->read_reinstruct > read_reinstruct)
2030 read_reinstruct = geomp->read_reinstruct;
2031 }
2032
2033 /* setup geometry from first column */
2034 assert(raidp->cols.cols_len > 0);
2035 if ((geomp = metagetgeom(raidp->cols.cols_val[0].colnamep,
2036 ep)) == NULL) {
2037 return (-1);
2038 }
2039 if (meta_setup_geom((md_unit_t *)mr, raidp->common.namep, geomp,
2040 write_reinstruct, read_reinstruct, round_cyl, ep) != 0)
2041 return (-1);
2042
2043 /* return success */
2044 return (0);
2045 }
2046
2047 int
meta_raid_state_cnt(mr_unit_t * mr,rcs_state_t state)2048 meta_raid_state_cnt(mr_unit_t *mr, rcs_state_t state)
2049 {
2050 int statecnt = 0;
2051 int col;
2052
2053 for (col = 0; col < mr->un_totalcolumncnt; col++)
2054 if (mr->un_column[col].un_devstate & state)
2055 statecnt++;
2056 return (statecnt);
2057 }
2058 /*
2059 * validate that a raid device being created with the -k flag is a real
2060 * raid device
2061 */
2062 int
meta_raid_valid(md_raid_t * raidp,mr_unit_t * mr)2063 meta_raid_valid(md_raid_t *raidp, mr_unit_t *mr)
2064 {
2065 long long buf[DEV_BSIZE / sizeof (long long)];
2066 raid_pwhdr_t pwhdr;
2067 raid_pwhdr_t *rpw = &pwhdr;
2068 minor_t mnum;
2069 int col;
2070 int fd;
2071
2072 for (col = 0; col < mr->un_totalcolumncnt; col++) {
2073 md_raidcol_t *cp = &raidp->cols.cols_val[col];
2074 mdname_t *colnp = cp->colnamep;
2075
2076 if ((fd = open(colnp->rname, O_RDONLY)) < 0)
2077 goto error_exit;
2078
2079 if (lseek64(fd,
2080 (mr->un_column[col].un_pwstart * DEV_BSIZE), SEEK_SET) < 0)
2081 goto error_exit;
2082
2083 if (read(fd, buf, DEV_BSIZE) < 0)
2084 goto error_exit;
2085
2086 /*
2087 * If our raid device is a 64 bit device, we can accept the
2088 * pw header we just read in.
2089 * Otherwise it's of type raid_pwhdr32_od_t and has to
2090 * be converted.
2091 */
2092 if (mr->c.un_revision & MD_64BIT_META_DEV) {
2093 rpw = (raid_pwhdr_t *)buf;
2094 } else {
2095 RAID_CONVERT_RPW((raid_pwhdr32_od_t *)buf, rpw);
2096 }
2097
2098 if (rpw->rpw_column != col)
2099 goto error_exit;
2100
2101 if (col == 0)
2102 mnum = rpw->rpw_unit;
2103
2104 if (rpw->rpw_unit != mnum)
2105 goto error_exit;
2106
2107 if (rpw->rpw_magic_ext == RAID_PWMAGIC) {
2108 /* 4.1 prewrite header */
2109 if ((rpw->rpw_origcolumncnt != mr->un_origcolumncnt) ||
2110 (rpw->rpw_totalcolumncnt !=
2111 mr->un_totalcolumncnt) ||
2112 (rpw->rpw_segsize != mr->un_segsize) ||
2113 (rpw->rpw_segsincolumn != mr->un_segsincolumn) ||
2114 (rpw->rpw_pwcnt != mr->un_pwcnt) ||
2115 (rpw->rpw_pwstart !=
2116 mr->un_column[col].un_pwstart) ||
2117 (rpw->rpw_devstart !=
2118 mr->un_column[col].un_devstart) ||
2119 (rpw->rpw_pwsize != mr->un_pwsize))
2120 goto error_exit;
2121 }
2122 /*
2123 * this is an old prewrite header (4.0) the unit structure
2124 * will have to be trusted.
2125 */
2126 (void) close(fd);
2127 }
2128
2129 return (0);
2130
2131 error_exit:
2132 (void) close(fd);
2133 return (-1);
2134 }
2135
2136 /*
2137 * create raid
2138 */
2139 int
meta_create_raid(mdsetname_t * sp,md_raid_t * raidp,mdcmdopts_t options,md_error_t * ep)2140 meta_create_raid(
2141 mdsetname_t *sp,
2142 md_raid_t *raidp,
2143 mdcmdopts_t options,
2144 md_error_t *ep
2145 )
2146 {
2147 mdname_t *raidnp = raidp->common.namep;
2148 uint_t ncol = raidp->cols.cols_len;
2149 uint_t orig_ncol = raidp->orig_ncol;
2150 size_t rdsize;
2151 mr_unit_t *mr;
2152 uint_t col;
2153 diskaddr_t disk_size = 0;
2154 uint_t disk_maxio = 0;
2155 uint_t pwes;
2156 diskaddr_t non_pw_blks, column_size;
2157 mdnamelist_t *keynlp = NULL;
2158 md_set_params_t set_params;
2159 int rval = -1;
2160 md_timeval32_t creation_time;
2161 int create_flag = MD_CRO_32BIT;
2162
2163 /* validate raid */
2164 if (meta_check_raid(sp, raidp, options, ep) != 0)
2165 return (-1);
2166
2167 /* allocate raid unit */
2168 rdsize = sizeof (*mr) - sizeof (mr->un_column[0]);
2169 rdsize += ncol * sizeof (mr->un_column[0]);
2170 mr = Zalloc(rdsize);
2171
2172 if (meta_gettimeofday(&creation_time) == -1)
2173 return (mdsyserror(ep, errno, NULL));
2174 /*
2175 * initialize the top level mr_unit_t structure
2176 * setup the unit state to indicate whether to retain
2177 * any data currently on the metadevice or to clear it
2178 */
2179 mr->c.un_type = MD_METARAID;
2180 MD_SID(mr) = meta_getminor(raidnp->dev);
2181 mr->c.un_size = rdsize;
2182 mr->un_magic = RAID_UNMAGIC;
2183 mr->un_state = raidp->state;
2184 mr->un_timestamp = creation_time;
2185 mr->un_origcolumncnt = orig_ncol;
2186 mr->un_segsize = (uint_t)raidp->interlace;
2187 if (raidp->hspnamep != NULL) {
2188 mr->un_hsp_id = raidp->hspnamep->hsp;
2189 } else {
2190 mr->un_hsp_id = MD_HSP_NONE;
2191 }
2192 /*
2193 * setup original columns, saving start_block and
2194 * finding smallest size and maxio
2195 */
2196 for (col = 0; (col < orig_ncol); ++col) {
2197 md_raidcol_t *cp = &raidp->cols.cols_val[col];
2198 mdname_t *colnp = cp->colnamep;
2199 mr_column_t *mdc = &mr->un_column[col];
2200 diskaddr_t size;
2201 uint_t maxio;
2202 mdcinfo_t *cinfop;
2203
2204 /* setup state */
2205 mdc->un_devstate = cp->state;
2206
2207 /* setup creation time */
2208 mdc->un_devtimestamp = creation_time;
2209
2210 /* get start, size, and maxio */
2211 if ((mdc->un_orig_devstart = metagetstart(sp, colnp, ep)) ==
2212 MD_DISKADDR_ERROR)
2213 goto out;
2214 if ((size = metagetsize(colnp, ep)) == MD_DISKADDR_ERROR)
2215 goto out;
2216 size -= mdc->un_orig_devstart;
2217 if ((cinfop = metagetcinfo(colnp, ep)) == NULL)
2218 goto out;
2219 maxio = cinfop->maxtransfer;
2220
2221 if (options & MDCMD_DOIT) {
2222 /* store name in namespace */
2223 if (add_key_name(sp, colnp, &keynlp, ep) != 0)
2224 goto out;
2225 }
2226
2227 /* setup column */
2228 mdc->un_orig_key = colnp->key;
2229 mdc->un_orig_dev = colnp->dev;
2230 mdc->un_dev = mdc->un_orig_dev;
2231 mdc->un_pwstart = mdc->un_orig_pwstart;
2232 mdc->un_devstart = mdc->un_orig_devstart;
2233 mdc->un_alt_dev = NODEV64;
2234 mdc->un_alt_pwstart = 0;
2235 mdc->un_alt_devstart = 0;
2236 mdc->un_hs_id = 0;
2237 if (mr->un_state == RUS_INIT)
2238 mdc->un_devstate = RCS_INIT;
2239 else
2240 mdc->un_devstate = RCS_OKAY;
2241
2242 /* adjust for smallest disk */
2243 if (disk_size == 0) {
2244 disk_size = size;
2245 } else if (size < disk_size) {
2246 disk_size = size;
2247 }
2248 if (disk_maxio == 0) {
2249 disk_maxio = maxio;
2250 } else if (maxio < disk_maxio) {
2251 disk_maxio = maxio;
2252 }
2253 }
2254 assert(col == mr->un_origcolumncnt);
2255
2256 /*
2257 * before processing any of the attached column(s)
2258 * set up the composition of the metadevice for column
2259 * sizes and pre-write information
2260 */
2261 mr->un_maxio = disk_maxio; /* smallest maxio */
2262 mr->un_iosize = min(mr->un_maxio, (mr->un_segsize + 1));
2263 pwes = mr->un_iosize;
2264 if (raidp->pw_count)
2265 mr->un_pwcnt = raidp->pw_count;
2266 else
2267 mr->un_pwcnt = PWCNT_MIN;
2268 if ((mr->un_pwcnt < PWCNT_MIN) || (mr->un_pwcnt > PWCNT_MAX)) {
2269 (void) mderror(ep, MDE_RAID_BAD_PW_CNT, raidnp->cname);
2270 goto out;
2271 }
2272 mr->un_pwsize = roundup((mr->un_pwcnt * pwes), 2);
2273
2274 /* now calculate the number of segments per column */
2275 non_pw_blks = disk_size - mr->un_pwsize; /* smallest disk */
2276 if ((mr->un_pwsize > disk_size) ||
2277 (non_pw_blks < (diskaddr_t)mr->un_segsize)) {
2278 (void) mdsyserror(ep, ENOSPC, raidnp->cname);
2279 goto out;
2280 }
2281 mr->un_segsincolumn = non_pw_blks / mr->un_segsize;
2282 column_size = mr->un_segsize * mr->un_segsincolumn;
2283
2284 /*
2285 * adjust the pw_cnt, pw_size, to fit into any fragmentation
2286 * left over after column_size has been computed
2287 */
2288 mr->un_pwsize = rounddown(((uint_t)(disk_size - column_size)), 2);
2289 mr->un_pwcnt = mr->un_pwsize / pwes;
2290 assert(mr->un_pwcnt >= PWCNT_MIN);
2291 mr->un_pwsize = roundup((mr->un_pwcnt * pwes), 2);
2292 assert((mr->un_pwsize + column_size) <= disk_size);
2293
2294 /*
2295 * calculate the actual block count available based on the
2296 * segment size and the number of segments per column ...
2297 * ... and adjust for the number of parity segments
2298 */
2299 mr->c.un_actual_tb = column_size * (mr->un_origcolumncnt - 1);
2300
2301 if (raid_geom(raidp, mr, ep) != 0)
2302 goto out;
2303
2304 create_flag = meta_check_devicesize(mr->c.un_total_blocks);
2305
2306 /*
2307 * now calculate the pre-write offset and update the column
2308 * structures to include the address of the individual pre-write
2309 * areas
2310 */
2311 for (col = 0; (col < orig_ncol); ++col) {
2312 md_raidcol_t *cp = &raidp->cols.cols_val[col];
2313 mdname_t *colnp = cp->colnamep;
2314 mr_column_t *mdc = &mr->un_column[col];
2315 diskaddr_t size;
2316
2317 /* get size */
2318 if ((size = metagetsize(colnp, ep)) == MD_DISKADDR_ERROR)
2319 goto out;
2320
2321 /* adjust start and size by prewrite */
2322 mdc->un_orig_pwstart = mdc->un_orig_devstart;
2323 mdc->un_orig_devstart += mr->un_pwsize;
2324 mdc->un_pwstart = mdc->un_orig_pwstart;
2325 mdc->un_devstart = mdc->un_orig_devstart;
2326
2327 assert(size >= mdc->un_orig_devstart);
2328 size -= mdc->un_orig_devstart;
2329
2330 /* make sure we still have something left */
2331 assert(size >= column_size);
2332 }
2333
2334 /* do concat cols */
2335 mr->un_totalcolumncnt = mr->un_origcolumncnt;
2336 assert(col == mr->un_origcolumncnt);
2337 for (col = orig_ncol; (col < ncol); ++col) {
2338 md_raidcol_t *cp = &raidp->cols.cols_val[col];
2339 mdname_t *colnp = cp->colnamep;
2340 mr_column_t *mdc = &mr->un_column[col];
2341
2342 /* attach column */
2343 if (attach_raid_col(sp, raidnp, mr, mdc, colnp,
2344 cp->state, &keynlp, options, ep) != 0) {
2345 goto out;
2346 }
2347 }
2348 assert(mr->un_totalcolumncnt == ncol);
2349
2350 /* fill in the size of the raid */
2351 if (options & MDCMD_UPDATE) {
2352 raidp->common.size = mr->c.un_total_blocks;
2353 raidp->column_size = mr->un_segsize * mr->un_segsincolumn;
2354 }
2355
2356 /* if we're not doing anything, return success */
2357 if (! (options & MDCMD_DOIT)) {
2358 rval = 0; /* success */
2359 goto out;
2360 }
2361
2362 if ((mr->un_state & RUS_OKAY) &&
2363 (meta_raid_valid(raidp, mr) != 0)) {
2364 (void) mderror(ep, MDE_RAID_INVALID, raidnp->cname);
2365 goto out;
2366 }
2367
2368 /* create raid */
2369 (void) memset(&set_params, 0, sizeof (set_params));
2370 /* did the user tell us to generate a large device? */
2371 if (create_flag == MD_CRO_64BIT) {
2372 mr->c.un_revision |= MD_64BIT_META_DEV;
2373 set_params.options = MD_CRO_64BIT;
2374 } else {
2375 mr->c.un_revision &= ~MD_64BIT_META_DEV;
2376 set_params.options = MD_CRO_32BIT;
2377 }
2378 set_params.mnum = MD_SID(mr);
2379 set_params.size = mr->c.un_size;
2380 set_params.mdp = (uintptr_t)mr;
2381 MD_SETDRIVERNAME(&set_params, MD_RAID, MD_MIN2SET(set_params.mnum));
2382 if (metaioctl(MD_IOCSET, &set_params, &set_params.mde,
2383 raidnp->cname) != 0) {
2384 (void) mdstealerror(ep, &set_params.mde);
2385 goto out;
2386 }
2387 rval = 0; /* success */
2388
2389 /* cleanup, return success */
2390 out:
2391 Free(mr);
2392 if (rval != 0) {
2393 (void) del_key_names(sp, keynlp, NULL);
2394 }
2395 metafreenamelist(keynlp);
2396 if ((rval == 0) && (options & MDCMD_DOIT)) {
2397 if (invalidate_columns(sp, raidnp, ep) != 0)
2398 rval = -1;
2399 meta_invalidate_name(raidnp);
2400 }
2401 return (rval);
2402 }
2403
2404 /*
2405 * initialize raid
2406 * NOTE: this functions is metainit(1m)'s command line parser!
2407 */
2408 int
meta_init_raid(mdsetname_t ** spp,int argc,char * argv[],mdcmdopts_t options,md_error_t * ep)2409 meta_init_raid(
2410 mdsetname_t **spp,
2411 int argc,
2412 char *argv[],
2413 mdcmdopts_t options,
2414 md_error_t *ep
2415 )
2416 {
2417 char *uname = argv[0];
2418 mdname_t *raidnp = NULL;
2419 int old_optind;
2420 int c;
2421 md_raid_t *raidp = NULL;
2422 uint_t ncol, col;
2423 int rval = -1;
2424 md_set_desc *sd;
2425
2426 /* get raid name */
2427 assert(argc > 0);
2428 if (argc < 1)
2429 goto syntax;
2430 if ((raidnp = metaname(spp, uname, META_DEVICE, ep)) == NULL)
2431 goto out;
2432 assert(*spp != NULL);
2433
2434 /*
2435 * Raid metadevice not allowed on multi-node diskset.
2436 */
2437 if (! metaislocalset(*spp)) {
2438 if ((sd = metaget_setdesc(*spp, ep)) == NULL)
2439 goto out;
2440 if (MD_MNSET_DESC(sd)) {
2441 rval = meta_cook_syntax(ep, MDE_MNSET_NORAID, uname,
2442 argc, argv);
2443 goto out;
2444 }
2445 }
2446
2447 uname = raidnp->cname;
2448 if (metachkmeta(raidnp, ep) != 0)
2449 goto out;
2450
2451 if (!(options & MDCMD_NOLOCK)) {
2452 /* grab set lock */
2453 if (meta_lock(*spp, TRUE, ep) != 0)
2454 goto out;
2455
2456 if (meta_check_ownership(*spp, ep) != 0)
2457 goto out;
2458 }
2459
2460 /* see if it exists already */
2461 if (metagetmiscname(raidnp, ep) != NULL) {
2462 (void) mdmderror(ep, MDE_UNIT_ALREADY_SETUP,
2463 meta_getminor(raidnp->dev), uname);
2464 goto out;
2465 } else if (! mdismderror(ep, MDE_UNIT_NOT_SETUP)) {
2466 goto out;
2467 } else {
2468 mdclrerror(ep);
2469 }
2470 --argc, ++argv;
2471
2472 /* grab -r */
2473 if ((argc < 1) || (strcmp(argv[0], "-r") != 0))
2474 goto syntax;
2475 --argc, ++argv;
2476
2477 /* parse general options */
2478 optind = 0;
2479 opterr = 0;
2480 if (getopt(argc, argv, "") != -1)
2481 goto options;
2482
2483 /* allocate raid */
2484 raidp = Zalloc(sizeof (*raidp));
2485
2486 /* setup common */
2487 raidp->common.namep = raidnp;
2488 raidp->common.type = MD_METARAID;
2489 raidp->state = RUS_INIT;
2490
2491 /* allocate and parse cols */
2492 for (ncol = 0; ((ncol < argc) && (argv[ncol][0] != '-')); ++ncol)
2493 ;
2494 raidp->cols.cols_len = ncol;
2495 if (ncol != 0) {
2496 raidp->cols.cols_val =
2497 Zalloc(ncol * sizeof (*raidp->cols.cols_val));
2498 }
2499 for (col = 0; ((argc > 0) && (col < ncol)); ++col) {
2500 md_raidcol_t *mdc = &raidp->cols.cols_val[col];
2501 mdname_t *colnp;
2502
2503 /* parse column name */
2504 if ((colnp = metaname(spp, argv[0], UNKNOWN, ep)) == NULL)
2505 goto out;
2506 /* check for soft partitions */
2507 if (meta_sp_issp(*spp, colnp, ep) != 0) {
2508 /* check disks */
2509 if (metachkcomp(colnp, ep) != 0)
2510 goto out;
2511 }
2512 mdc->colnamep = colnp;
2513 --argc, ++argv;
2514 }
2515
2516 /* parse raid options */
2517 old_optind = optind = 0;
2518 opterr = 0;
2519 while ((c = getopt(argc, argv, "h:i:ko:w:")) != -1) {
2520 switch (c) {
2521 case 'h':
2522 if ((raidp->hspnamep = metahspname(spp, optarg,
2523 ep)) == NULL) {
2524 goto out;
2525 }
2526
2527 /*
2528 * Get out if the specified hotspare pool really
2529 * doesn't exist.
2530 */
2531 if (raidp->hspnamep->hsp == MD_HSP_NONE) {
2532 (void) mdhsperror(ep, MDE_INVAL_HSP,
2533 raidp->hspnamep->hsp, optarg);
2534 goto out;
2535 }
2536 break;
2537
2538 case 'i':
2539 if (parse_interlace(uname, optarg, &raidp->interlace,
2540 ep) != 0) {
2541 goto out;
2542 }
2543 if (meta_raid_check_interlace(raidp->interlace,
2544 uname, ep))
2545 goto out;
2546 break;
2547
2548 case 'k':
2549 raidp->state = RUS_OKAY;
2550 break;
2551
2552 case 'o':
2553 if ((sscanf(optarg, "%u", &raidp->orig_ncol) != 1) ||
2554 ((int)raidp->orig_ncol < 0)) {
2555 goto syntax;
2556 }
2557 if ((raidp->orig_ncol < MD_RAID_MIN) ||
2558 (raidp->orig_ncol > ncol)) {
2559 rval = mderror(ep, MDE_BAD_ORIG_NCOL, uname);
2560 goto out;
2561 }
2562 break;
2563 case 'w':
2564 if ((sscanf(optarg, "%d", &raidp->pw_count) != 1) ||
2565 ((int)raidp->pw_count < 0))
2566 goto syntax;
2567 if (((int)raidp->pw_count < PWCNT_MIN) ||
2568 ((int)raidp->pw_count > PWCNT_MAX)) {
2569 rval = mderror(ep, MDE_RAID_BAD_PW_CNT, uname);
2570 goto out;
2571 }
2572 break;
2573 default:
2574 argc += old_optind;
2575 argv -= old_optind;
2576 goto options;
2577 }
2578 old_optind = optind;
2579 }
2580 argc -= optind;
2581 argv += optind;
2582
2583 /* we should be at the end */
2584 if (argc != 0)
2585 goto syntax;
2586
2587 /* default to all original columns */
2588 if (raidp->orig_ncol == 0)
2589 raidp->orig_ncol = ncol;
2590
2591 /* create raid */
2592 if (meta_create_raid(*spp, raidp, options, ep) != 0)
2593 goto out;
2594 rval = 0; /* success */
2595
2596 /* let em know */
2597 if (options & MDCMD_PRINT) {
2598 (void) printf(dgettext(TEXT_DOMAIN, "%s: RAID is setup\n"),
2599 uname);
2600 (void) fflush(stdout);
2601 }
2602 goto out;
2603
2604 /* syntax error */
2605 syntax:
2606 rval = meta_cook_syntax(ep, MDE_SYNTAX, uname, argc, argv);
2607 goto out;
2608
2609 /* options error */
2610 options:
2611 rval = meta_cook_syntax(ep, MDE_OPTION, uname, argc, argv);
2612 goto out;
2613
2614 /* cleanup, return error */
2615 out:
2616 if (raidp != NULL)
2617 meta_free_raid(raidp);
2618 return (rval);
2619 }
2620
2621 /*
2622 * reset RAIDs
2623 */
2624 int
meta_raid_reset(mdsetname_t * sp,mdname_t * raidnp,mdcmdopts_t options,md_error_t * ep)2625 meta_raid_reset(
2626 mdsetname_t *sp,
2627 mdname_t *raidnp,
2628 mdcmdopts_t options,
2629 md_error_t *ep
2630 )
2631 {
2632 md_raid_t *raidp;
2633 int rval = -1;
2634 int col;
2635
2636 /* should have same set */
2637 assert(sp != NULL);
2638 assert((raidnp == NULL) ||
2639 (sp->setno == MD_MIN2SET(meta_getminor(raidnp->dev))));
2640
2641 /* reset all raids */
2642 if (raidnp == NULL) {
2643 mdnamelist_t *raidnlp = NULL;
2644 mdnamelist_t *p;
2645
2646 /* for each raid */
2647 rval = 0;
2648 if (meta_get_raid_names(sp, &raidnlp, 0, ep) < 0)
2649 return (-1);
2650 for (p = raidnlp; (p != NULL); p = p->next) {
2651 /* reset RAID */
2652 raidnp = p->namep;
2653 if (meta_raid_reset(sp, raidnp, options, ep) != 0) {
2654 rval = -1;
2655 break;
2656 }
2657 }
2658
2659 /* cleanup, return success */
2660 metafreenamelist(raidnlp);
2661 return (rval);
2662 }
2663
2664 /* check name */
2665 if (metachkmeta(raidnp, ep) != 0)
2666 return (-1);
2667
2668 /* get unit structure */
2669 if ((raidp = meta_get_raid(sp, raidnp, ep)) == NULL)
2670 return (-1);
2671
2672 /* make sure nobody owns us */
2673 if (MD_HAS_PARENT(raidp->common.parent)) {
2674 return (mdmderror(ep, MDE_IN_USE, meta_getminor(raidnp->dev),
2675 raidnp->cname));
2676 }
2677
2678 /* clear subdevices cache */
2679 if (invalidate_columns(sp, raidnp, ep) != 0)
2680 return (-1);
2681
2682 /* clear metadevice */
2683 if (meta_reset(sp, raidnp, options, ep) != 0)
2684 goto out;
2685 rval = 0; /* success */
2686
2687 /* let em know */
2688 if (options & MDCMD_PRINT) {
2689 (void) printf(dgettext(TEXT_DOMAIN, "%s: RAID is cleared\n"),
2690 raidnp->cname);
2691 (void) fflush(stdout);
2692 }
2693
2694 /* clear subdevices */
2695 if (! (options & MDCMD_RECURSE))
2696 goto out;
2697
2698 for (col = 0; (col < raidp->cols.cols_len); ++col) {
2699 md_raidcol_t *cp = &raidp->cols.cols_val[col];
2700 mdname_t *colnp = cp->colnamep;
2701
2702 /* only recurse on metadevices */
2703 if (! metaismeta(colnp))
2704 continue;
2705
2706 if (meta_reset_by_name(sp, colnp, options, ep) != 0)
2707 rval = -1;
2708 }
2709
2710 /* cleanup, return success */
2711 out:
2712 meta_invalidate_name(raidnp);
2713 return (rval);
2714 }
2715
2716 /*
2717 * reports TRUE if any RAID component is in error
2718 */
2719 int
meta_raid_anycomp_is_err(mdsetname_t * sp,mdnamelist_t * raid_names)2720 meta_raid_anycomp_is_err(mdsetname_t *sp, mdnamelist_t *raid_names)
2721 {
2722 mdnamelist_t *nlp;
2723 md_error_t status = mdnullerror;
2724 md_error_t *ep = &status;
2725 int any_errs = FALSE;
2726
2727 for (nlp = raid_names; nlp; nlp = nlp->next) {
2728 md_raid_t *raidp;
2729
2730 if ((raidp = meta_get_raid(sp, nlp->namep, ep)) == NULL) {
2731 any_errs |= TRUE;
2732 goto out;
2733 }
2734 if (raidp->state != RUS_OKAY && raidp->state != RUS_INIT) {
2735 any_errs |= TRUE;
2736 goto out;
2737 }
2738 }
2739 out:
2740 if (!mdisok(ep))
2741 mdclrerror(ep);
2742
2743 return (any_errs);
2744 }
2745 /*
2746 * regen parity on a raid
2747 */
2748 int
meta_raid_regen_byname(mdsetname_t * sp,mdname_t * raidnp,diskaddr_t size,md_error_t * ep)2749 meta_raid_regen_byname(mdsetname_t *sp, mdname_t *raidnp, diskaddr_t size,
2750 md_error_t *ep)
2751 {
2752 char *miscname;
2753 md_resync_ioctl_t ri;
2754
2755 /* should have a set */
2756 assert(sp != NULL);
2757 assert(sp->setno == MD_MIN2SET(meta_getminor(raidnp->dev)));
2758
2759 /* make sure we have a raid */
2760 if ((miscname = metagetmiscname(raidnp, ep)) == NULL)
2761 return (-1);
2762 if (strcmp(miscname, MD_RAID) != 0) {
2763 return (mdmderror(ep, MDE_NOT_RAID, meta_getminor(raidnp->dev),
2764 raidnp->cname));
2765 }
2766
2767 /* start resync */
2768 (void) memset(&ri, 0, sizeof (ri));
2769 MD_SETDRIVERNAME(&ri, MD_RAID, sp->setno);
2770 ri.ri_mnum = meta_getminor(raidnp->dev);
2771 ri.ri_copysize = size;
2772 if (metaioctl(MD_IOCSETREGEN, &ri, &ri.mde, raidnp->cname) != 0)
2773 return (mdstealerror(ep, &ri.mde));
2774
2775 /* return success */
2776 return (0);
2777 }
2778
2779 int
meta_raid_check_component(mdsetname_t * sp,mdname_t * np,md_dev64_t mydevs,md_error_t * ep)2780 meta_raid_check_component(
2781 mdsetname_t *sp,
2782 mdname_t *np,
2783 md_dev64_t mydevs,
2784 md_error_t *ep
2785 )
2786 {
2787 md_raid_t *raid;
2788 mdnm_params_t nm;
2789 md_getdevs_params_t mgd;
2790 side_t sideno;
2791 char *miscname;
2792 md_dev64_t *mydev = NULL;
2793 mdkey_t key;
2794 char *pname = NULL, *t;
2795 char *ctd_name = NULL;
2796 char *devname = NULL;
2797 int len;
2798 int i;
2799 int rval = -1;
2800
2801 (void) memset(&nm, '\0', sizeof (nm));
2802 if ((raid = meta_get_raid_common(sp, np, 0, ep)) == NULL)
2803 return (-1);
2804
2805 if ((miscname = metagetmiscname(np, ep)) == NULL)
2806 return (-1);
2807
2808 sideno = getmyside(sp, ep);
2809
2810 /* get count of underlying devices */
2811
2812 (void) memset(&mgd, '\0', sizeof (mgd));
2813 MD_SETDRIVERNAME(&mgd, miscname, sp->setno);
2814 mgd.mnum = meta_getminor(np->dev);
2815 mgd.cnt = 0;
2816 mgd.devs = NULL;
2817 if (metaioctl(MD_IOCGET_DEVS, &mgd, &mgd.mde, np->cname) != 0) {
2818 (void) mdstealerror(ep, &mgd.mde);
2819 rval = 0;
2820 goto out;
2821 } else if (mgd.cnt <= 0) {
2822 assert(mgd.cnt >= 0);
2823 rval = 0;
2824 goto out;
2825 }
2826
2827 /*
2828 * Now get the data from the unit structure.
2829 * The compnamep stuff contains the data from
2830 * the namespace and we need the un_dev
2831 * from the unit structure.
2832 */
2833 mydev = Zalloc(sizeof (*mydev) * mgd.cnt);
2834 mgd.devs = (uintptr_t)mydev;
2835 if (metaioctl(MD_IOCGET_DEVS, &mgd, &mgd.mde, np->cname) != 0) {
2836 (void) mdstealerror(ep, &mgd.mde);
2837 rval = 0;
2838 goto out;
2839 } else if (mgd.cnt <= 0) {
2840 assert(mgd.cnt >= 0);
2841 rval = 0;
2842 goto out;
2843 }
2844
2845 for (i = 0; i < raid->orig_ncol; i++) {
2846 md_raidcol_t *colp = &raid->cols.cols_val[i];
2847 mdname_t *compnp = colp->colnamep;
2848
2849 if (mydevs == mydev[i]) {
2850 /* Get the devname from the name space. */
2851 if ((devname = meta_getnmentbydev(sp->setno, sideno,
2852 compnp->dev, NULL, NULL, &key, ep)) == NULL) {
2853 goto out;
2854 }
2855
2856 if (compnp->dev != meta_getminor(mydev[i])) {
2857 /*
2858 * The minor numbers are different. Update
2859 * the namespace with the information from
2860 * the component.
2861 */
2862
2863 t = strrchr(devname, '/');
2864 t++;
2865 ctd_name = Strdup(t);
2866
2867 len = strlen(devname);
2868 t = strrchr(devname, '/');
2869 t++;
2870 pname = Zalloc((len - strlen(t)) + 1);
2871 (void) strncpy(pname, devname,
2872 (len - strlen(t)));
2873
2874 if (meta_update_namespace(sp->setno, sideno,
2875 ctd_name, mydev[i], key, pname,
2876 ep) != 0) {
2877 goto out;
2878 }
2879 }
2880 rval = 0;
2881 break;
2882 } /* End of if (mydevs == mydev[i]) */
2883 } /* end of for loop */
2884 out:
2885 if (pname != NULL)
2886 Free(pname);
2887 if (ctd_name != NULL)
2888 Free(ctd_name);
2889 if (devname != NULL)
2890 Free(devname);
2891 if (mydev != NULL)
2892 Free(mydev);
2893 return (rval);
2894 }
2895