OpenSolaris_b135/lib/lvm/libmeta/common/metagetroot.c

/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License (the "License").
 * You may not use this file except in compliance with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */

/*
 * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

#pragma ident	"%Z%%M%	%I%	%E% SMI"

/*
 * get root device
 */

#include <meta.h>
#include "meta_lib_prv.h"

#include <sys/mnttab.h>

/*
 * Return the current root filesystem block device name
 */
void *
meta_get_current_root(
	md_error_t	*ep
)
{
	FILE		*fp;
	struct mnttab	mp;

	if ((fp = open_mnttab()) == NULL) {
		(void) mdsyserror(ep, errno, MNTTAB);
		return (NULL);
	}

	while (getmntent(fp, &mp) == 0) {
	if (strcmp(mp.mnt_mountp, "/") == 0)
		return (mp.mnt_special);
	}
	(void) mderror(ep, MDE_NOROOT, NULL);
	return (NULL);
}

/*
 * Return the current root filesystem block device name. This is only valid
 * when root is either a slice, a stripe or a mirror.
 */
mdname_t *
meta_get_current_root_dev(
	mdsetname_t	*sp,
	md_error_t	*ep
)
{
	md_stripe_t	*stripep;
	md_mirror_t	*mirrorp;
	md_row_t	*rp;
	md_comp_t	*cp;
	mdname_t	*rootnp;
	void		*curroot;
	char		*miscname;
	int		smi;

	if ((curroot = meta_get_current_root(ep)) == NULL)
		return (NULL);
	if ((rootnp = metaname(&sp, curroot, UNKNOWN, ep)) == NULL)
		return (NULL);
	if (metaismeta(rootnp)) {
		if ((miscname = metagetmiscname(rootnp, ep)) == NULL)
			return (NULL);
		if ((strcmp(miscname, MD_MIRROR) == 0) &&
		    ((mirrorp = meta_get_mirror(sp, rootnp, ep)) != NULL)) {
			for (smi = 0; smi < NMIRROR; smi++) {
				md_submirror_t *mdsp =
				    &mirrorp->submirrors[smi];
				rootnp = mdsp->submirnamep;
				/* skip unused submirrors */
				if (rootnp == NULL) {
					assert(mdsp->state == SMS_UNUSED);
					continue;
				}
				if ((miscname = metagetmiscname(rootnp, ep))
				    == NULL) {
					(void) mdmderror(ep, MDE_UNKNOWN_TYPE,
					    meta_getminor(rootnp->dev),
					    rootnp->cname);
					return (NULL);
				}
				break;
			}
		}
		if ((strcmp(miscname, MD_STRIPE) == 0) &&
		    ((stripep = meta_get_stripe(sp, rootnp, ep)) != NULL)) {
			rp = &stripep->rows.rows_val[0];
			cp = &rp->comps.comps_val[0];
			if (metachkcomp(cp->compnamep, ep) == 0)
				return (cp->compnamep);
		}
		/* Root is not a single stripe metadevice */
		(void) mddeverror(ep, MDE_INV_ROOT, rootnp->dev, rootnp->cname);
		return (NULL);
	} else return (rootnp);
}