275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock/*
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock * CDDL HEADER START
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock *
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock * The contents of this file are subject to the terms of the
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock * Common Development and Distribution License (the "License").
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock * You may not use this file except in compliance with the License.
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock *
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock * or http://www.opensolaris.org/os/licensing.
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock * See the License for the specific language governing permissions
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock * and limitations under the License.
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock *
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock * When distributing Covered Code, include this CDDL HEADER in each
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock * If applicable, add the following below this CDDL HEADER, with the
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock * fields enclosed by brackets "[]" replaced with your own identifying
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock * information: Portions Copyright [yyyy] [name of copyright owner]
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock *
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock * CDDL HEADER END
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock */
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock/*
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock */
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock#include <scsi/libses.h>
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock#include "ses_impl.h"
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock#define NEXT_ED(eip) \
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock ((ses2_ed_impl_t *)((uint8_t *)(eip) + \
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock ((eip)->st_hdr.sehi_ed_len + sizeof (ses2_ed_hdr_impl_t))))
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrockstatic ses_node_t *
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrockses_find_enclosure(ses_snap_t *sp, uint64_t number)
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock{
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock ses_node_t *np;
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock for (np = sp->ss_root->sn_first_child; np != NULL;
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock np = np->sn_next_sibling) {
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock ASSERT(np->sn_type == SES_NODE_ENCLOSURE);
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock if (np->sn_enc_num == number)
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock return ((ses_node_t *)np);
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock }
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock return (NULL);
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock}
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
c4800545504378963d9f2eeb253f06899664f9f6jmcp/*
c4800545504378963d9f2eeb253f06899664f9f6jmcp * ses_snap_primary_enclosure() finds the primary enclosure for
c4800545504378963d9f2eeb253f06899664f9f6jmcp * the supplied ses_snap_t.
c4800545504378963d9f2eeb253f06899664f9f6jmcp */
c4800545504378963d9f2eeb253f06899664f9f6jmcpses_node_t *
c4800545504378963d9f2eeb253f06899664f9f6jmcpses_snap_primary_enclosure(ses_snap_t *sp)
c4800545504378963d9f2eeb253f06899664f9f6jmcp{
c4800545504378963d9f2eeb253f06899664f9f6jmcp return (ses_find_enclosure(sp, 0));
c4800545504378963d9f2eeb253f06899664f9f6jmcp}
c4800545504378963d9f2eeb253f06899664f9f6jmcp
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrockvoid
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrockses_node_teardown(ses_node_t *np)
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock{
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock ses_node_t *rp;
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock if (np == NULL)
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock return;
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock for (; np != NULL; np = rp) {
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock ses_node_teardown(np->sn_first_child);
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock rp = np->sn_next_sibling;
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock nvlist_free(np->sn_props);
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock ses_free(np);
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock }
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock}
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrockstatic ses_node_t *
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrockses_node_alloc(ses_snap_t *sp, ses_node_t *pnp)
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock{
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock ses_node_t *np;
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock np = ses_zalloc(sizeof (ses_node_t));
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock if (np == NULL)
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock goto fail;
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock if (nvlist_alloc(&np->sn_props, NV_UNIQUE_NAME, 0) != 0)
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock goto fail;
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock np->sn_snapshot = sp;
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock np->sn_id = sp->ss_n_nodes++;
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock if (pnp == NULL) {
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock ASSERT(sp->ss_root == NULL);
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock sp->ss_root = np;
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock } else {
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock np->sn_parent = pnp;
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock np->sn_prev_sibling = pnp->sn_last_child;
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock if (pnp->sn_first_child == NULL)
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock pnp->sn_first_child = np;
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock else
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock pnp->sn_last_child->sn_next_sibling = np;
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock pnp->sn_last_child = np;
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock }
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock return (np);
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrockfail:
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock ses_free(np);
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock ses_node_teardown(sp->ss_root);
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock sp->ss_root = NULL;
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock return (NULL);
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock}
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock/*
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock * Parse element type descriptor.
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock */
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrockstatic int
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrockelem_parse_td(ses2_td_hdr_impl_t *tip, const char *tp, nvlist_t *nvl)
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock{
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock int nverr;
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock if (tp != NULL)
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock SES_NV_ADD(fixed_string, nverr, nvl, SES_PROP_CLASS_DESCRIPTION,
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock tp, tip->sthi_text_len);
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock return (0);
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock}
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock/*
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock * Build a skeleton tree of nodes in the given snapshot. This is the heart of
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock * libses, and is responsible for parsing the config page into a tree and
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock * populating nodes with data from the config page.
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock */
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrockstatic int
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrockses_build_snap_skel(ses_snap_t *sp)
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock{
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock ses2_ed_impl_t *eip;
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock ses2_td_hdr_impl_t *tip, *ftip;
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock ses_node_t *np, *pnp, *cnp, *root;
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock ses_snap_page_t *pp;
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock ses2_config_page_impl_t *pip;
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock int i, j, n_etds = 0;
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock off_t toff;
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock char *tp, *text;
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock int err;
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim uint64_t idx, eidx;
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock pp = ses_snap_find_page(sp, SES2_DIAGPAGE_CONFIG, B_FALSE);
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock if (pp == NULL)
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock return (ses_error(ESES_BAD_RESPONSE, "target does not support "
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock "configuration diagnostic page"));
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock pip = (ses2_config_page_impl_t *)pp->ssp_page;
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock if (pp->ssp_len < offsetof(ses2_config_page_impl_t, scpi_data))
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock return (ses_error(ESES_BAD_RESPONSE, "no enclosure "
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock "descriptors found"));
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock /*
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock * Start with the root of the tree, which is a target node, containing
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock * just the SCSI inquiry properties.
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock */
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock if ((root = ses_node_alloc(sp, sp->ss_root)) == NULL)
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock return (-1);
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock root->sn_type = SES_NODE_TARGET;
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock SES_NV_ADD(string, err, root->sn_props, SCSI_PROP_VENDOR,
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock libscsi_vendor(sp->ss_target->st_target));
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock SES_NV_ADD(string, err, root->sn_props, SCSI_PROP_PRODUCT,
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock libscsi_product(sp->ss_target->st_target));
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock SES_NV_ADD(string, err, root->sn_props, SCSI_PROP_REVISION,
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock libscsi_revision(sp->ss_target->st_target));
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock for (eip = (ses2_ed_impl_t *)pip->scpi_data, i = 0;
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock i < pip->scpi_n_subenclosures + 1;
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock i++, eip = NEXT_ED(eip)) {
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock if (!SES_WITHIN_PAGE_STRUCT(eip, pp->ssp_page, pp->ssp_len))
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock break;
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock n_etds += eip->st_hdr.sehi_n_etd_hdrs;
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock }
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock ftip = (ses2_td_hdr_impl_t *)eip;
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock /*
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock * There should really be only one Enclosure element possible for a
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock * give subenclosure ID. The standard never comes out and says this,
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock * but it does describe this element as "managing the enclosure itself"
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock * which implies rather strongly that the subenclosure ID field is that
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock * of, well, the enclosure itself. Since an enclosure can't contain
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock * itself, it follows logically that each subenclosure has at most one
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock * Enclosure type descriptor elements matching its ID. Of course, some
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock * enclosure firmware is buggy, so this may not always work out; in
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock * this case we just ignore all but the first Enclosure-type element
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock * with our subenclosure ID.
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock */
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock for (eip = (ses2_ed_impl_t *)pip->scpi_data, i = 0;
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock i < pip->scpi_n_subenclosures + 1;
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock i++, eip = NEXT_ED(eip)) {
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock if (!SES_WITHIN_PAGE_STRUCT(eip, pp->ssp_page, pp->ssp_len))
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock break;
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock if ((np = ses_node_alloc(sp, root)) == NULL)
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock return (-1);
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock np->sn_type = SES_NODE_ENCLOSURE;
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock np->sn_enc_num = eip->st_hdr.sehi_subenclosure_id;
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock if (!SES_WITHIN_PAGE(eip, eip->st_hdr.sehi_ed_len +
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock sizeof (ses2_ed_hdr_impl_t),
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock pp->ssp_page, pp->ssp_len))
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock break;
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock if (enc_parse_ed(eip, np->sn_props) != 0)
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock return (-1);
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock }
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock if (root->sn_first_child == NULL)
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock return (ses_error(ESES_BAD_RESPONSE, "no enclosure "
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock "descriptors found"));
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock tp = (char *)(ftip + n_etds);
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim for (i = 0, toff = 0, idx = eidx = 0; i < n_etds; i++) {
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock tip = ftip + i;
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock if (!SES_WITHIN_PAGE_STRUCT(tip, pp->ssp_page, pp->ssp_len))
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock break;
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock pnp = ses_find_enclosure(sp,
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock tip->sthi_subenclosure_id);
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock if (pnp == NULL) {
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock idx += tip->sthi_max_elements + 1;
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim eidx += tip->sthi_max_elements;
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock toff += tip->sthi_text_len;
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock continue;
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock }
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock if (tip->sthi_element_type == SES_ET_ENCLOSURE) {
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock if (tip->sthi_max_elements == 0) {
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock SES_NV_ADD(uint64, err, pnp->sn_props,
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock SES_PROP_ELEMENT_INDEX, idx);
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock pnp->sn_rootidx = idx;
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock } else {
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock SES_NV_ADD(uint64, err, pnp->sn_props,
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock SES_PROP_ELEMENT_INDEX, idx + 1);
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim SES_NV_ADD(uint64, err, pnp->sn_props,
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim SES_PROP_ELEMENT_ONLY_INDEX, eidx);
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock pnp->sn_rootidx = idx + 1;
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock }
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock if (tip->sthi_text_len > 0 &&
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock SES_WITHIN_PAGE(tp + toff, tip->sthi_text_len,
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock pp->ssp_page, pp->ssp_len)) {
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock text = tp + toff;
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock toff += tip->sthi_text_len;
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock } else {
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock text = NULL;
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock }
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock SES_NV_ADD(uint64, err, pnp->sn_props,
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock SES_PROP_ELEMENT_TYPE, SES_ET_ENCLOSURE);
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock if (enc_parse_td(tip, text, pnp->sn_props) != 0)
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock return (-1);
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock idx += tip->sthi_max_elements + 1;
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim eidx += tip->sthi_max_elements;
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock continue;
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock }
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock if ((np = ses_node_alloc(sp, pnp)) == NULL)
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock return (-1);
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock np->sn_type = SES_NODE_AGGREGATE;
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock np->sn_enc_num = tip->sthi_subenclosure_id;
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock np->sn_parent = pnp;
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock np->sn_rootidx = idx;
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock SES_NV_ADD(uint64, err, np->sn_props,
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock SES_PROP_ELEMENT_INDEX, idx);
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock SES_NV_ADD(uint64, err, np->sn_props,
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock SES_PROP_ELEMENT_TYPE, tip->sthi_element_type);
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock if (tip->sthi_text_len > 0 &&
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock SES_WITHIN_PAGE(tp + toff, tip->sthi_text_len,
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock pp->ssp_page, pp->ssp_len)) {
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock text = tp + toff;
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock toff += tip->sthi_text_len;
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock } else {
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock text = NULL;
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock }
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock if (elem_parse_td(tip, text, np->sn_props) != 0)
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock return (-1);
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock idx += tip->sthi_max_elements + 1;
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock if (tip->sthi_max_elements == 0)
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock continue;
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock for (j = 0; j < tip->sthi_max_elements; j++) {
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock cnp = ses_node_alloc(sp, np);
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock if (cnp == NULL)
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock return (-1);
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock cnp->sn_type = SES_NODE_ELEMENT;
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock SES_NV_ADD(uint64, err, cnp->sn_props,
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock SES_PROP_ELEMENT_INDEX, np->sn_rootidx + j + 1);
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim SES_NV_ADD(uint64, err, cnp->sn_props,
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim SES_PROP_ELEMENT_ONLY_INDEX, eidx + j);
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock SES_NV_ADD(uint64, err, cnp->sn_props,
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock SES_PROP_ELEMENT_CLASS_INDEX, j);
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock SES_NV_ADD(uint64, err, cnp->sn_props,
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock SES_PROP_ELEMENT_TYPE, tip->sthi_element_type);
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock }
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim eidx += tip->sthi_max_elements;
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock }
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock np->sn_snapshot->ss_n_elem = idx;
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock return (0);
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock}
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrockstatic int
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrockses_fill_tree(ses_node_t *np)
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock{
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock if (np == NULL)
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock return (0);
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock for (; np != NULL; np = np->sn_next_sibling) {
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock if (ses_fill_node(np) != 0)
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock return (-1);
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock if (ses_fill_tree(np->sn_first_child) != 0)
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock return (-1);
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock }
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock return (0);
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock}
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrockint
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrockses_fill_snap(ses_snap_t *sp)
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock{
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock if (ses_build_snap_skel(sp) != 0)
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock return (-1);
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock if (ses_fill_tree(sp->ss_root) != 0)
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock return (-1);
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock return (0);
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock}
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrockses_node_t *
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrockses_root_node(ses_snap_t *sp)
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock{
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock return (sp->ss_root);
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock}
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrockses_node_t *
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrockses_node_sibling(ses_node_t *np)
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock{
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock return (np->sn_next_sibling);
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock}
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrockses_node_t *
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrockses_node_prev_sibling(ses_node_t *np)
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock{
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock return (np->sn_prev_sibling);
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock}
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrockses_node_t *
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrockses_node_parent(ses_node_t *np)
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock{
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock return (np->sn_parent);
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock}
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrockses_node_t *
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrockses_node_child(ses_node_t *np)
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock{
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock return (np->sn_first_child);
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock}
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrockses_node_type_t
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrockses_node_type(ses_node_t *np)
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock{
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock return (np->sn_type);
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock}
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrockses_snap_t *
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrockses_node_snapshot(ses_node_t *np)
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock{
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock return ((ses_snap_t *)np->sn_snapshot);
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock}
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrockses_target_t *
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrockses_node_target(ses_node_t *np)
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock{
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock return (np->sn_snapshot->ss_target);
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock}
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrocknvlist_t *
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrockses_node_props(ses_node_t *np)
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock{
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock return (np->sn_props);
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock}
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock/*
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock * A node identifier is a (generation, index) tuple that can be used to lookup a
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock * node within this target at a later point. This will be valid across
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock * snapshots, though it will return failure if the generation count has changed.
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock */
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrockuint64_t
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrockses_node_id(ses_node_t *np)
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock{
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock return (((uint64_t)np->sn_snapshot->ss_generation << 32) |
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock np->sn_id);
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock}