xref: /titanic_41/usr/src/lib/lvm/libmeta/common/meta_raid.c (revision 2f172c55ef76964744bc62b4500ece87f3089b4d)
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
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
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 *
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 *
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
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
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
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
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
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 *
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
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 *
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 *
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
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
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
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
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
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
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
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
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
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
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
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
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(&params, 0, sizeof (params));
1624 	params.mnum = meta_getminor(raidnp->dev);
1625 	MD_SETDRIVERNAME(&params, 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, &params, 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, &params, &params.mde, NULL) != 0) {
1702 		(void) del_key_name(sp, newnp, ep);
1703 		return (mdstealerror(ep, &params.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
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(&params, 0, sizeof (params));
1804 	params.mnum = meta_getminor(raidnp->dev);
1805 	MD_SETDRIVERNAME(&params, 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, &params, 1, ep) != 0)
1814 		return (-1);
1815 
1816 	/* enable column */
1817 	if (metaioctl(MD_IOCREPLACE, &params, &params.mde, NULL) != 0)
1818 		return (mdstealerror(ep, &params.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
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
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
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
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
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
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
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
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
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
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
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
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
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