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(¶ms, 0, sizeof (params));
1980 params.mnum = meta_getminor(mirnp->dev);
1981 MD_SETDRIVERNAME(¶ms, 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, ¶ms, ¶ms.mde, NULL) != 0) {
1994 (void) del_key_name(sp, newnp, ep);
1995 return (mdstealerror(ep, ¶ms.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(¶ms, 0, sizeof (params));
2094 params.mnum = meta_getminor(mirnp->dev);
2095 MD_SETDRIVERNAME(¶ms, 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, ¶ms, ¶ms.mde, NULL) != 0)
2148 return (mdstealerror(ep, ¶ms.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