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