xref: /titanic_41/usr/src/lib/lvm/libmeta/common/meta_mirror.c (revision 32e0da9f9721fdfe44802ab869bc447dc4357bc6)
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 2007 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #pragma ident	"%Z%%M%	%I%	%E% SMI"
27 
28 /*
29  * Just in case we're not in a build environment, make sure that
30  * TEXT_DOMAIN gets set to something.
31  */
32 #if !defined(TEXT_DOMAIN)
33 #define	TEXT_DOMAIN "SYS_TEST"
34 #endif
35 
36 /*
37  * mirror operations
38  */
39 
40 #include <meta.h>
41 #include <sys/lvm/md_mirror.h>
42 #include <sys/lvm/md_convert.h>
43 
44 #include <ctype.h>
45 #include <stddef.h>
46 
47 /*
48  * FUNCTION:    meta_get_mirror_names()
49  * INPUT:       sp      - the set name to get mirrors from
50  *              options - options from the command line
51  * OUTPUT:      nlpp    - list of all mirror names
52  *              ep      - return error pointer
53  * RETURNS:     int     - -1 if error, 0 success
54  * PURPOSE:     returns a list of all mirrors in the metadb
55  *              for all devices in the specified set
56  */
57 int
meta_get_mirror_names(mdsetname_t * sp,mdnamelist_t ** nlpp,int options,md_error_t * ep)58 meta_get_mirror_names(
59 	mdsetname_t	*sp,
60 	mdnamelist_t	**nlpp,
61 	int		options,
62 	md_error_t	*ep
63 )
64 {
65 	return (meta_get_names(MD_MIRROR, sp, nlpp, options, ep));
66 }
67 
68 /*
69  * free mirror unit
70  */
71 void
meta_free_mirror(md_mirror_t * mirrorp)72 meta_free_mirror(
73 	md_mirror_t	*mirrorp
74 )
75 {
76 	Free(mirrorp);
77 }
78 
79 /*
80  * get mirror unit
81  */
82 static md_mirror_t *
meta_get_mirror_common(mdsetname_t * sp,mdname_t * mirnp,int fast,md_error_t * ep)83 meta_get_mirror_common(
84 	mdsetname_t	*sp,
85 	mdname_t	*mirnp,
86 	int		fast,
87 	md_error_t	*ep
88 )
89 {
90 	mddrivename_t	*dnp = mirnp->drivenamep;
91 	char		*miscname;
92 	mm_unit_t	*mm;
93 	md_mirror_t	*mirrorp;
94 	uint_t		smi, nsm;
95 	md_resync_ioctl_t ri;
96 
97 	/* must have set */
98 	assert(sp != NULL);
99 
100 	/* short circuit */
101 	if (dnp->unitp != NULL) {
102 		assert(dnp->unitp->type == MD_METAMIRROR);
103 		return ((md_mirror_t *)dnp->unitp);
104 	}
105 
106 	/* get miscname and unit */
107 	if ((miscname = metagetmiscname(mirnp, ep)) == NULL)
108 		return (NULL);
109 	if (strcmp(miscname, MD_MIRROR) != 0) {
110 		(void) mdmderror(ep, MDE_NOT_MM, meta_getminor(mirnp->dev),
111 		    mirnp->cname);
112 		return (NULL);
113 	}
114 	if ((mm = (mm_unit_t *)meta_get_mdunit(sp, mirnp, ep)) == NULL)
115 		return (NULL);
116 	assert(mm->c.un_type == MD_METAMIRROR);
117 
118 	/* allocate mirror */
119 	mirrorp = Zalloc(sizeof (*mirrorp));
120 
121 	/* get common info */
122 	mirrorp->common.namep = mirnp;
123 	mirrorp->common.type = mm->c.un_type;
124 	mirrorp->common.state = mm->c.un_status;
125 	mirrorp->common.capabilities = mm->c.un_capabilities;
126 	mirrorp->common.parent = mm->c.un_parent;
127 	mirrorp->common.size = mm->c.un_total_blocks;
128 	mirrorp->common.user_flags = mm->c.un_user_flags;
129 	mirrorp->common.revision = mm->c.un_revision;
130 
131 	/* get options */
132 	mirrorp->read_option = mm->un_read_option;
133 	mirrorp->write_option = mm->un_write_option;
134 	mirrorp->pass_num = mm->un_pass_num;
135 
136 	/* get submirrors */
137 	for (smi = 0, nsm = 0; (smi < NMIRROR); ++smi) {
138 		mm_submirror_t	*mmsp = &mm->un_sm[smi];
139 		md_submirror_t	*mdsp = &mirrorp->submirrors[smi];
140 
141 		/* get submirror state */
142 		mdsp->state = mmsp->sm_state;
143 		if (mdsp->state == SMS_UNUSED)
144 			continue;
145 		++nsm;
146 
147 		/* get submirror time of last state change */
148 		mdsp->timestamp = mmsp->sm_timestamp;
149 
150 		/* get submirror flags */
151 		mdsp->flags = mmsp->sm_flags;
152 
153 		/* get submirror name */
154 		mdsp->submirnamep = metakeyname(&sp, mmsp->sm_key, fast, ep);
155 		if (mdsp->submirnamep == NULL)
156 			goto out;
157 	}
158 	assert(nsm == mm->un_nsm);
159 
160 	/* get resync info */
161 	(void) memset(&ri, 0, sizeof (ri));
162 	ri.ri_mnum = meta_getminor(mirnp->dev);
163 	MD_SETDRIVERNAME(&ri, MD_MIRROR, sp->setno);
164 	if (metaioctl(MD_IOCGETSYNC, &ri, &ri.mde, mirnp->cname) != 0) {
165 		(void) mdstealerror(ep, &ri.mde);
166 		goto out;
167 	}
168 	mirrorp->percent_done = ri.ri_percent_done;
169 	mirrorp->percent_dirty = ri.ri_percent_dirty;
170 
171 	/* cleanup, return success */
172 	Free(mm);
173 	dnp->unitp = (md_common_t *)mirrorp;
174 	return (mirrorp);
175 
176 	/* cleanup, return error */
177 out:
178 	Free(mm);
179 	meta_free_mirror(mirrorp);
180 	return (NULL);
181 }
182 
183 /*
184  * get mirror unit
185  */
186 md_mirror_t *
meta_get_mirror(mdsetname_t * sp,mdname_t * mirnp,md_error_t * ep)187 meta_get_mirror(
188 	mdsetname_t	*sp,
189 	mdname_t	*mirnp,
190 	md_error_t	*ep
191 )
192 {
193 	return (meta_get_mirror_common(sp, mirnp, 0, ep));
194 }
195 
196 /*
197  * check mirror for dev
198  */
199 static int
in_mirror(mdsetname_t * sp,mdname_t * mirnp,mdname_t * np,diskaddr_t slblk,diskaddr_t nblks,md_error_t * ep)200 in_mirror(
201 	mdsetname_t	*sp,
202 	mdname_t	*mirnp,
203 	mdname_t	*np,
204 	diskaddr_t	slblk,
205 	diskaddr_t	nblks,
206 	md_error_t	*ep
207 )
208 {
209 	md_mirror_t	*mirrorp;
210 	uint_t		smi;
211 
212 	/* should be in the same set */
213 	assert(sp != NULL);
214 	assert(sp->setno == MD_MIN2SET(meta_getminor(mirnp->dev)));
215 
216 	/* get unit */
217 	if ((mirrorp = meta_get_mirror(sp, mirnp, ep)) == NULL)
218 		return (-1);
219 
220 	/* look in submirrors */
221 	for (smi = 0; (smi < NMIRROR); ++smi) {
222 		md_submirror_t	*mdsp = &mirrorp->submirrors[smi];
223 		mdname_t	*submirnp = mdsp->submirnamep;
224 
225 		/* skip unused submirrors */
226 		if (submirnp == NULL) {
227 			assert(mdsp->state == SMS_UNUSED);
228 			continue;
229 		}
230 
231 		/* check overlap */
232 		if (metaismeta(submirnp))
233 			continue;
234 		if (meta_check_overlap(mirnp->cname, np, slblk, nblks,
235 		    submirnp, 0, -1, ep) != 0)
236 			return (-1);
237 	}
238 
239 	/* return success */
240 	return (0);
241 }
242 
243 /*
244  * check to see if we're in a mirror
245  */
246 int
meta_check_inmirror(mdsetname_t * sp,mdname_t * np,diskaddr_t slblk,diskaddr_t nblks,md_error_t * ep)247 meta_check_inmirror(
248 	mdsetname_t	*sp,
249 	mdname_t	*np,
250 	diskaddr_t	slblk,
251 	diskaddr_t	nblks,
252 	md_error_t	*ep
253 )
254 {
255 	mdnamelist_t	*mirrornlp = NULL;
256 	mdnamelist_t	*p;
257 	int		rval = 0;
258 
259 	/* should have a set */
260 	assert(sp != NULL);
261 
262 	/* for each mirror */
263 	if (meta_get_mirror_names(sp, &mirrornlp, 0, ep) < 0)
264 		return (-1);
265 	for (p = mirrornlp; (p != NULL); p = p->next) {
266 		mdname_t	*mirnp = p->namep;
267 
268 		/* check mirror */
269 		if (in_mirror(sp, mirnp, np, slblk, nblks, ep) != 0) {
270 			rval = -1;
271 			break;
272 		}
273 	}
274 
275 	/* cleanup, return success */
276 	metafreenamelist(mirrornlp);
277 	return (rval);
278 }
279 
280 /*
281  * Check to see if the primary mirror is built on top of a
282  * root slice which is mounted. This check is primarily to
283  * account for this case -
284  *
285  * # metainit -f d1 1 1 <root slice>
286  * # metainit d0 -m d1
287  * # metainit d2 1 1 ctds
288  * # metattach d0 d2
289  *
290  * The metattach here needs to fail if the root slice is
291  * being mirrored; otherwise there is a potential for
292  * data corruption.
293  */
294 static int
meta_check_primary_mirror(mdsetname_t * sp,mdname_t * mirnp,md_error_t * ep)295 meta_check_primary_mirror(
296 	mdsetname_t	*sp,
297 	mdname_t	*mirnp,
298 	md_error_t	*ep
299 )
300 {
301 	int		smi;
302 	char		*curroot;
303 	char		*temproot;
304 	mdname_t	*rootnp;
305 	md_mirror_t	*mirrorp;
306 	md_stripe_t	*stripep;
307 	md_row_t	*rp;
308 	md_comp_t	*cp;
309 
310 	if ((curroot = meta_get_current_root(ep)) == NULL)
311 		return (-1);
312 
313 	/*
314 	 * We need to take the canonical name here otherwise the call to
315 	 * metaname will add a bad entry to the drivelistp cache and
316 	 * things will get nasty later on.
317 	 * However we also need to trap the case where we have a logical
318 	 * device name and meta_canonicalize returns NULL.
319 	 */
320 	temproot = meta_canonicalize(sp, curroot);
321 	if (temproot != NULL) {
322 		curroot = Strdup(temproot);
323 		Free(temproot);
324 	}
325 
326 	/*
327 	 * Get device name of current root metadevice. If root
328 	 * is net mounted as happens if we're part of the
329 	 * install process, rootnp will be set to NULL and we
330 	 * return success.
331 	 *
332 	 * Since curroot should be a complete path, we only
333 	 * need to check whether the device is a logical device.
334 	 * The metaname below returns NULL if curroot is not a logical
335 	 * device.
336 	 */
337 	if ((rootnp = metaname(&sp, curroot, LOGICAL_DEVICE, ep)) == NULL)
338 		return (0);
339 	/*
340 	 * If we're here, the curroot is a mounted on a logical device.
341 	 * Make sure this mirror is not on the root logical device.
342 	 */
343 	if (metaismeta(mirnp)) {
344 		if ((mirrorp = meta_get_mirror(sp, mirnp, ep)) == NULL)
345 			return (-1);
346 
347 		for (smi = 0; (smi < NMIRROR); ++smi) {
348 			/* Check all submirrors */
349 			md_submirror_t	*mdsp = &mirrorp->submirrors[smi];
350 			mdname_t	*submirnamep = mdsp->submirnamep;
351 
352 			/* skip unused submirrors */
353 			if (submirnamep == NULL) {
354 				assert(mdsp->state == SMS_UNUSED);
355 				continue;
356 			}
357 			/* check if submirror is a stripe or not */
358 			if (strcmp(metagetmiscname(submirnamep, ep), MD_STRIPE)
359 			    != 0)
360 				return (-1);
361 			if ((stripep = meta_get_stripe(sp, submirnamep, ep))
362 			    == NULL)
363 				return (-1);
364 
365 			/*
366 			 * Examine the first component of the first row and
367 			 * check to see if it has a mounted root slice
368 			 */
369 			rp = &stripep->rows.rows_val[0];
370 			cp = &rp->comps.comps_val[0];
371 			/*
372 			 * we just care about the component built on
373 			 * top of a raw device
374 			 */
375 			if (!metaismeta(cp->compnamep)) {
376 				/*
377 				 * If root device is the 1st component of
378 				 * the stripe, then fail.
379 				 */
380 				if (strcmp(rootnp->cname, cp->compnamep->cname)
381 				    == 0) {
382 					(void) mduseerror(ep, MDE_IS_MOUNTED,
383 					rootnp->dev, "/", rootnp->cname);
384 					return (-1);
385 				}
386 			}
387 		}
388 	}
389 	/* return success */
390 	return (0);
391 }
392 
393 /*
394  * check submirror
395  */
396 int
meta_check_submirror(mdsetname_t * sp,mdname_t * np,mdname_t * mirnp,int force,md_error_t * ep)397 meta_check_submirror(
398 	mdsetname_t	*sp,
399 	mdname_t	*np,
400 	mdname_t	*mirnp,
401 	int		force,
402 	md_error_t	*ep
403 )
404 {
405 	mdchkopts_t	options = 0;
406 	md_common_t	*mdp;
407 
408 	/* make sure we have a metadevice disk */
409 	if (metachkmeta(np, ep) != 0)
410 		return (-1);
411 
412 	/*
413 	 * Check to see if the primary mirror consists of a root
414 	 * mounted device
415 	 */
416 	if (mirnp && (!force) && ((meta_check_primary_mirror(sp, mirnp, ep)
417 	    != 0)))
418 		return (-1);
419 
420 	/* check to ensure that it is not already in use */
421 	if ((! force) &&
422 	    (meta_check_inuse(sp, np, MDCHK_INUSE, ep) != 0)) {
423 		return (-1);
424 	}
425 
426 	/* make sure it is in the set */
427 	if (meta_check_inset(sp, np, ep) != 0)
428 		return (-1);
429 
430 	/* make sure its not in a metadevice */
431 	if (! metaismeta(np)) {		/* Non-metadevices */
432 		if (meta_check_inmeta(sp, np, options, 0, -1, ep) != 0)
433 			return (-1);
434 	} else {			/* Metadevices only! */
435 		/* make sure it can be parented */
436 		if ((mdp = meta_get_unit(sp, np, ep)) == NULL)
437 			return (-1);
438 
439 		if ((! (mdp->capabilities & MD_CAN_PARENT)) ||
440 		    (! (mdp->capabilities & MD_CAN_SUB_MIRROR)) ||
441 		    (mdp->parent != MD_NO_PARENT)) {
442 			return (mdmderror(ep, MDE_INVAL_UNIT,
443 					meta_getminor(np->dev), np->cname));
444 		}
445 	}
446 
447 	/* return success */
448 	return (0);
449 }
450 
451 /*
452  * convert read options
453  */
454 char *
rd_opt_to_name(mm_rd_opt_t opt)455 rd_opt_to_name(
456 	mm_rd_opt_t	opt
457 )
458 {
459 	switch (opt) {
460 	case RD_LOAD_BAL:
461 		return ("roundrobin");
462 	case RD_GEOMETRY:
463 		return ("geometric");
464 	case RD_FIRST:
465 		return ("first");
466 	default:
467 		assert(0);
468 		return (dgettext(TEXT_DOMAIN, "invalid"));
469 	}
470 }
471 
472 static char *
rd_opt_to_opt(mm_rd_opt_t opt)473 rd_opt_to_opt(
474 	mm_rd_opt_t	opt
475 )
476 {
477 	switch (opt) {
478 	case RD_LOAD_BAL:
479 		return (NULL);	/* default */
480 	case RD_GEOMETRY:
481 		return ("-g");
482 	case RD_FIRST:
483 		return ("-r");
484 	default:
485 		assert(0);
486 		return (dgettext(TEXT_DOMAIN, "invalid"));
487 	}
488 }
489 
490 int
name_to_rd_opt(char * uname,char * name,mm_rd_opt_t * optp,md_error_t * ep)491 name_to_rd_opt(
492 	char		*uname,
493 	char		*name,
494 	mm_rd_opt_t	*optp,
495 	md_error_t	*ep
496 )
497 {
498 	if (strcasecmp(name, "roundrobin") == 0) {
499 		*optp = RD_LOAD_BAL;
500 		return (0);
501 	}
502 	if (strcasecmp(name, "geometric") == 0) {
503 		*optp = RD_GEOMETRY;
504 		return (0);
505 	}
506 	if (strcasecmp(name, "first") == 0) {
507 		*optp = RD_FIRST;
508 		return (0);
509 	}
510 	return (meta_cook_syntax(ep, MDE_BAD_RD_OPT, uname, 1, &name));
511 }
512 
513 /*
514  * convert write options
515  */
516 char *
wr_opt_to_name(mm_wr_opt_t opt)517 wr_opt_to_name(
518 	mm_wr_opt_t	opt
519 )
520 {
521 	switch (opt) {
522 	case WR_PARALLEL:
523 		return ("parallel");
524 	case WR_SERIAL:
525 		return ("serial");
526 	default:
527 		assert(0);
528 		return (dgettext(TEXT_DOMAIN, "invalid"));
529 	}
530 }
531 
532 static char *
wr_opt_to_opt(mm_wr_opt_t opt)533 wr_opt_to_opt(
534 	mm_wr_opt_t	opt
535 )
536 {
537 	switch (opt) {
538 	case WR_PARALLEL:
539 		return (NULL);	/* default */
540 	case WR_SERIAL:
541 		return ("-S");
542 	default:
543 		assert(0);
544 		return (dgettext(TEXT_DOMAIN, "invalid"));
545 	}
546 }
547 
548 int
name_to_wr_opt(char * uname,char * name,mm_wr_opt_t * optp,md_error_t * ep)549 name_to_wr_opt(
550 	char		*uname,
551 	char		*name,
552 	mm_wr_opt_t	*optp,
553 	md_error_t	*ep
554 )
555 {
556 	if (strcasecmp(name, "parallel") == 0) {
557 		*optp = WR_PARALLEL;
558 		return (0);
559 	}
560 	if (strcasecmp(name, "serial") == 0) {
561 		*optp = WR_SERIAL;
562 		return (0);
563 	}
564 	return (meta_cook_syntax(ep, MDE_BAD_WR_OPT, uname, 1, &name));
565 }
566 
567 /*
568  * convert pass numbers
569  */
570 int
name_to_pass_num(char * uname,char * name,mm_pass_num_t * passp,md_error_t * ep)571 name_to_pass_num(
572 	char		*uname,
573 	char		*name,
574 	mm_pass_num_t	*passp,
575 	md_error_t	*ep
576 )
577 {
578 	if ((sscanf(name, "%hd", passp) != 1) ||
579 	    (*passp < 0) || (*passp > MD_PASS_MAX)) {
580 		return (meta_cook_syntax(ep, MDE_BAD_PASS_NUM,
581 		    uname, 1, &name));
582 	}
583 	return (0);
584 }
585 
586 /*
587  * convert resync option
588  */
589 
590 static char *
resync_opt_to_name(uint_t tstate)591 resync_opt_to_name(
592 	uint_t	tstate
593 )
594 {
595 	if (tstate & MD_ABR_CAP)
596 		return (dgettext(TEXT_DOMAIN, "application based"));
597 	else
598 		return (dgettext(TEXT_DOMAIN, "optimized resync"));
599 }
600 
601 /*
602  * print mirror
603  */
604 static int
mirror_print(md_mirror_t * mirrorp,char * fname,FILE * fp,mdprtopts_t options,md_error_t * ep)605 mirror_print(
606 	md_mirror_t	*mirrorp,
607 	char		*fname,
608 	FILE		*fp,
609 	mdprtopts_t	options,
610 	md_error_t	*ep
611 )
612 {
613 	uint_t		smi;
614 	char		*p;
615 	int		rval = -1;
616 
617 
618 	if (options & PRINT_LARGEDEVICES) {
619 		if ((mirrorp->common.revision & MD_64BIT_META_DEV) == 0) {
620 			rval = 0;
621 			goto out;
622 		}
623 	}
624 
625 	if (options & PRINT_FN) {
626 		if ((mirrorp->common.revision & MD_FN_META_DEV) == 0) {
627 			rval = 0;
628 			goto out;
629 		}
630 	}
631 
632 	/* print name and -m */
633 	if (fprintf(fp, "%s -m", mirrorp->common.namep->cname) == EOF)
634 		goto out;
635 
636 	/* print submirrors */
637 	for (smi = 0; (smi < NMIRROR); ++smi) {
638 		md_submirror_t	*mdsp = &mirrorp->submirrors[smi];
639 		mdname_t	*submirnamep = mdsp->submirnamep;
640 
641 		/* skip unused submirrors */
642 		if (submirnamep == NULL) {
643 			assert(mdsp->state == SMS_UNUSED);
644 			continue;
645 		}
646 
647 		/* print submirror */
648 		if (fprintf(fp, " %s", submirnamep->rname) == EOF)
649 			goto out;
650 	}
651 
652 	/* print options */
653 	if ((p = rd_opt_to_opt(mirrorp->read_option)) != NULL) {
654 		if (fprintf(fp, " %s", p) == EOF)
655 			goto out;
656 	}
657 	if ((p = wr_opt_to_opt(mirrorp->write_option)) != NULL) {
658 		if (fprintf(fp, " %s", p) == EOF)
659 			goto out;
660 	}
661 	if (fprintf(fp, " %u\n", mirrorp->pass_num) == EOF)
662 		goto out;
663 
664 	/* success */
665 	rval = 0;
666 
667 	/* cleanup, return error */
668 out:
669 	if (rval != 0)
670 		(void) mdsyserror(ep, errno, fname);
671 	return (rval);
672 }
673 
674 /*
675  * convert submirror state to name
676  */
677 char *
sm_state_to_name(md_submirror_t * mdsp,md_status_t mirror_status,md_timeval32_t * tvp,uint_t tstate)678 sm_state_to_name(
679 	md_submirror_t	*mdsp,
680 	md_status_t	mirror_status,
681 	md_timeval32_t	*tvp,
682 	uint_t		tstate
683 )
684 {
685 	static char	state_to_str[100];
686 	sm_state_t	state = mdsp->state;
687 	uint_t		is_target = mdsp->flags & MD_SM_RESYNC_TARGET;
688 
689 	/* grab time */
690 	if (tvp != NULL)
691 		*tvp = mdsp->timestamp;
692 
693 	/*
694 	 * Only return Unavailable if there is no flagged error on the
695 	 * submirror. If the mirror has received any writes since the submirror
696 	 * went into Unavailable state a resync is required. To alert the
697 	 * administrator to this we return a 'Needs maintenance' message.
698 	 */
699 	if ((tstate != 0) && (state & SMS_RUNNING)) {
700 		return (dgettext(TEXT_DOMAIN, "Unavailable"));
701 	}
702 
703 	/* all is well */
704 	if (state & SMS_RUNNING) {
705 		if (!(mirror_status & MD_UN_OPT_NOT_DONE) ||
706 		    ((mirror_status & MD_UN_OPT_NOT_DONE) && !is_target)) {
707 			return (dgettext(TEXT_DOMAIN, "Okay"));
708 		}
709 	}
710 
711 	/* resyncing, needs repair */
712 	if ((state & (SMS_COMP_RESYNC | SMS_ATTACHED_RESYNC |
713 	    SMS_OFFLINE_RESYNC)) ||
714 	    (mirror_status & MD_UN_OPT_NOT_DONE)) {
715 		if (mirror_status & MD_UN_RESYNC_ACTIVE) {
716 			return (dgettext(TEXT_DOMAIN, "Resyncing"));
717 		}
718 		if (mirror_status & MD_UN_RESYNC_CANCEL) {
719 			return (dgettext(TEXT_DOMAIN, "Resync cancelled"));
720 		}
721 		return (dgettext(TEXT_DOMAIN, "Needs maintenance"));
722 	}
723 
724 	/* needs repair */
725 	if (state & (SMS_COMP_ERRED | SMS_ATTACHED | SMS_OFFLINE)) {
726 		if (mirror_status & MD_UN_RESYNC_CANCEL) {
727 			return (dgettext(TEXT_DOMAIN, "Resync cancelled"));
728 		}
729 		return (dgettext(TEXT_DOMAIN, "Needs maintenance"));
730 	}
731 
732 	/* unknown */
733 	assert(0);
734 	(void) sprintf(state_to_str, "0x%x", state);
735 	return (state_to_str);
736 }
737 
738 /*
739  * convert submirror state to repair action
740  */
741 int
sm_state_to_action(mdsetname_t * sp,md_submirror_t * mdsp,md_status_t mirror_status,md_mirror_t * mirrorp,char ** actionp,md_error_t * ep)742 sm_state_to_action(
743 	mdsetname_t	*sp,
744 	md_submirror_t	*mdsp,
745 	md_status_t	mirror_status,
746 	md_mirror_t	*mirrorp,
747 	char		**actionp,
748 	md_error_t	*ep
749 )
750 {
751 	static char	buf[1024];
752 	mdname_t	*submirnamep = mdsp->submirnamep;
753 	sm_state_t	state = mdsp->state;
754 	char		*miscname;
755 
756 	/* all is well */
757 	*actionp = NULL;
758 	if (mirror_status & MD_UN_RESYNC_ACTIVE)
759 		return (0);
760 	if ((state == SMS_RUNNING) && !(mirror_status & MD_UN_OPT_NOT_DONE))
761 		return (0);
762 
763 	/* complete cancelled resync */
764 	if (mirror_status & MD_UN_RESYNC_CANCEL) {
765 		(void) snprintf(buf, sizeof (buf),
766 		    dgettext(TEXT_DOMAIN, "metasync %s"),
767 		    mirrorp->common.namep->cname);
768 		*actionp = buf;
769 		return (0);
770 	}
771 
772 	/* replace stripe component */
773 	if ((metaismeta(submirnamep)) && (state & SMS_COMP_ERRED)) {
774 		if ((miscname = metagetmiscname(submirnamep, ep)) == NULL)
775 			return (-1);
776 		if (strcmp(miscname, MD_STRIPE) == 0) {
777 			mdname_t	*compnamep;
778 			comp_state_t	compstate;
779 
780 			if (meta_find_erred_comp(sp, submirnamep,
781 			    &compnamep, &compstate, ep) != 0) {
782 				return (-1);
783 			}
784 			if (compstate != CS_LAST_ERRED)
785 				(void) snprintf(buf, sizeof (buf),
786 				    "metareplace %s %s <%s>",
787 				    mirrorp->common.namep->cname,
788 				    compnamep->cname,
789 				    dgettext(TEXT_DOMAIN, "new device"));
790 			else
791 				(void) snprintf(buf, sizeof (buf),
792 				    dgettext(TEXT_DOMAIN,
793 				    "after replacing \"Maintenance\" "
794 				    "components:\n"
795 				    "\t\tmetareplace %s %s <new device>"),
796 				    mirrorp->common.namep->cname,
797 				    compnamep->cname);
798 			*actionp = buf;
799 			return (0);
800 		}
801 	}
802 
803 	/* resync mirror */
804 	if ((state & (SMS_ATTACHED_RESYNC | SMS_OFFLINE_RESYNC |
805 	    SMS_COMP_RESYNC | SMS_ATTACHED)) ||
806 	    (mirror_status & MD_UN_OPT_NOT_DONE)) {
807 		(void) snprintf(buf, sizeof (buf), "metasync %s",
808 		    mirrorp->common.namep->cname);
809 		*actionp = buf;
810 		return (0);
811 	}
812 
813 	/* online submirror */
814 	if (state & SMS_OFFLINE) {
815 		(void) snprintf(buf, sizeof (buf), "metaonline %s %s",
816 		    mirrorp->common.namep->cname, submirnamep->cname);
817 		*actionp = buf;
818 		return (0);
819 	}
820 
821 	/* unknown action */
822 	*actionp = dgettext(TEXT_DOMAIN, "???");
823 	return (0);
824 }
825 
826 /*
827  * print mirror options
828  */
829 int
meta_print_mirror_options(mm_rd_opt_t read_option,mm_wr_opt_t write_option,mm_pass_num_t pass_num,uint_t tstate,char * fname,mdsetname_t * sp,FILE * fp,md_error_t * ep)830 meta_print_mirror_options(
831 	mm_rd_opt_t	read_option,
832 	mm_wr_opt_t	write_option,
833 	mm_pass_num_t	pass_num,
834 	uint_t		tstate,
835 	char		*fname,
836 	mdsetname_t	*sp,
837 	FILE		*fp,
838 	md_error_t	*ep
839 )
840 {
841 	char		*p;
842 	int		rval = -1;
843 
844 	/* print options */
845 	if (fprintf(fp, dgettext(TEXT_DOMAIN, "    Pass: %u\n"),
846 	    pass_num) == EOF) {
847 		goto out;
848 	}
849 	if ((p = rd_opt_to_opt(read_option)) == NULL)
850 		p = dgettext(TEXT_DOMAIN, "default");
851 	if (fprintf(fp, dgettext(TEXT_DOMAIN, "    Read option: %s (%s)\n"),
852 	    rd_opt_to_name(read_option), p) == EOF) {
853 		goto out;
854 	}
855 	if ((p = wr_opt_to_opt(write_option)) == NULL)
856 		p = dgettext(TEXT_DOMAIN, "default");
857 	if (fprintf(fp, dgettext(TEXT_DOMAIN, "    Write option: %s (%s)\n"),
858 	    wr_opt_to_name(write_option), p) == EOF) {
859 		goto out;
860 	}
861 	/* Display resync option for mirror, if MultiNode set */
862 	if (meta_is_mn_set(sp, ep)) {
863 		if (fprintf(fp, dgettext(TEXT_DOMAIN,
864 		    "    Resync option: %s\n"),
865 		    resync_opt_to_name(tstate)) == EOF) {
866 			goto out;
867 		}
868 	}
869 
870 	/* success */
871 	rval = 0;
872 
873 	/* cleanup, return error */
874 out:
875 	if (rval != 0)
876 		(void) mdsyserror(ep, errno, fname);
877 	return (rval);
878 }
879 
880 static char *
get_node_name(uint_t nid,md_error_t * ep)881 get_node_name(uint_t nid, md_error_t *ep)
882 {
883 	mndiskset_membershiplist_t	*nl, *p;
884 	int				n;
885 	char				*node_nm;
886 
887 	/* get the known membership list */
888 	if (meta_read_nodelist(&n, &nl, ep)) {
889 		return (NULL);
890 	}
891 
892 	/* find the matching node and return the name */
893 	for (p = nl; (p != NULL); p = p->next) {
894 		if (nid == p->msl_node_id) {
895 			/* match found */
896 			node_nm = Strdup(p->msl_node_name);
897 			goto out;
898 		}
899 	}
900 
901 	/* match not found */
902 	node_nm = Strdup(dgettext(TEXT_DOMAIN, "None"));
903 
904 out:
905 	meta_free_nodelist(nl);
906 	return (node_nm);
907 }
908 
909 /*
910  * report mirror
911  */
912 static int
mirror_report(mdsetname_t * sp,md_mirror_t * mirrorp,mdnamelist_t ** nlpp,char * fname,FILE * fp,mdprtopts_t options,md_error_t * ep)913 mirror_report(
914 	mdsetname_t	*sp,
915 	md_mirror_t	*mirrorp,
916 	mdnamelist_t	**nlpp,
917 	char		*fname,
918 	FILE		*fp,
919 	mdprtopts_t	options,
920 	md_error_t	*ep
921 )
922 {
923 	md_status_t	status = mirrorp->common.state;
924 	uint_t		smi;
925 	char		*p;
926 	int		rval = -1;
927 	uint_t		tstate = 0;
928 
929 	/*
930 	 * check for the -B option. If -B and the metadevice is
931 	 * a 64 bit device, get the dev for relocation information
932 	 * printout. If not a 64 bit device, just don't print this
933 	 * information out but you need to go down to the subdevice
934 	 * level and print there if appropriate.
935 	 */
936 	if (options & PRINT_LARGEDEVICES) {
937 		if ((mirrorp->common.revision & MD_64BIT_META_DEV) == 0) {
938 			for (smi = 0; (smi < NMIRROR); ++smi) {
939 				md_submirror_t	*mdsp =
940 				    &mirrorp->submirrors[smi];
941 				mdname_t	*submirnamep =
942 				    mdsp->submirnamep;
943 				if (submirnamep == NULL) {
944 					continue;
945 				}
946 				if ((metaismeta(submirnamep)) &&
947 				    (meta_print_name(sp, submirnamep, nlpp,
948 				    fname, fp, options | PRINT_SUBDEVS, NULL,
949 				    ep) != 0)) {
950 					return (-1);
951 				}
952 			}
953 			rval = 0;
954 			goto out;
955 		} else {
956 			if (meta_getdevs(sp, mirrorp->common.namep,
957 			    nlpp, ep) != 0)
958 				goto out;
959 		}
960 	}
961 
962 	/*
963 	 * check for the -D option. If -D and the name is
964 	 * a descriptive name, get the dev for relocation information
965 	 * printout. If not a descriptive name, don't print this
966 	 * information out but you need to go down to the subdevice
967 	 * level and print there if appropriate.
968 	 */
969 	if (options & PRINT_FN) {
970 		if ((mirrorp->common.revision & MD_FN_META_DEV) == 0) {
971 			for (smi = 0; (smi < NMIRROR); ++smi) {
972 				md_submirror_t	*mdsp =
973 				    &mirrorp->submirrors[smi];
974 				mdname_t	*submirnamep =
975 				    mdsp->submirnamep;
976 				if (submirnamep == NULL) {
977 					continue;
978 				}
979 				if ((metaismeta(submirnamep)) &&
980 				    (meta_print_name(sp, submirnamep, nlpp,
981 				    fname, fp, options | PRINT_SUBDEVS, NULL,
982 				    ep) != 0)) {
983 					return (-1);
984 				}
985 			}
986 			rval = 0;
987 			goto out;
988 		} else {
989 			if (meta_getdevs(sp, mirrorp->common.namep,
990 			    nlpp, ep) != 0)
991 				goto out;
992 		}
993 	}
994 
995 	/* print header */
996 	if (options & PRINT_HEADER) {
997 		if (fprintf(fp, dgettext(TEXT_DOMAIN, "%s: Mirror\n"),
998 		    mirrorp->common.namep->cname) == EOF) {
999 			goto out;
1000 		}
1001 	}
1002 
1003 	/* print submirrors, adjust status */
1004 	for (smi = 0; (smi < NMIRROR); ++smi) {
1005 		md_submirror_t	*mdsp = &mirrorp->submirrors[smi];
1006 		mdname_t	*submirnamep = mdsp->submirnamep;
1007 		char		*sm_state;
1008 		md_timeval32_t	tv;
1009 		char		*timep;
1010 
1011 		/* skip unused submirrors */
1012 		if (submirnamep == NULL) {
1013 			assert(mdsp->state == SMS_UNUSED);
1014 			continue;
1015 		}
1016 
1017 		if (mdsp->state & SMS_OFFLINE)
1018 			status &= ~MD_UN_OPT_NOT_DONE;
1019 
1020 		/* print submirror */
1021 		if (fprintf(fp, dgettext(TEXT_DOMAIN, "    Submirror %u: %s\n"),
1022 		    smi, submirnamep->cname) == EOF) {
1023 			goto out;
1024 		}
1025 
1026 		/* print state */
1027 		if (metaismeta(mdsp->submirnamep)) {
1028 			if (meta_get_tstate(mdsp->submirnamep->dev, &tstate,
1029 			    ep) != 0)
1030 				return (-1);
1031 		}
1032 		sm_state = sm_state_to_name(mdsp, status, &tv,
1033 		    tstate & MD_DEV_ERRORED);
1034 		if (options & PRINT_TIMES) {
1035 			timep = meta_print_time(&tv);
1036 		} else {
1037 			timep = "";
1038 		}
1039 		if (fprintf(fp, dgettext(TEXT_DOMAIN,
1040 		    "      State: %-12s %s\n"),
1041 		    sm_state, timep) == EOF) {
1042 			goto out;
1043 		}
1044 	}
1045 
1046 	/* print resync status */
1047 	if (status & MD_UN_RESYNC_CANCEL) {
1048 		/* Resync was cancelled but is restartable */
1049 		if (mirrorp->common.revision & MD_64BIT_META_DEV) {
1050 			if (fprintf(fp, dgettext(TEXT_DOMAIN,
1051 			    "    Resync cancelled: %2d.%1d %% done\n"),
1052 			    mirrorp->percent_done/10,
1053 			    mirrorp->percent_done%10) == EOF) {
1054 				goto out;
1055 			}
1056 		} else {
1057 			if (fprintf(fp, dgettext(TEXT_DOMAIN,
1058 			    "    Resync cancelled: %d %% done\n"),
1059 			    mirrorp->percent_done) == EOF) {
1060 				goto out;
1061 			}
1062 		}
1063 	} else if (status & MD_UN_RESYNC_ACTIVE) {
1064 		if (mirrorp->common.revision & MD_64BIT_META_DEV) {
1065 			if (fprintf(fp, dgettext(TEXT_DOMAIN,
1066 			    "    Resync in progress: %2d.%1d %% done\n"),
1067 			    mirrorp->percent_done/10,
1068 			    mirrorp->percent_done%10) == EOF) {
1069 				goto out;
1070 			}
1071 		} else {
1072 			if (fprintf(fp, dgettext(TEXT_DOMAIN,
1073 			    "    Resync in progress: %d %% done\n"),
1074 			    mirrorp->percent_done) == EOF) {
1075 				goto out;
1076 			}
1077 		}
1078 	}
1079 
1080 	/* print options */
1081 	if (meta_get_tstate(mirrorp->common.namep->dev, &tstate, ep) != 0)
1082 		return (-1);
1083 
1084 	if (meta_print_mirror_options(mirrorp->read_option,
1085 	    mirrorp->write_option, mirrorp->pass_num,
1086 	    tstate, fname, sp, fp, ep) != 0)
1087 		return (-1);
1088 
1089 	/* print mirror owner for multi-node metadevice */
1090 	if (meta_is_mn_set(sp, ep)) {
1091 		md_set_mmown_params_t	ownpar;
1092 		mdname_t		*mirnp = mirrorp->common.namep;
1093 		char			*node_name;
1094 
1095 		(void) memset(&ownpar, 0, sizeof (ownpar));
1096 		ownpar.d.mnum = meta_getminor(mirnp->dev);
1097 		MD_SETDRIVERNAME(&ownpar, MD_MIRROR, sp->setno);
1098 
1099 		if (metaioctl(MD_MN_GET_MM_OWNER, &ownpar, ep,
1100 		    "MD_MN_GET_MM_OWNER") != 0) {
1101 			return (-1);
1102 		}
1103 
1104 		node_name = get_node_name(ownpar.d.owner, ep);
1105 		if (node_name == NULL)
1106 			return (-1);
1107 		else if (fprintf(fp, dgettext(TEXT_DOMAIN, "    Owner: %s\n"),
1108 		    node_name) == EOF) {
1109 			Free(node_name);
1110 			goto out;
1111 		}
1112 		Free(node_name);
1113 
1114 	}
1115 
1116 	/* print size */
1117 	if (fprintf(fp, dgettext(TEXT_DOMAIN, "    Size: %lld blocks (%s)\n"),
1118 	    mirrorp->common.size,
1119 	    meta_number_to_string(mirrorp->common.size, DEV_BSIZE))
1120 	    == EOF) {
1121 		goto out;
1122 	}
1123 
1124 	/* MD_DEBUG stuff */
1125 	if (options & PRINT_DEBUG) {
1126 		mdname_t	*mirnp = mirrorp->common.namep;
1127 		mm_unit_t	*mm;
1128 		mddb_optloc_t	optloc;
1129 		uint_t		i;
1130 
1131 		/* get real mirror unit */
1132 		if ((mm = (mm_unit_t *)meta_get_mdunit(sp, mirnp, ep))
1133 		    == NULL) {
1134 			return (-1);
1135 		}
1136 		assert(mm->c.un_type == MD_METAMIRROR);
1137 
1138 		/* print dirty regions */
1139 		if (fprintf(fp, dgettext(TEXT_DOMAIN,
1140 "    Regions which are dirty: %d%% (blksize %d num %d)\n"),
1141 		    mirrorp->percent_dirty, mm->un_rrd_blksize,
1142 		    mm->un_rrd_num) == EOF) {
1143 			Free(mm);
1144 			goto out;
1145 		}
1146 
1147 		/* print optimized resync record locations */
1148 		(void) memset(&optloc, 0, sizeof (optloc));
1149 		optloc.recid = mm->un_rr_dirty_recid;
1150 		if (metaioctl(MD_DB_GETOPTLOC, &optloc, ep,
1151 		    "MD_DB_GETOPTLOC") != 0) {
1152 			Free(mm);
1153 			return (-1);
1154 		}
1155 		for (i = 0; (i < ((sizeof optloc.li) / sizeof (optloc.li[0])));
1156 		    ++i) {
1157 			mddb_config_t	dbconf;
1158 			char		*devname;
1159 
1160 			(void) memset(&dbconf, 0, sizeof (dbconf));
1161 			dbconf.c_id = optloc.li[i];
1162 			dbconf.c_setno = sp->setno;
1163 			dbconf.c_subcmd = MDDB_CONFIG_ABS;
1164 			/* Don't need device id information from this ioctl */
1165 			dbconf.c_locator.l_devid = (uint64_t)0;
1166 			dbconf.c_locator.l_devid_flags = 0;
1167 			if (metaioctl(MD_DB_ENDDEV, &dbconf, &dbconf.c_mde,
1168 			    "MD_DB_ENDDEV") != 0) {
1169 				Free(mm);
1170 				return (mdstealerror(ep, &dbconf.c_mde));
1171 			}
1172 			if ((devname = splicename(&dbconf.c_devname))
1173 			    == NULL) {
1174 				devname = Strdup(dgettext(TEXT_DOMAIN,
1175 				    "unknown"));
1176 			}
1177 			if (fprintf(fp, dgettext(TEXT_DOMAIN,
1178 			    "    Resync record[%u]: %d (%s %d %d)\n"), i,
1179 			    optloc.li[i], devname, dbconf.c_locator.l_blkno,
1180 			    (dbconf.c_dbend - dbconf.c_locator.l_blkno + 1))
1181 			    == EOF) {
1182 				Free(mm);
1183 				Free(devname);
1184 				goto out;
1185 			}
1186 			Free(devname);
1187 		}
1188 		Free(mm);
1189 	}
1190 
1191 	/* print submirror details */
1192 	for (smi = 0; (smi < NMIRROR); ++smi) {
1193 		md_submirror_t	*mdsp = &mirrorp->submirrors[smi];
1194 		mdname_t	*submirnamep = mdsp->submirnamep;
1195 		char		*sm_state;
1196 		md_timeval32_t	tv;
1197 		char		*timep;
1198 		md_stripe_t	*stripep;
1199 
1200 		/* skip unused submirrors */
1201 		if (submirnamep == NULL) {
1202 			assert(mdsp->state == SMS_UNUSED);
1203 			continue;
1204 		}
1205 
1206 		if (options & PRINT_FN) {
1207 			/* get unit structure */
1208 			if ((stripep = meta_get_stripe_common(sp, submirnamep,
1209 			    ((options & PRINT_FAST) ? 1 : 0), ep)) == NULL)
1210 				goto out;
1211 
1212 			if ((stripep->common.revision & MD_FN_META_DEV)
1213 			    == 0)
1214 				continue;
1215 		}
1216 
1217 		/* add extra line */
1218 		if (fprintf(fp, "\n") == EOF)
1219 			goto out;
1220 
1221 		/* print submirror */
1222 		if (fprintf(fp, dgettext(TEXT_DOMAIN,
1223 		    "%s: Submirror of %s\n"),
1224 		    submirnamep->cname,
1225 		    mirrorp->common.namep->cname) == EOF) {
1226 			goto out;
1227 		}
1228 
1229 		/* print state */
1230 		if (metaismeta(mdsp->submirnamep)) {
1231 			if (meta_get_tstate(mdsp->submirnamep->dev, &tstate, ep)
1232 			    != 0)
1233 				return (-1);
1234 		}
1235 		sm_state = sm_state_to_name(mdsp, status, &tv, NULL);
1236 		if (options & PRINT_TIMES) {
1237 			timep = meta_print_time(&tv);
1238 		} else {
1239 			timep = "";
1240 		}
1241 
1242 		if ((tstate & MD_DEV_ERRORED) == 0) {
1243 			if (fprintf(fp, dgettext(TEXT_DOMAIN,
1244 			    "    State: %-12s %s\n"),
1245 			    sm_state, timep) == EOF) {
1246 				goto out;
1247 			}
1248 
1249 			/* print what to do */
1250 			if (sm_state_to_action(sp, mdsp, status,
1251 			    mirrorp, &p, ep) != 0)
1252 				return (-1);
1253 			if ((p != NULL) &&
1254 			    (fprintf(fp, dgettext(TEXT_DOMAIN,
1255 			    "    Invoke: %s\n"), p) == EOF)) {
1256 				goto out;
1257 			}
1258 		}
1259 
1260 		/* print underlying metadevice */
1261 		if ((metaismeta(submirnamep)) &&
1262 		    (meta_print_name(sp, submirnamep, nlpp, fname, fp,
1263 		    ((options & ~PRINT_HEADER) | PRINT_SUBDEVS),
1264 		    NULL, ep) != 0)) {
1265 			return (-1);
1266 		}
1267 	}
1268 
1269 	/* add extra line */
1270 	if (fprintf(fp, "\n") == EOF)
1271 		goto out;
1272 
1273 	/* success */
1274 	rval = 0;
1275 
1276 	/* cleanup, return error */
1277 out:
1278 	if (rval != 0)
1279 		(void) mdsyserror(ep, errno, fname);
1280 	return (rval);
1281 }
1282 
1283 /*
1284  * print/report mirror
1285  */
1286 int
meta_mirror_print(mdsetname_t * sp,mdname_t * mirnp,mdnamelist_t ** nlpp,char * fname,FILE * fp,mdprtopts_t options,md_error_t * ep)1287 meta_mirror_print(
1288 	mdsetname_t	*sp,
1289 	mdname_t	*mirnp,
1290 	mdnamelist_t	**nlpp,
1291 	char		*fname,
1292 	FILE		*fp,
1293 	mdprtopts_t	options,
1294 	md_error_t	*ep
1295 )
1296 {
1297 	md_mirror_t	*mirrorp;
1298 	uint_t		smi;
1299 
1300 	/* should have same set */
1301 	assert(sp != NULL);
1302 	assert((mirnp == NULL) ||
1303 	    (sp->setno == MD_MIN2SET(meta_getminor(mirnp->dev))));
1304 
1305 	/* print all mirrors */
1306 	if (mirnp == NULL) {
1307 		mdnamelist_t	*nlp = NULL;
1308 		mdnamelist_t	*p;
1309 		int		cnt;
1310 		int		rval = 0;
1311 
1312 		/* get list */
1313 		if ((cnt = meta_get_mirror_names(sp, &nlp, options, ep)) < 0)
1314 			return (-1);
1315 		else if (cnt == 0)
1316 			return (0);
1317 
1318 		/* recurse */
1319 		for (p = nlp; (p != NULL); p = p->next) {
1320 			mdname_t	*np = p->namep;
1321 
1322 			if (meta_mirror_print(sp, np, nlpp, fname, fp,
1323 			    options, ep) != 0)
1324 				rval = -1;
1325 		}
1326 
1327 		/* cleanup, return success */
1328 		metafreenamelist(nlp);
1329 		return (rval);
1330 	}
1331 
1332 	/* get unit structure */
1333 	if ((mirrorp = meta_get_mirror_common(sp, mirnp,
1334 	    ((options & PRINT_FAST) ? 1 : 0), ep)) == NULL)
1335 		return (-1);
1336 
1337 	/* check for parented */
1338 	if ((! (options & PRINT_SUBDEVS)) &&
1339 	    (MD_HAS_PARENT(mirrorp->common.parent))) {
1340 		return (0);
1341 	}
1342 
1343 	/* print appropriate detail */
1344 	if (options & PRINT_SHORT) {
1345 		/* print mirror */
1346 		if (mirror_print(mirrorp, fname, fp, options, ep) != 0)
1347 			return (-1);
1348 
1349 		/* print underlying metadevices */
1350 		for (smi = 0; (smi < NMIRROR); ++smi) {
1351 			md_submirror_t	*mdsp = &mirrorp->submirrors[smi];
1352 			mdname_t	*submirnamep = mdsp->submirnamep;
1353 
1354 			/* skip unused submirrors */
1355 			if (submirnamep == NULL) {
1356 				assert(mdsp->state == SMS_UNUSED);
1357 				continue;
1358 			}
1359 
1360 			/* print submirror */
1361 			if (metaismeta(submirnamep)) {
1362 				if (meta_print_name(sp, submirnamep, nlpp,
1363 				    fname, fp, (options | PRINT_SUBDEVS), NULL,
1364 				    ep) != 0) {
1365 					return (-1);
1366 				}
1367 			}
1368 		}
1369 
1370 		/* return success */
1371 		return (0);
1372 	} else {
1373 		return (mirror_report(sp, mirrorp, nlpp, fname, fp,
1374 		    options, ep));
1375 	}
1376 }
1377 
1378 /*
1379  * online submirror
1380  */
1381 int
meta_mirror_online(mdsetname_t * sp,mdname_t * mirnp,mdname_t * submirnp,mdcmdopts_t options,md_error_t * ep)1382 meta_mirror_online(
1383 	mdsetname_t	*sp,
1384 	mdname_t	*mirnp,
1385 	mdname_t	*submirnp,
1386 	mdcmdopts_t	options,
1387 	md_error_t	*ep
1388 )
1389 {
1390 	md_i_off_on_t	mio;
1391 	md_mirror_t	*mirrorp;
1392 	md_set_desc	*sd;
1393 	uint_t		tstate;
1394 
1395 	/* should have same set */
1396 	assert(sp != NULL);
1397 	assert(sp->setno == MD_MIN2SET(meta_getminor(mirnp->dev)));
1398 
1399 	/* check name */
1400 	if (metachkmeta(mirnp, ep) != 0)
1401 		return (-1);
1402 
1403 	if ((mirrorp = meta_get_mirror(sp, mirnp, ep)) == NULL)
1404 		return (-1);
1405 
1406 	/* Only valid for mirror without ABR set */
1407 	if (meta_get_tstate(mirrorp->common.namep->dev, &tstate, ep) != 0)
1408 		return (-1);
1409 	if (tstate & MD_ABR_CAP) {
1410 		(void) mderror(ep, MDE_ABR_SET, NULL);
1411 		return (-1);
1412 	}
1413 
1414 	/*
1415 	 * In a MN set, the master always executes the online command first.
1416 	 * Before the master executes the IOC_ONLINE ioctl,
1417 	 * the master sends a message to all nodes to suspend writes to
1418 	 * this mirror.  Then the master executes the IOC_ONLINE ioctl
1419 	 * which resumes writes to this mirror from the master node.
1420 	 * As each slave executes the online command, each slave will
1421 	 * call the IOC_ONLINE ioctl which will resume writes to this mirror
1422 	 * from that slave node.
1423 	 */
1424 	if (! metaislocalset(sp)) {
1425 		if ((sd = metaget_setdesc(sp, ep)) == NULL)
1426 			return (-1);
1427 		if ((MD_MNSET_DESC(sd)) && sd->sd_mn_am_i_master)
1428 			if (meta_mn_send_suspend_writes(
1429 			    meta_getminor(mirnp->dev), ep) != 0)
1430 				return (-1);
1431 	}
1432 
1433 	/* online submirror */
1434 	(void) memset(&mio, 0, sizeof (mio));
1435 	mio.mnum = meta_getminor(mirnp->dev);
1436 	MD_SETDRIVERNAME(&mio, MD_MIRROR, sp->setno);
1437 	mio.submirror = submirnp->dev;
1438 	if (metaioctl(MD_IOCONLINE, &mio, &mio.mde, NULL) != 0)
1439 		return (mdstealerror(ep, &mio.mde));
1440 
1441 	/* clear cache */
1442 	meta_invalidate_name(mirnp);
1443 	meta_invalidate_name(submirnp);
1444 
1445 	/* let em know */
1446 	if (options & MDCMD_PRINT) {
1447 		(void) printf(dgettext(TEXT_DOMAIN,
1448 		    "%s: submirror %s is onlined\n"),
1449 		    mirnp->cname, submirnp->cname);
1450 		(void) fflush(stdout);
1451 	}
1452 
1453 	/* return success */
1454 	return (0);
1455 }
1456 
1457 /*
1458  * offline submirror
1459  */
1460 int
meta_mirror_offline(mdsetname_t * sp,mdname_t * mirnp,mdname_t * submirnp,mdcmdopts_t options,md_error_t * ep)1461 meta_mirror_offline(
1462 	mdsetname_t	*sp,
1463 	mdname_t	*mirnp,
1464 	mdname_t	*submirnp,
1465 	mdcmdopts_t	options,
1466 	md_error_t	*ep
1467 )
1468 {
1469 	int		force = ((options & MDCMD_FORCE) ? 1 : 0);
1470 	md_i_off_on_t	mio;
1471 	md_mirror_t	*mirrorp;
1472 	md_set_desc	*sd;
1473 	uint_t		tstate;
1474 
1475 	/* should have same set */
1476 	assert(sp != NULL);
1477 	assert(sp->setno == MD_MIN2SET(meta_getminor(mirnp->dev)));
1478 
1479 	/* check name */
1480 	if (metachkmeta(mirnp, ep) != 0)
1481 		return (-1);
1482 
1483 	if ((mirrorp = meta_get_mirror(sp, mirnp, ep)) == NULL)
1484 		return (-1);
1485 
1486 	/* Only valid for mirror without ABR set */
1487 	if (meta_get_tstate(mirrorp->common.namep->dev, &tstate, ep) != 0)
1488 		return (-1);
1489 	if (tstate & MD_ABR_CAP) {
1490 		(void) mderror(ep, MDE_ABR_SET, NULL);
1491 		return (-1);
1492 	}
1493 
1494 	/*
1495 	 * In a MN set, the master always executes the offline command first.
1496 	 * Before the master executes the IOC_OFFLINE ioctl,
1497 	 * the master sends a message to all nodes to suspend writes to
1498 	 * this mirror.  Then the master executes the IOC_OFFLINE ioctl
1499 	 * which resumes writes to this mirror from the master node.
1500 	 * As each slave executes the offline command, each slave will
1501 	 * call the IOC_OFFLINE ioctl which will resume writes to this mirror
1502 	 * from that slave node.
1503 	 */
1504 	if (! metaislocalset(sp)) {
1505 		if ((sd = metaget_setdesc(sp, ep)) == NULL)
1506 			return (-1);
1507 		if ((MD_MNSET_DESC(sd)) && sd->sd_mn_am_i_master)
1508 			if (meta_mn_send_suspend_writes(
1509 			    meta_getminor(mirnp->dev), ep) != 0)
1510 				return (-1);
1511 	}
1512 
1513 	/* offline submirror */
1514 	(void) memset(&mio, 0, sizeof (mio));
1515 	mio.mnum = meta_getminor(mirnp->dev);
1516 	MD_SETDRIVERNAME(&mio, MD_MIRROR, sp->setno);
1517 	mio.submirror = submirnp->dev;
1518 	mio.force_offline = force;
1519 	if (metaioctl(MD_IOCOFFLINE, &mio, &mio.mde, NULL) != 0)
1520 		return (mdstealerror(ep, &mio.mde));
1521 
1522 	/* clear cache */
1523 	meta_invalidate_name(mirnp);
1524 	meta_invalidate_name(submirnp);
1525 
1526 	/* let em know */
1527 	if (options & MDCMD_PRINT) {
1528 		(void) printf(dgettext(TEXT_DOMAIN,
1529 		    "%s: submirror %s is offlined\n"),
1530 		    mirnp->cname, submirnp->cname);
1531 		(void) fflush(stdout);
1532 	}
1533 
1534 	/* return success */
1535 	return (0);
1536 }
1537 
1538 /*
1539  * attach submirror to mirror
1540  * we actually never have to worry about crossing a thresh hold here.
1541  * 2 cases 1) attach and the only way the mirror can be 64 bit is if
1542  * one of the submirrors already is. 2) grow and the only way the mirror
1543  * is 64 bit is if one of the submirror's already is.
1544  */
1545 int
meta_mirror_attach(mdsetname_t * sp,mdname_t * mirnp,mdname_t * submirnp,mdcmdopts_t options,md_error_t * ep)1546 meta_mirror_attach(
1547 	mdsetname_t	*sp,
1548 	mdname_t	*mirnp,
1549 	mdname_t	*submirnp,
1550 	mdcmdopts_t	options,
1551 	md_error_t	*ep
1552 )
1553 {
1554 	md_att_struct_t	att;
1555 	md_set_desc		*sd;
1556 
1557 	/* should have same set */
1558 	assert(sp != NULL);
1559 	assert(sp->setno == MD_MIN2SET(meta_getminor(mirnp->dev)));
1560 
1561 	/* check name */
1562 	if (metachkmeta(mirnp, ep) != 0)
1563 		return (-1);
1564 
1565 	/* just grow */
1566 	if (submirnp == NULL) {
1567 		return (meta_concat_generic(sp, mirnp, NULL, ep));
1568 	}
1569 
1570 	/* check submirror */
1571 	if (meta_check_submirror(sp, submirnp, mirnp, 0, ep) != 0)
1572 		return (-1);
1573 
1574 	/* In dryrun mode (DOIT not set) we must not alter the mddb */
1575 	if (options & MDCMD_DOIT) {
1576 		/* store name in namespace */
1577 		if (add_key_name(sp, submirnp, NULL, ep) != 0)
1578 			return (-1);
1579 	}
1580 
1581 	/*
1582 	 * In a MN set, the master always executes the attach command first.
1583 	 * Before the master executes the IOC_ATTACH ioctl, in non-DRYRUN mode
1584 	 * the master sends a message to all nodes to suspend writes to
1585 	 * this mirror.  Then the master executes the IOC_ATTACH ioctl
1586 	 * which resumes writes to this mirror from the master node.
1587 	 * As each slave executes the attach command, each slave will
1588 	 * call the IOC_ATTACH ioctl which will resume writes to this mirror
1589 	 * from that slave node.
1590 	 */
1591 	if (! metaislocalset(sp)) {
1592 		if ((sd = metaget_setdesc(sp, ep)) == NULL)
1593 			return (-1);
1594 		if ((MD_MNSET_DESC(sd)) && (options & MDCMD_DOIT) &&
1595 		    sd->sd_mn_am_i_master)
1596 			if (meta_mn_send_suspend_writes(
1597 			    meta_getminor(mirnp->dev), ep) != 0)
1598 				return (-1);
1599 	}
1600 
1601 	/* attach submirror */
1602 	(void) memset(&att, 0, sizeof (att));
1603 	att.mnum = meta_getminor(mirnp->dev);
1604 	MD_SETDRIVERNAME(&att, MD_MIRROR, sp->setno);
1605 	att.submirror = submirnp->dev;
1606 	att.key = submirnp->key;
1607 	/* if the comamnd was issued with -n option, use dryrun mode */
1608 	if ((options & MDCMD_DOIT) == 0) {
1609 		att.options = MDIOCTL_DRYRUN;
1610 	}
1611 	if (metaioctl(MD_IOCATTACH, &att, &att.mde, NULL) != 0) {
1612 		/* In dryrun mode (DOIT not set) we must not alter the mddb */
1613 		if (options & MDCMD_DOIT) {
1614 			(void) del_key_name(sp, submirnp, ep);
1615 		}
1616 		return (mdstealerror(ep, &att.mde));
1617 	}
1618 
1619 	/* In dryrun mode (DOIT not set) we must not alter the mddb */
1620 	if (options & MDCMD_DOIT) {
1621 		/* clear cache */
1622 		meta_invalidate_name(mirnp);
1623 		meta_invalidate_name(submirnp);
1624 	}
1625 
1626 	/* let em know */
1627 	if (options & MDCMD_PRINT) {
1628 		(void) printf(dgettext(TEXT_DOMAIN,
1629 		    "%s: submirror %s %s\n"), mirnp->cname, submirnp->cname,
1630 		    (options & MDCMD_DOIT) ? "is attached" : "would attach");
1631 		(void) fflush(stdout);
1632 	}
1633 
1634 	/* return success */
1635 	return (0);
1636 }
1637 
1638 /*
1639  * detach submirror
1640  */
1641 int
meta_mirror_detach(mdsetname_t * sp,mdname_t * mirnp,mdname_t * submirnp,mdcmdopts_t options,md_error_t * ep)1642 meta_mirror_detach(
1643 	mdsetname_t		*sp,
1644 	mdname_t		*mirnp,
1645 	mdname_t		*submirnp,
1646 	mdcmdopts_t		options,
1647 	md_error_t		*ep
1648 )
1649 {
1650 	int			force = ((options & MDCMD_FORCE) ? 1 : 0);
1651 	md_detach_params_t	detach;
1652 	md_set_desc		*sd;
1653 
1654 	/* should have same set */
1655 	assert(sp != NULL);
1656 	assert(sp->setno == MD_MIN2SET(meta_getminor(mirnp->dev)));
1657 
1658 	/* check name */
1659 	if (metachkmeta(mirnp, ep) != 0)
1660 		return (-1);
1661 
1662 	/*
1663 	 * In a MN set, the master always executes the detach command first.
1664 	 * Before the master executes the IOC_DETACH ioctl,
1665 	 * the master sends a message to all nodes to suspend writes to
1666 	 * this mirror.  Then the master executes the IOC_DETACH ioctl
1667 	 * which resumes writes to this mirror from the master node.
1668 	 * As each slave executes the detach command, each slave will
1669 	 * call the IOC_DETACH ioctl which will resume writes to this mirror
1670 	 * from that slave node.
1671 	 */
1672 	if (! metaislocalset(sp)) {
1673 		if ((sd = metaget_setdesc(sp, ep)) == NULL)
1674 			return (-1);
1675 		if ((MD_MNSET_DESC(sd)) && sd->sd_mn_am_i_master)
1676 			if (meta_mn_send_suspend_writes(
1677 			    meta_getminor(mirnp->dev), ep) != 0)
1678 				return (-1);
1679 	}
1680 
1681 	/* detach submirror */
1682 	(void) memset(&detach, 0, sizeof (detach));
1683 	detach.mnum = meta_getminor(mirnp->dev);
1684 	MD_SETDRIVERNAME(&detach, MD_MIRROR, sp->setno);
1685 	detach.submirror = submirnp->dev;
1686 	detach.force_detach = force;
1687 	if (metaioctl(MD_IOCDETACH, &detach, &detach.mde, NULL) != 0)
1688 		return (mdstealerror(ep, &detach.mde));
1689 
1690 	/* clear cache */
1691 	meta_invalidate_name(mirnp);
1692 	meta_invalidate_name(submirnp);
1693 
1694 	/* let em know */
1695 	if (options & MDCMD_PRINT) {
1696 		(void) printf(dgettext(TEXT_DOMAIN,
1697 		    "%s: submirror %s is detached\n"),
1698 		    mirnp->cname, submirnp->cname);
1699 		(void) fflush(stdout);
1700 	}
1701 
1702 	/* return success */
1703 	return (0);
1704 }
1705 
1706 /*
1707  * get mirror parameters
1708  */
1709 int
meta_mirror_get_params(mdsetname_t * sp,mdname_t * mirnp,mm_params_t * paramsp,md_error_t * ep)1710 meta_mirror_get_params(
1711 	mdsetname_t	*sp,
1712 	mdname_t	*mirnp,
1713 	mm_params_t	*paramsp,
1714 	md_error_t	*ep
1715 )
1716 {
1717 	md_mirror_t	*mirrorp;
1718 
1719 	/* should have a set */
1720 	assert(sp != NULL);
1721 	assert(sp->setno == MD_MIN2SET(meta_getminor(mirnp->dev)));
1722 
1723 	/* check name */
1724 	if (metachkmeta(mirnp, ep) != 0)
1725 		return (-1);
1726 
1727 	/* get unit */
1728 	if ((mirrorp = meta_get_mirror(sp, mirnp, ep)) == NULL)
1729 		return (-1);
1730 
1731 	/* return parameters */
1732 	(void) memset(paramsp, 0, sizeof (*paramsp));
1733 	paramsp->read_option = mirrorp->read_option;
1734 	paramsp->write_option = mirrorp->write_option;
1735 	paramsp->pass_num = mirrorp->pass_num;
1736 	return (0);
1737 }
1738 
1739 /*
1740  * set mirror parameters
1741  */
1742 int
meta_mirror_set_params(mdsetname_t * sp,mdname_t * mirnp,mm_params_t * paramsp,md_error_t * ep)1743 meta_mirror_set_params(
1744 	mdsetname_t		*sp,
1745 	mdname_t		*mirnp,
1746 	mm_params_t		*paramsp,
1747 	md_error_t		*ep
1748 )
1749 {
1750 	md_mirror_params_t	mmp;
1751 
1752 	/* should have a set */
1753 	assert(sp != NULL);
1754 	assert(sp->setno == MD_MIN2SET(meta_getminor(mirnp->dev)));
1755 
1756 	/* check name */
1757 	if (metachkmeta(mirnp, ep) != 0)
1758 		return (-1);
1759 
1760 	/* set parameters */
1761 	(void) memset(&mmp, 0, sizeof (mmp));
1762 	MD_SETDRIVERNAME(&mmp, MD_MIRROR, sp->setno);
1763 	mmp.mnum = meta_getminor(mirnp->dev);
1764 	mmp.params = *paramsp;
1765 	if (metaioctl(MD_IOCCHANGE, &mmp, &mmp.mde, mirnp->cname) != 0)
1766 		return (mdstealerror(ep, &mmp.mde));
1767 
1768 	/* clear cache */
1769 	meta_invalidate_name(mirnp);
1770 
1771 	/* return success */
1772 	return (0);
1773 }
1774 
1775 /*
1776  * invalidate submirror names
1777  */
1778 static int
invalidate_submirrors(mdsetname_t * sp,mdname_t * mirnp,md_error_t * ep)1779 invalidate_submirrors(
1780 	mdsetname_t	*sp,
1781 	mdname_t	*mirnp,
1782 	md_error_t	*ep
1783 )
1784 {
1785 	md_mirror_t	*mirrorp;
1786 	uint_t		smi;
1787 
1788 	if ((mirrorp = meta_get_mirror(sp, mirnp, ep)) == NULL)
1789 		return (-1);
1790 	for (smi = 0; (smi < NMIRROR); ++smi) {
1791 		md_submirror_t	*mdsp = &mirrorp->submirrors[smi];
1792 		mdname_t	*submirnp = mdsp->submirnamep;
1793 
1794 		if (submirnp == NULL) {
1795 			assert(mdsp->state == SMS_UNUSED);
1796 			continue;
1797 		}
1798 		meta_invalidate_name(submirnp);
1799 	}
1800 	return (0);
1801 }
1802 
1803 /*
1804  * replace mirror component
1805  */
1806 int
meta_mirror_replace(mdsetname_t * sp,mdname_t * mirnp,mdname_t * oldnp,mdname_t * newnp,mdcmdopts_t options,md_error_t * ep)1807 meta_mirror_replace(
1808 	mdsetname_t		*sp,
1809 	mdname_t		*mirnp,
1810 	mdname_t		*oldnp,
1811 	mdname_t		*newnp,
1812 	mdcmdopts_t		options,
1813 	md_error_t		*ep
1814 )
1815 {
1816 	md_mirror_t		*mirrorp;
1817 	uint_t			smi;
1818 	replace_params_t	params;
1819 	diskaddr_t		size, label, start_blk;
1820 	md_dev64_t		old_dev, new_dev;
1821 	diskaddr_t		new_start_blk, new_end_blk;
1822 	int			rebind;
1823 	md_set_desc		*sd;
1824 	char			*new_devidp = NULL;
1825 	int			ret;
1826 	md_error_t		xep = mdnullerror;
1827 
1828 	/* should have same set */
1829 	assert(sp != NULL);
1830 	assert(sp->setno == MD_MIN2SET(meta_getminor(mirnp->dev)));
1831 
1832 	/* check name */
1833 	if (metachkmeta(mirnp, ep) != 0)
1834 		return (-1);
1835 
1836 	/* save new binding incase this is a rebind where oldnp==newnp */
1837 	new_dev = newnp->dev;
1838 	new_start_blk = newnp->start_blk;
1839 	new_end_blk = newnp->end_blk;
1840 
1841 	/* invalidate, then get the mirror (fill in oldnp from metadb) */
1842 	meta_invalidate_name(mirnp);
1843 	if ((mirrorp = meta_get_mirror(sp, mirnp, ep)) == NULL)
1844 		return (-1);
1845 	for (smi = 0; (smi < NMIRROR); ++smi) {
1846 		md_submirror_t	*mdsp = &mirrorp->submirrors[smi];
1847 		mdname_t	*submirnp = mdsp->submirnamep;
1848 
1849 		if (submirnp == NULL) {
1850 			assert(mdsp->state == SMS_UNUSED);
1851 			continue;
1852 		}
1853 
1854 		if (! metaismeta(submirnp))
1855 			continue;
1856 
1857 		meta_invalidate_name(submirnp);
1858 		if (meta_get_unit(sp, submirnp, ep) == NULL)
1859 			return (-1);
1860 	}
1861 
1862 	/* the old device binding is now established */
1863 	if ((old_dev = oldnp->dev) == NODEV64)
1864 		return (mdsyserror(ep, ENODEV, oldnp->cname));
1865 
1866 	/*
1867 	 * check for the case where oldnp and newnp indicate the same
1868 	 * device, but the dev_t of the device has changed between old
1869 	 * and new.  This is called a rebind.  On entry the dev_t
1870 	 * represents the new device binding determined from the
1871 	 * filesystem (meta_getdev). After calling meta_get_unit
1872 	 * oldnp (and maybe newnp if this is a rebind) is updated based
1873 	 * to the old binding from the metadb (done by metakeyname).
1874 	 */
1875 	if ((strcmp(oldnp->rname, newnp->rname) == 0) &&
1876 	    (old_dev != new_dev)) {
1877 		rebind = 1;
1878 	} else {
1879 		rebind = 0;
1880 	}
1881 	if (rebind) {
1882 		newnp->dev = new_dev;
1883 		newnp->start_blk = new_start_blk;
1884 		newnp->end_blk = new_end_blk;
1885 	}
1886 
1887 	/*
1888 	 * Save a copy of the devid associated with the new disk, the reason
1889 	 * is that if we are rebinding then the call to meta_check_component()
1890 	 * will cause the devid of the disk to be overwritten with what is in
1891 	 * the replica namespace. The function that actually overwrites the
1892 	 * devid is dr2drivedesc().
1893 	 */
1894 	if (newnp->drivenamep->devid != NULL)
1895 		new_devidp = Strdup(newnp->drivenamep->devid);
1896 
1897 	/* if it's a multi-node diskset clear new_devidp */
1898 	if (!metaislocalset(sp)) {
1899 		if ((sd = metaget_setdesc(sp, ep)) == NULL)
1900 			return (-1);
1901 		if (MD_MNSET_DESC(sd))
1902 			new_devidp = NULL;
1903 	}
1904 
1905 	/* check it out (dup on rebind is ok) */
1906 	if (meta_check_component(sp, newnp, 0, ep) != 0) {
1907 		if ((! rebind) || (! mdisuseerror(ep, MDE_ALREADY))) {
1908 			Free(new_devidp);
1909 			return (-1);
1910 		}
1911 		mdclrerror(ep);
1912 	}
1913 	if ((size = metagetsize(newnp, ep)) == MD_DISKADDR_ERROR) {
1914 		Free(new_devidp);
1915 		return (-1);
1916 	}
1917 	if ((label = metagetlabel(newnp, ep)) == MD_DISKADDR_ERROR) {
1918 		Free(new_devidp);
1919 		return (-1);
1920 	}
1921 	if ((start_blk = metagetstart(sp, newnp, ep)) == MD_DISKADDR_ERROR) {
1922 		Free(new_devidp);
1923 		return (-1);
1924 	}
1925 	if (start_blk >= size) {
1926 		(void) mdsyserror(ep, ENOSPC, newnp->cname);
1927 		Free(new_devidp);
1928 		return (-1);
1929 	}
1930 
1931 	/*
1932 	 * Copy back the saved devid.
1933 	 */
1934 	Free(newnp->drivenamep->devid);
1935 	if (new_devidp != NULL) {
1936 		newnp->drivenamep->devid = Strdup(new_devidp);
1937 		Free(new_devidp);
1938 	}
1939 
1940 	/* store name in namespace, allocate new key */
1941 	if (add_key_name(sp, newnp, NULL, ep) != 0)
1942 		return (-1);
1943 
1944 	/*
1945 	 * In a MN set, the master always executes the replace command first.
1946 	 * Before the master executes the IOC_REPLACE ioctl, in non-DRYRUN mode
1947 	 * the master sends a message to all nodes to suspend writes to
1948 	 * this mirror.  Then the master executes the IOC_REPLACE ioctl
1949 	 * which resumes writes to this mirror from the master node.
1950 	 * As each slave executes the replace command, each slave will
1951 	 * call the IOC_REPLACE ioctl which will resume writes to this mirror
1952 	 * from that slave node.
1953 	 */
1954 	if (! metaislocalset(sp)) {
1955 		if ((MD_MNSET_DESC(sd)) && (options & MDCMD_DOIT) &&
1956 		    sd->sd_mn_am_i_master)
1957 			if (meta_mn_send_suspend_writes(
1958 			    meta_getminor(mirnp->dev), ep) != 0)
1959 				return (-1);
1960 	}
1961 
1962 	if (rebind && !metaislocalset(sp)) {
1963 		/*
1964 		 * We are 'rebind'ing a disk that is in a diskset so as well
1965 		 * as updating the diskset's namespace the local set needs
1966 		 * to be updated because it also contains a reference to
1967 		 * the disk in question.
1968 		 */
1969 		ret = meta_fixdevid(sp, DEV_UPDATE|DEV_LOCAL_SET,
1970 		    newnp->cname, ep);
1971 
1972 		if (ret != METADEVADM_SUCCESS) {
1973 			(void) del_key_name(sp, newnp, &xep);
1974 			return (-1);
1975 		}
1976 	}
1977 
1978 	/* replace component */
1979 	(void) memset(&params, 0, sizeof (params));
1980 	params.mnum = meta_getminor(mirnp->dev);
1981 	MD_SETDRIVERNAME(&params, MD_MIRROR, sp->setno);
1982 	params.cmd = REPLACE_COMP;
1983 	params.old_dev = old_dev;
1984 	params.new_dev = new_dev;
1985 	params.start_blk = start_blk;
1986 	params.has_label = ((label > 0) ? 1 : 0);
1987 	params.number_blks = size;
1988 	params.new_key = newnp->key;
1989 	/* Is this just a dryrun ? */
1990 	if ((options & MDCMD_DOIT) == 0) {
1991 		params.options |= MDIOCTL_DRYRUN;
1992 	}
1993 	if (metaioctl(MD_IOCREPLACE, &params, &params.mde, NULL) != 0) {
1994 		(void) del_key_name(sp, newnp, ep);
1995 		return (mdstealerror(ep, &params.mde));
1996 	}
1997 
1998 	/* clear cache */
1999 	meta_invalidate_name(oldnp);
2000 	meta_invalidate_name(newnp);
2001 	if (invalidate_submirrors(sp, mirnp, ep) != 0) {
2002 		meta_invalidate_name(mirnp);
2003 		return (-1);
2004 	}
2005 	meta_invalidate_name(mirnp);
2006 
2007 	/* let em know */
2008 	if (options & MDCMD_PRINT) {
2009 		(void) printf(dgettext(TEXT_DOMAIN,
2010 		    "%s: device %s is replaced with %s\n"),
2011 		    mirnp->cname, oldnp->cname, newnp->cname);
2012 		(void) fflush(stdout);
2013 	}
2014 
2015 	/* return success */
2016 	return (0);
2017 }
2018 
2019 /*
2020  * enable mirror component
2021  */
2022 int
meta_mirror_enable(mdsetname_t * sp,mdname_t * mirnp,mdname_t * compnp,mdcmdopts_t options,md_error_t * ep)2023 meta_mirror_enable(
2024 	mdsetname_t		*sp,
2025 	mdname_t		*mirnp,
2026 	mdname_t		*compnp,
2027 	mdcmdopts_t		options,
2028 	md_error_t		*ep
2029 )
2030 {
2031 	md_mirror_t		*mirrorp;
2032 	uint_t			smi;
2033 	replace_params_t	params;
2034 	diskaddr_t		size, label, start_blk;
2035 	md_dev64_t		fs_dev;
2036 	md_set_desc		*sd;
2037 	int			ret;
2038 
2039 	/* should have same set */
2040 	assert(sp != NULL);
2041 	assert(sp->setno == MD_MIN2SET(meta_getminor(mirnp->dev)));
2042 
2043 	/* check name */
2044 	if (metachkmeta(mirnp, ep) != 0)
2045 		return (-1);
2046 
2047 	/* get the file_system dev binding */
2048 	if (meta_getdev(sp, compnp, ep) != 0)
2049 		return (-1);
2050 	fs_dev = compnp->dev;
2051 
2052 	/* get the mirror unit (fill in compnp->dev with metadb version) */
2053 	meta_invalidate_name(mirnp);
2054 	if ((mirrorp = meta_get_mirror(sp, mirnp, ep)) == NULL)
2055 		return (-1);
2056 
2057 	for (smi = 0; (smi < NMIRROR); ++smi) {
2058 		md_submirror_t	*mdsp = &mirrorp->submirrors[smi];
2059 		mdname_t	*submirnp = mdsp->submirnamep;
2060 
2061 		if (submirnp == NULL) {
2062 			assert(mdsp->state == SMS_UNUSED);
2063 			continue;
2064 		}
2065 
2066 		if (! metaismeta(submirnp))
2067 			continue;
2068 
2069 		meta_invalidate_name(submirnp);
2070 		if (meta_get_unit(sp, submirnp, ep) == NULL)
2071 			return (-1);
2072 	}
2073 
2074 	/* the metadb device binding is now established */
2075 	if (compnp->dev == NODEV64)
2076 		return (mdsyserror(ep, ENODEV, compnp->cname));
2077 
2078 	/*
2079 	 * check for the case where the dev_t has changed between the
2080 	 * filesystem and the metadb.  This is called a rebind, and
2081 	 * is handled by meta_mirror_replace.
2082 	 */
2083 	if (fs_dev != compnp->dev) {
2084 		/* establish file system binding with invalid start/end */
2085 		compnp->dev = fs_dev;
2086 		compnp->start_blk = -1;
2087 		compnp->end_blk = -1;
2088 		return (meta_mirror_replace(sp, mirnp,
2089 		    compnp, compnp, options, ep));
2090 	}
2091 
2092 	/* setup mirror info */
2093 	(void) memset(&params, 0, sizeof (params));
2094 	params.mnum = meta_getminor(mirnp->dev);
2095 	MD_SETDRIVERNAME(&params, MD_MIRROR, sp->setno);
2096 	params.cmd = ENABLE_COMP;
2097 
2098 	/* check it out */
2099 	if (meta_check_component(sp, compnp, 0, ep) != 0) {
2100 		if (! mdisuseerror(ep, MDE_ALREADY))
2101 			return (-1);
2102 		mdclrerror(ep);
2103 	}
2104 
2105 	if ((size = metagetsize(compnp, ep)) == MD_DISKADDR_ERROR)
2106 		return (-1);
2107 	if ((label = metagetlabel(compnp, ep)) == MD_DISKADDR_ERROR)
2108 		return (-1);
2109 	if ((start_blk = metagetstart(sp, compnp, ep)) == MD_DISKADDR_ERROR)
2110 		return (-1);
2111 	if (start_blk >= size) {
2112 		(void) mdsyserror(ep, ENOSPC, compnp->cname);
2113 		return (-1);
2114 	}
2115 
2116 	/*
2117 	 * In a MN set, the master always executes the replace command first.
2118 	 * Before the master executes the IOC_REPLACE ioctl, in non-DRYRUN mode
2119 	 * the master sends a message to all nodes to suspend writes to
2120 	 * this mirror.  Then the master executes the IOC_REPLACE ioctl
2121 	 * which resumes writes to this mirror from the master node.
2122 	 * As each slave executes the replace command, each slave will
2123 	 * call the IOC_REPLACE ioctl which will resume writes to this mirror
2124 	 * from that slave node.
2125 	 */
2126 	if (! metaislocalset(sp)) {
2127 		if ((sd = metaget_setdesc(sp, ep)) == NULL)
2128 			return (-1);
2129 		if ((MD_MNSET_DESC(sd)) && (options & MDCMD_DOIT) &&
2130 		    sd->sd_mn_am_i_master)
2131 			if (meta_mn_send_suspend_writes(
2132 			    meta_getminor(mirnp->dev), ep) != 0)
2133 				return (-1);
2134 	}
2135 
2136 	/* enable component */
2137 	params.old_dev = compnp->dev;
2138 	params.new_dev = compnp->dev;
2139 	params.start_blk = start_blk;
2140 	params.has_label = ((label > 0) ? 1 : 0);
2141 	params.number_blks = size;
2142 
2143 	/* Is this just a dryrun ? */
2144 	if ((options & MDCMD_DOIT) == 0) {
2145 		params.options |= MDIOCTL_DRYRUN;
2146 	}
2147 	if (metaioctl(MD_IOCREPLACE, &params, &params.mde, NULL) != 0)
2148 		return (mdstealerror(ep, &params.mde));
2149 
2150 	/*
2151 	 * Are we dealing with a non-local set? If so need to update the
2152 	 * local namespace so that the disk record has the correct devid.
2153 	 */
2154 	if (!metaislocalset(sp)) {
2155 		ret = meta_fixdevid(sp, DEV_UPDATE|DEV_LOCAL_SET, compnp->cname,
2156 		    ep);
2157 
2158 		if (ret != METADEVADM_SUCCESS) {
2159 			/*
2160 			 * Failed to update the local set. Nothing to do here
2161 			 * apart from report the error. The namespace is
2162 			 * most likely broken and some form of remedial
2163 			 * recovery is going to be required.
2164 			 */
2165 			mde_perror(ep, "");
2166 			mdclrerror(ep);
2167 		}
2168 	}
2169 
2170 	/* clear cache */
2171 	meta_invalidate_name(compnp);
2172 	if (invalidate_submirrors(sp, mirnp, ep) != 0) {
2173 		meta_invalidate_name(mirnp);
2174 		return (-1);
2175 	}
2176 	meta_invalidate_name(mirnp);
2177 
2178 	/* let em know */
2179 	if (options & MDCMD_PRINT) {
2180 		(void) printf(dgettext(TEXT_DOMAIN,
2181 		    "%s: device %s is enabled\n"),
2182 		    mirnp->cname, compnp->cname);
2183 		(void) fflush(stdout);
2184 	}
2185 
2186 	/* return success */
2187 	return (0);
2188 }
2189 
2190 /*
2191  * check for dups in the mirror itself
2192  */
2193 static int
check_twice(md_mirror_t * mirrorp,uint_t smi,md_error_t * ep)2194 check_twice(
2195 	md_mirror_t	*mirrorp,
2196 	uint_t		smi,
2197 	md_error_t	*ep
2198 )
2199 {
2200 	mdname_t	*mirnp = mirrorp->common.namep;
2201 	mdname_t	*thisnp;
2202 	uint_t		s;
2203 
2204 	thisnp = mirrorp->submirrors[smi].submirnamep;
2205 	for (s = 0; (s < smi); ++s) {
2206 		md_submirror_t	*mdsp = &mirrorp->submirrors[s];
2207 		mdname_t	*submirnp = mdsp->submirnamep;
2208 
2209 		if (submirnp == NULL)
2210 			continue;
2211 
2212 		if (meta_check_overlap(mirnp->cname, thisnp, 0, -1,
2213 		    submirnp, 0, -1, ep) != 0) {
2214 			return (-1);
2215 		}
2216 	}
2217 	return (0);
2218 }
2219 
2220 /*
2221  * check mirror
2222  */
2223 int
meta_check_mirror(mdsetname_t * sp,md_mirror_t * mirrorp,mdcmdopts_t options,md_error_t * ep)2224 meta_check_mirror(
2225 	mdsetname_t	*sp,
2226 	md_mirror_t	*mirrorp,
2227 	mdcmdopts_t	options,
2228 	md_error_t	*ep
2229 )
2230 {
2231 	mdname_t	*mirnp = mirrorp->common.namep;
2232 	int		force = ((options & MDCMD_FORCE) ? 1 : 0);
2233 	int		doit = ((options & MDCMD_DOIT) ? 1 : 0);
2234 	uint_t		nsm = 0;
2235 	uint_t		smi;
2236 
2237 	/* check submirrors */
2238 	for (smi = 0; (smi < NMIRROR); ++smi) {
2239 		md_submirror_t	*mdsp = &mirrorp->submirrors[smi];
2240 		mdname_t	*submirnp = mdsp->submirnamep;
2241 
2242 		if (submirnp == NULL)
2243 			continue;
2244 		++nsm;
2245 	}
2246 	if (nsm < 1) {
2247 		return (mdmderror(ep, MDE_BAD_MIRROR,
2248 		    meta_getminor(mirnp->dev), mirnp->cname));
2249 	}
2250 	for (smi = 0; (smi < NMIRROR); ++smi) {
2251 		md_submirror_t	*mdsp = &mirrorp->submirrors[smi];
2252 		mdname_t	*submirnp = mdsp->submirnamep;
2253 		diskaddr_t	size;
2254 
2255 		/* skip unused submirrors */
2256 		if (submirnp == NULL) {
2257 			if (mdsp->state != SMS_UNUSED) {
2258 				return (mdmderror(ep, MDE_BAD_MIRROR,
2259 				    meta_getminor(mirnp->dev), mirnp->cname));
2260 			}
2261 			continue;
2262 		}
2263 
2264 		/* check submirror */
2265 		if (doit) {
2266 			if (meta_check_submirror(sp, submirnp, NULL, force,
2267 			    ep) != 0)
2268 				return (-1);
2269 			if ((size = metagetsize(submirnp, ep)) ==
2270 			    MD_DISKADDR_ERROR) {
2271 				return (-1);
2272 			} else if (size == 0) {
2273 				return (mdsyserror(ep, ENOSPC,
2274 					submirnp->cname));
2275 			}
2276 		}
2277 
2278 		/* check this mirror too */
2279 		if (check_twice(mirrorp, smi, ep) != 0)
2280 			return (-1);
2281 	}
2282 
2283 	/* check read option */
2284 	switch (mirrorp->read_option) {
2285 	case RD_LOAD_BAL:
2286 	case RD_GEOMETRY:
2287 	case RD_FIRST:
2288 		break;
2289 	default:
2290 		return (mderror(ep, MDE_BAD_RD_OPT, mirnp->cname));
2291 	}
2292 
2293 	/* check write option */
2294 	switch (mirrorp->write_option) {
2295 	case WR_PARALLEL:
2296 	case WR_SERIAL:
2297 		break;
2298 	default:
2299 		return (mderror(ep, MDE_BAD_WR_OPT, mirnp->cname));
2300 	}
2301 
2302 	/* check pass number */
2303 	if ((mirrorp->pass_num < 0) || (mirrorp->pass_num > MD_PASS_MAX))
2304 		return (mderror(ep, MDE_BAD_PASS_NUM, mirnp->cname));
2305 
2306 	/* return success */
2307 	return (0);
2308 }
2309 
2310 /*
2311  * setup mirror geometry
2312  */
2313 static int
mirror_geom(md_mirror_t * mirrorp,mm_unit_t * mm,md_error_t * ep)2314 mirror_geom(
2315 	md_mirror_t	*mirrorp,
2316 	mm_unit_t	*mm,
2317 	md_error_t	*ep
2318 )
2319 {
2320 	uint_t		write_reinstruct = 0;
2321 	uint_t		read_reinstruct = 0;
2322 	uint_t		round_cyl = 1;
2323 	mdname_t	*smnp = NULL;
2324 	uint_t		smi;
2325 	mdgeom_t	*geomp;
2326 
2327 	/* get worst reinstructs */
2328 	for (smi = 0; (smi < NMIRROR); ++smi) {
2329 		md_submirror_t	*mdsp = &mirrorp->submirrors[smi];
2330 		mdname_t	*submirnp = mdsp->submirnamep;
2331 
2332 		if (submirnp == NULL)
2333 			continue;
2334 
2335 		if ((geomp = metagetgeom(submirnp, ep)) == NULL)
2336 			return (-1);
2337 		if (geomp->write_reinstruct > write_reinstruct)
2338 			write_reinstruct = geomp->write_reinstruct;
2339 		if (geomp->read_reinstruct > read_reinstruct)
2340 			read_reinstruct = geomp->read_reinstruct;
2341 
2342 		if (smnp == NULL)
2343 			smnp = submirnp;
2344 	}
2345 
2346 	/* setup geometry from first submirror */
2347 	assert(smnp != NULL);
2348 	if ((geomp = metagetgeom(smnp, ep)) == NULL)
2349 		return (-1);
2350 	if (meta_setup_geom((md_unit_t *)mm, mirrorp->common.namep, geomp,
2351 	    write_reinstruct, read_reinstruct, round_cyl, ep) != 0)
2352 		return (-1);
2353 
2354 	/* return success */
2355 	return (0);
2356 }
2357 
2358 /*
2359  * create mirror
2360  */
2361 int
meta_create_mirror(mdsetname_t * sp,md_mirror_t * mirrorp,mdcmdopts_t options,md_error_t * ep)2362 meta_create_mirror(
2363 	mdsetname_t	*sp,
2364 	md_mirror_t	*mirrorp,
2365 	mdcmdopts_t	options,
2366 	md_error_t	*ep
2367 )
2368 {
2369 	mdname_t	*mirnp = mirrorp->common.namep;
2370 	mm_unit_t	*mm;
2371 	diskaddr_t	submir_size = MD_DISKADDR_ERROR;
2372 	ushort_t	nsm = 0;
2373 	uint_t		smi;
2374 	mdnamelist_t	*keynlp = NULL;
2375 	md_set_params_t	set_params;
2376 	int		rval = -1;
2377 	md_timeval32_t	creation_time;
2378 	int		create_flag = MD_CRO_32BIT;
2379 
2380 	/* validate mirror */
2381 	if (meta_check_mirror(sp, mirrorp, options, ep) != 0)
2382 		return (-1);
2383 
2384 
2385 	/* allocate mirror unit */
2386 	mm = Zalloc(sizeof (*mm));
2387 
2388 	if (meta_gettimeofday(&creation_time) == -1)
2389 		return (mdsyserror(ep, errno, NULL));
2390 
2391 	/* do submirrors */
2392 	for (smi = 0; (smi < NMIRROR); ++smi) {
2393 		md_submirror_t	*mdsp = &mirrorp->submirrors[smi];
2394 		mdname_t	*submirnp = mdsp->submirnamep;
2395 		mm_submirror_t	*mmsp = &mm->un_sm[smi];
2396 		diskaddr_t	size;
2397 
2398 		/* skip unused submirrors */
2399 		if (submirnp == NULL) {
2400 			assert(mdsp->state == SMS_UNUSED);
2401 			continue;
2402 		}
2403 		++nsm;
2404 
2405 		/* get size */
2406 		if ((size = metagetsize(submirnp, ep)) == MD_DISKADDR_ERROR)
2407 			goto out;
2408 		assert(size > 0);
2409 
2410 		/* adjust for smallest submirror */
2411 		if (submir_size == MD_DISKADDR_ERROR) {
2412 			submir_size = size;
2413 		} else if (size < submir_size) {
2414 			submir_size = size;
2415 		}
2416 
2417 		if (options & MDCMD_DOIT) {
2418 			/* store name in namespace */
2419 			if (add_key_name(sp, submirnp, &keynlp, ep) != 0)
2420 				goto out;
2421 		}
2422 
2423 		/* setup submirror */
2424 		mmsp->sm_key = submirnp->key;
2425 		mmsp->sm_dev = submirnp->dev;
2426 		mmsp->sm_state = SMS_RUNNING;
2427 		mmsp->sm_timestamp = creation_time;
2428 	}
2429 
2430 	/* setup unit */
2431 	mm->c.un_type = MD_METAMIRROR;
2432 	MD_SID(mm) = meta_getminor(mirnp->dev);
2433 	mm->c.un_actual_tb = submir_size;
2434 	mm->c.un_size = offsetof(mm_unit_t, un_smic);
2435 	mm->un_nsm = nsm;
2436 	mm->un_read_option = mirrorp->read_option;
2437 	mm->un_write_option = mirrorp->write_option;
2438 	mm->un_pass_num = mirrorp->pass_num;
2439 	if (mirror_geom(mirrorp, mm, ep) != 0)
2440 		goto out;
2441 
2442 	/* fill in the size of the mirror */
2443 	if (options & MDCMD_UPDATE) {
2444 		mirrorp->common.size = mm->c.un_total_blocks;
2445 	}
2446 
2447 	/* if we're not doing anything, return success */
2448 	if (! (options & MDCMD_DOIT)) {
2449 		rval = 0;	/* success */
2450 		goto out;
2451 	}
2452 
2453 	/* create mirror */
2454 	(void) memset(&set_params, 0, sizeof (set_params));
2455 	/* did the user tell us to generate a large device? */
2456 	create_flag = meta_check_devicesize(mm->c.un_total_blocks);
2457 	if (create_flag == MD_CRO_64BIT) {
2458 		mm->c.un_revision |= MD_64BIT_META_DEV;
2459 		set_params.options = MD_CRO_64BIT;
2460 	} else {
2461 		mm->c.un_revision &= ~MD_64BIT_META_DEV;
2462 		set_params.options = MD_CRO_32BIT;
2463 	}
2464 	set_params.mnum = MD_SID(mm);
2465 	set_params.size = mm->c.un_size;
2466 	set_params.mdp = (uintptr_t)mm;
2467 	MD_SETDRIVERNAME(&set_params, MD_MIRROR, MD_MIN2SET(set_params.mnum));
2468 	if (metaioctl(MD_IOCSET, &set_params, &set_params.mde,
2469 	    mirnp->cname) != 0) {
2470 		(void) mdstealerror(ep, &set_params.mde);
2471 		goto out;
2472 	}
2473 	rval = 0;	/* success */
2474 
2475 	/* cleanup, return success */
2476 out:
2477 	Free(mm);
2478 	if (rval != 0) {
2479 		(void) del_key_names(sp, keynlp, NULL);
2480 	}
2481 	metafreenamelist(keynlp);
2482 	if ((rval == 0) && (options & MDCMD_DOIT)) {
2483 		if (invalidate_submirrors(sp, mirnp, ep) != 0)
2484 			rval = -1;
2485 		meta_invalidate_name(mirnp);
2486 	}
2487 	return (rval);
2488 }
2489 
2490 /*
2491  * initialize mirror
2492  * NOTE: this functions is metainit(1m)'s command line parser!
2493  */
2494 int
meta_init_mirror(mdsetname_t ** spp,int argc,char * argv[],mdcmdopts_t options,md_error_t * ep)2495 meta_init_mirror(
2496 	mdsetname_t	**spp,
2497 	int		argc,
2498 	char		*argv[],
2499 	mdcmdopts_t	options,
2500 	md_error_t	*ep
2501 )
2502 {
2503 	char		*uname = argv[0];
2504 	mdname_t	*mirnp = NULL;
2505 	int		old_optind;
2506 	int		c;
2507 	md_mirror_t	*mirrorp = NULL;
2508 	uint_t		smi;
2509 	int		rval = -1;
2510 
2511 	/* get mirror name */
2512 	assert(argc > 0);
2513 	if (argc < 1)
2514 		goto syntax;
2515 	if ((mirnp = metaname(spp, uname, META_DEVICE, ep)) == NULL)
2516 		goto out;
2517 	assert(*spp != NULL);
2518 	uname = mirnp->cname;
2519 	if (metachkmeta(mirnp, ep) != 0)
2520 		goto out;
2521 
2522 	if (!(options & MDCMD_NOLOCK)) {
2523 		/* grab set lock */
2524 		if (meta_lock(*spp, TRUE, ep) != 0)
2525 			goto out;
2526 
2527 		if (meta_check_ownership(*spp, ep) != 0)
2528 			goto out;
2529 	}
2530 
2531 	/* see if it exists already */
2532 	if (metagetmiscname(mirnp, ep) != NULL) {
2533 		(void) mdmderror(ep, MDE_UNIT_ALREADY_SETUP,
2534 		    meta_getminor(mirnp->dev), uname);
2535 		goto out;
2536 	} else if (! mdismderror(ep, MDE_UNIT_NOT_SETUP)) {
2537 		goto out;
2538 	} else {
2539 		mdclrerror(ep);
2540 	}
2541 	--argc, ++argv;
2542 
2543 	/* grab -m */
2544 	if ((argc < 1) || (strcmp(argv[0], "-m") != 0))
2545 		goto syntax;
2546 	--argc, ++argv;
2547 
2548 	if (argc == 0)
2549 		goto syntax;
2550 
2551 	/* parse general options */
2552 	optind = 0;
2553 	opterr = 0;
2554 	if (getopt(argc, argv, "") != -1)
2555 		goto options;
2556 
2557 	/* allocate mirror */
2558 	mirrorp = Zalloc(sizeof (*mirrorp));
2559 
2560 	/* setup common */
2561 	mirrorp->common.namep = mirnp;
2562 	mirrorp->common.type = MD_METAMIRROR;
2563 
2564 	/* parse submirrors */
2565 	for (smi = 0; ((argc > 0) && (argv[0][0] != '-') &&
2566 	    (! isdigit(argv[0][0]))); ++smi) {
2567 		md_submirror_t	*mdsm = &mirrorp->submirrors[smi];
2568 		mdname_t	*submirnamep;
2569 
2570 		/* check for room */
2571 		if (smi >= NMIRROR) {
2572 			(void) mdmderror(ep, MDE_MIRROR_FULL,
2573 			    meta_getminor(mirnp->dev), uname);
2574 			goto out;
2575 		}
2576 
2577 		/* parse submirror name */
2578 		if ((submirnamep = metaname(spp, argv[0],
2579 		    META_DEVICE, ep)) == NULL)
2580 			goto out;
2581 		mdsm->submirnamep = submirnamep;
2582 		--argc, ++argv;
2583 	}
2584 	if (smi == 0) {
2585 		(void) mdmderror(ep, MDE_NSUBMIRS, meta_getminor(mirnp->dev),
2586 					uname);
2587 		goto out;
2588 	}
2589 
2590 	/* dangerous n-way mirror creation */
2591 	if ((smi > 1) && (options & MDCMD_PRINT)) {
2592 		md_eprintf(dgettext(TEXT_DOMAIN,
2593 "%s: WARNING: This form of metainit is not recommended.\n"
2594 "The submirrors may not have the same data.\n"
2595 "Please see ERRORS in metainit(1M) for additional information.\n"),
2596 		    uname);
2597 	}
2598 
2599 	/* parse mirror options */
2600 	mirrorp->read_option = RD_LOAD_BAL;
2601 	mirrorp->write_option = WR_PARALLEL;
2602 	mirrorp->pass_num = MD_PASS_DEFAULT;
2603 	old_optind = optind = 0;
2604 	opterr = 0;
2605 	while ((c = getopt(argc, argv, "grS")) != -1) {
2606 		switch (c) {
2607 		case 'g':
2608 			if (mirrorp->read_option != RD_LOAD_BAL) {
2609 				(void) mderror(ep, MDE_BAD_RD_OPT, uname);
2610 				goto out;
2611 			}
2612 			mirrorp->read_option = RD_GEOMETRY;
2613 			break;
2614 
2615 		case 'r':
2616 			if (mirrorp->read_option != RD_LOAD_BAL) {
2617 				(void) mderror(ep, MDE_BAD_RD_OPT, uname);
2618 				goto out;
2619 			}
2620 			mirrorp->read_option = RD_FIRST;
2621 			break;
2622 
2623 		case 'S':
2624 			if (mirrorp->write_option != WR_PARALLEL) {
2625 				(void) mderror(ep, MDE_BAD_WR_OPT, uname);
2626 				goto out;
2627 			}
2628 			mirrorp->write_option = WR_SERIAL;
2629 			break;
2630 
2631 		default:
2632 			argc -= old_optind;
2633 			argv += old_optind;
2634 			goto options;
2635 		}
2636 		old_optind = optind;
2637 	}
2638 	argc -= optind;
2639 	argv += optind;
2640 
2641 	/* parse pass number */
2642 	if ((argc > 0) && (isdigit(argv[0][0]))) {
2643 		if (name_to_pass_num(uname, argv[0],
2644 		    &mirrorp->pass_num, ep) != 0) {
2645 			goto out;
2646 		}
2647 		--argc, ++argv;
2648 	}
2649 
2650 	/* we should be at the end */
2651 	if (argc != 0)
2652 		goto syntax;
2653 
2654 	/* create mirror */
2655 	if (meta_create_mirror(*spp, mirrorp, options, ep) != 0)
2656 		goto out;
2657 	rval = 0;	/* success */
2658 
2659 	/* let em know */
2660 	if (options & MDCMD_PRINT) {
2661 		(void) printf(dgettext(TEXT_DOMAIN,
2662 		    "%s: Mirror is setup\n"),
2663 		    uname);
2664 		(void) fflush(stdout);
2665 	}
2666 	goto out;
2667 
2668 	/* syntax error */
2669 syntax:
2670 	rval = meta_cook_syntax(ep, MDE_SYNTAX, uname, argc, argv);
2671 	goto out;
2672 
2673 	/* options error */
2674 options:
2675 	rval = meta_cook_syntax(ep, MDE_OPTION, uname, argc, argv);
2676 	goto out;
2677 
2678 	/* cleanup, return error */
2679 out:
2680 	if (mirrorp != NULL)
2681 		meta_free_mirror(mirrorp);
2682 	return (rval);
2683 }
2684 
2685 /*
2686  * reset mirrors
2687  */
2688 int
meta_mirror_reset(mdsetname_t * sp,mdname_t * mirnp,mdcmdopts_t options,md_error_t * ep)2689 meta_mirror_reset(
2690 	mdsetname_t	*sp,
2691 	mdname_t	*mirnp,
2692 	mdcmdopts_t	options,
2693 	md_error_t	*ep
2694 )
2695 {
2696 	md_mirror_t	*mirrorp;
2697 	uint_t		smi;
2698 	int		rval = -1;
2699 
2700 	/* should have same set */
2701 	assert(sp != NULL);
2702 	assert((mirnp == NULL) ||
2703 	    (sp->setno == MD_MIN2SET(meta_getminor(mirnp->dev))));
2704 
2705 	/* reset all mirrors */
2706 	if (mirnp == NULL) {
2707 		mdnamelist_t	*mirrornlp = NULL;
2708 		mdnamelist_t	*p;
2709 
2710 		/* for each mirror */
2711 		rval = 0;
2712 		if (meta_get_mirror_names(sp, &mirrornlp, 0, ep) < 0)
2713 			return (-1);
2714 		for (p = mirrornlp; (p != NULL); p = p->next) {
2715 			/* reset mirror */
2716 			mirnp = p->namep;
2717 			/*
2718 			 * If this is a multi-node set, we send a series
2719 			 * of individual metaclear commands.
2720 			 */
2721 			if (meta_is_mn_set(sp, ep)) {
2722 				if (meta_mn_send_metaclear_command(sp,
2723 				    mirnp->cname, options, 0, ep) != 0) {
2724 					rval = -1;
2725 					break;
2726 				}
2727 			} else {
2728 				if (meta_mirror_reset(sp, mirnp, options,
2729 				    ep) != 0) {
2730 					rval = -1;
2731 					break;
2732 				}
2733 			}
2734 		}
2735 
2736 		/* cleanup return success */
2737 		metafreenamelist(mirrornlp);
2738 		return (rval);
2739 	}
2740 
2741 	/* check name */
2742 	if (metachkmeta(mirnp, ep) != 0)
2743 		return (-1);
2744 
2745 	/* get unit structure */
2746 	if ((mirrorp = meta_get_mirror(sp, mirnp, ep)) == NULL)
2747 		return (-1);
2748 
2749 	/* make sure nobody owns us */
2750 	if (MD_HAS_PARENT(mirrorp->common.parent)) {
2751 		return (mdmderror(ep, MDE_IN_USE, meta_getminor(mirnp->dev),
2752 		    mirnp->cname));
2753 	}
2754 
2755 	/* clear subdevices cache */
2756 	if (invalidate_submirrors(sp, mirnp, ep) != 0)
2757 		return (-1);
2758 
2759 	/* clear metadevice */
2760 	if (meta_reset(sp, mirnp, options, ep) != 0)
2761 		goto out;
2762 	rval = 0;	/* success */
2763 
2764 	/* let em know */
2765 	if (options & MDCMD_PRINT) {
2766 		(void) printf(dgettext(TEXT_DOMAIN,
2767 		    "%s: Mirror is cleared\n"), mirnp->cname);
2768 		(void) fflush(stdout);
2769 	}
2770 
2771 	/* clear subdevices */
2772 	if (! (options & MDCMD_RECURSE))
2773 		goto out;
2774 	for (smi = 0; (smi < NMIRROR); ++smi) {
2775 		md_submirror_t	*mdsp = &mirrorp->submirrors[smi];
2776 		mdname_t	*submirnp = mdsp->submirnamep;
2777 
2778 		/* skip unused submirrors */
2779 		if (submirnp == NULL) {
2780 			assert(mdsp->state == SMS_UNUSED);
2781 			continue;
2782 		}
2783 
2784 		/* make sure we have a metadevice */
2785 		if (! metaismeta(submirnp))
2786 			continue;
2787 
2788 		/* clear submirror */
2789 		if (meta_reset_by_name(sp, submirnp, options, ep) != 0)
2790 			rval = -1;
2791 	}
2792 
2793 	/* cleanup, return success */
2794 out:
2795 	meta_invalidate_name(mirnp);
2796 	return (rval);
2797 }
2798 
2799 /*
2800  * reports TRUE if any mirror component is in error
2801  */
2802 int
meta_mirror_anycomp_is_err(mdsetname_t * sp,mdnamelist_t * mirror_names)2803 meta_mirror_anycomp_is_err(mdsetname_t *sp, mdnamelist_t *mirror_names)
2804 {
2805 	mdnamelist_t	*nlp;
2806 	md_error_t	  status	= mdnullerror;
2807 	md_error_t	 *ep		= &status;
2808 	int		  any_errs	= FALSE;
2809 
2810 	for (nlp = mirror_names; nlp; nlp = nlp->next) {
2811 		md_mirror_t	*mirrorp;
2812 		int		 smi;
2813 
2814 		if ((mirrorp = meta_get_mirror(sp, nlp->namep, ep)) == NULL) {
2815 			any_errs |= TRUE;
2816 			goto out;
2817 		}
2818 
2819 		for (smi = 0; smi < NMIRROR; ++smi) {
2820 			md_submirror_t	*mdsp = &mirrorp->submirrors[smi];
2821 
2822 			if (mdsp->state &
2823 			    (SMS_COMP_ERRED|SMS_ATTACHED|SMS_OFFLINE)) {
2824 				any_errs |= TRUE;
2825 				goto out;
2826 			}
2827 		}
2828 	}
2829 out:
2830 	if (!mdisok(ep))
2831 		mdclrerror(ep);
2832 
2833 	return (any_errs);
2834 }
2835