xref: /onnv-gate/usr/src/lib/lvm/libmeta/common/meta_error.c (revision 645:04950962cda2)
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, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 /*
30  * Just in case we're not in a build environment, make sure that
31  * TEXT_DOMAIN gets set to something.
32  */
33 #if !defined(TEXT_DOMAIN)
34 #define	TEXT_DOMAIN "SYS_TEST"
35 #endif
36 
37 /*
38  * print metedevice errors
39  */
40 
41 #include <meta.h>
42 #include <sys/lvm/md_mddb.h>
43 
44 #include <syslog.h>
45 
46 /*
47  * clear error
48  */
49 void
50 mdclrerror(
51 	md_error_t	*ep
52 )
53 {
54 	if (ep->name != NULL)
55 		Free(ep->name);
56 	if (ep->host != NULL)
57 		Free(ep->host);
58 	if (ep->extra != NULL)
59 		Free(ep->extra);
60 	(void) memset(ep, '\0', sizeof (*ep));
61 }
62 
63 /*
64  * cook names
65  */
66 static char *
67 md_name(
68 	minor_t	mnum
69 )
70 {
71 	char	*name;
72 
73 	/* get name, or fake it */
74 	if ((name = get_mdname(mnum)) == NULL) {
75 		char	buf[40];
76 
77 		(void) sprintf(buf, "%lu/d%lu", MD_MIN2SET(mnum),
78 		    MD_MIN2UNIT(mnum));
79 		return (Strdup(buf));
80 	}
81 	return (Strdup(name));
82 }
83 
84 static char *
85 dev_name(
86 	set_t	setno,
87 	md_dev64_t dev
88 )
89 {
90 	char	*name;
91 
92 	/* get name or fake it */
93 	if (dev == NODEV64)
94 		return (Strdup(dgettext(TEXT_DOMAIN, "unknown device")));
95 	if ((name = get_devname(setno, dev)) == NULL) {
96 		char	buf[40];
97 
98 		(void) sprintf(buf, "%lu.%lu", meta_getmajor(dev),
99 		    meta_getminor(dev));
100 		return (Strdup(buf));
101 	}
102 	return (Strdup(name));
103 }
104 
105 static char *
106 hsp_name(
107 	hsp_t	hsp
108 )
109 {
110 	char	*name;
111 
112 	if ((name = get_hspname(hsp)) == NULL) {
113 		char	buf[40];
114 
115 		(void) sprintf(buf, "%u/hsp%03u", HSP_SET(hsp), HSP_ID(hsp));
116 		return (Strdup(buf));
117 	}
118 	return (Strdup(name));
119 }
120 
121 static char *
122 set_name(
123 	set_t		setno
124 )
125 {
126 	mdsetname_t	*sp;
127 	md_error_t	xep = mdnullerror;
128 
129 	if (setno == MD_SET_BAD)
130 		return (NULL);
131 
132 	if ((sp = metasetnosetname(setno, &xep)) == NULL) {
133 		char	buf[40];
134 
135 		mdclrerror(&xep);
136 		(void) sprintf(buf, "setno %u", setno);
137 		return (Strdup(buf));
138 	}
139 	return (Strdup(sp->setname));
140 }
141 
142 /*
143  * fill in all the appropriate md_error_t fields
144  */
145 static void
146 metacookerror(
147 	md_error_t	*ep,		/* generic error */
148 	char		*name		/* optional name or host */
149 )
150 {
151 	/* get host name */
152 	if (ep->host != NULL) {
153 		Free(ep->host);
154 		ep->host = NULL;
155 	}
156 	if ((ep->info.errclass == MDEC_RPC) &&
157 	    (name != NULL) && (*name != '\0')) {
158 		ep->host = Strdup(name);
159 		name = NULL;
160 	} else
161 		ep->host = Strdup(mynode());
162 
163 	/* get appropriate name */
164 	if (ep->name != NULL) {
165 		Free(ep->name);
166 		ep->name = NULL;
167 	}
168 	if ((name != NULL) && (*name != '\0')) {
169 		ep->name = Strdup(name);
170 	} else {
171 		switch (ep->info.errclass) {
172 
173 		/* can't do anything about these */
174 		case MDEC_VOID:
175 		case MDEC_SYS:
176 		case MDEC_RPC:
177 		default:
178 			break;
179 
180 		/* device name */
181 		case MDEC_DEV:
182 		{
183 			md_dev_error_t	*ip =
184 					&ep->info.md_error_info_t_u.dev_error;
185 
186 			ep->name = dev_name(MD_SET_BAD, ip->dev);
187 			break;
188 		}
189 
190 		/* device name */
191 		case MDEC_USE:
192 		{
193 			md_use_error_t	*ip =
194 					&ep->info.md_error_info_t_u.use_error;
195 
196 			ep->name = dev_name(MD_SET_BAD, ip->dev);
197 			if (ip->where == NULL) {
198 				ip->where = Strdup(dgettext(TEXT_DOMAIN,
199 				    "unknown"));
200 			}
201 			break;
202 		}
203 
204 		/* metadevice name */
205 		case MDEC_MD:
206 		{
207 			md_md_error_t	*ip =
208 					&ep->info.md_error_info_t_u.md_error;
209 
210 			ep->name = md_name(ip->mnum);
211 			break;
212 		}
213 
214 		/* component name */
215 		case MDEC_COMP:
216 		{
217 			md_comp_error_t	*ip =
218 					&ep->info.md_error_info_t_u.comp_error;
219 			char		*mdname, *devname;
220 			size_t 		len;
221 
222 			mdname = md_name(ip->comp.mnum);
223 			devname = dev_name(MD_MIN2SET(ip->comp.mnum),
224 			    ip->comp.dev);
225 			len = strlen(mdname) + strlen(": ")
226 			    + strlen(devname) + 1;
227 			ep->name = Malloc(len);
228 			(void) snprintf(ep->name, len, "%s: %s",
229 			    mdname, devname);
230 			Free(mdname);
231 			Free(devname);
232 			break;
233 		}
234 
235 		/* hotspare pool name */
236 		case MDEC_HSP:
237 		{
238 			md_hsp_error_t	*ip =
239 					&ep->info.md_error_info_t_u.hsp_error;
240 
241 			ep->name = hsp_name(ip->hsp);
242 			break;
243 		}
244 
245 		/* hotspare name */
246 		case MDEC_HS:
247 		{
248 			md_hs_error_t	*ip =
249 					&ep->info.md_error_info_t_u.hs_error;
250 			char		*hspname, *devname;
251 			size_t 		len;
252 
253 			hspname = hsp_name(ip->hs.hsp);
254 			devname = dev_name(HSP_SET(ip->hs.hsp), ip->hs.dev);
255 			len = strlen(hspname) + strlen(": ")
256 			    + strlen(devname) + 1;
257 			ep->name = Malloc(len);
258 			(void) snprintf(ep->name, len, "%s: %s",
259 			    hspname, devname);
260 			Free(hspname);
261 			Free(devname);
262 			break;
263 		}
264 
265 		/* mddb name */
266 		case MDEC_MDDB:
267 		{
268 			md_mddb_error_t	*ip =
269 					&ep->info.md_error_info_t_u.mddb_error;
270 			if (ip->mnum != NODEV32)
271 				ep->name = md_name(ip->mnum);
272 			ep->name = set_name(ip->setno);
273 			break;
274 		}
275 
276 		/* set name */
277 		case MDEC_DS:
278 		{
279 			md_ds_error_t	*ip =
280 			    &ep->info.md_error_info_t_u.ds_error;
281 
282 			ep->name = set_name(ip->setno);
283 			break;
284 		}
285 		}
286 	}
287 }
288 
289 /*
290  * simple error
291  */
292 int
293 mderror(
294 	md_error_t	*ep,
295 	md_void_errno_t	errnum,
296 	char		*name
297 )
298 {
299 	md_void_error_t	*ip = &ep->info.md_error_info_t_u.void_error;
300 
301 	mdclrerror(ep);
302 	ep->info.errclass = MDEC_VOID;
303 	ip->errnum = errnum;
304 
305 	metacookerror(ep, name);
306 	return (-1);
307 }
308 
309 /*
310  * system error
311  */
312 int
313 mdsyserror(
314 	md_error_t	*ep,
315 	int		errnum,
316 	char		*name
317 )
318 {
319 	md_sys_error_t	*ip = &ep->info.md_error_info_t_u.sys_error;
320 
321 	mdclrerror(ep);
322 	if (errnum != 0) {
323 		ep->info.errclass = MDEC_SYS;
324 		ip->errnum = errnum;
325 	}
326 
327 	metacookerror(ep, name);
328 	return (-1);
329 }
330 
331 /*
332  * RPC error
333  */
334 int
335 mdrpcerror(
336 	md_error_t	*ep,
337 	CLIENT		*clntp,
338 	char		*host,
339 	char		*extra
340 )
341 {
342 	md_rpc_error_t	*ip = &ep->info.md_error_info_t_u.rpc_error;
343 	struct rpc_err	rpcerr;
344 
345 	mdclrerror(ep);
346 	clnt_geterr(clntp, &rpcerr);
347 	ep->info.errclass = MDEC_RPC;
348 	ip->errnum = rpcerr.re_status;
349 
350 	metacookerror(ep, host);
351 	mderrorextra(ep, extra);
352 	return (-1);
353 }
354 
355 /*
356  * RPC create error
357  */
358 int
359 mdrpccreateerror(
360 	md_error_t	*ep,
361 	char		*host,
362 	char		*extra
363 )
364 {
365 	md_rpc_error_t	*ip = &ep->info.md_error_info_t_u.rpc_error;
366 
367 	mdclrerror(ep);
368 	ep->info.errclass = MDEC_RPC;
369 	ip->errnum = rpc_createerr.cf_stat;
370 
371 	metacookerror(ep, host);
372 	mderrorextra(ep, extra);
373 	return (-1);
374 }
375 
376 /*
377  * device error
378  */
379 int
380 mddeverror(
381 	md_error_t	*ep,
382 	md_dev_errno_t	errnum,
383 	md_dev64_t	dev,
384 	char		*name
385 )
386 {
387 	md_dev_error_t	*ip = &ep->info.md_error_info_t_u.dev_error;
388 
389 	mdclrerror(ep);
390 	ep->info.errclass = MDEC_DEV;
391 	ip->errnum = errnum;
392 	ip->dev = dev;
393 
394 	metacookerror(ep, name);
395 	return (-1);
396 }
397 
398 /*
399  * use error
400  */
401 int
402 mduseerror(
403 	md_error_t	*ep,
404 	md_use_errno_t	errnum,
405 	md_dev64_t	dev,
406 	char		*where,
407 	char		*name
408 )
409 {
410 	md_use_error_t	*ip = &ep->info.md_error_info_t_u.use_error;
411 
412 	assert(where != NULL);
413 	mdclrerror(ep);
414 	ep->info.errclass = MDEC_USE;
415 	ip->errnum = errnum;
416 	ip->dev = dev;
417 	ip->where = Strdup(where);
418 
419 	metacookerror(ep, name);
420 	return (-1);
421 }
422 
423 /*
424  * overlap error
425  */
426 int
427 mdoverlaperror(
428 	md_error_t		*ep,
429 	md_overlap_errno_t	errnum,
430 	char			*name,
431 	char			*where,
432 	char			*overlap
433 )
434 {
435 	md_overlap_error_t *ip =
436 			&ep->info.md_error_info_t_u.overlap_error;
437 
438 	assert(overlap != NULL);
439 	mdclrerror(ep);
440 	ep->info.errclass = MDEC_OVERLAP;
441 	ip->errnum = errnum;
442 	ip->overlap = Strdup(overlap);
443 	ip->where = NULL;
444 	if (where != NULL)
445 	    ip->where = Strdup(where);
446 
447 	metacookerror(ep, name);
448 	return (-1);
449 }
450 
451 /*
452  * metadevice error
453  */
454 int
455 mdmderror(
456 	md_error_t	*ep,
457 	md_md_errno_t	errnum,
458 	minor_t		mnum,
459 	char		*name
460 )
461 {
462 	md_md_error_t	*ip = &ep->info.md_error_info_t_u.md_error;
463 
464 	mdclrerror(ep);
465 	ep->info.errclass = MDEC_MD;
466 	ip->errnum = errnum;
467 	ip->mnum = mnum;
468 
469 	metacookerror(ep, name);
470 	return (-1);
471 }
472 
473 /*
474  * component error
475  */
476 int
477 mdcomperror(
478 	md_error_t	*ep,
479 	md_comp_errno_t	errnum,
480 	minor_t		mnum,
481 	md_dev64_t	dev,
482 	char		*name
483 )
484 {
485 	md_comp_error_t	*ip = &ep->info.md_error_info_t_u.comp_error;
486 
487 	mdclrerror(ep);
488 	ep->info.errclass = MDEC_COMP;
489 	ip->errnum = errnum;
490 	ip->comp.mnum = mnum;
491 	ip->comp.dev = dev;
492 
493 	metacookerror(ep, name);
494 	return (-1);
495 }
496 
497 /*
498  * hotspare pool error
499  */
500 int
501 mdhsperror(
502 	md_error_t	*ep,
503 	md_hsp_errno_t	errnum,
504 	hsp_t		hsp,
505 	char		*name
506 )
507 {
508 	md_hsp_error_t	*ip = &ep->info.md_error_info_t_u.hsp_error;
509 
510 	mdclrerror(ep);
511 	ep->info.errclass = MDEC_HSP;
512 	ip->errnum = errnum;
513 	ip->hsp = hsp;
514 
515 	metacookerror(ep, name);
516 	return (-1);
517 }
518 
519 /*
520  * hotspare error
521  */
522 int
523 mdhserror(
524 	md_error_t	*ep,
525 	md_hs_errno_t	errnum,
526 	hsp_t		hsp,
527 	md_dev64_t	dev,
528 	char		*name
529 )
530 {
531 	md_hs_error_t	*ip = &ep->info.md_error_info_t_u.hs_error;
532 
533 	mdclrerror(ep);
534 	ep->info.errclass = MDEC_HS;
535 	ip->errnum = errnum;
536 	ip->hs.hsp = hsp;
537 	ip->hs.dev = dev;
538 
539 	metacookerror(ep, name);
540 	return (-1);
541 }
542 
543 /*
544  * MDDB error
545  */
546 int
547 mdmddberror(
548 	md_error_t	*ep,
549 	md_mddb_errno_t	errnum,
550 	minor_t		mnum,
551 	set_t		setno,
552 	size_t		size,
553 	char		*name
554 )
555 {
556 	md_mddb_error_t	*ip = &ep->info.md_error_info_t_u.mddb_error;
557 
558 	mdclrerror(ep);
559 	ep->info.errclass = MDEC_MDDB;
560 	ip->errnum = errnum;
561 	ip->mnum = mnum;
562 	ip->setno = setno;
563 	ip->size = size;
564 
565 	metacookerror(ep, name);
566 	return (-1);
567 }
568 
569 /*
570  * metadevice diskset (ds) error
571  */
572 int
573 mddserror(
574 	md_error_t	*ep,
575 	md_ds_errno_t	errnum,
576 	set_t		setno,
577 	char		*node,
578 	char		*drive,
579 	char		*name
580 )
581 {
582 	md_ds_error_t	*ip = &ep->info.md_error_info_t_u.ds_error;
583 
584 	mdclrerror(ep);
585 	ep->info.errclass = MDEC_DS;
586 	ip->errnum = errnum;
587 	ip->setno = setno;
588 	ip->node = ((node != NULL) ? Strdup(node) : NULL);
589 	ip->drive = ((drive != NULL) ? Strdup(drive) : NULL);
590 
591 	metacookerror(ep, name);
592 	return (-1);
593 }
594 
595 /*
596  * clear/attach extra context information
597  */
598 void
599 mderrorextra(
600 	md_error_t	*ep,
601 	char		*extra
602 )
603 {
604 	if (ep->extra != NULL)
605 		Free(ep->extra);
606 	if (extra != NULL)
607 		ep->extra = Strdup(extra);
608 	else
609 		ep->extra = NULL;
610 }
611 
612 /*
613  * steal (copy) an error code safely
614  */
615 int
616 mdstealerror(
617 	md_error_t	*to,
618 	md_error_t	*from
619 )
620 {
621 	mdclrerror(to);
622 	*to = *from;
623 	(void) memset(from, '\0', sizeof (*from));
624 	return (-1);
625 }
626 
627 /*
628  * do an ioctl, cook the error, and return status
629  */
630 int
631 metaioctl(
632 	int		cmd,
633 	void		*data,
634 	md_error_t	*ep,
635 	char		*name
636 )
637 {
638 	int		fd;
639 
640 	/* open admin device */
641 	if ((fd = open_admin(ep)) < 0)
642 		return (-1);
643 
644 	/* do ioctl */
645 	mdclrerror(ep);
646 	if (ioctl(fd, cmd, data) != 0) {
647 		return (mdsyserror(ep, errno, name));
648 	} else if (! mdisok(ep)) {
649 		metacookerror(ep, name);
650 		return (-1);
651 	}
652 
653 	/* return success */
654 	return (0);
655 }
656 
657 /*
658  * print void class errors
659  */
660 static char *
661 void_to_str(
662 	md_error_t	*ep,
663 	char		*buf,
664 	size_t		size
665 )
666 {
667 	md_void_error_t	*ip = &ep->info.md_error_info_t_u.void_error;
668 	char		*p = buf + strlen(buf);
669 	size_t		psize = size - strlen(buf);
670 
671 	switch (ip->errnum) {
672 	case MDE_NONE:
673 		(void) snprintf(p, psize,
674 		    dgettext(TEXT_DOMAIN, "no error"));
675 		break;
676 	case MDE_UNIT_NOT_FOUND:
677 		(void) snprintf(p, psize,
678 		    dgettext(TEXT_DOMAIN, "unit not found"));
679 		break;
680 	case MDE_DUPDRIVE:
681 		(void) snprintf(p, psize,
682 		    dgettext(TEXT_DOMAIN, "drive specified more than once"));
683 		break;
684 	case MDE_INVAL_HSOP:
685 		(void) snprintf(p, psize,
686 		    dgettext(TEXT_DOMAIN, "illegal hot spare operation"));
687 		break;
688 	case MDE_NO_SET:
689 		(void) snprintf(p, psize,
690 		    dgettext(TEXT_DOMAIN, "no such set"));
691 		break;
692 	case MDE_SET_DIFF:
693 		(void) snprintf(p, psize,
694 		    dgettext(TEXT_DOMAIN, "set name is inconsistent"));
695 		break;
696 	case MDE_BAD_RD_OPT:
697 		(void) snprintf(p, psize,
698 		    dgettext(TEXT_DOMAIN, "invalid read option"));
699 		break;
700 	case MDE_BAD_WR_OPT:
701 		(void) snprintf(p, psize,
702 		    dgettext(TEXT_DOMAIN, "invalid write option"));
703 		break;
704 	case MDE_BAD_PASS_NUM:
705 		(void) snprintf(p, psize,
706 		    dgettext(TEXT_DOMAIN, "invalid pass number"));
707 		break;
708 	case MDE_BAD_RESYNC_OPT:
709 		(void) snprintf(p, psize,
710 		    dgettext(TEXT_DOMAIN, "invalid resync option"));
711 		break;
712 	case MDE_BAD_INTERLACE:
713 		(void) snprintf(p, psize,
714 		    dgettext(TEXT_DOMAIN, "invalid interlace"));
715 		break;
716 	case MDE_NO_HSPS:
717 		(void) snprintf(p, psize,
718 		    dgettext(TEXT_DOMAIN, "no hotspare pools found"));
719 		break;
720 	case MDE_NOTENOUGH_DB:
721 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
722 			"must have at least 1 database (-f overrides)"));
723 		break;
724 	case MDE_DELDB_NOTALLOWED:
725 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
726 		    "cannot delete the last database replica in the diskset"));
727 		break;
728 	case MDE_DEL_VALIDDB_NOTALLOWED:
729 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
730 		    "Deleting specified valid replicas results in stale "
731 		    "state database. Configuration changes with stale "
732 		    "database result in panic(-f overrides)"));
733 		break;
734 	case MDE_SYSTEM_FILE:
735 		(void) snprintf(p, psize,
736 		    dgettext(TEXT_DOMAIN, "error in system file"));
737 		break;
738 	case MDE_MDDB_FILE:
739 		(void) snprintf(p, psize,
740 		    dgettext(TEXT_DOMAIN, "error in mddb.cf file"));
741 		break;
742 	case MDE_MDDB_CKSUM:
743 		(void) snprintf(p, psize,
744 		    dgettext(TEXT_DOMAIN, "checksum error in mddb.cf file"));
745 		break;
746 	case MDE_VFSTAB_FILE:
747 		(void) snprintf(p, psize,
748 		    dgettext(TEXT_DOMAIN, "error in vfstab file"));
749 		break;
750 	case MDE_NOSLICE:
751 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
752 		    "invalid slice number for drive name"));
753 		break;
754 	case MDE_SYNTAX:
755 		(void) snprintf(p, psize,
756 		    dgettext(TEXT_DOMAIN, "syntax error"));
757 		break;
758 	case MDE_OPTION:
759 		(void) snprintf(p, psize,
760 		    dgettext(TEXT_DOMAIN, "illegal option"));
761 		break;
762 	case MDE_TAKE_OWN:
763 		(void) snprintf(p, psize,
764 		    dgettext(TEXT_DOMAIN, "failed to reserve any drives"));
765 		break;
766 	case MDE_NOT_DRIVENAME:
767 		(void) snprintf(p, psize,
768 		    dgettext(TEXT_DOMAIN, "not a valid drive name"));
769 		break;
770 	case MDE_RESERVED:
771 		(void) snprintf(p, psize,
772 		    dgettext(TEXT_DOMAIN, "reserved by another host"));
773 		break;
774 	case MDE_DVERSION:
775 		(void) snprintf(p, psize,
776 		    dgettext(TEXT_DOMAIN, "driver version mismatch"));
777 		break;
778 	case MDE_MVERSION:
779 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
780 		    "metadevice state database version mismatch"));
781 		break;
782 	case MDE_TESTERROR:
783 		(void) snprintf(p, psize,
784 		    dgettext(TEXT_DOMAIN, "TEST ERROR MESSAGE"));
785 		break;
786 	case MDE_BAD_ORIG_NCOL:
787 		(void) snprintf(p, psize,
788 		    dgettext(TEXT_DOMAIN, "invalid column count"));
789 		break;
790 	case MDE_RAID_INVALID:
791 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
792 		    "devices were not RAIDed previously or "
793 		    "are specified in the wrong order"));
794 		break;
795 	case MDE_MED_ERROR:
796 		break;
797 	case MDE_TOOMANYMED:
798 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
799 		    "too many mediator hosts requested"));
800 		break;
801 	case MDE_NOMED:
802 		(void) snprintf(p, psize,
803 		    dgettext(TEXT_DOMAIN, "no mediator hosts found"));
804 		break;
805 	case MDE_ONLYNODENAME:
806 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
807 		    "only the nodename of a host is required for deletes"));
808 		break;
809 	case MDE_RAID_BAD_PW_CNT:
810 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
811 		    "simultaneous writes out of range"));
812 		break;
813 	case MDE_DEVID_TOOBIG:
814 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
815 		    "relocation information size is greater than reported"));
816 		break;
817 	case MDE_NOPERM:
818 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
819 		    "Permission denied.  You must have root privilege "
820 		    "to execute this command."));
821 		break;
822 	case MDE_NODEVID:
823 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
824 		    "Device relocation information not available "
825 		    "for this device"));
826 		break;
827 	case MDE_NOROOT:
828 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
829 		    "no root filesystem in /etc/mnttab"));
830 		break;
831 	case MDE_EOF_TRANS:
832 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
833 		    MD_EOF_TRANS_MSG));
834 		break;
835 	case MDE_NOT_MN:
836 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
837 		    "option only valid within a multi-owner set"));
838 		break;
839 	case MDE_ABR_SET:
840 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
841 		    "Invalid command for mirror with ABR set"));
842 		break;
843 	case MDE_INVAL_MNOP:
844 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
845 		    "Invalid operation on multi-owner set"));
846 		break;
847 	case MDE_MNSET_NOTRANS:
848 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
849 		    "Trans metadevice not supported on multi-owner set"));
850 		break;
851 	case MDE_MNSET_NORAID:
852 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
853 		    "RAID-5 metadevice not supported on multi-owner set"));
854 		break;
855 	case MDE_FORCE_DEL_ALL_DRV:
856 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
857 		    "Must specify -f option to delete all drives from set"));
858 		break;
859 	case MDE_STRIPE_TRUNC_SINGLE:
860 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
861 		    "The necessary rounding would result in data loss.  "
862 		    "You can avoid this by concatenating additional devices "
863 		    "totaling at least %s blocks, or by increasing the size "
864 		    "of the specified component by exactly %s blocks."),
865 		    ep->extra, ep->extra);
866 		break;
867 	case MDE_STRIPE_TRUNC_MULTIPLE:
868 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
869 		    "The necessary rounding would result in data loss.  "
870 		    "You can avoid this by concatenating additional devices "
871 		    "totaling at least %s blocks."), ep->extra);
872 		break;
873 	case MDE_SMF_FAIL:
874 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
875 		    "failed to enable/disable SVM service"));
876 		break;
877 	case MDE_SMF_NO_SERVICE:
878 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
879 		    "service(s) not online in SMF"));
880 		break;
881 	case MDE_ZONE_ADMIN:
882 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
883 		"Volume administration unavailable within non-global zones."));
884 		break;
885 	default:
886 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
887 		    "unknown void error code %d"), ip->errnum);
888 		break;
889 	}
890 
891 	return (buf);
892 }
893 
894 /*
895  * print sys class errors
896  */
897 static char *
898 sys_to_str(
899 	md_error_t	*ep,
900 	char		*buf,
901 	size_t		size
902 )
903 {
904 	md_sys_error_t	*ip = &ep->info.md_error_info_t_u.sys_error;
905 	char		*emsg;
906 	char		*p = buf + strlen(buf);
907 	size_t		psize = size - strlen(buf);
908 
909 	if ((emsg = strerror(ip->errnum)) == NULL) {
910 		(void) snprintf(p, psize,
911 		    dgettext(TEXT_DOMAIN, "unknown errno %d out of range"),
912 		    ip->errnum);
913 	} else {
914 		(void) snprintf(p, psize, "%s", emsg);
915 	}
916 
917 	return (buf);
918 }
919 
920 /*
921  * print RPC class errors
922  */
923 static char *
924 rpc_to_str(
925 	md_error_t	*ep,
926 	char		*buf,
927 	size_t		size
928 )
929 {
930 	md_rpc_error_t	*ip = &ep->info.md_error_info_t_u.rpc_error;
931 	char		*p = buf + strlen(buf);
932 	size_t		psize = size - strlen(buf);
933 
934 	(void) snprintf(p, psize, "%s", clnt_sperrno(ip->errnum));
935 	return (buf);
936 }
937 
938 /*
939  * print dev class errors
940  */
941 static char *
942 dev_to_str(
943 	md_error_t	*ep,
944 	char		*buf,
945 	size_t		size
946 )
947 {
948 	md_dev_error_t	*ip = &ep->info.md_error_info_t_u.dev_error;
949 	char		*p = buf + strlen(buf);
950 	size_t		psize = size - strlen(buf);
951 
952 	switch (ip->errnum) {
953 	case MDE_INVAL_HS:
954 		(void) snprintf(p, psize,
955 		    dgettext(TEXT_DOMAIN, "hotspare doesn't exist"));
956 		break;
957 	case MDE_FIX_INVAL_STATE:
958 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
959 		    "cannot enable hotspared device"));
960 		break;
961 	case MDE_FIX_INVAL_HS_STATE:
962 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
963 		    "hotspare isn't broken, can't enable"));
964 		break;
965 	case MDE_NOT_META:
966 		(void) snprintf(p, psize,
967 		    dgettext(TEXT_DOMAIN, "not a metadevice"));
968 		break;
969 	case MDE_IS_DUMP:
970 		(void) snprintf(p, psize,
971 		    dgettext(TEXT_DOMAIN, "is a dump device"));
972 		break;
973 	case MDE_IS_META:
974 		(void) snprintf(p, psize,
975 		    dgettext(TEXT_DOMAIN, "is a metadevice"));
976 		break;
977 	case MDE_IS_SWAPPED:
978 		(void) snprintf(p, psize,
979 		    dgettext(TEXT_DOMAIN, "is swapped on"));
980 		break;
981 	case MDE_NAME_SPACE:
982 		(void) snprintf(p, psize,
983 		    dgettext(TEXT_DOMAIN, "namespace error"));
984 		break;
985 	case MDE_IN_SHARED_SET:
986 		(void) snprintf(p, psize,
987 		    dgettext(TEXT_DOMAIN, "device in shared set"));
988 		break;
989 	case MDE_NOT_IN_SET:
990 		(void) snprintf(p, psize,
991 		    dgettext(TEXT_DOMAIN, "device not in set"));
992 		break;
993 	case MDE_NOT_DISK:
994 		(void) snprintf(p, psize,
995 		    dgettext(TEXT_DOMAIN, "not a disk device"));
996 		break;
997 	case MDE_CANT_CONFIRM:
998 		(void) snprintf(p, psize,
999 		    dgettext(TEXT_DOMAIN, "can't confirm device"));
1000 		break;
1001 	case MDE_INVALID_PART:
1002 		(void) snprintf(p, psize,
1003 		    dgettext(TEXT_DOMAIN, "invalid partition"));
1004 		break;
1005 	case MDE_HAS_MDDB:
1006 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1007 		    "has a metadevice database replica"));
1008 		break;
1009 	case MDE_NO_DB:
1010 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1011 		    "no metadevice database replica on device"));
1012 		break;
1013 	case MDE_CANTVERIFY_VTOC:
1014 		(void) snprintf(p, psize,
1015 		    dgettext(TEXT_DOMAIN, "unable to verify the vtoc"));
1016 		break;
1017 	case MDE_NOT_LOCAL:
1018 		(void) snprintf(p, psize,
1019 		    dgettext(TEXT_DOMAIN, "not in local set"));
1020 		break;
1021 	case MDE_DEVICES_NAME:
1022 		(void) snprintf(p, psize,
1023 		    dgettext(TEXT_DOMAIN, "can't parse /devices name"));
1024 		break;
1025 	case MDE_REPCOMP_INVAL:
1026 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1027 		    "replica slice is not usable as a metadevice component"));
1028 		break;
1029 	case MDE_REPCOMP_ONLY:
1030 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1031 		    "only replica slice is usable for a diskset "
1032 		    "database replica"));
1033 		break;
1034 	case MDE_INV_ROOT:
1035 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1036 		    "invalid root device for this operation"));
1037 		break;
1038 	case MDE_MULTNM:
1039 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1040 		    "multiple entries for device in Solaris Volume Manager "
1041 		    "configuration"));
1042 		break;
1043 	case MDE_TOO_MANY_PARTS:
1044 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1045 		    "Disks with more than %d partitions are not supported "
1046 		    "in Solaris Volume Manager"), MD_MAX_PARTS);
1047 		break;
1048 	case MDE_REPART_REPLICA:
1049 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1050 		    "cannot repartition a slice with an existing replica"));
1051 		break;
1052 	default:
1053 		(void) snprintf(p, psize,
1054 		    dgettext(TEXT_DOMAIN, "unknown dev error code %d"),
1055 		    ip->errnum);
1056 		break;
1057 	}
1058 
1059 	return (buf);
1060 }
1061 
1062 /*
1063  * print overlap class errors
1064  */
1065 static char *
1066 overlap_to_str(
1067 	md_error_t	*ep,
1068 	char		*buf,
1069 	size_t		size
1070 )
1071 {
1072 	md_overlap_error_t	*ip =
1073 			&ep->info.md_error_info_t_u.overlap_error;
1074 	char		*p = buf + strlen(buf);
1075 	size_t		psize = size - strlen(buf);
1076 
1077 	switch (ip->errnum) {
1078 	case MDE_OVERLAP_MOUNTED:
1079 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1080 		    "overlaps with %s which is mounted as \'%s\'"),
1081 			ip->overlap, ip->where);
1082 		break;
1083 	case MDE_OVERLAP_SWAP:
1084 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1085 		    "overlaps with %s which is a swap device"), ip->overlap);
1086 		break;
1087 	case MDE_OVERLAP_DUMP:
1088 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1089 		    "overlaps with %s which is the dump device"), ip->overlap);
1090 		break;
1091 	default:
1092 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1093 		    "unknown overlap error code %d"), ip->errnum);
1094 		break;
1095 	}
1096 
1097 	return (buf);
1098 }
1099 
1100 /*
1101  * print use class errors
1102  */
1103 static char *
1104 use_to_str(
1105 	md_error_t	*ep,
1106 	char		*buf,
1107 	size_t		size
1108 )
1109 {
1110 	md_use_error_t	*ip = &ep->info.md_error_info_t_u.use_error;
1111 	char		*p = buf + strlen(buf);
1112 	size_t		psize = size - strlen(buf);
1113 
1114 	switch (ip->errnum) {
1115 	case MDE_IS_MOUNTED:
1116 		(void) snprintf(p, psize,
1117 		    dgettext(TEXT_DOMAIN, "is mounted on %s"),
1118 		    ip->where);
1119 		break;
1120 	case MDE_ALREADY:
1121 		/*
1122 		 * when the object of the error (existing device that
1123 		 * would being used by SVM) is the metadb then it is necessary
1124 		 * to explicitly specify the string in the error message so
1125 		 * that it can be successfully localized for the Asian locales.
1126 		 */
1127 		if (strcmp(ip->where, MDB_STR) != 0) {
1128 			(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1129 				"has appeared more than once in the "
1130 				"specification of %s"), ip->where);
1131 		} else {
1132 			(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1133 				"has appeared more than once in the "
1134 				"specification of " MDB_STR));
1135 		}
1136 		break;
1137 	case MDE_OVERLAP:
1138 		/*
1139 		 * when the object of the error (existing device that
1140 		 * would overlap) is the metadb then it is necessary
1141 		 * to explicitly specify the string in the error message so
1142 		 * that it can be successfully localized for the Asian locales.
1143 		 */
1144 		if (strcmp(ip->where, MDB_STR) != 0) {
1145 			(void) snprintf(p, psize,
1146 			    dgettext(TEXT_DOMAIN, "overlaps with device in %s"),
1147 			    ip->where);
1148 		} else {
1149 			(void) snprintf(p, psize,
1150 			    dgettext(TEXT_DOMAIN, "overlaps with device in "
1151 			    MDB_STR));
1152 		}
1153 		break;
1154 	case MDE_SAME_DEVID:
1155 		/*
1156 		 * when the object of the error (existing device in the
1157 		 * metaconfiguration that has the same devid)
1158 		 * is the metadb then it is necessary
1159 		 * to explicitly specify the string in the error message so
1160 		 * that it can be successfully localized for the Asian locales.
1161 		 */
1162 		if (strcmp(ip->where, MDB_STR) != 0) {
1163 			(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1164 			    "identical devid detected on %s"), ip->where);
1165 		} else {
1166 			(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1167 			    "identical devid detected in " MDB_STR));
1168 		}
1169 		break;
1170 	default:
1171 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1172 		    "unknown dev error code %d"), ip->errnum);
1173 		break;
1174 	}
1175 
1176 	return (buf);
1177 }
1178 
1179 /*
1180  * print md class errors
1181  */
1182 static char *
1183 md_to_str(
1184 	md_error_t	*ep,
1185 	char		*buf,
1186 	size_t		size
1187 )
1188 {
1189 	md_md_error_t	*ip = &ep->info.md_error_info_t_u.md_error;
1190 	char		*p = buf + strlen(buf);
1191 	size_t		psize = size - strlen(buf);
1192 
1193 	switch (ip->errnum) {
1194 	case MDE_INVAL_UNIT:
1195 		(void) snprintf(p, psize,
1196 		    dgettext(TEXT_DOMAIN, "invalid unit"));
1197 		break;
1198 	case MDE_UNIT_NOT_SETUP:
1199 		(void) snprintf(p, psize,
1200 		    dgettext(TEXT_DOMAIN, "unit not set up"));
1201 		break;
1202 	case MDE_UNIT_ALREADY_SETUP:
1203 		(void) snprintf(p, psize,
1204 		    dgettext(TEXT_DOMAIN, "unit already set up"));
1205 		break;
1206 	case MDE_NOT_MM:
1207 		(void) snprintf(p, psize,
1208 		    dgettext(TEXT_DOMAIN, "unit is not a mirror"));
1209 		break;
1210 	case MDE_IS_SM:
1211 		(void) snprintf(p, psize,
1212 		    dgettext(TEXT_DOMAIN, "illegal to clear submirror"));
1213 		break;
1214 	case MDE_IS_OPEN:
1215 		(void) snprintf(p, psize,
1216 		    dgettext(TEXT_DOMAIN, "metadevice is open"));
1217 		break;
1218 	case MDE_C_WITH_INVAL_SM:
1219 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1220 		    "attempted to clear mirror with submirror(s) "
1221 		    "in invalid state"));
1222 		break;
1223 	case MDE_RESYNC_ACTIVE:
1224 		(void) snprintf(p, psize,
1225 		    dgettext(TEXT_DOMAIN, "resync in progress"));
1226 		break;
1227 	case MDE_LAST_SM_RE:
1228 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1229 		    "attempt to replace a component on the last "
1230 		    "running submirror"));
1231 		break;
1232 	case MDE_MIRROR_FULL:
1233 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1234 		    "mirror has maximum number of submirrors"));
1235 		break;
1236 	case MDE_IN_UNAVAIL_STATE:
1237 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1238 		    "component is in unavailable state; run 'metastat -i'"));
1239 		break;
1240 	case MDE_IN_USE:
1241 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1242 		    "metadevice in use"));
1243 		break;
1244 	case MDE_SM_TOO_SMALL:
1245 		(void) snprintf(p, psize,
1246 		    dgettext(TEXT_DOMAIN, "submirror too small to attach"));
1247 		break;
1248 	case MDE_NO_LABELED_SM:
1249 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1250 		    "can't attach labeled submirror to an unlabeled mirror"));
1251 		break;
1252 	case MDE_SM_OPEN_ERR:
1253 		(void) snprintf(p, psize,
1254 		    dgettext(TEXT_DOMAIN, "submirror open error"));
1255 		break;
1256 	case MDE_CANT_FIND_SM:
1257 		(void) snprintf(p, psize,
1258 		    dgettext(TEXT_DOMAIN, "can't find submirror in mirror"));
1259 		break;
1260 	case MDE_LAST_SM:
1261 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1262 			"attempt to detach last running submirror"));
1263 		break;
1264 	case MDE_NO_READABLE_SM:
1265 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1266 		    "operation would result in no readable submirrors"));
1267 		break;
1268 	case MDE_SM_FAILED_COMPS:
1269 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1270 		    "attempt an operation on a submirror "
1271 		    "that has erred components"));
1272 		break;
1273 	case MDE_ILLEGAL_SM_STATE:
1274 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1275 		    "attempt operation on a submirror in illegal state"));
1276 		break;
1277 	case MDE_RR_ALLOC_ERROR:
1278 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1279 		    "attach failed, unable to allocate new resync info"));
1280 		break;
1281 	case MDE_MIRROR_OPEN_FAILURE:
1282 		(void) snprintf(p, psize,
1283 		    dgettext(TEXT_DOMAIN, "insufficient devices to open"));
1284 		break;
1285 	case MDE_MIRROR_THREAD_FAILURE:
1286 		(void) snprintf(p, psize,
1287 		    dgettext(TEXT_DOMAIN, "mirror thread failure"));
1288 		break;
1289 	case MDE_GROW_DELAYED:
1290 		(void) snprintf(p, psize,
1291 		    dgettext(TEXT_DOMAIN, "growing of metadevice delayed"));
1292 		break;
1293 	case MDE_NOT_MT:
1294 		(void) snprintf(p, psize,
1295 		    dgettext(TEXT_DOMAIN, "unit is not a trans"));
1296 		break;
1297 	case MDE_HS_IN_USE:
1298 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1299 		    "can't modify hot spare pool, hot spare in use"));
1300 		break;
1301 	case MDE_HAS_LOG:
1302 		(void) snprintf(p, psize,
1303 		    dgettext(TEXT_DOMAIN, "already has log"));
1304 		break;
1305 	case MDE_UNKNOWN_TYPE:
1306 		(void) snprintf(p, psize,
1307 		    dgettext(TEXT_DOMAIN, "unknown metadevice type"));
1308 		break;
1309 	case MDE_NOT_STRIPE:
1310 		(void) snprintf(p, psize,
1311 		    dgettext(TEXT_DOMAIN, "unit is not a concat/stripe"));
1312 		break;
1313 	case MDE_NOT_RAID:
1314 		(void) snprintf(p, psize,
1315 		    dgettext(TEXT_DOMAIN, "unit is not a RAID"));
1316 		break;
1317 	case MDE_NROWS:
1318 		(void) snprintf(p, psize,
1319 		    dgettext(TEXT_DOMAIN, "not enough stripes specified"));
1320 		break;
1321 	case MDE_NCOMPS:
1322 		(void) snprintf(p, psize,
1323 		    dgettext(TEXT_DOMAIN, "not enough components specified"));
1324 		break;
1325 	case MDE_NSUBMIRS:
1326 		(void) snprintf(p, psize,
1327 		    dgettext(TEXT_DOMAIN, "not enough submirrors specified"));
1328 		break;
1329 	case MDE_BAD_STRIPE:
1330 		(void) snprintf(p, psize,
1331 		    dgettext(TEXT_DOMAIN, "invalid stripe configuration"));
1332 		break;
1333 	case MDE_BAD_MIRROR:
1334 		(void) snprintf(p, psize,
1335 		    dgettext(TEXT_DOMAIN, "invalid mirror configuration"));
1336 		break;
1337 	case MDE_BAD_TRANS:
1338 		(void) snprintf(p, psize,
1339 		    dgettext(TEXT_DOMAIN, "invalid trans configuration"));
1340 		break;
1341 	case MDE_BAD_RAID:
1342 		(void) snprintf(p, psize,
1343 		    dgettext(TEXT_DOMAIN, "invalid RAID configuration"));
1344 		break;
1345 	case MDE_RAID_OPEN_FAILURE:
1346 		(void) snprintf(p, psize,
1347 		    dgettext(TEXT_DOMAIN, "resync unable to open RAID unit"));
1348 		break;
1349 	case MDE_RAID_THREAD_FAILURE:
1350 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1351 		    "attempt to start resync thread failed"));
1352 		break;
1353 	case MDE_RAID_NEED_FORCE:
1354 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1355 		    "operation requires -f (force) flag"));
1356 		break;
1357 	case MDE_NO_LOG:
1358 		(void) snprintf(p, psize,
1359 		    dgettext(TEXT_DOMAIN, "log has already been detached"));
1360 		break;
1361 	case MDE_RAID_DOI:
1362 		(void) snprintf(p, psize,
1363 		    dgettext(TEXT_DOMAIN, "only valid action is metaclear"));
1364 		break;
1365 	case MDE_RAID_LAST_ERRED:
1366 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1367 		    "in Last Erred state, "
1368 		    "errored components must be replaced"));
1369 		break;
1370 	case MDE_RAID_NOT_OKAY:
1371 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1372 		    "all components must be Okay to perform this operation"));
1373 		break;
1374 	case MDE_RENAME_BUSY:
1375 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1376 		    "metadevice is temporarily too busy for renames"));
1377 		break;
1378 	case MDE_RENAME_SOURCE_BAD:
1379 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1380 		    "source metadevice is not able to be renamed"));
1381 		break;
1382 	case MDE_RENAME_TARGET_BAD:
1383 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1384 		    "target metadevice is not able to be renamed"));
1385 		break;
1386 	case MDE_RENAME_TARGET_UNRELATED:
1387 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1388 		    "target metadevice is not related to source metadevice"));
1389 		break;
1390 	case MDE_RENAME_CONFIG_ERROR:
1391 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1392 		    "metadevice driver configuration error; "
1393 		    "rename can't occur"));
1394 		break;
1395 	case MDE_RENAME_ORDER:
1396 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1397 		    "units may not be renamed in that order"));
1398 		break;
1399 	case MDE_RECOVER_FAILED:
1400 		(void) snprintf(p, psize,
1401 		    dgettext(TEXT_DOMAIN, "recovery failed"));
1402 		break;
1403 	case MDE_SP_NOSPACE:
1404 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1405 		    "not enough space available for request"));
1406 		break;
1407 	case MDE_SP_BADWMREAD:
1408 		(void) snprintf(p, psize,
1409 		    dgettext(TEXT_DOMAIN, "error reading extent header"));
1410 		break;
1411 	case MDE_SP_BADWMWRITE:
1412 		(void) snprintf(p, psize,
1413 		    dgettext(TEXT_DOMAIN, "error writing extent header"));
1414 		break;
1415 	case MDE_SP_BADWMMAGIC:
1416 		(void) snprintf(p, psize,
1417 		    dgettext(TEXT_DOMAIN, "bad magic number in extent header"));
1418 		break;
1419 	case MDE_SP_BADWMCRC:
1420 		(void) snprintf(p, psize,
1421 		    dgettext(TEXT_DOMAIN, "bad checksum in extent header"));
1422 		break;
1423 	case MDE_NOT_SP:
1424 		(void) snprintf(p, psize,
1425 		    dgettext(TEXT_DOMAIN, "unit is not a soft partition"));
1426 		break;
1427 	case MDE_SP_OVERLAP:
1428 		(void) snprintf(p, psize,
1429 		    dgettext(TEXT_DOMAIN, "overlapping extents specified"));
1430 		break;
1431 	case MDE_SP_BAD_LENGTH:
1432 		(void) snprintf(p, psize,
1433 		    dgettext(TEXT_DOMAIN, "bad length specified"));
1434 		break;
1435 	case MDE_SP_NOSP:
1436 		(void) snprintf(p, psize,
1437 		    dgettext(TEXT_DOMAIN, "no soft partitions on this device"));
1438 		break;
1439 	case MDE_UNIT_TOO_LARGE:
1440 		(void) snprintf(p, psize,
1441 		    dgettext(TEXT_DOMAIN, "Volume size cannot exceed 1 TByte"));
1442 		break;
1443 	case MDE_LOG_TOO_LARGE:
1444 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1445 		    "Trans log size must be less than 1 TByte"));
1446 		break;
1447 	default:
1448 		(void) snprintf(p, psize,
1449 		    dgettext(TEXT_DOMAIN, "unknown md error code %d"),
1450 		    ip->errnum);
1451 		break;
1452 	}
1453 
1454 	return (buf);
1455 }
1456 
1457 /*
1458  * print comp class errors
1459  */
1460 static char *
1461 comp_to_str(
1462 	md_error_t	*ep,
1463 	char		*buf,
1464 	size_t		size
1465 )
1466 {
1467 	md_comp_error_t	*ip = &ep->info.md_error_info_t_u.comp_error;
1468 	char		*p = buf + strlen(buf);
1469 	size_t		psize = size - strlen(buf);
1470 
1471 	switch (ip->errnum) {
1472 	case MDE_CANT_FIND_COMP:
1473 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1474 		    "can't find component in unit"));
1475 		break;
1476 	case MDE_REPL_INVAL_STATE:
1477 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1478 		    "component in invalid state to replace - "
1479 		    "Replace \"Maintenance\" components first"));
1480 		break;
1481 	case MDE_COMP_TOO_SMALL:
1482 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1483 		    "replace failure, new component is too small"));
1484 		break;
1485 	case MDE_COMP_OPEN_ERR:
1486 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1487 		    "unable to open concat/stripe component"));
1488 		break;
1489 	case MDE_RAID_COMP_ERRED:
1490 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1491 		    "must replace errored component first"));
1492 		break;
1493 	case MDE_MAXIO:
1494 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1495 		    "maxtransfer is too small"));
1496 		break;
1497 	case MDE_SP_COMP_OPEN_ERR:
1498 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1499 		    "error opening device under soft partition. Check"
1500 		    " device status, then use metadevadm(1M)."));
1501 		break;
1502 	default:
1503 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1504 		    "unknown comp error code %d"), ip->errnum);
1505 		break;
1506 	}
1507 
1508 	return (buf);
1509 }
1510 
1511 /*
1512  * print hsp class errors
1513  */
1514 static char *
1515 hsp_to_str(
1516 	md_error_t	*ep,
1517 	char		*buf,
1518 	size_t		size
1519 )
1520 {
1521 	md_hsp_error_t	*ip = &ep->info.md_error_info_t_u.hsp_error;
1522 	char		*p = buf + strlen(buf);
1523 	size_t		psize = size - strlen(buf);
1524 
1525 	switch (ip->errnum) {
1526 	case MDE_HSP_CREATE_FAILURE:
1527 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1528 		    "hotspare pool database create failure"));
1529 		break;
1530 	case MDE_HSP_IN_USE:
1531 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1532 		    "hotspare pool in use"));
1533 		break;
1534 	case MDE_INVAL_HSP:
1535 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1536 		    "invalid hotspare pool"));
1537 		break;
1538 	case MDE_HSP_BUSY:
1539 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1540 		    "hotspare pool is busy"));
1541 		break;
1542 	case MDE_HSP_REF:
1543 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1544 		    "hotspare pool is referenced"));
1545 		break;
1546 	case MDE_HSP_ALREADY_SETUP:
1547 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1548 		    "hotspare pool is already setup"));
1549 		break;
1550 	case MDE_BAD_HSP:
1551 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1552 		    "invalid hotspare pool configuration"));
1553 		break;
1554 	case MDE_HSP_UNIT_TOO_LARGE:
1555 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1556 		    "units in the hotspare pool cannot exceed 1 TByte"));
1557 		break;
1558 	default:
1559 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1560 		    "unknown hsp error code %d"), ip->errnum);
1561 		break;
1562 	}
1563 
1564 	return (buf);
1565 }
1566 
1567 /*
1568  * print hs class errors
1569  */
1570 static char *
1571 hs_to_str(
1572 	md_error_t	*ep,
1573 	char		*buf,
1574 	size_t		size
1575 )
1576 {
1577 	md_hs_error_t	*ip = &ep->info.md_error_info_t_u.hs_error;
1578 	char		*p = buf + strlen(buf);
1579 	size_t		psize = size - strlen(buf);
1580 
1581 	switch (ip->errnum) {
1582 	case MDE_HS_RESVD:
1583 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1584 		    "hotspare is in use"));
1585 		break;
1586 	case MDE_HS_CREATE_FAILURE:
1587 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1588 		    "hotspare database create failure"));
1589 		break;
1590 	case MDE_HS_INUSE:
1591 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1592 		    "add or replace failed, hot spare is already in use"));
1593 		break;
1594 	case MDE_HS_UNIT_TOO_LARGE:
1595 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1596 		    "hotspare size cannot exceed 1 TByte"));
1597 		break;
1598 	default:
1599 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1600 		    "unknown hs error code %d"), ip->errnum);
1601 		break;
1602 	}
1603 
1604 	return (buf);
1605 }
1606 
1607 /*
1608  * print mddb class errors
1609  */
1610 static char *
1611 mddb_to_str(
1612 	md_error_t	*ep,
1613 	char		*buf,
1614 	size_t		size
1615 )
1616 {
1617 	md_mddb_error_t	*ip = &ep->info.md_error_info_t_u.mddb_error;
1618 	char		*p = buf + strlen(buf);
1619 	size_t		psize = size - strlen(buf);
1620 
1621 	switch (ip->errnum) {
1622 	case MDE_TOOMANY_REPLICAS:
1623 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1624 	"%d metadevice database replicas is too many; the maximum is %d"),
1625 		    ip->size, MDDB_NLB);
1626 		break;
1627 	case MDE_REPLICA_TOOSMALL:
1628 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1629 	"device size %d is too small for metadevice database replica"),
1630 		    ip->size);
1631 		break;
1632 	case MDE_NOTVERIFIED:
1633 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1634 		    "data not returned correctly from disk"));
1635 		break;
1636 	case MDE_DB_INVALID:
1637 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1638 		    "invalid argument"));
1639 		break;
1640 	case MDE_DB_EXISTS:
1641 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1642 		    "metadevice database replica exists on device"));
1643 		break;
1644 	case MDE_DB_MASTER:
1645 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1646 		    "has bad master block on device"));
1647 		break;
1648 	case MDE_DB_TOOSMALL:
1649 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1650 		    "device is too small"));
1651 		break;
1652 	case MDE_DB_NORECORD:
1653 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1654 		    "no such metadevice database record"));
1655 		break;
1656 	case MDE_DB_NOSPACE:
1657 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1658 		    "metadevice database is full, can't create new records"));
1659 		break;
1660 	case MDE_DB_NOTNOW:
1661 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1662 		    "metadevice database has too few replicas, for "
1663 		    "metadevice database operation"));
1664 		break;
1665 	case MDE_DB_NODB:
1666 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1667 		    "there are no existing databases"));
1668 		break;
1669 	case MDE_DB_NOTOWNER:
1670 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1671 		    "not owner of metadevice database"));
1672 		break;
1673 	case MDE_DB_STALE:
1674 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1675 		    "stale databases"));
1676 		break;
1677 	case MDE_DB_TOOFEW:
1678 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1679 		    "not enough databases"));
1680 		break;
1681 	case MDE_DB_TAGDATA:
1682 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1683 		    "tagged data detected, user intervention required"));
1684 		break;
1685 	case MDE_DB_ACCOK:
1686 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1687 		    "50% replicas & 50% mediator hosts available, "
1688 		    "user intervention required"));
1689 		break;
1690 	case MDE_DB_NTAGDATA:
1691 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1692 		    "no tagged data available or only one tag found"));
1693 		break;
1694 	case MDE_DB_ACCNOTOK:
1695 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1696 		    "50% replicas & 50% mediator hosts not available"));
1697 		break;
1698 	case MDE_DB_NOLOCBLK:
1699 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1700 		    "no valid locator blocks were found"));
1701 		break;
1702 	case MDE_DB_NOLOCNMS:
1703 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1704 		    "no valid locator name information was found"));
1705 		break;
1706 	case MDE_DB_NODIRBLK:
1707 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1708 		    "no valid directory blocks were found"));
1709 		break;
1710 	case MDE_DB_NOTAGREC:
1711 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1712 		    "no tag record was allocated, so data "
1713 		    "tagging is disabled"));
1714 		break;
1715 	case MDE_DB_NOTAG:
1716 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1717 		    "no tag records exist or no matching tag was found"));
1718 		break;
1719 	case MDE_DB_BLKRANGE:
1720 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1721 		    "logical block number %d out of range"), ip->size);
1722 		break;
1723 	default:
1724 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1725 		    "unknown mddb error code %d"), ip->errnum);
1726 		break;
1727 	}
1728 
1729 	return (buf);
1730 }
1731 
1732 /*
1733  * print diskset (ds) class errors
1734  */
1735 static char *
1736 ds_to_str(
1737 	md_error_t	*ep,
1738 	char		*buf,
1739 	size_t		size
1740 )
1741 {
1742 	md_ds_error_t	*ip = &ep->info.md_error_info_t_u.ds_error;
1743 	char		*p = buf + strlen(buf);
1744 	size_t		psize = size - strlen(buf);
1745 
1746 	switch (ip->errnum) {
1747 	case MDE_DS_DUPHOST:
1748 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1749 		    "host %s is specified more than once"), ip->node);
1750 		break;
1751 	case MDE_DS_NOTNODENAME:
1752 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1753 		    "\"%s\" is not a nodename, but a network name"), ip->node);
1754 		break;
1755 	case MDE_DS_SELFNOTIN:
1756 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1757 		    "nodename of host %s creating the set must be included"),
1758 		    ip->node);
1759 		break;
1760 	case MDE_DS_NODEHASSET:
1761 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1762 		    "host %s already has set"), ip->node);
1763 		break;
1764 	case MDE_DS_NODENOSET:
1765 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1766 		    "host %s does not have set"), ip->node);
1767 		break;
1768 	case MDE_DS_NOOWNER:
1769 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1770 		    "must be owner of the set for this command"));
1771 		break;
1772 	case MDE_DS_NOTOWNER:
1773 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1774 		    "only the current owner %s may operate on this set"),
1775 		    ip->node);
1776 		break;
1777 	case MDE_DS_NODEISNOTOWNER:
1778 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1779 		    "host %s is not the owner"), ip->node);
1780 		break;
1781 	case MDE_DS_NODEINSET:
1782 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1783 		    "host %s is already in the set"), ip->node);
1784 		break;
1785 	case MDE_DS_NODENOTINSET:
1786 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1787 		    "host %s is not in the set"), ip->node);
1788 		break;
1789 	case MDE_DS_SETNUMBUSY:
1790 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1791 		    "host %s already has a set numbered %ld"),
1792 		    ip->node, ip->setno);
1793 		break;
1794 	case MDE_DS_SETNUMNOTAVAIL:
1795 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1796 		    "no available set numbers"));
1797 		break;
1798 	case MDE_DS_SETNAMEBUSY:
1799 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1800 		    "set name is in-use or invalid on host %s"), ip->node);
1801 		break;
1802 	case MDE_DS_DRIVENOTCOMMON:
1803 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1804 		    "drive %s is not common with host %s"),
1805 		    ip->drive, ip->node);
1806 		break;
1807 	case MDE_DS_DRIVEINSET:
1808 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1809 		    "drive %s is in set %s"), ip->drive, ip->node);
1810 		break;
1811 	case MDE_DS_DRIVENOTINSET:
1812 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1813 		    "drive %s is not in set"), ip->drive);
1814 		break;
1815 	case MDE_DS_DRIVEINUSE:
1816 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1817 		    "drive %s is in use"), ip->drive);
1818 		break;
1819 	case MDE_DS_DUPDRIVE:
1820 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1821 		    "drive %s is specified more than once"), ip->drive);
1822 		break;
1823 	case MDE_DS_INVALIDSETNAME:
1824 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1825 		    "set name contains invalid characters"));
1826 		break;
1827 	case MDE_DS_HASDRIVES:
1828 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1829 		    "unable to delete set, it still has drives"));
1830 		break;
1831 	case MDE_DS_SIDENUMNOTAVAIL:
1832 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1833 		    "maximum number of nodenames exceeded"));
1834 		break;
1835 	case MDE_DS_SETNAMETOOLONG:
1836 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1837 		    "set name is too long"));
1838 		break;
1839 	case MDE_DS_NODENAMETOOLONG:
1840 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1841 		    "host name %s is too long"), ip->node);
1842 		break;
1843 	case MDE_DS_OHACANTDELSELF:
1844 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1845 "administrator host %s deletion disallowed in one host admin mode"),
1846 		    ip->node);
1847 		break;
1848 	case MDE_DS_HOSTNOSIDE:
1849 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1850 		    "side information missing for host %s"), ip->node);
1851 		break;
1852 	case MDE_DS_SETLOCKED:
1853 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1854 	    "host %s is modifying set - try later or restart rpc.metad"),
1855 		    ip->drive);
1856 		break;
1857 	case MDE_DS_ULKSBADKEY:
1858 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1859 		    "set unlock failed - bad key"));
1860 		break;
1861 	case MDE_DS_LKSBADKEY:
1862 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1863 		    "set lock failed - bad key"));
1864 		break;
1865 	case MDE_DS_WRITEWITHSULK:
1866 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1867 		    "write operation attempted on set with set unlocked"));
1868 		break;
1869 	case MDE_DS_SETCLEANUP:
1870 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1871 		    "set \"%s\" is out of date - cleaning up - take failed"),
1872 		    ip->node);
1873 		break;
1874 	case MDE_DS_CANTDELSELF:
1875 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1876 "administrator host %s can't be deleted, other hosts still in set\n"
1877 "Use -f to override"), ip->node);
1878 		break;
1879 	case MDE_DS_HASMED:
1880 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1881 		    "unable to delete set, it still has mediator hosts"));
1882 		break;
1883 	case MDE_DS_TOOMANYALIAS:
1884 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1885 		    "%s causes there to be more aliases than allowed"),
1886 		    ip->node);
1887 		break;
1888 	case MDE_DS_ISMED:
1889 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1890 		    "%s is already a mediator host"), ip->node);
1891 		break;
1892 	case MDE_DS_ISNOTMED:
1893 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1894 		    "%s is not a mediator host"), ip->node);
1895 		break;
1896 	case MDE_DS_INVALIDMEDNAME:
1897 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1898 		    "mediator name \"%s\" contains invalid characters"),
1899 		    ip->node);
1900 		break;
1901 	case MDE_DS_ALIASNOMATCH:
1902 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1903 		    "mediator alias \"%s\" is not an alias for host "
1904 		    "\"%s\""), ip->node, ip->drive);
1905 		break;
1906 	case MDE_DS_NOMEDONHOST:
1907 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1908 		    "unable to contact %s on host \"%s\""),
1909 		    MED_SERVNAME, ip->node);
1910 		break;
1911 	case MDE_DS_DRIVENOTONHOST:
1912 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1913 		    "drive %s is not present on host %s"),
1914 		    ip->drive, ip->node);
1915 		break;
1916 	case MDE_DS_CANTDELMASTER:
1917 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1918 		    "master %s can't be deleted, other hosts still in set"),
1919 		    ip->node);
1920 		break;
1921 	case MDE_DS_NOTINMEMBERLIST:
1922 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1923 		    "node %s is not in membership list"),
1924 		    ip->node);
1925 		break;
1926 	case MDE_DS_MNCANTDELSELF:
1927 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1928 		    "host %s can't delete self from multi-owner set\n"
1929 		    "while other hosts still in set"),
1930 		    ip->node);
1931 		break;
1932 	case MDE_DS_RPCVERSMISMATCH:
1933 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1934 		    "host %s does not support multi-owner diskset"),
1935 		    ip->node);
1936 		break;
1937 	case MDE_DS_WITHDRAWMASTER:
1938 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1939 		    "master host %s cannot withdraw from multi-owner diskset "
1940 		    "when other owner nodes are still present in diskset"),
1941 		    ip->node);
1942 		break;
1943 	case MDE_DS_CANTRESNARF:
1944 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1945 		    "imported set could not be loaded"));
1946 		break;
1947 	case MDE_DS_INSUFQUORUM:
1948 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1949 		    "insufficient replica quorum detected. Use "
1950 		    "-f to force import of the set"));
1951 		break;
1952 	case MDE_DS_EXTENDEDNM:
1953 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1954 		    "multiple namespace records detected"));
1955 		break;
1956 	case MDE_DS_PARTIALSET:
1957 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1958 		    "partial diskset detected\n"
1959 		    "Please refer to the Solaris Volume Manager documentation,"
1960 		    "\nTroubleshooting section, at http://docs.sun.com or from"
1961 		    "\nyour local copy"));
1962 		break;
1963 	case MDE_DS_COMMDCTL_SUSPEND_NYD:
1964 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1965 		    "rpc.mdcommd on host %s is not yet drained during "
1966 		    "suspend operation"),
1967 		    ip->node);
1968 		break;
1969 	case MDE_DS_COMMDCTL_SUSPEND_FAIL:
1970 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1971 		    "rpc.mdcommd on host %s failed suspend operation"),
1972 		    ip->node);
1973 		break;
1974 	case MDE_DS_COMMDCTL_REINIT_FAIL:
1975 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1976 		    "rpc.mdcommd on host %s failed reinitialization operation"),
1977 		    ip->node);
1978 		break;
1979 	case MDE_DS_COMMDCTL_RESUME_FAIL:
1980 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1981 		    "rpc.mdcommd on host %s failed resume operation"),
1982 		    ip->node);
1983 		break;
1984 	case MDE_DS_NOTNOW_RECONFIG:
1985 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1986 		    "command terminated, host %s starting reconfig cycle"),
1987 		    ip->node);
1988 		break;
1989 	case MDE_DS_NOTNOW_CMD:
1990 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1991 		    "metaset or metadb command already running on diskset "
1992 		    "on host %s"), ip->node);
1993 		break;
1994 	case MDE_DS_COMMD_SEND_FAIL:
1995 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
1996 		    "rpc.mdcommd on host %s failed operation"),
1997 		    ip->node);
1998 		break;
1999 	case MDE_DS_MASTER_ONLY:
2000 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
2001 		    "this command must be run on the master node of the set,"
2002 		    " which is currently %s"), ip->node);
2003 		break;
2004 	case MDE_DS_SINGLEHOST:
2005 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
2006 		    "diskset is auto-take; cannot accept additional hosts"));
2007 		break;
2008 	case MDE_DS_AUTONOTSET:
2009 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
2010 		    "auto-take is not enabled on diskset"));
2011 		break;
2012 	case MDE_DS_INVALIDDEVID:
2013 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
2014 		    "Invalid device id on drive %s on host %s"), ip->drive,
2015 		    ip->node);
2016 		break;
2017 	case MDE_DS_SETNOTIMP:
2018 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
2019 		    "Unable to import set on node %s"), ip->node);
2020 		break;
2021 	case MDE_DS_NOTSELFIDENTIFY:
2022 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
2023 		    "Drive %s won't be self identifying"), ip->drive);
2024 		break;
2025 	default:
2026 		(void) snprintf(p, psize, dgettext(TEXT_DOMAIN,
2027 		    "unknown diskset error code %d"), ip->errnum);
2028 		break;
2029 	}
2030 
2031 	return (buf);
2032 }
2033 
2034 /*
2035  * convert error to printable string
2036  */
2037 static char *
2038 mde_to_str(
2039 	md_error_t	*ep
2040 )
2041 {
2042 	static char	buf[BUFSIZ];
2043 	size_t		bufsz;
2044 
2045 	/* intialize buf */
2046 	buf[0] = '\0';
2047 	bufsz  = sizeof (buf);
2048 
2049 	/* class specific */
2050 	switch (ep->info.errclass) {
2051 	case MDEC_VOID:
2052 		return (void_to_str(ep, buf, bufsz));
2053 	case MDEC_SYS:
2054 		return (sys_to_str(ep, buf, bufsz));
2055 	case MDEC_RPC:
2056 		return (rpc_to_str(ep, buf, bufsz));
2057 	case MDEC_DEV:
2058 		return (dev_to_str(ep, buf, bufsz));
2059 	case MDEC_USE:
2060 		return (use_to_str(ep, buf, bufsz));
2061 	case MDEC_MD:
2062 		return (md_to_str(ep, buf, bufsz));
2063 	case MDEC_COMP:
2064 		return (comp_to_str(ep, buf, bufsz));
2065 	case MDEC_HSP:
2066 		return (hsp_to_str(ep, buf, bufsz));
2067 	case MDEC_HS:
2068 		return (hs_to_str(ep, buf, bufsz));
2069 	case MDEC_MDDB:
2070 		return (mddb_to_str(ep, buf, bufsz));
2071 	case MDEC_DS:
2072 		return (ds_to_str(ep, buf, bufsz));
2073 	case MDEC_OVERLAP:
2074 		return (overlap_to_str(ep, buf, bufsz));
2075 	default:
2076 		(void) snprintf(buf, bufsz,
2077 		    dgettext(TEXT_DOMAIN, "unknown error class %d"),
2078 		    ep->info.errclass);
2079 		return (buf);
2080 	}
2081 }
2082 
2083 /*
2084  * print log prefix
2085  */
2086 void
2087 md_logpfx(
2088 	FILE		*fp
2089 )
2090 {
2091 	time_t		t;
2092 	struct tm	*tm;
2093 	char		buf[100];
2094 
2095 	if ((time(&t) != (time_t)-1) &&
2096 	    ((tm = localtime(&t)) != NULL) &&
2097 	    (strftime(buf, sizeof (buf), (char *)0, tm) < sizeof (buf))) {
2098 		(void) fprintf(fp, "%s: ", buf);
2099 	}
2100 	(void) fprintf(fp, "%s: ", myname);
2101 }
2102 
2103 /*
2104  * varargs sperror()
2105  */
2106 /*PRINTFLIKE2*/
2107 static char *
2108 mde_vsperror(
2109 	md_error_t	*ep,
2110 	const char	*fmt,
2111 	va_list		ap
2112 )
2113 {
2114 	static char	buf[BUFSIZ];
2115 	size_t		bufsz = sizeof (buf);
2116 	char		*p = buf;
2117 	char		*host1 = "";
2118 	char		*host2 = "";
2119 	char		*extra1 = "";
2120 	char		*extra2 = "";
2121 	char		*name1 = "";
2122 	char		*name2 = "";
2123 
2124 	/* get stuff */
2125 	if ((ep->host != NULL) && (*(ep->host) != '\0')) {
2126 		host1 = ep->host;
2127 		host2 = ": ";
2128 	}
2129 	if ((ep->extra != NULL) && (*(ep->extra) != '\0')) {
2130 		extra1 = ep->extra;
2131 		extra2 = ": ";
2132 	}
2133 	if ((ep->name != NULL) && (*(ep->name) != '\0')) {
2134 		name1 = ep->name;
2135 		name2 = ": ";
2136 	}
2137 
2138 	/* context */
2139 	(void) snprintf(p, bufsz, "%s%s%s%s%s%s",
2140 	    host1, host2, extra1, extra2, name1, name2);
2141 	p = &buf[strlen(buf)];
2142 	bufsz -= strlen(buf);
2143 
2144 	/* user defined part */
2145 	if ((fmt != NULL) && (*fmt != '\0')) {
2146 		(void) vsnprintf(p, bufsz, fmt, ap);
2147 		p = &buf[strlen(buf)];
2148 		bufsz = sizeof (buf) - strlen(buf);
2149 		(void) snprintf(p, bufsz, ": ");
2150 		p = &buf[strlen(buf)];
2151 		bufsz = sizeof (buf) - strlen(buf);
2152 	}
2153 
2154 	/* error code */
2155 	(void) snprintf(p, bufsz, "%s\n", mde_to_str(ep));
2156 
2157 	/* return error message */
2158 	return (buf);
2159 }
2160 
2161 /*
2162  * printf-like sperror()
2163  */
2164 /*PRINTFLIKE2*/
2165 char *
2166 mde_sperror(
2167 	md_error_t	*ep,
2168 	const char	*fmt,
2169 	...
2170 )
2171 {
2172 	va_list		ap;
2173 	char		*emsg;
2174 
2175 	va_start(ap, fmt);
2176 	emsg = mde_vsperror(ep, fmt, ap);
2177 	va_end(ap);
2178 	return (emsg);
2179 }
2180 
2181 /*
2182  * printf-like perror()
2183  */
2184 /*PRINTFLIKE2*/
2185 void
2186 mde_perror(
2187 	md_error_t	*ep,
2188 	const char	*fmt,
2189 	...
2190 )
2191 {
2192 	va_list		ap;
2193 	char		*emsg;
2194 
2195 	/* get error message */
2196 	va_start(ap, fmt);
2197 	emsg = mde_vsperror(ep, fmt, ap);
2198 	va_end(ap);
2199 	assert((emsg != NULL) && (*emsg != '\0'));
2200 
2201 	/* stderr */
2202 	(void) fprintf(stderr, "%s: %s\n", myname, emsg);
2203 	(void) fflush(stderr);
2204 
2205 	/* metalog */
2206 	if (metalogfp != NULL) {
2207 		md_logpfx(metalogfp);
2208 		(void) fprintf(metalogfp, "%s\n", emsg);
2209 		(void) fflush(metalogfp);
2210 		(void) fsync(fileno(metalogfp));
2211 	}
2212 
2213 	/* syslog */
2214 	if (metasyslog) {
2215 		syslog(LOG_ERR, emsg);
2216 	}
2217 }
2218 
2219 /*
2220  * printf-like perror()
2221  */
2222 /*PRINTFLIKE1*/
2223 void
2224 md_perror(
2225 	const char	*fmt,
2226 	...
2227 )
2228 {
2229 	md_error_t	status = mdnullerror;
2230 	va_list		ap;
2231 	char		*emsg;
2232 
2233 	/* get error message */
2234 	(void) mdsyserror(&status, errno, NULL);
2235 	va_start(ap, fmt);
2236 	emsg = mde_vsperror(&status, fmt, ap);
2237 	va_end(ap);
2238 	assert((emsg != NULL) && (*emsg != '\0'));
2239 	mdclrerror(&status);
2240 
2241 	/* stderr */
2242 	(void) fprintf(stderr, "%s: %s\n", myname, emsg);
2243 	(void) fflush(stderr);
2244 
2245 	/* metalog */
2246 	if (metalogfp != NULL) {
2247 		md_logpfx(metalogfp);
2248 		(void) fprintf(metalogfp, "%s\n", emsg);
2249 		(void) fflush(metalogfp);
2250 		(void) fsync(fileno(metalogfp));
2251 	}
2252 
2253 	/* syslog */
2254 	if (metasyslog) {
2255 		syslog(LOG_ERR, emsg);
2256 	}
2257 }
2258 
2259 /*
2260  * printf-like log
2261  */
2262 /*PRINTFLIKE1*/
2263 void
2264 md_eprintf(
2265 	const char	*fmt,
2266 	...
2267 )
2268 {
2269 	va_list		ap;
2270 
2271 	/* begin */
2272 	va_start(ap, fmt);
2273 
2274 	/* stderr */
2275 	(void) fprintf(stderr, "%s: ", myname);
2276 	(void) vfprintf(stderr, fmt, ap);
2277 	(void) fflush(stderr);
2278 
2279 	/* metalog */
2280 	if (metalogfp != NULL) {
2281 		md_logpfx(metalogfp);
2282 		(void) vfprintf(metalogfp, fmt, ap);
2283 		(void) fflush(metalogfp);
2284 		(void) fsync(fileno(metalogfp));
2285 	}
2286 
2287 	/* syslog */
2288 	if (metasyslog) {
2289 		vsyslog(LOG_ERR, fmt, ap);
2290 	}
2291 
2292 	/* end */
2293 	va_end(ap);
2294 }
2295 
2296 /*
2297  * metaclust timing messages logging routine
2298  *
2299  * level	- The class of the message to be logged. Message will be logged
2300  *		  if this is less than or equal to the verbosity level.
2301  */
2302 void
2303 meta_mc_log(int level, const char *fmt, ...)
2304 {
2305 	va_list	args;
2306 
2307 	va_start(args, fmt);
2308 	/*
2309 	 * Log all messages upto MC_LOG2 to syslog regardless of the
2310 	 * verbosity level
2311 	 */
2312 	if (metasyslog && (level <= MC_LOG2)) {
2313 		if (level <= MC_LOG1)
2314 			(void) vsyslog(LOG_ERR, fmt, args);
2315 		else
2316 			(void) vsyslog(LOG_INFO, fmt, args);
2317 	}
2318 	/*
2319 	 * Print all messages to stderr provided the message level is
2320 	 * within the verbosity level
2321 	 */
2322 	if (level <= verbosity) {
2323 		(void) fprintf(stderr, "%s: ", myname);
2324 		(void) vfprintf(stderr, fmt, args);
2325 		(void) fprintf(stderr, "\n");
2326 		(void) fflush(stderr);
2327 	}
2328 	va_end(args);
2329 }
2330