xref: /onnv-gate/usr/src/lib/lvm/libmeta/common/meta_trans.c (revision 1623:7bac4a816ebe)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*1623Stw21770  * Common Development and Distribution License (the "License").
6*1623Stw21770  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
210Sstevel@tonic-gate /*
22*1623Stw21770  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
230Sstevel@tonic-gate  * Use is subject to license terms.
240Sstevel@tonic-gate  */
250Sstevel@tonic-gate 
260Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
270Sstevel@tonic-gate 
280Sstevel@tonic-gate /*
290Sstevel@tonic-gate  * Just in case we're not in a build environment, make sure that
300Sstevel@tonic-gate  * TEXT_DOMAIN gets set to something.
310Sstevel@tonic-gate  */
320Sstevel@tonic-gate #if !defined(TEXT_DOMAIN)
330Sstevel@tonic-gate #define	TEXT_DOMAIN "SYS_TEST"
340Sstevel@tonic-gate #endif
350Sstevel@tonic-gate 
360Sstevel@tonic-gate /*
370Sstevel@tonic-gate  * trans operations
380Sstevel@tonic-gate  */
390Sstevel@tonic-gate 
400Sstevel@tonic-gate #include <meta.h>
410Sstevel@tonic-gate #include <meta_basic.h>
420Sstevel@tonic-gate #include <sys/lvm/md_trans.h>
430Sstevel@tonic-gate #include <sys/wait.h>
440Sstevel@tonic-gate #include <sys/mnttab.h>
450Sstevel@tonic-gate #include <stddef.h>
460Sstevel@tonic-gate 
470Sstevel@tonic-gate extern char *getfullblkname();
480Sstevel@tonic-gate 
490Sstevel@tonic-gate /*
500Sstevel@tonic-gate  * replace trans
510Sstevel@tonic-gate  */
520Sstevel@tonic-gate 
530Sstevel@tonic-gate int
meta_trans_replace(mdsetname_t * sp,mdname_t * transnp,mdname_t * oldnp,mdname_t * newnp,mdcmdopts_t options,md_error_t * ep)540Sstevel@tonic-gate meta_trans_replace(mdsetname_t *sp, mdname_t *transnp, mdname_t *oldnp,
550Sstevel@tonic-gate     mdname_t *newnp, mdcmdopts_t options, md_error_t *ep)
560Sstevel@tonic-gate {
570Sstevel@tonic-gate 	replace_params_t	params;
580Sstevel@tonic-gate 	md_dev64_t		old_dev,
590Sstevel@tonic-gate 				new_dev;
600Sstevel@tonic-gate 	daddr_t			new_start_blk,
610Sstevel@tonic-gate 				new_end_blk;
620Sstevel@tonic-gate 
630Sstevel@tonic-gate 	/* should have same set */
640Sstevel@tonic-gate 	assert(sp != NULL);
650Sstevel@tonic-gate 	assert(sp->setno == MD_MIN2SET(meta_getminor(transnp->dev)));
660Sstevel@tonic-gate 
670Sstevel@tonic-gate 	new_dev = newnp->dev;
680Sstevel@tonic-gate 	new_start_blk = newnp->start_blk;
690Sstevel@tonic-gate 	new_end_blk = newnp->end_blk;
700Sstevel@tonic-gate 
710Sstevel@tonic-gate 	meta_invalidate_name(transnp);
720Sstevel@tonic-gate 	/* the old device binding is now established */
730Sstevel@tonic-gate 	if ((old_dev = oldnp->dev) == NODEV64)
740Sstevel@tonic-gate 		return (mdsyserror(ep, ENODEV, oldnp->cname));
750Sstevel@tonic-gate 
760Sstevel@tonic-gate 	if (((strcmp(oldnp->rname, newnp->rname) == 0) &&
770Sstevel@tonic-gate 	    (old_dev != new_dev))) {
780Sstevel@tonic-gate 		newnp->dev = new_dev;
790Sstevel@tonic-gate 		newnp->start_blk = new_start_blk;
800Sstevel@tonic-gate 		newnp->end_blk = new_end_blk;
810Sstevel@tonic-gate 	}
820Sstevel@tonic-gate 
830Sstevel@tonic-gate 	if (add_key_name(sp, newnp, NULL, ep) != 0)
840Sstevel@tonic-gate 		return (-1);
850Sstevel@tonic-gate 
860Sstevel@tonic-gate 	(void) memset(&params, 0, sizeof (params));
870Sstevel@tonic-gate 	params.mnum = meta_getminor(transnp->dev);
880Sstevel@tonic-gate 	MD_SETDRIVERNAME(&params, MD_TRANS, sp->setno);
890Sstevel@tonic-gate 
900Sstevel@tonic-gate 	params.cmd = REPLACE_COMP;
910Sstevel@tonic-gate 	params.old_dev = old_dev;
920Sstevel@tonic-gate 	params.new_dev = new_dev;
930Sstevel@tonic-gate 	params.new_key = newnp->key;
940Sstevel@tonic-gate 	if (metaioctl(MD_IOCREPLACE, &params, &params.mde, NULL) != 0) {
950Sstevel@tonic-gate 		(void) del_key_name(sp, newnp, ep);
960Sstevel@tonic-gate 		return (mdstealerror(ep, &params.mde));
970Sstevel@tonic-gate 	}
980Sstevel@tonic-gate 	meta_invalidate_name(oldnp);
990Sstevel@tonic-gate 	meta_invalidate_name(newnp);
1000Sstevel@tonic-gate 	meta_invalidate_name(transnp);
1010Sstevel@tonic-gate 
1020Sstevel@tonic-gate 	if (options & MDCMD_PRINT) {
1030Sstevel@tonic-gate 		(void) printf(dgettext(TEXT_DOMAIN,
1040Sstevel@tonic-gate 		    "%s: device %s is replaced with %s\n"),
1050Sstevel@tonic-gate 		    transnp->cname, oldnp->cname, newnp->cname);
1060Sstevel@tonic-gate 	}
1070Sstevel@tonic-gate 	return (0);
1080Sstevel@tonic-gate }
1090Sstevel@tonic-gate 
1100Sstevel@tonic-gate 
1110Sstevel@tonic-gate 
1120Sstevel@tonic-gate /*
1130Sstevel@tonic-gate  * FUNCTION:	meta_get_trans_names()
1140Sstevel@tonic-gate  * INPUT:	sp	- the set name to get trans from
1150Sstevel@tonic-gate  *		options	- options from the command line
1160Sstevel@tonic-gate  * OUTPUT:	nlpp	- list of all trans names
1170Sstevel@tonic-gate  *		ep	- return error pointer
1180Sstevel@tonic-gate  * RETURNS:	int	- -1 if error, 0 success
1190Sstevel@tonic-gate  * PURPOSE:	returns a list of all trans in the metadb
1200Sstevel@tonic-gate  *		for all devices in the specified set
1210Sstevel@tonic-gate  */
1220Sstevel@tonic-gate int
meta_get_trans_names(mdsetname_t * sp,mdnamelist_t ** nlpp,int options,md_error_t * ep)1230Sstevel@tonic-gate meta_get_trans_names(
1240Sstevel@tonic-gate 	mdsetname_t	*sp,
1250Sstevel@tonic-gate 	mdnamelist_t	**nlpp,
1260Sstevel@tonic-gate 	int		options,
1270Sstevel@tonic-gate 	md_error_t	*ep
1280Sstevel@tonic-gate )
1290Sstevel@tonic-gate {
1300Sstevel@tonic-gate 	return (meta_get_names(MD_TRANS, sp, nlpp, options, ep));
1310Sstevel@tonic-gate }
1320Sstevel@tonic-gate 
1330Sstevel@tonic-gate /*
1340Sstevel@tonic-gate  * free trans unit
1350Sstevel@tonic-gate  */
1360Sstevel@tonic-gate void
meta_free_trans(md_trans_t * transp)1370Sstevel@tonic-gate meta_free_trans(
1380Sstevel@tonic-gate 	md_trans_t	*transp
1390Sstevel@tonic-gate )
1400Sstevel@tonic-gate {
1410Sstevel@tonic-gate 	Free(transp);
1420Sstevel@tonic-gate }
1430Sstevel@tonic-gate 
1440Sstevel@tonic-gate /*
1450Sstevel@tonic-gate  * get trans (common)
1460Sstevel@tonic-gate  */
1470Sstevel@tonic-gate md_trans_t *
meta_get_trans_common(mdsetname_t * sp,mdname_t * transnp,int fast,md_error_t * ep)1480Sstevel@tonic-gate meta_get_trans_common(
1490Sstevel@tonic-gate 	mdsetname_t	*sp,
1500Sstevel@tonic-gate 	mdname_t	*transnp,
1510Sstevel@tonic-gate 	int		fast,
1520Sstevel@tonic-gate 	md_error_t	*ep
1530Sstevel@tonic-gate )
1540Sstevel@tonic-gate {
1550Sstevel@tonic-gate 	mddrivename_t	*dnp = transnp->drivenamep;
1560Sstevel@tonic-gate 	char		*miscname;
1570Sstevel@tonic-gate 	mt_unit_t	*mt;
1580Sstevel@tonic-gate 	md_trans_t	*transp;
1590Sstevel@tonic-gate 	int		gotlog;
1600Sstevel@tonic-gate 
1610Sstevel@tonic-gate 	/* must have set */
1620Sstevel@tonic-gate 	assert(sp != NULL);
1630Sstevel@tonic-gate 	assert(sp->setno == MD_MIN2SET(meta_getminor(transnp->dev)));
1640Sstevel@tonic-gate 
1650Sstevel@tonic-gate 	/* short circuit */
1660Sstevel@tonic-gate 	if (dnp->unitp != NULL) {
1670Sstevel@tonic-gate 		assert(dnp->unitp->type == MD_METATRANS);
1680Sstevel@tonic-gate 		return ((md_trans_t *)dnp->unitp);
1690Sstevel@tonic-gate 	}
1700Sstevel@tonic-gate 
1710Sstevel@tonic-gate 	/* get miscname and unit */
1720Sstevel@tonic-gate 	if ((miscname = metagetmiscname(transnp, ep)) == NULL)
1730Sstevel@tonic-gate 		return (NULL);
1740Sstevel@tonic-gate 	if (strcmp(miscname, MD_TRANS) != 0) {
1750Sstevel@tonic-gate 		(void) mdmderror(ep, MDE_NOT_MT,
1760Sstevel@tonic-gate 		    meta_getminor(transnp->dev), transnp->cname);
1770Sstevel@tonic-gate 		return (NULL);
1780Sstevel@tonic-gate 	}
1790Sstevel@tonic-gate 	if ((mt = (mt_unit_t *)meta_get_mdunit(sp, transnp, ep)) == NULL)
1800Sstevel@tonic-gate 		return (NULL);
1810Sstevel@tonic-gate 	assert(mt->c.un_type == MD_METATRANS);
1820Sstevel@tonic-gate 
1830Sstevel@tonic-gate 	/* allocate trans */
1840Sstevel@tonic-gate 	transp = Zalloc(sizeof (*transp));
1850Sstevel@tonic-gate 
1860Sstevel@tonic-gate 	/* get common info */
1870Sstevel@tonic-gate 	transp->common.namep = transnp;
1880Sstevel@tonic-gate 	transp->common.type = mt->c.un_type;
1890Sstevel@tonic-gate 	transp->common.state = mt->c.un_status;
1900Sstevel@tonic-gate 	transp->common.capabilities = mt->c.un_capabilities;
1910Sstevel@tonic-gate 	transp->common.parent = mt->c.un_parent;
1920Sstevel@tonic-gate 	transp->common.size = mt->c.un_total_blocks;
1930Sstevel@tonic-gate 	transp->common.user_flags = mt->c.un_user_flags;
1940Sstevel@tonic-gate 	transp->common.revision = mt->c.un_revision;
1950Sstevel@tonic-gate 
1960Sstevel@tonic-gate 	/* get master */
1970Sstevel@tonic-gate 	transp->masternamep = metakeyname(&sp, mt->un_m_key, fast, ep);
1980Sstevel@tonic-gate 	if (transp->masternamep == NULL)
1990Sstevel@tonic-gate 		goto out;
2000Sstevel@tonic-gate 
2010Sstevel@tonic-gate 	/* get log */
2020Sstevel@tonic-gate 	gotlog = ((mt->un_flags & TRANS_DETACHED) == 0);
2030Sstevel@tonic-gate 	if (gotlog) {
2040Sstevel@tonic-gate 		daddr_t	sblk;
2050Sstevel@tonic-gate 
2060Sstevel@tonic-gate 		transp->lognamep = metakeyname(&sp, mt->un_l_key, fast, ep);
2070Sstevel@tonic-gate 		if (transp->lognamep == NULL)
2080Sstevel@tonic-gate 			goto out;
2090Sstevel@tonic-gate 
2100Sstevel@tonic-gate 		/* calculate the kernels start block */
2110Sstevel@tonic-gate 		sblk = mt->un_l_pwsblk + mt->un_l_maxtransfer;
2120Sstevel@tonic-gate 
2130Sstevel@tonic-gate 		if (getenv("META_DEBUG_START_BLK") != NULL) {
2140Sstevel@tonic-gate 			if (metagetstart(sp, transp->lognamep, ep) ==
2150Sstevel@tonic-gate 			    MD_DISKADDR_ERROR)
2160Sstevel@tonic-gate 				mdclrerror(ep);
2170Sstevel@tonic-gate 
2180Sstevel@tonic-gate 			if (transp->lognamep->start_blk > sblk)
2190Sstevel@tonic-gate 				md_eprintf(dgettext(TEXT_DOMAIN,
2200Sstevel@tonic-gate 				    "%s: suspected bad start block [trans]\n"),
2210Sstevel@tonic-gate 				    transp->lognamep->cname);
2220Sstevel@tonic-gate 		}
2230Sstevel@tonic-gate 
2240Sstevel@tonic-gate 		/* override any start_blk */
2250Sstevel@tonic-gate 		transp->lognamep->start_blk = sblk;
2260Sstevel@tonic-gate 	}
2270Sstevel@tonic-gate 
2280Sstevel@tonic-gate 	/* get flags, etc. */
2290Sstevel@tonic-gate 	transp->flags = mt->un_flags;
2300Sstevel@tonic-gate 	transp->timestamp = mt->un_timestamp;
2310Sstevel@tonic-gate 	transp->log_error = mt->un_l_error;
2320Sstevel@tonic-gate 	transp->log_timestamp = mt->un_l_timestamp;
2330Sstevel@tonic-gate 	transp->log_size = mt->un_l_nblks;
2340Sstevel@tonic-gate 	transp->debug = mt->un_debug;
2350Sstevel@tonic-gate 
2360Sstevel@tonic-gate 	/* cleanup, return success */
2370Sstevel@tonic-gate 	Free(mt);
2380Sstevel@tonic-gate 	dnp->unitp = (md_common_t *)transp;
2390Sstevel@tonic-gate 	return (transp);
2400Sstevel@tonic-gate 
2410Sstevel@tonic-gate 	/* cleanup, return error */
2420Sstevel@tonic-gate out:
2430Sstevel@tonic-gate 	Free(mt);
2440Sstevel@tonic-gate 	meta_free_trans(transp);
2450Sstevel@tonic-gate 	return (NULL);
2460Sstevel@tonic-gate }
2470Sstevel@tonic-gate 
2480Sstevel@tonic-gate /*
2490Sstevel@tonic-gate  * get trans
2500Sstevel@tonic-gate  */
2510Sstevel@tonic-gate md_trans_t *
meta_get_trans(mdsetname_t * sp,mdname_t * transnp,md_error_t * ep)2520Sstevel@tonic-gate meta_get_trans(
2530Sstevel@tonic-gate 	mdsetname_t	*sp,
2540Sstevel@tonic-gate 	mdname_t	*transnp,
2550Sstevel@tonic-gate 	md_error_t	*ep
2560Sstevel@tonic-gate )
2570Sstevel@tonic-gate {
2580Sstevel@tonic-gate 	return (meta_get_trans_common(sp, transnp, 0, ep));
2590Sstevel@tonic-gate }
2600Sstevel@tonic-gate 
2610Sstevel@tonic-gate /*
2620Sstevel@tonic-gate  * check trans for dev
2630Sstevel@tonic-gate  */
2640Sstevel@tonic-gate static int
in_trans(mdsetname_t * sp,mdname_t * transnp,mdname_t * np,mdchkopts_t options,diskaddr_t slblk,diskaddr_t nblks,md_error_t * ep)2650Sstevel@tonic-gate in_trans(
2660Sstevel@tonic-gate 	mdsetname_t	*sp,
2670Sstevel@tonic-gate 	mdname_t	*transnp,
2680Sstevel@tonic-gate 	mdname_t	*np,
2690Sstevel@tonic-gate 	mdchkopts_t	options,
2700Sstevel@tonic-gate 	diskaddr_t	slblk,
2710Sstevel@tonic-gate 	diskaddr_t	nblks,
2720Sstevel@tonic-gate 	md_error_t	*ep
2730Sstevel@tonic-gate )
2740Sstevel@tonic-gate {
2750Sstevel@tonic-gate 	md_trans_t	*transp;
2760Sstevel@tonic-gate 	mdname_t	*masternp;
2770Sstevel@tonic-gate 	mdname_t	*lognp;
2780Sstevel@tonic-gate 
2790Sstevel@tonic-gate 	/* should be in the same set */
2800Sstevel@tonic-gate 	assert(sp != NULL);
2810Sstevel@tonic-gate 	assert(sp->setno == MD_MIN2SET(meta_getminor(transnp->dev)));
2820Sstevel@tonic-gate 
2830Sstevel@tonic-gate 	/* get unit */
2840Sstevel@tonic-gate 	if ((transp = meta_get_trans(sp, transnp, ep)) == NULL)
2850Sstevel@tonic-gate 		return (-1);
2860Sstevel@tonic-gate 
2870Sstevel@tonic-gate 	/* check master */
2880Sstevel@tonic-gate 	masternp = transp->masternamep;
2890Sstevel@tonic-gate 	if ((! metaismeta(masternp)) &&
2900Sstevel@tonic-gate 	    (meta_check_overlap(transnp->cname, np, slblk, nblks,
2910Sstevel@tonic-gate 	    masternp, 0, -1, ep) != 0)) {
2920Sstevel@tonic-gate 		return (-1);
2930Sstevel@tonic-gate 	}
2940Sstevel@tonic-gate 
2950Sstevel@tonic-gate 	/* check log */
2960Sstevel@tonic-gate 	if (((lognp = transp->lognamep) != NULL) &&
2970Sstevel@tonic-gate 	    (! (options & MDCHK_ALLOW_LOG)) &&
2980Sstevel@tonic-gate 	    (! metaismeta(lognp))) {
2990Sstevel@tonic-gate 		daddr_t		log_start;
3000Sstevel@tonic-gate 		int		err;
3010Sstevel@tonic-gate 
3020Sstevel@tonic-gate 		/* check same drive since metagetstart() can fail */
3030Sstevel@tonic-gate 		if ((err = meta_check_samedrive(np, lognp, ep)) < 0)
3040Sstevel@tonic-gate 			return (-1);
3050Sstevel@tonic-gate 
3060Sstevel@tonic-gate 		/* check overlap */
3070Sstevel@tonic-gate 		if (err != 0) {
3080Sstevel@tonic-gate 			if ((log_start = metagetstart(sp, lognp, ep)) ==
3090Sstevel@tonic-gate 			    MD_DISKADDR_ERROR)
3100Sstevel@tonic-gate 				return (-1);
3110Sstevel@tonic-gate 			if (meta_check_overlap(transnp->cname, np, slblk,
3120Sstevel@tonic-gate 			    nblks, lognp, log_start, -1, ep) != 0) {
3130Sstevel@tonic-gate 				return (-1);
3140Sstevel@tonic-gate 			}
3150Sstevel@tonic-gate 		}
3160Sstevel@tonic-gate 	}
3170Sstevel@tonic-gate 
3180Sstevel@tonic-gate 	/* return success */
3190Sstevel@tonic-gate 	return (0);
3200Sstevel@tonic-gate }
3210Sstevel@tonic-gate 
3220Sstevel@tonic-gate /*
3230Sstevel@tonic-gate  * check to see if we're in a trans
3240Sstevel@tonic-gate  */
3250Sstevel@tonic-gate int
meta_check_intrans(mdsetname_t * sp,mdname_t * np,mdchkopts_t options,diskaddr_t slblk,diskaddr_t nblks,md_error_t * ep)3260Sstevel@tonic-gate meta_check_intrans(
3270Sstevel@tonic-gate 	mdsetname_t	*sp,
3280Sstevel@tonic-gate 	mdname_t	*np,
3290Sstevel@tonic-gate 	mdchkopts_t	options,
3300Sstevel@tonic-gate 	diskaddr_t	slblk,
3310Sstevel@tonic-gate 	diskaddr_t	nblks,
3320Sstevel@tonic-gate 	md_error_t	*ep
3330Sstevel@tonic-gate )
3340Sstevel@tonic-gate {
3350Sstevel@tonic-gate 	mdnamelist_t	*transnlp = NULL;
3360Sstevel@tonic-gate 	mdnamelist_t	*p;
3370Sstevel@tonic-gate 	int		rval = 0;
3380Sstevel@tonic-gate 
3390Sstevel@tonic-gate 	/* should have a set */
3400Sstevel@tonic-gate 	assert(sp != NULL);
3410Sstevel@tonic-gate 
3420Sstevel@tonic-gate 	/* for each trans */
3430Sstevel@tonic-gate 	if (meta_get_trans_names(sp, &transnlp, 0, ep) < 0)
3440Sstevel@tonic-gate 		return (-1);
3450Sstevel@tonic-gate 	for (p = transnlp; (p != NULL); p = p->next) {
3460Sstevel@tonic-gate 		mdname_t	*transnp = p->namep;
3470Sstevel@tonic-gate 
3480Sstevel@tonic-gate 		/* check trans */
3490Sstevel@tonic-gate 		if (in_trans(sp, transnp, np, options, slblk, nblks, ep) != 0) {
3500Sstevel@tonic-gate 			rval = -1;
3510Sstevel@tonic-gate 			break;
3520Sstevel@tonic-gate 		}
3530Sstevel@tonic-gate 	}
3540Sstevel@tonic-gate 
3550Sstevel@tonic-gate 	/* cleanup, return success */
3560Sstevel@tonic-gate 	metafreenamelist(transnlp);
3570Sstevel@tonic-gate 	return (rval);
3580Sstevel@tonic-gate }
3590Sstevel@tonic-gate 
3600Sstevel@tonic-gate /*
3610Sstevel@tonic-gate  * check master
3620Sstevel@tonic-gate  */
3630Sstevel@tonic-gate int
meta_check_master(mdsetname_t * sp,mdname_t * np,int force,md_error_t * ep)3640Sstevel@tonic-gate meta_check_master(
3650Sstevel@tonic-gate 	mdsetname_t	*sp,
3660Sstevel@tonic-gate 	mdname_t	*np,
3670Sstevel@tonic-gate 	int		force,
3680Sstevel@tonic-gate 	md_error_t	*ep
3690Sstevel@tonic-gate )
3700Sstevel@tonic-gate {
3710Sstevel@tonic-gate 	mdchkopts_t	options = 0;
3720Sstevel@tonic-gate 	md_common_t	*mdp;
3730Sstevel@tonic-gate 
3740Sstevel@tonic-gate 	/* make sure we have a disk */
3750Sstevel@tonic-gate 	if (metachkdisk(np, ep) != 0)
3760Sstevel@tonic-gate 		return (-1);
3770Sstevel@tonic-gate 
3780Sstevel@tonic-gate 	/* check to ensure that it is not already in use */
3790Sstevel@tonic-gate 	if ((!force) && meta_check_inuse(sp, np, MDCHK_INUSE, ep) != 0) {
3800Sstevel@tonic-gate 		return (-1);
3810Sstevel@tonic-gate 	}
3820Sstevel@tonic-gate 
3830Sstevel@tonic-gate 	/* make sure it is in the set */
3840Sstevel@tonic-gate 	if (meta_check_inset(sp, np, ep) != 0)
3850Sstevel@tonic-gate 		return (-1);
3860Sstevel@tonic-gate 
3870Sstevel@tonic-gate 	/* make sure its not in a metadevice */
3880Sstevel@tonic-gate 	if (! metaismeta(np)) {		/* Non-metadevices */
3890Sstevel@tonic-gate 		if (meta_check_inmeta(sp, np, options, 0, -1, ep) != 0)
3900Sstevel@tonic-gate 			return (-1);
3910Sstevel@tonic-gate 	} else {			/* Metadevices only! */
3920Sstevel@tonic-gate 		if ((mdp = meta_get_unit(sp, np, ep)) == NULL)
3930Sstevel@tonic-gate 			return (-1);
3940Sstevel@tonic-gate 
3950Sstevel@tonic-gate 		/*
3960Sstevel@tonic-gate 		 * Since soft partitions may appear at the top or bottom
3970Sstevel@tonic-gate 		 * of the metadevice stack, we check them separately.
3980Sstevel@tonic-gate 		 * A trans may be built on top of a soft partition if
3990Sstevel@tonic-gate 		 * the soft partition has no parent (can't rely on the
4000Sstevel@tonic-gate 		 * MD_CAN_PARENT flag in this case since a soft partition
4010Sstevel@tonic-gate 		 * built on a metadevice clears this flag to prevent nested
4020Sstevel@tonic-gate 		 * configurations).
4030Sstevel@tonic-gate 		 */
4040Sstevel@tonic-gate 		if ((meta_sp_issp(sp, np, ep) == 0) &&
4050Sstevel@tonic-gate 		    (mdp->parent == MD_NO_PARENT))
4060Sstevel@tonic-gate 			return (0);
4070Sstevel@tonic-gate 
4080Sstevel@tonic-gate 		if ((! (mdp->capabilities & MD_CAN_PARENT)) ||
4090Sstevel@tonic-gate 		    (mdp->parent != MD_NO_PARENT)) {
4100Sstevel@tonic-gate 			return (mdmderror(ep, MDE_INVAL_UNIT,
4110Sstevel@tonic-gate 			    meta_getminor(np->dev), np->cname));
4120Sstevel@tonic-gate 		}
4130Sstevel@tonic-gate 	}
4140Sstevel@tonic-gate 
4150Sstevel@tonic-gate 	/* return success */
4160Sstevel@tonic-gate 	return (0);
4170Sstevel@tonic-gate }
4180Sstevel@tonic-gate 
4190Sstevel@tonic-gate /*
4200Sstevel@tonic-gate  * check log
4210Sstevel@tonic-gate  */
4220Sstevel@tonic-gate int
meta_check_log(mdsetname_t * sp,mdname_t * np,md_error_t * ep)4230Sstevel@tonic-gate meta_check_log(
4240Sstevel@tonic-gate 	mdsetname_t	*sp,
4250Sstevel@tonic-gate 	mdname_t	*np,
4260Sstevel@tonic-gate 	md_error_t	*ep
4270Sstevel@tonic-gate )
4280Sstevel@tonic-gate {
4290Sstevel@tonic-gate 	mdchkopts_t	options = (MDCHK_ALLOW_MDDB | MDCHK_ALLOW_LOG);
4300Sstevel@tonic-gate 	md_common_t	*mdp;
4310Sstevel@tonic-gate 
4320Sstevel@tonic-gate 	/* make sure we have a disk */
4330Sstevel@tonic-gate 	if (metachkdisk(np, ep) != 0)
4340Sstevel@tonic-gate 		return (-1);
4350Sstevel@tonic-gate 
4360Sstevel@tonic-gate 	/* check to ensure that it is not already in use */
4370Sstevel@tonic-gate 	if (meta_check_inuse(sp, np, MDCHK_INUSE, ep) != 0) {
4380Sstevel@tonic-gate 		return (-1);
4390Sstevel@tonic-gate 	}
4400Sstevel@tonic-gate 
4410Sstevel@tonic-gate 	/* make sure it is in the set */
4420Sstevel@tonic-gate 	if (meta_check_inset(sp, np, ep) != 0)
4430Sstevel@tonic-gate 		return (-1);
4440Sstevel@tonic-gate 
4450Sstevel@tonic-gate 	/* make sure its not in a metadevice */
4460Sstevel@tonic-gate 	if (! metaismeta(np)) {		/* Non-metadevices */
4470Sstevel@tonic-gate 		if (meta_check_inmeta(sp, np, options, 0, -1, ep) != 0)
4480Sstevel@tonic-gate 			return (-1);
4490Sstevel@tonic-gate 	} else {			/* Metadevices only! */
4500Sstevel@tonic-gate 		if ((mdp = meta_get_unit(sp, np, ep)) == NULL)
4510Sstevel@tonic-gate 			return (-1);
4520Sstevel@tonic-gate 
4530Sstevel@tonic-gate 		/*
4540Sstevel@tonic-gate 		 * Since soft partitions may appear at the top or bottom
4550Sstevel@tonic-gate 		 * of the metadevice stack, we check them separately.
4560Sstevel@tonic-gate 		 * A trans may be built on top of a soft partition if
4570Sstevel@tonic-gate 		 * the soft partition has no parent (can't rely on the
4580Sstevel@tonic-gate 		 * MD_CAN_PARENT flag in this case since a soft partition
4590Sstevel@tonic-gate 		 * built on a metadevice clears this flag to prevent nested
4600Sstevel@tonic-gate 		 * configurations).
4610Sstevel@tonic-gate 		 *
4620Sstevel@tonic-gate 		 */
4630Sstevel@tonic-gate 		if ((meta_sp_issp(sp, np, ep) == 0) &&
4640Sstevel@tonic-gate 		    (mdp->parent == MD_NO_PARENT))
4650Sstevel@tonic-gate 			return (0);
4660Sstevel@tonic-gate 
4670Sstevel@tonic-gate 		if ((! (mdp->capabilities & MD_CAN_PARENT)) ||
4680Sstevel@tonic-gate 		    ((mdp->parent != MD_NO_PARENT) &&
4690Sstevel@tonic-gate 		    (mdp->parent != MD_MULTI_PARENT))) {
4700Sstevel@tonic-gate 			return (mdmderror(ep, MDE_INVAL_UNIT,
4710Sstevel@tonic-gate 			    meta_getminor(np->dev), np->cname));
4720Sstevel@tonic-gate 		}
4730Sstevel@tonic-gate 	}
4740Sstevel@tonic-gate 
4750Sstevel@tonic-gate 	/* return success */
4760Sstevel@tonic-gate 	return (0);
4770Sstevel@tonic-gate }
4780Sstevel@tonic-gate 
4790Sstevel@tonic-gate /*
4800Sstevel@tonic-gate  * print trans
4810Sstevel@tonic-gate  */
4820Sstevel@tonic-gate static int
trans_print(md_trans_t * transp,char * fname,FILE * fp,md_error_t * ep)4830Sstevel@tonic-gate trans_print(
4840Sstevel@tonic-gate 	md_trans_t	*transp,
4850Sstevel@tonic-gate 	char		*fname,
4860Sstevel@tonic-gate 	FILE		*fp,
4870Sstevel@tonic-gate 	md_error_t	*ep
4880Sstevel@tonic-gate )
4890Sstevel@tonic-gate {
4900Sstevel@tonic-gate 	int		rval = -1;
4910Sstevel@tonic-gate 
4920Sstevel@tonic-gate 	/* print name and -t */
4930Sstevel@tonic-gate 	if (fprintf(fp, "%s -t", transp->common.namep->cname) == EOF)
4940Sstevel@tonic-gate 		goto out;
4950Sstevel@tonic-gate 
4960Sstevel@tonic-gate 	/* print master */
4970Sstevel@tonic-gate 	/*
4980Sstevel@tonic-gate 	 * If the path is our standard /dev/rdsk or /dev/md/rdsk
4990Sstevel@tonic-gate 	 * then just print out the cxtxdxsx or the dx, metainit
5000Sstevel@tonic-gate 	 * will assume the default, otherwise we need the full
5010Sstevel@tonic-gate 	 * pathname to make sure this works as we intend.
5020Sstevel@tonic-gate 	 */
5030Sstevel@tonic-gate 	if ((strstr(transp->masternamep->rname, "/dev/rdsk") == NULL) &&
5040Sstevel@tonic-gate 	    (strstr(transp->masternamep->rname, "/dev/md/rdsk") == NULL) &&
5050Sstevel@tonic-gate 	    (strstr(transp->masternamep->rname, "/dev/td/") == NULL)) {
5060Sstevel@tonic-gate 		/* not standard path, print full pathname */
5070Sstevel@tonic-gate 		if (fprintf(fp, " %s", transp->masternamep->rname) == EOF)
5080Sstevel@tonic-gate 			goto out;
5090Sstevel@tonic-gate 	} else {
5100Sstevel@tonic-gate 		/* standard path, print ctds or d number */
5110Sstevel@tonic-gate 		if (fprintf(fp, " %s", transp->masternamep->cname) == EOF)
5120Sstevel@tonic-gate 			goto out;
5130Sstevel@tonic-gate 	}
5140Sstevel@tonic-gate 
5150Sstevel@tonic-gate 
5160Sstevel@tonic-gate 	/* print log */
5170Sstevel@tonic-gate 	if (transp->lognamep != NULL) {
5180Sstevel@tonic-gate 		/*
5190Sstevel@tonic-gate 		 * If the path is our standard /dev/rdsk or /dev/md/rdsk
5200Sstevel@tonic-gate 		 * then just print out the cxtxdxsx or the dx, metainit
5210Sstevel@tonic-gate 		 * will assume the default, otherwise we need the full
5220Sstevel@tonic-gate 		 * pathname to make sure this works as we intend.
5230Sstevel@tonic-gate 		 */
5240Sstevel@tonic-gate 		if ((strstr(transp->lognamep->rname, "/dev/rdsk") == NULL) &&
5250Sstevel@tonic-gate 		    (strstr(transp->lognamep->rname, "/dev/md/rdsk") == NULL) &&
5260Sstevel@tonic-gate 		    (strstr(transp->lognamep->rname, "/dev/td/") == NULL)) {
5270Sstevel@tonic-gate 			/* not standard path, print full pathname */
5280Sstevel@tonic-gate 			if (fprintf(fp, " %s", transp->lognamep->rname) == EOF)
5290Sstevel@tonic-gate 				goto out;
5300Sstevel@tonic-gate 		} else {
5310Sstevel@tonic-gate 			/* standard path */
5320Sstevel@tonic-gate 			if (fprintf(fp, " %s", transp->lognamep->cname) == EOF)
5330Sstevel@tonic-gate 				goto out;
5340Sstevel@tonic-gate 		}
5350Sstevel@tonic-gate 	}
5360Sstevel@tonic-gate 
5370Sstevel@tonic-gate 	/* print terminating newline */
5380Sstevel@tonic-gate 	if (fprintf(fp, "\n") == EOF)
5390Sstevel@tonic-gate 		goto out;
5400Sstevel@tonic-gate 
5410Sstevel@tonic-gate 	/* success */
5420Sstevel@tonic-gate 	rval = 0;
5430Sstevel@tonic-gate 
5440Sstevel@tonic-gate 	/* cleanup, return error */
5450Sstevel@tonic-gate out:
5460Sstevel@tonic-gate 	if (rval != 0)
5470Sstevel@tonic-gate 		(void) mdsyserror(ep, errno, fname);
5480Sstevel@tonic-gate 	return (rval);
5490Sstevel@tonic-gate }
5500Sstevel@tonic-gate 
5510Sstevel@tonic-gate /*
5520Sstevel@tonic-gate  * convert flags to repair action
5530Sstevel@tonic-gate  */
5540Sstevel@tonic-gate 
5550Sstevel@tonic-gate char *
mt_flags_to_action(md_trans_t * transp)5560Sstevel@tonic-gate mt_flags_to_action(
5570Sstevel@tonic-gate 	md_trans_t *transp
5580Sstevel@tonic-gate )
5590Sstevel@tonic-gate {
5600Sstevel@tonic-gate 	int	 len;
5610Sstevel@tonic-gate 	char	*actionp	= NULL;
5620Sstevel@tonic-gate 	int	 err		= -1;
5630Sstevel@tonic-gate 
5640Sstevel@tonic-gate 	if (!transp) {
5650Sstevel@tonic-gate 		goto out;
5660Sstevel@tonic-gate 	}
5670Sstevel@tonic-gate 
5680Sstevel@tonic-gate 	/*
5690Sstevel@tonic-gate 	 * if in any of these states, the log_error word is not (yet) meaningful
5700Sstevel@tonic-gate 	 */
5710Sstevel@tonic-gate 	if (transp->flags & (TRANS_DETACHED|TRANS_DETACHING|TRANS_ATTACHING)) {
5720Sstevel@tonic-gate 		goto out;
5730Sstevel@tonic-gate 	}
5740Sstevel@tonic-gate 
5750Sstevel@tonic-gate 	if (transp->log_error & LDL_ANYERROR) {
5760Sstevel@tonic-gate 		char *fix_msg = dgettext(TEXT_DOMAIN,
5770Sstevel@tonic-gate 		    "    To Fix: Please refer to the log device's status.\n");
5780Sstevel@tonic-gate 
5790Sstevel@tonic-gate 		if ((len = strlen(fix_msg)) <= 0) {
5800Sstevel@tonic-gate 			goto out;
5810Sstevel@tonic-gate 		}
5820Sstevel@tonic-gate 		if (!(actionp = Zalloc(len+1))) {
5830Sstevel@tonic-gate 			goto out;
5840Sstevel@tonic-gate 		}
5850Sstevel@tonic-gate 		if (strncpy(actionp, fix_msg, len + 1) != actionp) {
5860Sstevel@tonic-gate 			goto out;
5870Sstevel@tonic-gate 		}
5880Sstevel@tonic-gate 	}
5890Sstevel@tonic-gate 	err = 0;
5900Sstevel@tonic-gate out:
5910Sstevel@tonic-gate 	if (err != 0) {
5920Sstevel@tonic-gate 		if (actionp) {
5930Sstevel@tonic-gate 			Free(actionp);
5940Sstevel@tonic-gate 			actionp = NULL;
5950Sstevel@tonic-gate 		}
5960Sstevel@tonic-gate 	}
5970Sstevel@tonic-gate 	return (actionp);
5980Sstevel@tonic-gate }
5990Sstevel@tonic-gate 
6000Sstevel@tonic-gate /*
6010Sstevel@tonic-gate  * convert log state to repair action
6020Sstevel@tonic-gate  */
6030Sstevel@tonic-gate char *
mt_l_error_to_action(mdsetname_t * sp,mdnamelist_t * transnlp,mdname_t * lognamep,md_error_t * ep)6040Sstevel@tonic-gate mt_l_error_to_action(
6050Sstevel@tonic-gate 	mdsetname_t	*sp,
6060Sstevel@tonic-gate 	mdnamelist_t	*transnlp,
6070Sstevel@tonic-gate 	mdname_t	*lognamep,
6080Sstevel@tonic-gate 	md_error_t	*ep
6090Sstevel@tonic-gate )
6100Sstevel@tonic-gate {
6110Sstevel@tonic-gate 	char		 umnt_msg[1024];
6120Sstevel@tonic-gate 	char		 fsck_msg[1024];
6130Sstevel@tonic-gate 	char		 mnt_msg[1024];
6140Sstevel@tonic-gate 	mdnamelist_t	*p;
6150Sstevel@tonic-gate 	md_trans_t	*tp;
6160Sstevel@tonic-gate 	int		 rc;
6170Sstevel@tonic-gate 	int		 len		= 0;
6180Sstevel@tonic-gate 	char		*rmsg		= NULL;
6190Sstevel@tonic-gate 	char		*mp		= NULL;
6200Sstevel@tonic-gate 	bool_t		 is_mounted	= FALSE;
6210Sstevel@tonic-gate 	bool_t		 any_in_error	= FALSE;
6220Sstevel@tonic-gate 	int		 only_fsck	= TRUE;
6230Sstevel@tonic-gate 
6240Sstevel@tonic-gate 	(void) memset(umnt_msg, 0, sizeof (umnt_msg));
6250Sstevel@tonic-gate 	(void) memset(fsck_msg, 0, sizeof (fsck_msg));
6260Sstevel@tonic-gate 	(void) memset(mnt_msg, 0, sizeof (mnt_msg));
6270Sstevel@tonic-gate 
6280Sstevel@tonic-gate 	/*
6290Sstevel@tonic-gate 	 * If a the trans devices listed in transnlp contain
6300Sstevel@tonic-gate 	 * devices which are in error and are sub-mount points
6310Sstevel@tonic-gate 	 * of each other, than it would need to be reverse sorted.
6320Sstevel@tonic-gate 	 * When this actually occurs, and customers find the usage
6330Sstevel@tonic-gate 	 * message insufficiently clear, then we should take the
6340Sstevel@tonic-gate 	 * hit to sort it.
6350Sstevel@tonic-gate 	 */
6360Sstevel@tonic-gate 
6370Sstevel@tonic-gate 	/*
6380Sstevel@tonic-gate 	 * this preliminary loop is necessary to keep the
6390Sstevel@tonic-gate 	 * fsck message greppable, if possible
6400Sstevel@tonic-gate 	 */
6410Sstevel@tonic-gate 	for (p = transnlp; ((p != NULL) && (only_fsck == TRUE)); p = p->next) {
6420Sstevel@tonic-gate 
6430Sstevel@tonic-gate 		if ((tp = meta_get_trans(sp, p->namep, ep)) == NULL) {
6440Sstevel@tonic-gate 			goto out;
6450Sstevel@tonic-gate 		}
6460Sstevel@tonic-gate 
6470Sstevel@tonic-gate 		if (!(tp->log_error & LDL_ANYERROR)) {
6480Sstevel@tonic-gate 			continue;
6490Sstevel@tonic-gate 		}
6500Sstevel@tonic-gate 
6510Sstevel@tonic-gate 		if ((tp->lognamep == NULL) ||
6520Sstevel@tonic-gate 		    (strcmp(lognamep->bname, tp->lognamep->bname) != 0)) {
6530Sstevel@tonic-gate 			continue;
6540Sstevel@tonic-gate 		}
6550Sstevel@tonic-gate 
6560Sstevel@tonic-gate 		mdclrerror(ep);
6570Sstevel@tonic-gate 		is_mounted = (meta_check_inuse(sp,
6580Sstevel@tonic-gate 		    p->namep, MDCHK_MOUNTED, ep) != 0);
6590Sstevel@tonic-gate 
6600Sstevel@tonic-gate 		if (!mdisok(ep) && mdiserror(ep, MDE_IS_MOUNTED)) {
6610Sstevel@tonic-gate 			goto out;
6620Sstevel@tonic-gate 		}
6630Sstevel@tonic-gate 
6640Sstevel@tonic-gate 		mdclrerror(ep);
6650Sstevel@tonic-gate 		mp = meta_get_mountp(sp, p->namep, ep);
6660Sstevel@tonic-gate 
6670Sstevel@tonic-gate 		if (!mdisok(ep)) {
6680Sstevel@tonic-gate 			goto out;
6690Sstevel@tonic-gate 		}
6700Sstevel@tonic-gate 
6710Sstevel@tonic-gate 		if (is_mounted) {
6720Sstevel@tonic-gate 			if (!mp) {
6730Sstevel@tonic-gate 				goto out;
6740Sstevel@tonic-gate 			}
6750Sstevel@tonic-gate 			only_fsck = FALSE;
6760Sstevel@tonic-gate 
6770Sstevel@tonic-gate 			/*
6780Sstevel@tonic-gate 			 * not greppable; there must be multiple commands, so
6790Sstevel@tonic-gate 			 * add preliminary newline so the formatting is uniform
6800Sstevel@tonic-gate 			 */
6810Sstevel@tonic-gate 			if (sprintf(umnt_msg, "\n") == EOF) {
6820Sstevel@tonic-gate 				goto out;
6830Sstevel@tonic-gate 			}
6840Sstevel@tonic-gate 
6850Sstevel@tonic-gate 		}
6860Sstevel@tonic-gate 
6870Sstevel@tonic-gate 		if (mp) {
6880Sstevel@tonic-gate 			Free(mp);
6890Sstevel@tonic-gate 			mp = NULL;
6900Sstevel@tonic-gate 		}
6910Sstevel@tonic-gate 	}
6920Sstevel@tonic-gate 
6930Sstevel@tonic-gate 	/*
6940Sstevel@tonic-gate 	 * although the log may either be in error or hard-error
6950Sstevel@tonic-gate 	 * states, the action is the same; unmount, fsck and remount
6960Sstevel@tonic-gate 	 * all fs associated with this log
6970Sstevel@tonic-gate 	 */
6980Sstevel@tonic-gate 	for (p = transnlp; (p != NULL); p = p->next) {
6990Sstevel@tonic-gate 
7000Sstevel@tonic-gate 		if ((tp = meta_get_trans(sp, p->namep, ep)) == NULL) {
7010Sstevel@tonic-gate 			goto out;
7020Sstevel@tonic-gate 		}
7030Sstevel@tonic-gate 
7040Sstevel@tonic-gate 		if (!(tp->log_error & LDL_ANYERROR)) {
7050Sstevel@tonic-gate 			continue;
7060Sstevel@tonic-gate 		}
7070Sstevel@tonic-gate 
7080Sstevel@tonic-gate 		if ((tp->lognamep == NULL) ||
7090Sstevel@tonic-gate 		    (strcmp(lognamep->bname, tp->lognamep->bname) != 0)) {
7100Sstevel@tonic-gate 			continue;
7110Sstevel@tonic-gate 		}
7120Sstevel@tonic-gate 
7130Sstevel@tonic-gate 		mdclrerror(ep);
7140Sstevel@tonic-gate 		is_mounted = (meta_check_inuse(sp,
7150Sstevel@tonic-gate 		    p->namep, MDCHK_MOUNTED, ep) != 0);
7160Sstevel@tonic-gate 
7170Sstevel@tonic-gate 		if (!mdisok(ep) && mdiserror(ep, MDE_IS_MOUNTED)) {
7180Sstevel@tonic-gate 			goto out;
7190Sstevel@tonic-gate 		}
7200Sstevel@tonic-gate 
7210Sstevel@tonic-gate 		mdclrerror(ep);
7220Sstevel@tonic-gate 		mp = meta_get_mountp(sp, p->namep, ep);
7230Sstevel@tonic-gate 
7240Sstevel@tonic-gate 		if (!mdisok(ep)) {
7250Sstevel@tonic-gate 			goto out;
7260Sstevel@tonic-gate 		}
7270Sstevel@tonic-gate 
7280Sstevel@tonic-gate 		if (is_mounted) {
7290Sstevel@tonic-gate 			if (!mp) {
7300Sstevel@tonic-gate 				goto out;
7310Sstevel@tonic-gate 			}
7320Sstevel@tonic-gate 		}
7330Sstevel@tonic-gate 
7340Sstevel@tonic-gate 		if (is_mounted) {
7350Sstevel@tonic-gate 			rc = snprintf(umnt_msg, sizeof (umnt_msg),
7360Sstevel@tonic-gate 			    "%s            umount %s\n", umnt_msg, mp);
7370Sstevel@tonic-gate 
7380Sstevel@tonic-gate 			if (rc < 0) {
7390Sstevel@tonic-gate 				goto out;
7400Sstevel@tonic-gate 			}
7410Sstevel@tonic-gate 		}
7420Sstevel@tonic-gate 
7430Sstevel@tonic-gate 		rc = snprintf(fsck_msg, sizeof (fsck_msg), "%s %s",
7440Sstevel@tonic-gate 		    (any_in_error) ? fsck_msg :
7450Sstevel@tonic-gate 		    ((only_fsck) ? "fsck" : "            fsck"),
7460Sstevel@tonic-gate 		    p->namep->rname);
7470Sstevel@tonic-gate 		if (rc < 0) {
7480Sstevel@tonic-gate 			goto out;
7490Sstevel@tonic-gate 		}
7500Sstevel@tonic-gate 
7510Sstevel@tonic-gate 		if (is_mounted) {
7520Sstevel@tonic-gate 			rc = snprintf(mnt_msg, sizeof (mnt_msg),
7530Sstevel@tonic-gate 			    "%s            mount %s %s\n",
7540Sstevel@tonic-gate 			    mnt_msg, p->namep->bname, mp);
7550Sstevel@tonic-gate 
7560Sstevel@tonic-gate 			if (rc < 0) {
7570Sstevel@tonic-gate 				goto out;
7580Sstevel@tonic-gate 			}
7590Sstevel@tonic-gate 		}
7600Sstevel@tonic-gate 
7610Sstevel@tonic-gate 		if (mp) {
7620Sstevel@tonic-gate 			Free(mp);
7630Sstevel@tonic-gate 			mp = NULL;
7640Sstevel@tonic-gate 		}
7650Sstevel@tonic-gate 
7660Sstevel@tonic-gate 		any_in_error |= TRUE;
7670Sstevel@tonic-gate 	}
7680Sstevel@tonic-gate 
7690Sstevel@tonic-gate 	if (!any_in_error) {
7700Sstevel@tonic-gate 		goto out;
7710Sstevel@tonic-gate 	}
7720Sstevel@tonic-gate 
7730Sstevel@tonic-gate 	len = strlen(umnt_msg) + strlen(fsck_msg) + strlen(mnt_msg) +
7740Sstevel@tonic-gate 							(only_fsck? 1: 0) + 1;
7750Sstevel@tonic-gate 	if (!(rmsg = Zalloc(len))) {
7760Sstevel@tonic-gate 		len = 0;
7770Sstevel@tonic-gate 		goto out;
7780Sstevel@tonic-gate 	}
7790Sstevel@tonic-gate 	rc = snprintf(rmsg, len, "%s%s%s%s", umnt_msg, fsck_msg,
7800Sstevel@tonic-gate 					    !only_fsck? "\n": "", mnt_msg);
7810Sstevel@tonic-gate 	if (rc == EOF) {
7820Sstevel@tonic-gate 		goto out;
7830Sstevel@tonic-gate 	}
7840Sstevel@tonic-gate 
7850Sstevel@tonic-gate out:
7860Sstevel@tonic-gate 	if (mp) {
7870Sstevel@tonic-gate 		Free(mp);
7880Sstevel@tonic-gate 		mp = NULL;
7890Sstevel@tonic-gate 	}
7900Sstevel@tonic-gate 	if (len == 0 && rmsg) {
7910Sstevel@tonic-gate 		Free(rmsg);
7920Sstevel@tonic-gate 		rmsg = NULL;
7930Sstevel@tonic-gate 	}
7940Sstevel@tonic-gate 
7950Sstevel@tonic-gate 	return (rmsg);
7960Sstevel@tonic-gate }
7970Sstevel@tonic-gate 
7980Sstevel@tonic-gate /*
7990Sstevel@tonic-gate  * printable log state
8000Sstevel@tonic-gate  */
8010Sstevel@tonic-gate char *
mt_l_error_to_name(md_trans_t * transp,md_timeval32_t * tvp,uint_t tstate)8020Sstevel@tonic-gate mt_l_error_to_name(
8030Sstevel@tonic-gate 	md_trans_t	*transp,
8040Sstevel@tonic-gate 	md_timeval32_t	*tvp,
8050Sstevel@tonic-gate 	uint_t		tstate	/* Errored tstate flags */
8060Sstevel@tonic-gate )
8070Sstevel@tonic-gate {
8080Sstevel@tonic-gate 	mt_l_error_t	log_error = transp->log_error;
8090Sstevel@tonic-gate 
8100Sstevel@tonic-gate 	/* grab time */
8110Sstevel@tonic-gate 	if (tvp != NULL)
8120Sstevel@tonic-gate 		*tvp = transp->log_timestamp;
8130Sstevel@tonic-gate 
8140Sstevel@tonic-gate 	if (tstate != 0) {
8150Sstevel@tonic-gate 		return (dgettext(TEXT_DOMAIN, "Unavailable"));
8160Sstevel@tonic-gate 	}
8170Sstevel@tonic-gate 
8180Sstevel@tonic-gate 	/* return state */
8190Sstevel@tonic-gate 	if (log_error & LDL_ERROR) {
8200Sstevel@tonic-gate 		return (dgettext(TEXT_DOMAIN, "Error"));
8210Sstevel@tonic-gate 	} else if (log_error & LDL_HERROR) {
8220Sstevel@tonic-gate 		return (dgettext(TEXT_DOMAIN, "Hard Error"));
8230Sstevel@tonic-gate 	} else {
8240Sstevel@tonic-gate 		return (dgettext(TEXT_DOMAIN, "Okay"));
8250Sstevel@tonic-gate 	}
8260Sstevel@tonic-gate }
8270Sstevel@tonic-gate 
8280Sstevel@tonic-gate /*
8290Sstevel@tonic-gate  * printable trans state
8300Sstevel@tonic-gate  */
8310Sstevel@tonic-gate char *
mt_flags_to_name(md_trans_t * transp,md_timeval32_t * tvp,uint_t tstate)8320Sstevel@tonic-gate mt_flags_to_name(
8330Sstevel@tonic-gate 	md_trans_t	*transp,
8340Sstevel@tonic-gate 	md_timeval32_t	*tvp,
8350Sstevel@tonic-gate 	uint_t		tstate	/* Errored tstate flags */
8360Sstevel@tonic-gate )
8370Sstevel@tonic-gate {
8380Sstevel@tonic-gate 	/* grab time */
8390Sstevel@tonic-gate 	if (tvp != NULL)
8400Sstevel@tonic-gate 		*tvp = transp->timestamp;
8410Sstevel@tonic-gate 
8420Sstevel@tonic-gate 	if (tstate != 0) {
8430Sstevel@tonic-gate 		return (dgettext(TEXT_DOMAIN, "Unavailable"));
8440Sstevel@tonic-gate 	}
8450Sstevel@tonic-gate 
8460Sstevel@tonic-gate 	/* return state */
8470Sstevel@tonic-gate 	if (transp->flags & TRANS_DETACHED)
8480Sstevel@tonic-gate 		return (dgettext(TEXT_DOMAIN, "Detached"));
8490Sstevel@tonic-gate 	else if (transp->flags & TRANS_DETACHING)
8500Sstevel@tonic-gate 		return (dgettext(TEXT_DOMAIN, "Detaching"));
8510Sstevel@tonic-gate 	else if (transp->flags & TRANS_ATTACHING)
8520Sstevel@tonic-gate 		return (dgettext(TEXT_DOMAIN, "Attaching"));
8530Sstevel@tonic-gate 	return (mt_l_error_to_name(transp, tvp, tstate));
8540Sstevel@tonic-gate }
8550Sstevel@tonic-gate 
8560Sstevel@tonic-gate /*
8570Sstevel@tonic-gate  * report trans
8580Sstevel@tonic-gate  */
8590Sstevel@tonic-gate static int
trans_report(mdsetname_t * sp,md_trans_t * transp,char * fname,FILE * fp,mdprtopts_t options,md_error_t * ep)8600Sstevel@tonic-gate trans_report(
8610Sstevel@tonic-gate 	mdsetname_t	*sp,
8620Sstevel@tonic-gate 	md_trans_t	*transp,
8630Sstevel@tonic-gate 	char		*fname,
8640Sstevel@tonic-gate 	FILE		*fp,
8650Sstevel@tonic-gate 	mdprtopts_t	options,
8660Sstevel@tonic-gate 	md_error_t	*ep
8670Sstevel@tonic-gate )
8680Sstevel@tonic-gate {
8690Sstevel@tonic-gate 	char		*mt_state;
8700Sstevel@tonic-gate 	md_timeval32_t	tv;
8710Sstevel@tonic-gate 	char		*timep;
8720Sstevel@tonic-gate 	int		rval = -1;
8730Sstevel@tonic-gate 	char		*actionp = NULL;
8740Sstevel@tonic-gate 	char 		*devid = "";
8750Sstevel@tonic-gate 	mdname_t	*didnp = NULL;
8760Sstevel@tonic-gate 	ddi_devid_t	dtp;
8770Sstevel@tonic-gate 	uint_t		tstate = 0;
8780Sstevel@tonic-gate 
8790Sstevel@tonic-gate 	/* print header */
8800Sstevel@tonic-gate 	if (options & PRINT_HEADER) {
8810Sstevel@tonic-gate 		if (fprintf(fp, dgettext(TEXT_DOMAIN, "%s: Trans"
8820Sstevel@tonic-gate 		    " (Feature replaced see message below)\n"),
8830Sstevel@tonic-gate 		    transp->common.namep->cname) == EOF) {
8840Sstevel@tonic-gate 			goto out;
8850Sstevel@tonic-gate 		}
8860Sstevel@tonic-gate 	}
8870Sstevel@tonic-gate 
8880Sstevel@tonic-gate 	/* print state */
8890Sstevel@tonic-gate 	if (metaismeta(transp->common.namep)) {
8900Sstevel@tonic-gate 		if (meta_get_tstate(transp->common.namep->dev, &tstate, ep)
8910Sstevel@tonic-gate 		    != 0)
8920Sstevel@tonic-gate 			goto out;
8930Sstevel@tonic-gate 	}
8940Sstevel@tonic-gate 	mt_state = mt_flags_to_name(transp, &tv, tstate & MD_DEV_ERRORED);
8950Sstevel@tonic-gate 	if (options & PRINT_TIMES) {
8960Sstevel@tonic-gate 		timep = meta_print_time(&tv);
8970Sstevel@tonic-gate 	} else {
8980Sstevel@tonic-gate 		timep = "";
8990Sstevel@tonic-gate 	}
9000Sstevel@tonic-gate 	if (fprintf(fp, dgettext(TEXT_DOMAIN, "    State: %-12s %s\n"),
9010Sstevel@tonic-gate 	    mt_state, timep) == EOF) {
9020Sstevel@tonic-gate 		goto out;
9030Sstevel@tonic-gate 	}
9040Sstevel@tonic-gate 
9050Sstevel@tonic-gate 	if ((tstate & MD_DEV_ERRORED) == 0) {
9060Sstevel@tonic-gate 		actionp = mt_flags_to_action(transp);
9070Sstevel@tonic-gate 		if (actionp) {
9080Sstevel@tonic-gate 			if (fprintf(fp, "%s", actionp) == EOF) {
9090Sstevel@tonic-gate 				goto out;
9100Sstevel@tonic-gate 			}
9110Sstevel@tonic-gate 			Free(actionp);
9120Sstevel@tonic-gate 			actionp = NULL;
9130Sstevel@tonic-gate 		}
9140Sstevel@tonic-gate 	}
9150Sstevel@tonic-gate 
9160Sstevel@tonic-gate 	/* debug stuff */
9170Sstevel@tonic-gate 	if (transp->debug) {
9180Sstevel@tonic-gate 		if (fprintf(fp,
9190Sstevel@tonic-gate 		    "    Debug Modes:%s%s%s%s%s%s%s%s%s%s%s\n",
9200Sstevel@tonic-gate 		    (transp->debug & MT_TRANSACT) ? " TRANSACT" : "",
9210Sstevel@tonic-gate 		    (transp->debug & MT_MATAMAP) ? " METADATA" : "",
9220Sstevel@tonic-gate 		    (transp->debug & MT_WRITE_CHECK) ?  " WRITES" : "",
9230Sstevel@tonic-gate 		    (transp->debug & MT_LOG_WRITE_CHECK) ? " LOGWRITES" : "",
9240Sstevel@tonic-gate 		    (transp->debug & MT_CHECK_MAP) ? " MAP" : "",
9250Sstevel@tonic-gate 		    (transp->debug & MT_TRACE) ? " TRACE" : "",
9260Sstevel@tonic-gate 		    (transp->debug & MT_SIZE) ? " SIZE" : "",
9270Sstevel@tonic-gate 		    (transp->debug & MT_NOASYNC) ? " NOASYNC" : "",
9280Sstevel@tonic-gate 		    (transp->debug & MT_FORCEROLL) ? " FORCEROLL" : "",
9290Sstevel@tonic-gate 		    (transp->debug & MT_SCAN) ? " SCAN" : "",
9300Sstevel@tonic-gate 		    (transp->debug & MT_PREWRITE) ? " PREWRITE" : "")
9310Sstevel@tonic-gate 		    == EOF) {
9320Sstevel@tonic-gate 			goto out;
9330Sstevel@tonic-gate 		}
9340Sstevel@tonic-gate 	}
9350Sstevel@tonic-gate 
9360Sstevel@tonic-gate 	/* print size */
9370Sstevel@tonic-gate 	if (fprintf(fp, dgettext(TEXT_DOMAIN, "    Size: %lld blocks (%s)\n"),
9380Sstevel@tonic-gate 	    transp->common.size,
9390Sstevel@tonic-gate 	    meta_number_to_string(transp->common.size, DEV_BSIZE)) == EOF) {
9400Sstevel@tonic-gate 		goto out;
9410Sstevel@tonic-gate 	}
9420Sstevel@tonic-gate 
9430Sstevel@tonic-gate 
9440Sstevel@tonic-gate 	/* print master */
9450Sstevel@tonic-gate 	if (fprintf(fp, dgettext(TEXT_DOMAIN, "    Master Device: %s\n"),
9460Sstevel@tonic-gate 	    transp->masternamep->cname) == EOF) {
9470Sstevel@tonic-gate 		goto out;
9480Sstevel@tonic-gate 	}
9490Sstevel@tonic-gate 
9500Sstevel@tonic-gate 	/* print log */
9510Sstevel@tonic-gate 	if (transp->lognamep != NULL) {
9520Sstevel@tonic-gate 		if (fprintf(fp, dgettext(TEXT_DOMAIN,
9530Sstevel@tonic-gate 		    "    Logging Device: %s\n"),
9540Sstevel@tonic-gate 		    transp->lognamep->cname) == EOF) {
9550Sstevel@tonic-gate 			goto out;
9560Sstevel@tonic-gate 		}
9570Sstevel@tonic-gate 	}
9580Sstevel@tonic-gate 
9590Sstevel@tonic-gate 	/* add extra line */
9600Sstevel@tonic-gate 	if (fprintf(fp, "\n") == EOF)
9610Sstevel@tonic-gate 		goto out;
9620Sstevel@tonic-gate 
9630Sstevel@tonic-gate 	/* print master details if regular device */
9640Sstevel@tonic-gate 	if (! metaismeta(transp->masternamep)) {
9650Sstevel@tonic-gate 		daddr_t	start_blk = 0;
9660Sstevel@tonic-gate 		char	*has_mddb_str = dgettext(TEXT_DOMAIN, "No");
9670Sstevel@tonic-gate 		int	len;
9680Sstevel@tonic-gate 
9690Sstevel@tonic-gate 		/*
9700Sstevel@tonic-gate 		 * Building a format string on the fly that will
9710Sstevel@tonic-gate 		 * be used in (f)printf. This allows the length
9720Sstevel@tonic-gate 		 * of the ctd to vary from small to large without
9730Sstevel@tonic-gate 		 * looking horrible.
9740Sstevel@tonic-gate 		 */
9750Sstevel@tonic-gate 		len = strlen(transp->masternamep->cname) + 2;
9760Sstevel@tonic-gate 		len = max(len, strlen(dgettext(TEXT_DOMAIN, "Master Device")));
9770Sstevel@tonic-gate 
9780Sstevel@tonic-gate 		/* print header */
9790Sstevel@tonic-gate 		if (fprintf(fp,
9800Sstevel@tonic-gate 		    "\t%-*.*s %-12.12s %-5.5s %s\n",
9810Sstevel@tonic-gate 		    len, len,
9820Sstevel@tonic-gate 		    dgettext(TEXT_DOMAIN, "Master Device"),
9830Sstevel@tonic-gate 		    dgettext(TEXT_DOMAIN, "Start Block"),
9840Sstevel@tonic-gate 		    dgettext(TEXT_DOMAIN, "Dbase"),
9850Sstevel@tonic-gate 			dgettext(TEXT_DOMAIN, "Reloc")) == EOF) {
9860Sstevel@tonic-gate 			goto out;
9870Sstevel@tonic-gate 		}
9880Sstevel@tonic-gate 
9890Sstevel@tonic-gate 		/* populate the key in the name_p structure */
9900Sstevel@tonic-gate 		if ((didnp = metadevname(&sp,
9910Sstevel@tonic-gate 				transp->masternamep->dev, ep)) == NULL) {
9920Sstevel@tonic-gate 			return (-1);
9930Sstevel@tonic-gate 		}
9940Sstevel@tonic-gate 
9950Sstevel@tonic-gate 	    /* determine if devid does NOT exist */
9960Sstevel@tonic-gate 		if (options & PRINT_DEVID)
9970Sstevel@tonic-gate 		    if ((dtp = meta_getdidbykey(sp->setno, getmyside(sp, ep),
9980Sstevel@tonic-gate 					didnp->key, ep)) == NULL)
9990Sstevel@tonic-gate 				devid = dgettext(TEXT_DOMAIN, "No ");
10000Sstevel@tonic-gate 			else {
10010Sstevel@tonic-gate 				devid = dgettext(TEXT_DOMAIN, "Yes");
10020Sstevel@tonic-gate 				free(dtp);
10030Sstevel@tonic-gate 			}
10040Sstevel@tonic-gate 
10050Sstevel@tonic-gate 		/* print info */
10060Sstevel@tonic-gate 		/*
10070Sstevel@tonic-gate 		 * This allows the length
10080Sstevel@tonic-gate 		 * of the ctd to vary from small to large without
10090Sstevel@tonic-gate 		 * looking horrible.
10100Sstevel@tonic-gate 		 */
10110Sstevel@tonic-gate 		if (fprintf(fp, "\t%-*s %8ld     %-5.5s %s\n", len,
10120Sstevel@tonic-gate 		    transp->masternamep->cname,
10130Sstevel@tonic-gate 		    start_blk, has_mddb_str, devid) == EOF) {
10140Sstevel@tonic-gate 			goto out;
10150Sstevel@tonic-gate 		}
10160Sstevel@tonic-gate 		/* add extra line */
10170Sstevel@tonic-gate 		if (fprintf(fp, "\n") == EOF)
10180Sstevel@tonic-gate 			goto out;
10190Sstevel@tonic-gate 	}
10200Sstevel@tonic-gate 
10210Sstevel@tonic-gate 	/* success */
10220Sstevel@tonic-gate 	rval = 0;
10230Sstevel@tonic-gate 
10240Sstevel@tonic-gate 	/* cleanup, return error */
10250Sstevel@tonic-gate out:
10260Sstevel@tonic-gate 	if (rval != 0)
10270Sstevel@tonic-gate 		(void) mdsyserror(ep, errno, fname);
10280Sstevel@tonic-gate 	return (rval);
10290Sstevel@tonic-gate }
10300Sstevel@tonic-gate 
10310Sstevel@tonic-gate /*
10320Sstevel@tonic-gate  * print/report trans
10330Sstevel@tonic-gate  */
10340Sstevel@tonic-gate int
meta_trans_print(mdsetname_t * sp,mdname_t * transnp,mdnamelist_t ** nlistpp,char * fname,FILE * fp,mdprtopts_t options,int * meta_print_trans_msgp,mdnamelist_t ** lognlpp,md_error_t * ep)10350Sstevel@tonic-gate meta_trans_print(
10360Sstevel@tonic-gate 	mdsetname_t	*sp,
10370Sstevel@tonic-gate 	mdname_t	*transnp,
10380Sstevel@tonic-gate 	mdnamelist_t	**nlistpp,
10390Sstevel@tonic-gate 	char		*fname,
10400Sstevel@tonic-gate 	FILE		*fp,
10410Sstevel@tonic-gate 	mdprtopts_t	options,
10420Sstevel@tonic-gate 	int		*meta_print_trans_msgp, /* NULL if transnp != NULL */
10430Sstevel@tonic-gate 	mdnamelist_t	**lognlpp,
10440Sstevel@tonic-gate 	md_error_t	*ep
10450Sstevel@tonic-gate )
10460Sstevel@tonic-gate {
10470Sstevel@tonic-gate 	md_trans_t	*transp;
10480Sstevel@tonic-gate 	mdname_t	*lognamep;
10490Sstevel@tonic-gate 
10500Sstevel@tonic-gate 	/* should have same set */
10510Sstevel@tonic-gate 	assert(sp != NULL);
10520Sstevel@tonic-gate 
10530Sstevel@tonic-gate 	/* print all transs */
10540Sstevel@tonic-gate 	if (transnp == NULL) {
10550Sstevel@tonic-gate 		mdnamelist_t	*nlp = NULL;
10560Sstevel@tonic-gate 		mdnamelist_t	*p;
10570Sstevel@tonic-gate 		int		cnt;
10580Sstevel@tonic-gate 		int		rval = 0;
10590Sstevel@tonic-gate 
10600Sstevel@tonic-gate 		/* get list */
10610Sstevel@tonic-gate 		if ((cnt = meta_get_trans_names(sp, &nlp, options, ep)) < 0)
10620Sstevel@tonic-gate 			return (-1);
10630Sstevel@tonic-gate 		else if (cnt == 0)
10640Sstevel@tonic-gate 			return (0);
10650Sstevel@tonic-gate 
10660Sstevel@tonic-gate 		/* recurse */
10670Sstevel@tonic-gate 		for (p = nlp; (p != NULL); p = p->next) {
10680Sstevel@tonic-gate 			mdname_t	*np = p->namep;
10690Sstevel@tonic-gate 
10700Sstevel@tonic-gate 			if (meta_trans_print(sp, np, nlistpp, fname, fp,
10710Sstevel@tonic-gate 			    options, meta_print_trans_msgp, lognlpp, ep) != 0)
10720Sstevel@tonic-gate 				rval = -1;
10730Sstevel@tonic-gate 		}
10740Sstevel@tonic-gate 
10750Sstevel@tonic-gate 		if (meta_print_trans_msgp)
10760Sstevel@tonic-gate 			*meta_print_trans_msgp = 1;
10770Sstevel@tonic-gate 
10780Sstevel@tonic-gate 		/* cleanup, return success */
10790Sstevel@tonic-gate 		metafreenamelist(nlp);
10800Sstevel@tonic-gate 		return (rval);
10810Sstevel@tonic-gate 	}
10820Sstevel@tonic-gate 
10830Sstevel@tonic-gate 
10840Sstevel@tonic-gate 	/* get unit structure */
10850Sstevel@tonic-gate 	if ((transp = meta_get_trans_common(sp, transnp,
10860Sstevel@tonic-gate 	    ((options & PRINT_FAST) ? 1 : 0), ep)) == NULL)
10870Sstevel@tonic-gate 		return (-1);
10880Sstevel@tonic-gate 
10890Sstevel@tonic-gate 	/* save unique log */
10900Sstevel@tonic-gate 	if ((lognlpp != NULL) &&
10910Sstevel@tonic-gate 	    ((lognamep = transp->lognamep) != NULL)) {
10920Sstevel@tonic-gate 		mdnamelist_t	*p;
10930Sstevel@tonic-gate 
10940Sstevel@tonic-gate 		for (p = *lognlpp; (p != NULL); p = p->next) {
10950Sstevel@tonic-gate 			if (strcmp(lognamep->bname, p->namep->bname) == 0)
10960Sstevel@tonic-gate 				break;
10970Sstevel@tonic-gate 		}
10980Sstevel@tonic-gate 		if (p == NULL)
10990Sstevel@tonic-gate 			(void) metanamelist_append(lognlpp, lognamep);
11000Sstevel@tonic-gate 	}
11010Sstevel@tonic-gate 
11020Sstevel@tonic-gate 	/* check for parented */
11030Sstevel@tonic-gate 	if ((! (options & PRINT_SUBDEVS)) &&
11040Sstevel@tonic-gate 	    (MD_HAS_PARENT(transp->common.parent))) {
11050Sstevel@tonic-gate 		return (0);
11060Sstevel@tonic-gate 	}
11070Sstevel@tonic-gate 
1108*1623Stw21770 	/* can't have a large trans or descriptive name trans */
1109*1623Stw21770 	if (!(options & (PRINT_LARGEDEVICES | PRINT_FN))) {
11100Sstevel@tonic-gate 		/* print appropriate detail */
11110Sstevel@tonic-gate 		if (options & PRINT_SHORT) {
11120Sstevel@tonic-gate 			if (trans_print(transp, fname, fp, ep) != 0)
11130Sstevel@tonic-gate 				return (-1);
11140Sstevel@tonic-gate 		} else {
11150Sstevel@tonic-gate 			if (trans_report(sp, transp, fname, fp, options, ep)
11160Sstevel@tonic-gate 			    != 0)
11170Sstevel@tonic-gate 				return (-1);
11180Sstevel@tonic-gate 		}
11190Sstevel@tonic-gate 	}
11200Sstevel@tonic-gate 
11210Sstevel@tonic-gate 	/* print underlying metadevices, log is later */
11220Sstevel@tonic-gate 	if (metaismeta(transp->masternamep)) {
11230Sstevel@tonic-gate 		if (meta_print_name(sp, transp->masternamep, nlistpp, fname,
11240Sstevel@tonic-gate 		    fp, (options | PRINT_HEADER | PRINT_SUBDEVS), NULL, ep)
11250Sstevel@tonic-gate 		    != 0) {
11260Sstevel@tonic-gate 			return (-1);
11270Sstevel@tonic-gate 		}
11280Sstevel@tonic-gate 	}
11290Sstevel@tonic-gate 
11300Sstevel@tonic-gate 	/* return success */
11310Sstevel@tonic-gate 	return (0);
11320Sstevel@tonic-gate }
11330Sstevel@tonic-gate 
11340Sstevel@tonic-gate /*
11350Sstevel@tonic-gate  * print log
11360Sstevel@tonic-gate  */
11370Sstevel@tonic-gate static int
log_print(mdsetname_t * sp,mdname_t * lognamep,char * fname,FILE * fp,mdprtopts_t options,md_error_t * ep)11380Sstevel@tonic-gate log_print(
11390Sstevel@tonic-gate 	mdsetname_t	*sp,
11400Sstevel@tonic-gate 	mdname_t	*lognamep,
11410Sstevel@tonic-gate 	char		*fname,
11420Sstevel@tonic-gate 	FILE		*fp,
11430Sstevel@tonic-gate 	mdprtopts_t	options,
11440Sstevel@tonic-gate 	md_error_t	*ep
11450Sstevel@tonic-gate )
11460Sstevel@tonic-gate {
11470Sstevel@tonic-gate 	mdnamelist_t	*nlp = NULL;
11480Sstevel@tonic-gate 
11490Sstevel@tonic-gate 	/* metadevice info */
11500Sstevel@tonic-gate 	if (metaismeta(lognamep)) {
11510Sstevel@tonic-gate 		return (meta_print_name(sp, lognamep, &nlp, fname, fp,
11520Sstevel@tonic-gate 		    options, NULL, ep));
11530Sstevel@tonic-gate 	}
11540Sstevel@tonic-gate 
11550Sstevel@tonic-gate 	/* regular device info */
11560Sstevel@tonic-gate 	return (0);
11570Sstevel@tonic-gate }
11580Sstevel@tonic-gate 
11590Sstevel@tonic-gate /*
11600Sstevel@tonic-gate  * report log
11610Sstevel@tonic-gate  */
11620Sstevel@tonic-gate static int
log_report(mdsetname_t * sp,mdname_t * lognamep,mdnamelist_t ** nlistpp,char * fname,FILE * fp,mdprtopts_t options,mdnamelist_t * transnlp,md_error_t * ep)11630Sstevel@tonic-gate log_report(
11640Sstevel@tonic-gate 	mdsetname_t	*sp,
11650Sstevel@tonic-gate 	mdname_t	*lognamep,
11660Sstevel@tonic-gate 	mdnamelist_t	**nlistpp,
11670Sstevel@tonic-gate 	char		*fname,
11680Sstevel@tonic-gate 	FILE		*fp,
11690Sstevel@tonic-gate 	mdprtopts_t	options,
11700Sstevel@tonic-gate 	mdnamelist_t	*transnlp,
11710Sstevel@tonic-gate 	md_error_t	*ep
11720Sstevel@tonic-gate )
11730Sstevel@tonic-gate {
11740Sstevel@tonic-gate 	md_trans_t	*transp = NULL;
11750Sstevel@tonic-gate 	mdnamelist_t	*p;
11760Sstevel@tonic-gate 	char		*ml_state;
11770Sstevel@tonic-gate 	md_timeval32_t	tv;
11780Sstevel@tonic-gate 	char		*timep;
11790Sstevel@tonic-gate 	char		*actionp = NULL;
11800Sstevel@tonic-gate 	int		rval = -1;
11810Sstevel@tonic-gate 	char		*devid = " ";
11820Sstevel@tonic-gate 	mdname_t	*didnp = NULL;
11830Sstevel@tonic-gate 	ddi_devid_t	dtp;
11840Sstevel@tonic-gate 	uint_t		tstate = 0;
11850Sstevel@tonic-gate 
11860Sstevel@tonic-gate 	for (p = transnlp; (p != NULL); p = p->next) {
11870Sstevel@tonic-gate 		md_trans_t	*tp;
11880Sstevel@tonic-gate 
11890Sstevel@tonic-gate 		if ((tp = meta_get_trans(sp, p->namep, ep)) == NULL)
11900Sstevel@tonic-gate 			return (-1);
11910Sstevel@tonic-gate 		if ((tp->lognamep != NULL) &&
11920Sstevel@tonic-gate 		    (strcmp(lognamep->bname, tp->lognamep->bname) == 0)) {
11930Sstevel@tonic-gate 			transp = tp;	/* save any parent trans */
11940Sstevel@tonic-gate 		}
11950Sstevel@tonic-gate 	}
11960Sstevel@tonic-gate 
11970Sstevel@tonic-gate 	/* we must have at least one trans */
11980Sstevel@tonic-gate 	assert(transp != NULL);
11990Sstevel@tonic-gate 	if (transp == NULL) {
12000Sstevel@tonic-gate 		rval = 0;
12010Sstevel@tonic-gate 		goto out;
12020Sstevel@tonic-gate 	}
12030Sstevel@tonic-gate 
12040Sstevel@tonic-gate 	if ((options & PRINT_LARGEDEVICES) &&
12050Sstevel@tonic-gate 	    (transp->log_size <= MD_MAX_BLKS_FOR_SMALL_DEVS)) {
12060Sstevel@tonic-gate 		rval = 0;
12070Sstevel@tonic-gate 		goto out;
12080Sstevel@tonic-gate 	}
12090Sstevel@tonic-gate 
12100Sstevel@tonic-gate 	/* print header and trans devices, collect log_error and size */
12110Sstevel@tonic-gate 	if (fprintf(fp, dgettext(TEXT_DOMAIN, "%s: Logging device for"),
12120Sstevel@tonic-gate 	    lognamep->cname) == EOF) {
12130Sstevel@tonic-gate 		goto out;
12140Sstevel@tonic-gate 	}
12150Sstevel@tonic-gate 
12160Sstevel@tonic-gate 	if ((transp->lognamep != NULL) &&
12170Sstevel@tonic-gate 	    (strcmp(lognamep->bname, transp->lognamep->bname) == 0)) {
12180Sstevel@tonic-gate 		if (fprintf(fp, " %s", transp->common.namep->cname)
12190Sstevel@tonic-gate 		    == EOF) {
12200Sstevel@tonic-gate 			goto out;
12210Sstevel@tonic-gate 		}
12220Sstevel@tonic-gate 	}
12230Sstevel@tonic-gate 	if (fprintf(fp, "\n") == EOF)
12240Sstevel@tonic-gate 		goto out;
12250Sstevel@tonic-gate 
12260Sstevel@tonic-gate 	/* print state */
12270Sstevel@tonic-gate 	if (metaismeta(transp->lognamep)) {
12280Sstevel@tonic-gate 		if (meta_get_tstate(transp->lognamep->dev, &tstate, ep) != 0)
12290Sstevel@tonic-gate 			return (-1);
12300Sstevel@tonic-gate 	}
12310Sstevel@tonic-gate 	ml_state = mt_l_error_to_name(transp, &tv, tstate & MD_DEV_ERRORED);
12320Sstevel@tonic-gate 	if (options & PRINT_TIMES) {
12330Sstevel@tonic-gate 		timep = meta_print_time(&tv);
12340Sstevel@tonic-gate 	} else {
12350Sstevel@tonic-gate 		timep = "";
12360Sstevel@tonic-gate 	}
12370Sstevel@tonic-gate 	if (fprintf(fp, dgettext(TEXT_DOMAIN, "    State: %-12s %s\n"),
12380Sstevel@tonic-gate 	    ml_state, timep) == EOF) {
12390Sstevel@tonic-gate 		goto out;
12400Sstevel@tonic-gate 	}
12410Sstevel@tonic-gate 
12420Sstevel@tonic-gate 	if ((tstate & MD_DEV_ERRORED) == 0) {
12430Sstevel@tonic-gate 		actionp = mt_l_error_to_action(sp, transnlp, lognamep, ep);
12440Sstevel@tonic-gate 		if (actionp) {
12450Sstevel@tonic-gate 			if (fprintf(fp, dgettext(TEXT_DOMAIN,
12460Sstevel@tonic-gate 			    "    Invoke: %s\n"), actionp) == EOF) {
12470Sstevel@tonic-gate 				goto out;
12480Sstevel@tonic-gate 			}
12490Sstevel@tonic-gate 			Free(actionp);
12500Sstevel@tonic-gate 			actionp = NULL;
12510Sstevel@tonic-gate 		}
12520Sstevel@tonic-gate 	}
12530Sstevel@tonic-gate 
12540Sstevel@tonic-gate 	/* print size */
12550Sstevel@tonic-gate 	if (fprintf(fp, dgettext(TEXT_DOMAIN, "    Size: %ld blocks (%s)\n"),
12560Sstevel@tonic-gate 	    transp->log_size,
12570Sstevel@tonic-gate 	    meta_number_to_string(transp->log_size, DEV_BSIZE)) == EOF) {
12580Sstevel@tonic-gate 		goto out;
12590Sstevel@tonic-gate 	}
12600Sstevel@tonic-gate 
12610Sstevel@tonic-gate 	/* MD_DEBUG stuff */
12620Sstevel@tonic-gate 	if (options & PRINT_DEBUG) {
12630Sstevel@tonic-gate 		mdname_t	*transnp = transp->common.namep;
12640Sstevel@tonic-gate 		mt_unit_t	*mt;
12650Sstevel@tonic-gate 		daddr_t		blksinuse, head, tail, nblks, eblk, sblk;
12660Sstevel@tonic-gate 		int		percent;
12670Sstevel@tonic-gate 
12680Sstevel@tonic-gate 		if ((mt = (mt_unit_t *)meta_get_mdunit(sp, transnp, ep))
12690Sstevel@tonic-gate 		    == NULL) {
12700Sstevel@tonic-gate 			return (-1);
12710Sstevel@tonic-gate 		}
12720Sstevel@tonic-gate 		assert(mt->c.un_type == MD_METATRANS);
12730Sstevel@tonic-gate 
12740Sstevel@tonic-gate 		if (fprintf(fp, dgettext(TEXT_DOMAIN,
12750Sstevel@tonic-gate 		    "    Transfer Size: %d blocks\n"),
12760Sstevel@tonic-gate 		    mt->un_l_maxtransfer) == EOF) {
12770Sstevel@tonic-gate 			Free(mt);
12780Sstevel@tonic-gate 			goto out;
12790Sstevel@tonic-gate 		}
12800Sstevel@tonic-gate 
12810Sstevel@tonic-gate 		head = mt->un_l_head;
12820Sstevel@tonic-gate 		tail = mt->un_l_tail;
12830Sstevel@tonic-gate 		sblk = mt->un_l_sblk;
12840Sstevel@tonic-gate 		nblks = mt->un_l_nblks;
12850Sstevel@tonic-gate 		eblk = sblk + nblks;
12860Sstevel@tonic-gate 		if (head <= tail)
12870Sstevel@tonic-gate 			blksinuse = tail - head;
12880Sstevel@tonic-gate 		else
12890Sstevel@tonic-gate 			blksinuse = (eblk - head) + (tail - sblk);
12900Sstevel@tonic-gate 
12910Sstevel@tonic-gate 		percent = ((u_longlong_t)blksinuse * 100) / nblks;
12920Sstevel@tonic-gate 		if (fprintf(fp, dgettext(TEXT_DOMAIN,
12930Sstevel@tonic-gate 		    "    Full: %d%% (%ld of %ld blocks)\n"),
12940Sstevel@tonic-gate 		    percent, blksinuse, nblks) == EOF) {
12950Sstevel@tonic-gate 			Free(mt);
12960Sstevel@tonic-gate 			goto out;
12970Sstevel@tonic-gate 		}
12980Sstevel@tonic-gate 
12990Sstevel@tonic-gate 		percent = ((u_longlong_t)mt->un_l_resv * 100) /
13000Sstevel@tonic-gate 		    mt->un_l_maxresv;
13010Sstevel@tonic-gate 		if (fprintf(fp, dgettext(TEXT_DOMAIN,
13020Sstevel@tonic-gate 		    "    Reserved: %d%% (%ud of %ud bytes)\n"),
13030Sstevel@tonic-gate 		    percent, mt->un_l_resv, mt->un_l_maxresv) == EOF) {
13040Sstevel@tonic-gate 			Free(mt);
13050Sstevel@tonic-gate 			goto out;
13060Sstevel@tonic-gate 		}
13070Sstevel@tonic-gate 		Free(mt);
13080Sstevel@tonic-gate 	}
13090Sstevel@tonic-gate 
13100Sstevel@tonic-gate 	/* add extra line */
13110Sstevel@tonic-gate 	if (fprintf(fp, "\n") == EOF)
13120Sstevel@tonic-gate 		goto out;
13130Sstevel@tonic-gate 
13140Sstevel@tonic-gate 	/* print log details */
13150Sstevel@tonic-gate 	if (metaismeta(lognamep)) {
13160Sstevel@tonic-gate 		if (meta_print_name(sp, lognamep, nlistpp, fname, fp,
13170Sstevel@tonic-gate 		    options, NULL, ep) != 0) {
13180Sstevel@tonic-gate 			return (-1);
13190Sstevel@tonic-gate 		}
13200Sstevel@tonic-gate 	} else {
13210Sstevel@tonic-gate 		daddr_t		start_blk;
13220Sstevel@tonic-gate 		int		has_mddb;
13230Sstevel@tonic-gate 		char		*has_mddb_str;
13240Sstevel@tonic-gate 		int		len;
13250Sstevel@tonic-gate 
13260Sstevel@tonic-gate 		/*
13270Sstevel@tonic-gate 		 * Building a format string on the fly that will
13280Sstevel@tonic-gate 		 * be used in (f)printf. This allows the length
13290Sstevel@tonic-gate 		 * of the ctd to vary from small to large without
13300Sstevel@tonic-gate 		 * looking horrible.
13310Sstevel@tonic-gate 		 */
13320Sstevel@tonic-gate 		len = strlen(lognamep->cname) + 2;
13330Sstevel@tonic-gate 		len = max(len, strlen(dgettext(TEXT_DOMAIN, "Logging Device")));
13340Sstevel@tonic-gate 		/* print header */
13350Sstevel@tonic-gate 		if (fprintf(fp,
13360Sstevel@tonic-gate 		    "\t%-*.*s %-12.12s %-5.5s %s\n",
13370Sstevel@tonic-gate 		    len, len,
13380Sstevel@tonic-gate 		    dgettext(TEXT_DOMAIN, "Logging Device"),
13390Sstevel@tonic-gate 		    dgettext(TEXT_DOMAIN, "Start Block"),
13400Sstevel@tonic-gate 		    dgettext(TEXT_DOMAIN, "Dbase"),
13410Sstevel@tonic-gate 			dgettext(TEXT_DOMAIN, "Reloc")) == EOF) {
13420Sstevel@tonic-gate 			goto out;
13430Sstevel@tonic-gate 		}
13440Sstevel@tonic-gate 		/* get info */
13450Sstevel@tonic-gate 		if ((start_blk = metagetstart(sp, lognamep, ep)) ==
13460Sstevel@tonic-gate 		    MD_DISKADDR_ERROR) {
13470Sstevel@tonic-gate 			return (-1);
13480Sstevel@tonic-gate 		}
13490Sstevel@tonic-gate 		if ((has_mddb = metahasmddb(sp, lognamep, ep)) < 0) {
13500Sstevel@tonic-gate 			return (-1);
13510Sstevel@tonic-gate 		}
13520Sstevel@tonic-gate 		if (has_mddb)
13530Sstevel@tonic-gate 			has_mddb_str = dgettext(TEXT_DOMAIN, "Yes");
13540Sstevel@tonic-gate 		else
13550Sstevel@tonic-gate 			has_mddb_str = dgettext(TEXT_DOMAIN, "No");
13560Sstevel@tonic-gate 
13570Sstevel@tonic-gate 		/* populate the key in the name_p structure */
13580Sstevel@tonic-gate 		if ((didnp = metadevname(&sp, lognamep->dev, ep)) == NULL) {
13590Sstevel@tonic-gate 			return (-1);
13600Sstevel@tonic-gate 		}
13610Sstevel@tonic-gate 
13620Sstevel@tonic-gate 	    /* determine if devid does NOT exist */
13630Sstevel@tonic-gate 		if (options & PRINT_DEVID)
13640Sstevel@tonic-gate 		    if ((dtp = meta_getdidbykey(sp->setno, getmyside(sp, ep),
13650Sstevel@tonic-gate 					didnp->key, ep)) == NULL)
13660Sstevel@tonic-gate 				devid = dgettext(TEXT_DOMAIN, "No ");
13670Sstevel@tonic-gate 			else {
13680Sstevel@tonic-gate 				devid = dgettext(TEXT_DOMAIN, "Yes");
13690Sstevel@tonic-gate 				free(dtp);
13700Sstevel@tonic-gate 			}
13710Sstevel@tonic-gate 
13720Sstevel@tonic-gate 		/* print info */
13730Sstevel@tonic-gate 		/*
13740Sstevel@tonic-gate 		 * This allows the length
13750Sstevel@tonic-gate 		 * of the ctd to vary from small to large without
13760Sstevel@tonic-gate 		 * looking horrible.
13770Sstevel@tonic-gate 		 */
13780Sstevel@tonic-gate 		if (fprintf(fp, "\t%-*s %8ld     %-5.5s %s\n",
13790Sstevel@tonic-gate 		    len, lognamep->cname, start_blk,
13800Sstevel@tonic-gate 		    has_mddb_str, devid) == EOF) {
13810Sstevel@tonic-gate 			goto out;
13820Sstevel@tonic-gate 		}
13830Sstevel@tonic-gate 	}
13840Sstevel@tonic-gate 
13850Sstevel@tonic-gate 	/* add extra line */
13860Sstevel@tonic-gate 	if (fprintf(fp, "\n") == EOF)
13870Sstevel@tonic-gate 		goto out;
13880Sstevel@tonic-gate 
13890Sstevel@tonic-gate 	/* success */
13900Sstevel@tonic-gate 	rval = 0;
13910Sstevel@tonic-gate 
13920Sstevel@tonic-gate 	/* cleanup, return error */
13930Sstevel@tonic-gate out:
13940Sstevel@tonic-gate 	if (rval != 0)
13950Sstevel@tonic-gate 		(void) mdsyserror(ep, errno, fname);
13960Sstevel@tonic-gate 	return (rval);
13970Sstevel@tonic-gate }
13980Sstevel@tonic-gate 
13990Sstevel@tonic-gate /*
14000Sstevel@tonic-gate  * print/report logs
14010Sstevel@tonic-gate  */
14020Sstevel@tonic-gate int
meta_logs_print(mdsetname_t * sp,mdnamelist_t * lognlp,mdnamelist_t ** nlistpp,char * fname,FILE * fp,mdprtopts_t options,md_error_t * ep)14030Sstevel@tonic-gate meta_logs_print(
14040Sstevel@tonic-gate 	mdsetname_t	*sp,
14050Sstevel@tonic-gate 	mdnamelist_t	*lognlp,
14060Sstevel@tonic-gate 	mdnamelist_t	**nlistpp,
14070Sstevel@tonic-gate 	char		*fname,
14080Sstevel@tonic-gate 	FILE		*fp,
14090Sstevel@tonic-gate 	mdprtopts_t	options,
14100Sstevel@tonic-gate 	md_error_t	*ep
14110Sstevel@tonic-gate )
14120Sstevel@tonic-gate {
14130Sstevel@tonic-gate 	mdnamelist_t	*transnlp = NULL;
14140Sstevel@tonic-gate 	mdnamelist_t	*p;
14150Sstevel@tonic-gate 	int		rval = 0;
14160Sstevel@tonic-gate 
14170Sstevel@tonic-gate 	/* must have a set */
14180Sstevel@tonic-gate 	assert(sp != NULL);
14190Sstevel@tonic-gate 
14200Sstevel@tonic-gate 	/* get trans devices */
14210Sstevel@tonic-gate 	if (lognlp == NULL)
14220Sstevel@tonic-gate 		return (0);
14230Sstevel@tonic-gate 
14240Sstevel@tonic-gate 	if (! (options & PRINT_SHORT))
14250Sstevel@tonic-gate 		if (meta_get_trans_names(sp, &transnlp, options, ep) < 0)
14260Sstevel@tonic-gate 			return (-1);
14270Sstevel@tonic-gate 
14280Sstevel@tonic-gate 	/* print all logs */
14290Sstevel@tonic-gate 	options |= PRINT_SUBDEVS;
14300Sstevel@tonic-gate 	for (p = lognlp; (p != NULL); p = p->next) {
14310Sstevel@tonic-gate 		mdname_t	*lognamep = p->namep;
14320Sstevel@tonic-gate 
14330Sstevel@tonic-gate 		/* print appropriate detail */
14340Sstevel@tonic-gate 		if (options & PRINT_SHORT) {
14350Sstevel@tonic-gate 			if (log_print(sp, lognamep, fname, fp, options,
14360Sstevel@tonic-gate 			    ep) != 0) {
14370Sstevel@tonic-gate 				rval = -1;
14380Sstevel@tonic-gate 			}
14390Sstevel@tonic-gate 		} else {
14400Sstevel@tonic-gate 			if (log_report(sp, lognamep, nlistpp, fname, fp,
14410Sstevel@tonic-gate 			    options, transnlp, ep) != 0) {
14420Sstevel@tonic-gate 				rval = -1;
14430Sstevel@tonic-gate 			}
14440Sstevel@tonic-gate 		}
14450Sstevel@tonic-gate 	}
14460Sstevel@tonic-gate 
14470Sstevel@tonic-gate 	/* cleanup, return success */
14480Sstevel@tonic-gate out:
14490Sstevel@tonic-gate 	metafreenamelist(transnlp);
14500Sstevel@tonic-gate 	return (rval);
14510Sstevel@tonic-gate }
14520Sstevel@tonic-gate 
14530Sstevel@tonic-gate /*
14540Sstevel@tonic-gate  * meta_lockfs_common -- common lock and unlock code
14550Sstevel@tonic-gate  *
14560Sstevel@tonic-gate  * Normally this routine will return a 0 for success. Even if
14570Sstevel@tonic-gate  * lockfs wasn't able to lock down the filesystem. The reason
14580Sstevel@tonic-gate  * for this is that the master device can be in an errored state
14590Sstevel@tonic-gate  * and the lock can't be obtained. We don't want to prevent
14600Sstevel@tonic-gate  * possible recovery in this case and it's not likely any activity
14610Sstevel@tonic-gate  * will be occurring. If the filesystem is healthy with activity
14620Sstevel@tonic-gate  * lockfs will successfully lock the filesystem and return an
14630Sstevel@tonic-gate  * error code of 0.
14640Sstevel@tonic-gate  *
14650Sstevel@tonic-gate  * The one case where this routine returns a non-zero value would
14660Sstevel@tonic-gate  * be if we can't determine the outcome of the lockfs. This should
14670Sstevel@tonic-gate  * never occur because we don't catch signals that could cause
14680Sstevel@tonic-gate  * waitpid() to prematurely return.
14690Sstevel@tonic-gate  */
14700Sstevel@tonic-gate static int
meta_lockfs_common(mdname_t * fs,void ** cookie,int lockit)14710Sstevel@tonic-gate meta_lockfs_common(mdname_t *fs, void **cookie, int lockit)
14720Sstevel@tonic-gate {
14730Sstevel@tonic-gate 	char		*blkname;
14740Sstevel@tonic-gate 	FILE		*m;
14750Sstevel@tonic-gate 	struct mnttab	tab_wildcard, tab_match;
14760Sstevel@tonic-gate 	pid_t		pid;
14770Sstevel@tonic-gate 	int		lock_exit;
14780Sstevel@tonic-gate 
14790Sstevel@tonic-gate 	(void) memset(&tab_wildcard, 0, sizeof (tab_wildcard));
14800Sstevel@tonic-gate 	(void) memset(&tab_match, 0, sizeof (tab_match));
14810Sstevel@tonic-gate 
14820Sstevel@tonic-gate 	if ((blkname = fs->bname) == NULL)
14830Sstevel@tonic-gate 		blkname = getfullblkname(fs->cname);
14840Sstevel@tonic-gate 
14850Sstevel@tonic-gate 	tab_wildcard.mnt_special = blkname;
14860Sstevel@tonic-gate 
14870Sstevel@tonic-gate 	if ((m = fopen(MNTTAB, "r")) == NULL) {
14880Sstevel@tonic-gate 		/*
14890Sstevel@tonic-gate 		 * No mnttab means nothing is mounted
14900Sstevel@tonic-gate 		 */
14910Sstevel@tonic-gate 		*cookie = 0;
14920Sstevel@tonic-gate 		return (0);
14930Sstevel@tonic-gate 	}
14940Sstevel@tonic-gate 
14950Sstevel@tonic-gate 	if (getmntany(m, &tab_match, &tab_wildcard)) {
14960Sstevel@tonic-gate 		/*
14970Sstevel@tonic-gate 		 * No match in mnttab so we're not mounted ... at least
14980Sstevel@tonic-gate 		 * nothing better be mounted.
14990Sstevel@tonic-gate 		 */
15000Sstevel@tonic-gate 		*cookie = 0;
15010Sstevel@tonic-gate 		return (0);
15020Sstevel@tonic-gate 	}
15030Sstevel@tonic-gate 
15040Sstevel@tonic-gate 	(void) fclose(m);
15050Sstevel@tonic-gate 
15060Sstevel@tonic-gate 	switch (pid = fork()) {
15070Sstevel@tonic-gate 	    case -1:
15080Sstevel@tonic-gate 		/*
15090Sstevel@tonic-gate 		 * We've got some major trouble here and shouldn't
15100Sstevel@tonic-gate 		 * continue. The user needs to clear up the problems
15110Sstevel@tonic-gate 		 * that the system currently has before proceeding
15120Sstevel@tonic-gate 		 * to detach the log.
15130Sstevel@tonic-gate 		 */
15140Sstevel@tonic-gate 		(void) printf(dgettext(TEXT_DOMAIN, "failed to fork lockfs\n"));
15150Sstevel@tonic-gate 		*cookie = 0;
15160Sstevel@tonic-gate 		return (1);
15170Sstevel@tonic-gate 
15180Sstevel@tonic-gate 	    case 0:
15190Sstevel@tonic-gate 		(void) execl("/usr/sbin/lockfs", "lockfs", lockit ? "-w" : "-u",
15200Sstevel@tonic-gate 		    "-c", "Solaris Volume Manager detach lock",
15210Sstevel@tonic-gate 		    tab_match.mnt_mountp, 0);
15220Sstevel@tonic-gate 		/*
15230Sstevel@tonic-gate 		 * Shouldn't reach here, but if this code is run on
15240Sstevel@tonic-gate 		 * a release that doesn't have lockfs return an error
15250Sstevel@tonic-gate 		 * code so that the -f (force) option could be used
15260Sstevel@tonic-gate 		 * by metadetach.
15270Sstevel@tonic-gate 		 */
15280Sstevel@tonic-gate 		exit(1);
15290Sstevel@tonic-gate 
15300Sstevel@tonic-gate 	    default:
15310Sstevel@tonic-gate 		if (waitpid(pid, &lock_exit, 0) != pid) {
15320Sstevel@tonic-gate 			/*
15330Sstevel@tonic-gate 			 * We couldn't get status regarding the
15340Sstevel@tonic-gate 			 * outcome of the lockfs command. We should
15350Sstevel@tonic-gate 			 * attempt to unlock the filesystem though.
15360Sstevel@tonic-gate 			 * Return an error code so that if the user
15370Sstevel@tonic-gate 			 * is trying to force the detach make them
15380Sstevel@tonic-gate 			 * clear up this problem first.
15390Sstevel@tonic-gate 			 */
15400Sstevel@tonic-gate 			*cookie = (void *)1;
15410Sstevel@tonic-gate 			return (1);
15420Sstevel@tonic-gate 		}
15430Sstevel@tonic-gate 
15440Sstevel@tonic-gate 		*cookie = (void *)1;
15450Sstevel@tonic-gate 		return (0);
15460Sstevel@tonic-gate 	}
15470Sstevel@tonic-gate }
15480Sstevel@tonic-gate 
15490Sstevel@tonic-gate /*
15500Sstevel@tonic-gate  * meta_lockfs - if mounted, lock a given device against writes
15510Sstevel@tonic-gate  *
15520Sstevel@tonic-gate  * See comment section for meta_lockfs_common
15530Sstevel@tonic-gate  */
15540Sstevel@tonic-gate static int
meta_lockfs(mdname_t * fs,void ** cookie)15550Sstevel@tonic-gate meta_lockfs(mdname_t *fs, void **cookie)
15560Sstevel@tonic-gate {
15570Sstevel@tonic-gate 	return (meta_lockfs_common(fs, cookie, 1));
15580Sstevel@tonic-gate }
15590Sstevel@tonic-gate 
15600Sstevel@tonic-gate /*
15610Sstevel@tonic-gate  * meta_unlockfs - if mounted, unlock the filesystem if previously locked
15620Sstevel@tonic-gate  *
15630Sstevel@tonic-gate  * See comment section for meta_lockfs_common
15640Sstevel@tonic-gate  */
15650Sstevel@tonic-gate static void
meta_unlockfs(mdname_t * fs,void ** cookie)15660Sstevel@tonic-gate meta_unlockfs(mdname_t *fs, void **cookie)
15670Sstevel@tonic-gate {
15680Sstevel@tonic-gate 	/*
15690Sstevel@tonic-gate 	 * Simple time saver. We could always try to unlock
15700Sstevel@tonic-gate 	 * the filesystem, that takes time a resources.
15710Sstevel@tonic-gate 	 */
15720Sstevel@tonic-gate 	if (*cookie == (void *)1)
15730Sstevel@tonic-gate 		(void) meta_lockfs_common(fs, cookie, 0);
15740Sstevel@tonic-gate }
15750Sstevel@tonic-gate 
15760Sstevel@tonic-gate /*
15770Sstevel@tonic-gate  * meta_trans_detach -- detach log from trans device
15780Sstevel@tonic-gate  */
15790Sstevel@tonic-gate int
meta_trans_detach(mdsetname_t * sp,mdname_t * transnp,mdcmdopts_t options,int * delayed,md_error_t * ep)15800Sstevel@tonic-gate meta_trans_detach(
15810Sstevel@tonic-gate 	mdsetname_t	*sp,
15820Sstevel@tonic-gate 	mdname_t	*transnp,
15830Sstevel@tonic-gate 	mdcmdopts_t	options,
15840Sstevel@tonic-gate 	int		*delayed,
15850Sstevel@tonic-gate 	md_error_t	*ep
15860Sstevel@tonic-gate )
15870Sstevel@tonic-gate {
15880Sstevel@tonic-gate 	int		force = ((options & MDCMD_FORCE) ? 1 : 0);
15890Sstevel@tonic-gate 	md_i_get_t	detach;
15900Sstevel@tonic-gate 	md_trans_t	*transp;
15910Sstevel@tonic-gate 	mdname_t	*lognp;
15920Sstevel@tonic-gate 	void		*lock_cookie;
15930Sstevel@tonic-gate 
15940Sstevel@tonic-gate 	/* should have a set */
15950Sstevel@tonic-gate 	assert(sp != NULL);
15960Sstevel@tonic-gate 	assert(sp->setno == MD_MIN2SET(meta_getminor(transnp->dev)));
15970Sstevel@tonic-gate 
15980Sstevel@tonic-gate 	/* check name */
15990Sstevel@tonic-gate 	if (metachkmeta(transnp, ep) != 0)
16000Sstevel@tonic-gate 		return (-1);
16010Sstevel@tonic-gate 
16020Sstevel@tonic-gate 	/* save log name */
16030Sstevel@tonic-gate 	if ((transp = meta_get_trans(sp, transnp, ep)) == NULL)
16040Sstevel@tonic-gate 		return (-1);
16050Sstevel@tonic-gate 	if ((lognp = transp->lognamep) == NULL)
16060Sstevel@tonic-gate 		return (mdmderror(ep, MDE_NO_LOG, meta_getminor(transnp->dev),
16070Sstevel@tonic-gate 		    transnp->cname));
16080Sstevel@tonic-gate 
16090Sstevel@tonic-gate 	/*
16100Sstevel@tonic-gate 	 * If trans device is mounted lock the filesystem
16110Sstevel@tonic-gate 	 * against writes and mod time updates.
16120Sstevel@tonic-gate 	 */
16130Sstevel@tonic-gate 	if (force && meta_lockfs(transnp, &lock_cookie)) {
16140Sstevel@tonic-gate 		/*
16150Sstevel@tonic-gate 		 * This device is mounted and we were unable
16160Sstevel@tonic-gate 		 * lock the device. Data corruption can occur
16170Sstevel@tonic-gate 		 * if we don't lock the device before removing
16180Sstevel@tonic-gate 		 * the log so bail out here.
16190Sstevel@tonic-gate 		 * NOTE: There's one case were the exist status
16200Sstevel@tonic-gate 		 * of lockfs could have been lost yet the command
16210Sstevel@tonic-gate 		 * could have run. We should try to unlock the filesystem
16220Sstevel@tonic-gate 		 * before returning.
16230Sstevel@tonic-gate 		 */
16240Sstevel@tonic-gate 		meta_unlockfs(transnp, &lock_cookie);
16250Sstevel@tonic-gate 		return (mdmderror(ep, MDE_UNKNOWN_TYPE,
16260Sstevel@tonic-gate 		    meta_getminor(transnp->dev), transnp->cname));
16270Sstevel@tonic-gate 	}
16280Sstevel@tonic-gate 
16290Sstevel@tonic-gate 	/* detach log */
16300Sstevel@tonic-gate 	*delayed = 0;
16310Sstevel@tonic-gate 	(void) memset(&detach, 0, sizeof (detach));
16320Sstevel@tonic-gate 	detach.id = meta_getminor(transnp->dev);
16330Sstevel@tonic-gate 	MD_SETDRIVERNAME(&detach, MD_TRANS, sp->setno);
16340Sstevel@tonic-gate 	detach.size = force;
16350Sstevel@tonic-gate 	if (metaioctl(MD_IOC_TRANS_DETACH, &detach, &detach.mde, NULL) != 0) {
16360Sstevel@tonic-gate 		/* delayed detach */
16370Sstevel@tonic-gate 		if ((force) && (mdissyserror(&detach.mde, EBUSY))) {
16380Sstevel@tonic-gate 			*delayed = 1;
16390Sstevel@tonic-gate 			mdclrerror(&detach.mde);
16400Sstevel@tonic-gate 		} else {
16410Sstevel@tonic-gate 			meta_unlockfs(transnp, &lock_cookie);
16420Sstevel@tonic-gate 			return (mdstealerror(ep, &detach.mde));
16430Sstevel@tonic-gate 		}
16440Sstevel@tonic-gate 	}
16450Sstevel@tonic-gate 
16460Sstevel@tonic-gate 	/*
16470Sstevel@tonic-gate 	 * Unlock the filesystem
16480Sstevel@tonic-gate 	 */
16490Sstevel@tonic-gate 	meta_unlockfs(transnp, &lock_cookie);
16500Sstevel@tonic-gate 
16510Sstevel@tonic-gate 	/* clear cache */
16520Sstevel@tonic-gate 	meta_invalidate_name(lognp);
16530Sstevel@tonic-gate 	meta_invalidate_name(transnp);
16540Sstevel@tonic-gate 
16550Sstevel@tonic-gate 	/* let em know */
16560Sstevel@tonic-gate 	if (options & MDCMD_PRINT) {
16570Sstevel@tonic-gate 		if (*delayed) {
16580Sstevel@tonic-gate 			(void) printf(dgettext(TEXT_DOMAIN,
16590Sstevel@tonic-gate "%s: logging device %s will be detached at unmount or reboot\n"),
16600Sstevel@tonic-gate 			    transnp->cname, lognp->cname);
16610Sstevel@tonic-gate 		} else {
16620Sstevel@tonic-gate 			(void) printf(dgettext(TEXT_DOMAIN,
16630Sstevel@tonic-gate 			    "%s: logging device %s is detached\n"),
16640Sstevel@tonic-gate 			    transnp->cname, lognp->cname);
16650Sstevel@tonic-gate 		}
16660Sstevel@tonic-gate 		(void) fflush(stdout);
16670Sstevel@tonic-gate 	}
16680Sstevel@tonic-gate 
16690Sstevel@tonic-gate 	/* return success */
16700Sstevel@tonic-gate 	return (0);
16710Sstevel@tonic-gate }
16720Sstevel@tonic-gate 
16730Sstevel@tonic-gate /*
16740Sstevel@tonic-gate  * reset trans
16750Sstevel@tonic-gate  */
16760Sstevel@tonic-gate int
meta_trans_reset(mdsetname_t * sp,mdname_t * transnp,mdcmdopts_t options,md_error_t * ep)16770Sstevel@tonic-gate meta_trans_reset(
16780Sstevel@tonic-gate 	mdsetname_t	*sp,
16790Sstevel@tonic-gate 	mdname_t	*transnp,
16800Sstevel@tonic-gate 	mdcmdopts_t	options,
16810Sstevel@tonic-gate 	md_error_t	*ep
16820Sstevel@tonic-gate )
16830Sstevel@tonic-gate {
16840Sstevel@tonic-gate 	md_trans_t	*transp;
16850Sstevel@tonic-gate 	int		rval = -1;
16860Sstevel@tonic-gate 
16870Sstevel@tonic-gate 	/* should have a set */
16880Sstevel@tonic-gate 	assert(sp != NULL);
16890Sstevel@tonic-gate 	assert((transnp == NULL) ||
16900Sstevel@tonic-gate 	    (sp->setno == MD_MIN2SET(meta_getminor(transnp->dev))));
16910Sstevel@tonic-gate 
16920Sstevel@tonic-gate 	/* reset all trans */
16930Sstevel@tonic-gate 	if (transnp == NULL) {
16940Sstevel@tonic-gate 		mdnamelist_t	*transnlp = NULL;
16950Sstevel@tonic-gate 		mdnamelist_t	*p;
16960Sstevel@tonic-gate 
16970Sstevel@tonic-gate 		/* for each trans */
16980Sstevel@tonic-gate 		rval = 0;
16990Sstevel@tonic-gate 		if (meta_get_trans_names(sp, &transnlp, 0, ep) < 0)
17000Sstevel@tonic-gate 			return (-1);
17010Sstevel@tonic-gate 		for (p = transnlp; (p != NULL); p = p->next) {
17020Sstevel@tonic-gate 			/* reset trans */
17030Sstevel@tonic-gate 			transnp = p->namep;
17040Sstevel@tonic-gate 			if (meta_trans_reset(sp, transnp, options, ep) != 0) {
17050Sstevel@tonic-gate 				rval = -1;
17060Sstevel@tonic-gate 				break;
17070Sstevel@tonic-gate 			}
17080Sstevel@tonic-gate 		}
17090Sstevel@tonic-gate 
17100Sstevel@tonic-gate 		/* cleanup, return success */
17110Sstevel@tonic-gate 		metafreenamelist(transnlp);
17120Sstevel@tonic-gate 		return (rval);
17130Sstevel@tonic-gate 	}
17140Sstevel@tonic-gate 
17150Sstevel@tonic-gate 	/* check name */
17160Sstevel@tonic-gate 	if (metachkmeta(transnp, ep) != 0)
17170Sstevel@tonic-gate 		return (-1);
17180Sstevel@tonic-gate 	/* get unit structure */
17190Sstevel@tonic-gate 	if ((transp = meta_get_trans(sp, transnp, ep)) == NULL)
17200Sstevel@tonic-gate 		return (-1);
17210Sstevel@tonic-gate 
17220Sstevel@tonic-gate 	/* make sure nobody owns us */
17230Sstevel@tonic-gate 	if (MD_HAS_PARENT(transp->common.parent)) {
17240Sstevel@tonic-gate 		return (mdmderror(ep, MDE_IN_USE, meta_getminor(transnp->dev),
17250Sstevel@tonic-gate 		    transnp->cname));
17260Sstevel@tonic-gate 	}
17270Sstevel@tonic-gate 
17280Sstevel@tonic-gate 	/* clear subdevices cache */
17290Sstevel@tonic-gate 	meta_invalidate_name(transp->masternamep);
17300Sstevel@tonic-gate 	if (transp->lognamep)
17310Sstevel@tonic-gate 		meta_invalidate_name(transp->lognamep);
17320Sstevel@tonic-gate 
17330Sstevel@tonic-gate 	/* clear metadevice */
17340Sstevel@tonic-gate 	if (meta_reset(sp, transnp, options, ep) != 0)
17350Sstevel@tonic-gate 		goto out;
17360Sstevel@tonic-gate 	rval = 0;	/* success */
17370Sstevel@tonic-gate 
17380Sstevel@tonic-gate 	/* let em know */
17390Sstevel@tonic-gate 	if (options & MDCMD_PRINT) {
17400Sstevel@tonic-gate 		(void) printf(dgettext(TEXT_DOMAIN, "%s: Trans is cleared\n"),
17410Sstevel@tonic-gate 		    transnp->cname);
17420Sstevel@tonic-gate 		(void) fflush(stdout);
17430Sstevel@tonic-gate 	}
17440Sstevel@tonic-gate 
17450Sstevel@tonic-gate 	/* clear subdevices */
17460Sstevel@tonic-gate 	if (! (options & MDCMD_RECURSE))
17470Sstevel@tonic-gate 		goto out;
17480Sstevel@tonic-gate 	if (metaismeta(transp->masternamep)) {
17490Sstevel@tonic-gate 		mdname_t	*masternp = transp->masternamep;
17500Sstevel@tonic-gate 
17510Sstevel@tonic-gate 		if (meta_reset_by_name(sp, masternp, options, ep) != 0)
17520Sstevel@tonic-gate 			rval = -1;
17530Sstevel@tonic-gate 	}
17540Sstevel@tonic-gate 	/* (multi-parented) log will be cleared later */
17550Sstevel@tonic-gate 
17560Sstevel@tonic-gate 	/* cleanup, return success */
17570Sstevel@tonic-gate out:
17580Sstevel@tonic-gate 	meta_invalidate_name(transnp);
17590Sstevel@tonic-gate 	return (rval);
17600Sstevel@tonic-gate }
1761