OpenSolaris_b135/common/mdesc/mdesc_init_intern.c

Compare this file to the similar file:
Show the results in this format:

/*
 * 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"

#include <sys/types.h>
#include <sys/param.h>
#include <sys/mdesc.h>
#include <sys/mdesc_impl.h>

md_t *
md_init_intern(uint64_t *ptr,  void *(*allocp)(size_t),
	    void (*freep)(void *, size_t))
{
	md_impl_t	*mdp;
	int		idx;
	int		count;
	int		done;
	uint64_t	gen;
	mde_str_cookie_t root_name;

	/*
	 * Very basic checkup for alignment to avoid
	 * bus error issues.
	 */
	if ((((uintptr_t)ptr) & 7) != 0)
		return (NULL);

	mdp = (md_impl_t *)allocp(sizeof (md_impl_t));

	if (mdp == NULL)
		return (NULL);

	mdp->allocp = allocp;
	mdp->freep = freep;

	mdp->caddr = (char *)ptr;

	/*
	 * setup internal structures
	 */

	mdp->headerp = (md_header_t *)mdp->caddr;

	if (mdtoh32(mdp->headerp->transport_version) != MD_TRANSPORT_VERSION) {
		goto cleanup_nohash;
	}

	mdp->node_blk_size = mdtoh32(mdp->headerp->node_blk_sz);
	mdp->name_blk_size = mdtoh32(mdp->headerp->name_blk_sz);
	mdp->data_blk_size = mdtoh32(mdp->headerp->data_blk_sz);

	mdp->size = MD_HEADER_SIZE + mdp->node_blk_size +
	    mdp->name_blk_size + mdp->data_blk_size;

	mdp->mdep = (md_element_t *)(mdp->caddr + MD_HEADER_SIZE);
	mdp->namep = (char *)(mdp->caddr + MD_HEADER_SIZE + mdp->node_blk_size);
	mdp->datap = (uint8_t *)(mdp->caddr + MD_HEADER_SIZE +
	    mdp->name_blk_size + mdp->node_blk_size);

	mdp->root_node = MDE_INVAL_ELEM_COOKIE;


	/*
	 * Should do a lot more sanity checking here.
	 */

	/*
	 * Should initialize a name hash here if we intend to use one
	 */

	/*
	 * Setup to find the root node
	 */
	root_name = md_find_name((md_t *)mdp, "root");
	if (root_name == MDE_INVAL_STR_COOKIE) {
		goto cleanup;
	}

	/*
	 * One more property we need is the count of nodes in the
	 * DAG, not just the number of elements.
	 *
	 * We try and pickup the root node along the way here.
	 */

	for (done = 0, idx = 0, count = 0; !done; ) {
		md_element_t *np;

		np = &(mdp->mdep[idx]);

		switch (MDE_TAG(np)) {
		case MDET_LIST_END:
			done = 1;
			break;

		case MDET_NODE:
			if (root_name == MDE_NAME(np)) {
				if (mdp->root_node != MDE_INVAL_ELEM_COOKIE) {
					/* Gah .. more than one root */
					goto cleanup;
				}
				mdp->root_node = (mde_cookie_t)idx;
			}
			idx = MDE_PROP_INDEX(np);
			count++;
			break;

		default:
			idx++;	/* ignore */
		}
	}

	/*
	 * Ensure there is a root node
	 */
	if (mdp->root_node == MDE_INVAL_ELEM_COOKIE) {
		goto cleanup;
	}

	/*
	 * Register the counts
	 */

	mdp->element_count = idx + 1;	/* include LIST_END */
	mdp->node_count = count;

	/*
	 * Final sanity check that everything adds up
	 */
	if (mdp->element_count != (mdp->node_blk_size / MD_ELEMENT_SIZE))
		goto cleanup;

	mdp->md_magic = LIBMD_MAGIC;

	/*
	 * Setup MD generation
	 */
	if (md_get_prop_val((md_t *)mdp, mdp->root_node,
	    "md-generation#", &gen) != 0)
		mdp->gen = MDESC_INVAL_GEN;
	else
		mdp->gen = gen;

	return ((md_t *)mdp);

cleanup:
	/*
	 * Clean up here - including a name hash if
	 * we build one.
	 */

cleanup_nohash:
	mdp->freep(mdp, sizeof (md_impl_t));
	return (NULL);
}