Beispiel #1
0
int32_t
fnvlist_lookup_int32(nvlist_t *nvl, const char *name)
{
	int32_t rv;
	VERIFY0(nvlist_lookup_int32(nvl, name, &rv));
	return (rv);
}
Beispiel #2
0
static void
print_fmri_pgroup(topo_hdl_t *thp, const char *pgn, nvlist_t *nvl)
{
	char *dstab = NULL, *nstab = NULL;
	int32_t version = -1;
	nvlist_t *pnvl;
	nvpair_t *pnvp;

	(void) nvlist_lookup_string(nvl, TOPO_PROP_GROUP_NSTAB, &nstab);
	(void) nvlist_lookup_string(nvl, TOPO_PROP_GROUP_DSTAB, &dstab);
	(void) nvlist_lookup_int32(nvl, TOPO_PROP_GROUP_VERSION, &version);

	print_pgroup(thp, NULL, pgn, dstab, nstab, version);

	for (pnvp = nvlist_next_nvpair(nvl, NULL); pnvp != NULL;
	    pnvp = nvlist_next_nvpair(nvl, pnvp)) {

		/*
		 * Print property group and property name-value pair
		 */
		if (strcmp(TOPO_PROP_VAL, nvpair_name(pnvp))
		    == 0 && nvpair_type(pnvp) == DATA_TYPE_NVLIST) {
			(void) nvpair_value_nvlist(pnvp, &pnvl);
				print_prop_nameval(thp, NULL, pnvl);

		}

	}
}
Beispiel #3
0
/*
 * Top level function for event service
 */
void
event_service(void **data, size_t *datalen)
{
	int cmd;
	int lerrno;
	int seq_num;
	nvlist_t *nvl;
	nvlist_t *ret;

	rcm_log_message(RCM_TRACE1, "received door operation\n");

	/* Decode the data from the door into an unpacked nvlist */
	if (data == NULL || datalen == NULL) {
		rcm_log_message(RCM_ERROR, "received null door argument\n");
		return;
	}
	if (lerrno = nvlist_unpack(*data, *datalen, &nvl, 0)) {
		rcm_log_message(RCM_ERROR, "received bad door argument, %s\n",
		    strerror(lerrno));
		return;
	}

	/* Do nothing if the door is just being knocked on */
	if (errno = nvlist_lookup_int32(nvl, RCM_CMD, &cmd)) {
		rcm_log_message(RCM_ERROR,
		    "bad door argument (nvlist_lookup=%s)\n", strerror(errno));
		nvlist_free(nvl);
		return;
	}
	if (cmd == CMD_KNOCK) {
		rcm_log_message(RCM_TRACE1, "door event was just a knock\n");
		nvlist_free(nvl);
		*data = NULL;
		*datalen = 0;
		return;
	}

	/*
	 * Go increment thread count. Before daemon is fully initialized,
	 * the event processing blocks inside this function.
	 */
	seq_num = rcmd_thr_incr(cmd);

	process_event(cmd, seq_num, nvl, &ret);
	nvlist_free(nvl);
	assert(ret != NULL);

	/*
	 * Decrement thread count
	 */
	rcmd_thr_decr();

out:
	*data = ret;
	*datalen = 0;
}
Beispiel #4
0
static int32_t
fma_cap_cpu_info(cpu_tbl_t *ci)
{
    nvlist_t **cpus, *nvl;
    uint_t ncpu, i;
    fmd_agent_hdl_t *hdl;
    char *ven;
    int32_t family, model;

    if ((hdl = fmd_agent_open(FMD_AGENT_VERSION)) == NULL)
        return (-1);
    if (fmd_agent_physcpu_info(hdl, &cpus, &ncpu) != 0) {
        fmd_agent_close(hdl);
        return (-1);
    }
    fmd_agent_close(hdl);

    if (cpus == NULL)
        return (-1);

    /*
     * There is no mixed CPU type on x86 systems, it's ok to
     * just pick the first one
     */
    nvl = cpus[0];
    if (nvlist_lookup_string(nvl, FM_PHYSCPU_INFO_VENDOR_ID, &ven) != 0 ||
            nvlist_lookup_int32(nvl, FM_PHYSCPU_INFO_FAMILY, &family) != 0 ||
            nvlist_lookup_int32(nvl, FM_PHYSCPU_INFO_MODEL, &model) != 0) {
        for (i = 0; i < ncpu; i++)
            nvlist_free(cpus[i]);
        umem_free(cpus, sizeof (nvlist_t *) * ncpu);
        return (-1);
    }

    (void) snprintf(ci->vendor, X86_VENDOR_STRLEN, "%s", ven);
    ci->family = family;
    ci->model = model;

    for (i = 0; i < ncpu; i++)
        nvlist_free(cpus[i]);
    umem_free(cpus, sizeof (nvlist_t *) * ncpu);
    return (0);
}
Beispiel #5
0
static int
update_stat32(nvlist_t *stats, char *attr, uint32_t value)
{
	int32_t	currval;

	if (nvlist_lookup_int32(stats, attr, &currval) == 0) {
	    value += currval;
	}

	return (nvlist_add_uint32(stats, attr, value));
}
Beispiel #6
0
int
ct_pr_status_get_svc_ctid(ct_stathdl_t stathdl, ctid_t *ctid)
{
	struct ctlib_status_info *info = stathdl;
	if (info->status.ctst_type != CTT_PROCESS)
		return (EINVAL);
	if (info->nvl == NULL)
		return (ENOENT);
	return (nvlist_lookup_int32(info->nvl, CTPS_SVC_CTID,
	    (int32_t *)ctid));
}
Beispiel #7
0
int
ct_pr_event_get_exitstatus(ct_evthdl_t evthdl, int *exitstatus)
{
	struct ctlib_event_info *info = evthdl;
	if (info->event.ctev_cttype != CTT_PROCESS)
		return (EINVAL);
	if (info->event.ctev_type != CT_PR_EV_EXIT)
		return (EINVAL);
	if (info->nvl == NULL)
		return (ENOENT);
	return (nvlist_lookup_int32(info->nvl, CTPE_EXITSTATUS, exitstatus));
}
Beispiel #8
0
/*
 * cmd_changestate()
 *
 *	Implements the door command to initate a state change operation.
 *
 *	NOTE: requires 'modify' authorization.
 */
static int
cmd_changestate(nvlist_t *args, nvlist_t **resultsp)
{
    hp_node_t	root = NULL;
    nvlist_t	*results = NULL;
    char		*path, *connection;
    ucred_t		*uc = NULL;
    uint_t		flags;
    int		rv, state, old_state, status;

    dprintf("cmd_changestate:\n");

    /* Get arguments */
    if ((nvlist_lookup_string(args, HPD_PATH, &path) != 0) ||
            (nvlist_lookup_string(args, HPD_CONNECTION, &connection) != 0) ||
            (nvlist_lookup_int32(args, HPD_STATE, &state) != 0)) {
        dprintf("cmd_changestate: invalid arguments.\n");
        return (EINVAL);
    }
    if (nvlist_lookup_uint32(args, HPD_FLAGS, (uint32_t *)&flags) != 0)
        flags = 0;

    /* Get caller's credentials */
    if (door_ucred(&uc) != 0) {
        log_err("Cannot get door credentials (%s)\n", strerror(errno));
        return (EACCES);
    }

    /* Check authorization */
    if (check_auth(uc, HP_MODIFY_AUTH) != 0) {
        dprintf("cmd_changestate: access denied.\n");
        audit_changestate(uc, HP_MODIFY_AUTH, path, connection,
                          state, -1, ADT_FAIL_VALUE_AUTH);
        ucred_free(uc);
        return (EACCES);
    }

    /* Perform the state change operation */
    status = changestate(path, connection, state, flags, &old_state, &root);
    dprintf("cmd_changestate: changestate() == %d\n", status);

    /* Audit the operation */
    audit_changestate(uc, HP_MODIFY_AUTH, path, connection, state,
                      old_state, status);

    /* Caller's credentials no longer needed */
    ucred_free(uc);

    /*
     * Pack the results into an nvlist if there is an error snapshot.
     *
     * If any error occurs while packing the results, the original
     * error code from changestate() above is still returned.
     */
    if (root != NULL) {
        char	*buf = NULL;
        size_t	len = 0;

        dprintf("cmd_changestate: results nvlist required.\n");

        /* Pack and discard the error snapshot */
        rv = hp_pack(root, &buf, &len);
        hp_fini(root);
        if (rv != 0) {
            dprintf("cmd_changestate: hp_pack() failed (%s).\n",
                    strerror(rv));
            return (status);
        }

        /* Allocate nvlist for results */
        if (nvlist_alloc(&results, NV_UNIQUE_NAME_TYPE, 0) != 0) {
            dprintf("cmd_changestate: nvlist_alloc() failed.\n");
            free(buf);
            return (status);
        }

        /* Add the results into the nvlist */
        if ((nvlist_add_int32(results, HPD_STATUS, status) != 0) ||
                (nvlist_add_byte_array(results, HPD_INFO, (uchar_t *)buf,
                                       len) != 0)) {
            dprintf("cmd_changestate: nvlist add failed.\n");
            nvlist_free(results);
            free(buf);
            return (status);
        }

        *resultsp = results;
    }

    return (status);
}
Beispiel #9
0
/*ARGSUSED*/
static void
door_server(void *cookie, char *argp, size_t sz, door_desc_t *dp, uint_t ndesc)
{
    nvlist_t	*args = NULL;
    nvlist_t	*results = NULL;
    hp_cmd_t	cmd;
    int		rv;

    dprintf("Door call: cookie=%p, argp=%p, sz=%d\n", cookie, (void *)argp,
            sz);

    /* Special case to free a results buffer */
    if (sz == sizeof (uint64_t)) {
        free_buffer(*(uint64_t *)(uintptr_t)argp);
        (void) door_return(NULL, 0, NULL, 0);
        return;
    }

    /* Unpack the arguments nvlist */
    if (nvlist_unpack(argp, sz, &args, 0) != 0) {
        log_err("Cannot unpack door arguments.\n");
        rv = EINVAL;
        goto fail;
    }

    /* Extract the requested command */
    if (nvlist_lookup_int32(args, HPD_CMD, (int32_t *)&cmd) != 0) {
        log_err("Cannot decode door command.\n");
        rv = EINVAL;
        goto fail;
    }

    /* Implement the command */
    switch (cmd) {
    case HP_CMD_GETINFO:
        rv = cmd_getinfo(args, &results);
        break;
    case HP_CMD_CHANGESTATE:
        rv = cmd_changestate(args, &results);
        break;
    case HP_CMD_SETPRIVATE:
    case HP_CMD_GETPRIVATE:
        rv = cmd_private(cmd, args, &results);
        break;
    default:
        rv = EINVAL;
        break;
    }

    /* The arguments nvlist is no longer needed */
    nvlist_free(args);
    args = NULL;

    /*
     * If an nvlist was constructed for the results,
     * then pack the results nvlist and return it.
     */
    if (results != NULL) {
        uint64_t	seqnum;
        char		*buf = NULL;
        size_t		len = 0;

        /* Add a sequence number to the results */
        seqnum = get_seqnum();
        if (nvlist_add_uint64(results, HPD_SEQNUM, seqnum) != 0) {
            log_err("Cannot add sequence number.\n");
            rv = EFAULT;
            goto fail;
        }

        /* Pack the results nvlist */
        if (nvlist_pack(results, &buf, &len,
                        NV_ENCODE_NATIVE, 0) != 0) {
            log_err("Cannot pack door results.\n");
            rv = EFAULT;
            goto fail;
        }

        /* Link results buffer into list */
        add_buffer(seqnum, buf);

        /* The results nvlist is no longer needed */
        nvlist_free(results);

        /* Return the results */
        (void) door_return(buf, len, NULL, 0);
        return;
    }

    /* Return result code (when no nvlist) */
    (void) door_return((char *)&rv, sizeof (int), NULL, 0);
    return;

fail:
    log_err("Door call failed (%s)\n", strerror(rv));
    nvlist_free(args);
    nvlist_free(results);
    (void) door_return((char *)&rv, sizeof (int), NULL, 0);
}
Beispiel #10
0
/* ARGSUSED */
int
x86pi_check_comp(topo_mod_t *mod)
{
	int rv;
	int fd;
	int32_t legacy;
	nvlist_t *nvl = NULL;
	fm_ioc_data_t fid;
	char *ibuf = NULL, *obuf = NULL;
	size_t insz = 0, outsz = 0;
	char *f = "x86pi_check_comp";
	smbios_hdl_t *shp;

	shp = topo_mod_smbios(mod);
	if (shp == NULL)
		return (X86PI_NONE);

	/* open /dev/fm */
	fd = open("/dev/fm", O_RDONLY);
	if (fd < 0) {
		topo_mod_dprintf(mod, "%s: failed to open /dev/fm.\n", f);
		return (X86PI_NONE);
	}

	/* set up buffers and ioctl data structure */
	outsz = FM_IOC_MAXBUFSZ;
	obuf = topo_mod_alloc(mod, outsz);
	if (obuf == NULL) {
		perror("umem_alloc");
		return (X86PI_NONE);
	}

	fid.fid_version = 1;
	fid.fid_insz = insz;
	fid.fid_inbuf = ibuf;
	fid.fid_outsz = outsz;
	fid.fid_outbuf = obuf;

	/* send the ioctl to /dev/fm to retrieve legacy variable */
	rv = ioctl(fd, FM_IOC_GENTOPO_LEGACY, &fid);
	if (rv < 0) {
		topo_mod_dprintf(mod, "%s: ioctl to /dev/fm failed", f);
		perror("fm_ioctl");
		(void) close(fd);
		return (X86PI_NONE);
	}
	(void) close(fd);

	(void) nvlist_unpack(fid.fid_outbuf, fid.fid_outsz, &nvl, 0);
	(void) nvlist_lookup_int32(nvl, FM_GENTOPO_LEGACY, &legacy);

	nvlist_free(nvl);
	topo_mod_free(mod, obuf, outsz);

	if (legacy == 1) {
		/* legacy kernel variable set; will do the same */
		return (X86PI_NONE);
	}

	/* legacy kernel variable not set; generic topo enum */
	return (X86PI_FULL);
}
Beispiel #11
0
/*
 * Helper function for ipmgmt_setaddr_handler().
 * It converts the nvlist_t, `nvl', to aobjmap node `nodep'.
 */
static int
i_ipmgmt_nvl2aobjnode(nvlist_t *nvl, ipmgmt_aobjmap_t *nodep)
{
	char			*aobjname = NULL, *ifname = NULL;
	int32_t			lnum;
	nvlist_t		*nvladdr;
	struct sockaddr_storage	addr;
	uint_t			n;
	sa_family_t		af = AF_UNSPEC;
	ipadm_addr_type_t	addrtype = IPADM_ADDR_NONE;
	int			err = 0;

	/*
	 * Retrieve all the information needed to build '*nodep' from
	 * nvlist_t nvl.
	 */
	if ((err = nvlist_lookup_string(nvl, IPADM_NVP_AOBJNAME,
	    &aobjname)) != 0 ||
	    (err = nvlist_lookup_string(nvl, IPADM_NVP_IFNAME, &ifname)) != 0 ||
	    (err = nvlist_lookup_int32(nvl, IPADM_NVP_LIFNUM, &lnum)) != 0) {
		return (err);
	}
	if (nvlist_exists(nvl, IPADM_NVP_IPV4ADDR)) {
		af = AF_INET;
		addrtype = IPADM_ADDR_STATIC;
	} else if (nvlist_exists(nvl, IPADM_NVP_DHCP)) {
		af = AF_INET;
		addrtype = IPADM_ADDR_DHCP;
	} else if (nvlist_exists(nvl, IPADM_NVP_IPV6ADDR)) {
		af = AF_INET6;
		addrtype = IPADM_ADDR_STATIC;
	} else if (nvlist_lookup_nvlist(nvl, IPADM_NVP_INTFID, &nvladdr) == 0) {
		struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&addr;
		uint8_t	*addr6;
		uint32_t plen;

		af = AF_INET6;
		addrtype = IPADM_ADDR_IPV6_ADDRCONF;
		if (nvlist_lookup_uint32(nvladdr, IPADM_NVP_PREFIXLEN,
		    &plen) != 0)
			return (EINVAL);
		if (plen != 0) {
			if (nvlist_lookup_uint8_array(nvladdr,
			    IPADM_NVP_IPNUMADDR, &addr6, &n) != 0)
				return (EINVAL);
			bcopy(addr6, &sin6->sin6_addr, n);
		} else {
			bzero(&sin6->sin6_addr, sizeof (sin6->sin6_addr));
		}
	}

	/*
	 * populate the `*nodep' with retrieved values.
	 */
	(void) strlcpy(nodep->am_ifname, ifname, sizeof (nodep->am_ifname));
	(void) strlcpy(nodep->am_aobjname, aobjname,
	    sizeof (nodep->am_aobjname));
	nodep->am_lnum = lnum;
	nodep->am_family = af;
	nodep->am_atype = addrtype;
	if (addrtype == IPADM_ADDR_IPV6_ADDRCONF) {
		nodep->am_linklocal = B_TRUE;
		nodep->am_ifid = addr;
	}
	nodep->am_next = NULL;

	/*
	 * Do not store logical interface number in persistent store as it
	 * takes different value on reboot. So remove it from `nvl'.
	 */
	if (nvlist_exists(nvl, IPADM_NVP_LIFNUM))
		(void) nvlist_remove(nvl, IPADM_NVP_LIFNUM, DATA_TYPE_INT32);

	return (0);
}
Beispiel #12
0
static int
prop_getval(tnode_t *node, const char *pgname, const char *pname, void *val,
    topo_type_t type, uint_t *nelems, int *err)
{
	int i, j, ret = 0;
	topo_hdl_t *thp = node->tn_hdl;
	topo_propval_t *pv;

	topo_node_lock(node);
	if ((pv = prop_get(node, pgname, pname, NULL, err))
	    == NULL)
		return (get_properror(node, err, *err));

	if (pv->tp_type != type)
		return (get_properror(node, err, ETOPO_PROP_TYPE));

	switch (type) {
		case TOPO_TYPE_INT32:
			ret = nvlist_lookup_int32(pv->tp_val, TOPO_PROP_VAL_VAL,
			    (int32_t *)val);
			break;
		case TOPO_TYPE_UINT32:
			ret = nvlist_lookup_uint32(pv->tp_val,
			    TOPO_PROP_VAL_VAL, (uint32_t *)val);
			break;
		case TOPO_TYPE_INT64:
			ret = nvlist_lookup_int64(pv->tp_val, TOPO_PROP_VAL_VAL,
			    (int64_t *)val);
			break;
		case TOPO_TYPE_UINT64:
			ret = nvlist_lookup_uint64(pv->tp_val,
			    TOPO_PROP_VAL_VAL, (uint64_t *)val);
			break;
		case TOPO_TYPE_DOUBLE:
			ret = nvlist_lookup_double(pv->tp_val,
			    TOPO_PROP_VAL_VAL, (double *)val);
			break;
		case TOPO_TYPE_STRING: {
			char *str;

			ret = nvlist_lookup_string(pv->tp_val,
			    TOPO_PROP_VAL_VAL, &str);
			if (ret == 0) {
				char *s2;
				if ((s2 = topo_hdl_strdup(thp, str)) == NULL)
					ret = -1;
				else
					*(char **)val = s2;
			}
			break;
		}
		case TOPO_TYPE_FMRI: {
			nvlist_t *nvl;

			ret = nvlist_lookup_nvlist(pv->tp_val,
			    TOPO_PROP_VAL_VAL, &nvl);
			if (ret == 0)
				ret = topo_hdl_nvdup(thp, nvl,
				    (nvlist_t **)val);
			break;
		}
		case TOPO_TYPE_INT32_ARRAY: {
			int32_t *a1, *a2;

			if ((ret = nvlist_lookup_int32_array(pv->tp_val,
			    TOPO_PROP_VAL_VAL, &a2, nelems)) != 0)
				break;
			if ((a1 = topo_hdl_alloc(thp, sizeof (int32_t) *
			    *nelems)) == NULL) {
				ret = ETOPO_NOMEM;
				break;
			}
			for (i = 0; i < *nelems; ++i)
				a1[i] = a2[i];
			*(int32_t **)val = a1;
			break;
		}
		case TOPO_TYPE_UINT32_ARRAY: {
			uint32_t *a1, *a2;

			if ((ret = nvlist_lookup_uint32_array(pv->tp_val,
			    TOPO_PROP_VAL_VAL, &a2, nelems)) != 0)
				break;
			if ((a1 = topo_hdl_alloc(thp, sizeof (uint32_t) *
			    *nelems)) == NULL) {
				ret = ETOPO_NOMEM;
				break;
			}
			for (i = 0; i < *nelems; ++i)
				a1[i] = a2[i];
			*(uint32_t **)val = a1;
			break;
		}
		case TOPO_TYPE_INT64_ARRAY: {
			int64_t *a1, *a2;

			if ((ret = nvlist_lookup_int64_array(pv->tp_val,
			    TOPO_PROP_VAL_VAL, &a2, nelems)) != 0)
				break;
			if ((a1 = topo_hdl_alloc(thp, sizeof (int64_t) *
			    *nelems)) == NULL) {
				ret = ETOPO_NOMEM;
				break;
			}
			for (i = 0; i < *nelems; ++i)
				a1[i] = a2[i];
			*(int64_t **)val = a1;
			break;
		}
		case TOPO_TYPE_UINT64_ARRAY: {
			uint64_t *a1, *a2;

			if ((ret = nvlist_lookup_uint64_array(pv->tp_val,
			    TOPO_PROP_VAL_VAL, &a2, nelems)) != 0)
				break;
			if ((a1 = topo_hdl_alloc(thp, sizeof (uint64_t) *
			    *nelems)) == NULL) {
				ret = ETOPO_NOMEM;
				break;
			}
			for (i = 0; i < *nelems; ++i)
				a1[i] = a2[i];
			*(uint64_t **)val = a1;
			break;
		}
		case TOPO_TYPE_STRING_ARRAY: {
			char **a1, **a2;

			if ((ret = nvlist_lookup_string_array(pv->tp_val,
			    TOPO_PROP_VAL_VAL, &a2, nelems)) != 0)
				break;
			if ((a1 = topo_hdl_alloc(thp, sizeof (char *) *
			    *nelems)) == NULL) {
				ret = ETOPO_NOMEM;
				break;
			}
			for (i = 0; i < *nelems; ++i) {
				if ((a1[i] = topo_hdl_strdup(thp, a2[i]))
				    == NULL) {
					for (j = 0; j < i; ++j)
						topo_hdl_free(thp, a1[j],
						    sizeof (char *));
					topo_hdl_free(thp, a1,
					    sizeof (char *) * *nelems);
					break;
				}
			}
			*(char ***)val = a1;
			break;
		}
		case TOPO_TYPE_FMRI_ARRAY: {
			nvlist_t **a1, **a2;

			if ((ret = nvlist_lookup_nvlist_array(pv->tp_val,
			    TOPO_PROP_VAL_VAL, &a2, nelems)) != 0)
				break;
			if ((a1 = topo_hdl_alloc(thp, sizeof (nvlist_t *) *
			    *nelems)) == NULL) {
				ret = ETOPO_NOMEM;
				break;
			}
			for (i = 0; i < *nelems; ++i) {
				if (topo_hdl_nvdup(thp, a2[i], &a1[i]) < 0) {
					for (j = 0; j < i; ++j)
						nvlist_free(a1[j]);
					topo_hdl_free(thp, a1,
					    sizeof (nvlist_t *) * *nelems);
					break;
				}
			}
			*(nvlist_t ***)val = a1;
			break;
		}
		default:
			ret = ETOPO_PROP_NOENT;
	}

	if (ret != 0)
		if (ret == ENOENT)
			return (get_properror(node, err, ETOPO_PROP_NOENT));
		else if (ret < ETOPO_UNKNOWN)
			return (get_properror(node, err, ETOPO_PROP_NVL));
		else
			return (get_properror(node, err, ret));

	topo_node_unlock(node);
	return (0);
}
Beispiel #13
0
/*
 * pset_validate_remove()
 * 	Check to see if the requested cpu removal would be acceptable.
 * 	Returns RCM_FAILURE if not.
 */
static int
pset_validate_remove(nvlist_t *nvl, char **errorp)
{
	int error = RCM_SUCCESS;
	int32_t old_total, new_total, removed_total;
	processorid_t *removed_list = NULL; /* list terminated by (-1). */
	processorid_t *old_cpu_list = NULL, *new_cpu_list = NULL;
	int i, j;
	pool_conf_t *conf;
	pool_value_t *pvals[] = { NULL, NULL };
	pool_resource_t **res = NULL;
	uint_t nelem;
	const char *generic_error = gettext("POOL: Error processing request\n");

	if ((conf = pool_conf_alloc()) == NULL)
		return (RCM_FAILURE);
	if (pool_conf_open(conf, pool_dynamic_location(), PO_RDONLY) < 0) {
		rcm_log_message(RCM_TRACE1,
		    "POOL: failed to parse config file: '%s'\n",
		    pool_dynamic_location());
		pool_conf_free(conf);
		return (RCM_SUCCESS);
	}

	if ((error = nvlist_lookup_int32(nvl, "old_total", &old_total)) != 0) {
		(void) pool_conf_close(conf);
		pool_conf_free(conf);
		rcm_log_message(RCM_ERROR,
		    gettext("POOL: unable to find 'old_total' in nvlist: %s\n"),
		    strerror(error));
		*errorp = strdup(generic_error);
		return (RCM_FAILURE);
	}
	if ((error = nvlist_lookup_int32(nvl, "new_total", &new_total)) != 0) {
		(void) pool_conf_close(conf);
		pool_conf_free(conf);
		rcm_log_message(RCM_ERROR,
		    gettext("POOL: unable to find 'new_total' in nvlist: %s\n"),
		    strerror(error));
		*errorp = strdup(generic_error);
		return (RCM_FAILURE);
	}
	if (new_total >= old_total) {
		(void) pool_conf_close(conf);
		pool_conf_free(conf);
		/*
		 * This doesn't look like a cpu removal.
		 */
		rcm_log_message(RCM_TRACE1,
		    gettext("POOL: 'old_total' (%d) is less than 'new_total' "
		    "(%d)\n"), old_total, new_total);
		return (RCM_SUCCESS);
	}
	if ((removed_list = malloc((old_total - new_total + 1) * sizeof (int)))
	    == NULL) {
		rcm_log_message(RCM_ERROR,
		    gettext("POOL: malloc failed: %s\n"), strerror(errno));

		error = RCM_FAILURE;
		goto out;
	}
	if ((error = nvlist_lookup_int32_array(nvl, "old_cpu_list",
	    &old_cpu_list, &nelem)) != 0) {
		rcm_log_message(RCM_ERROR,
		    gettext("POOL: 'old_cpu_list' not found in nvlist: %s\n"),
		    strerror(error));
		error = RCM_FAILURE;
		goto out;
	}
	if ((int32_t)nelem != old_total) {
		rcm_log_message(RCM_ERROR,
		    gettext("POOL: 'old_cpu_list' size mismatch: %1$d vs "
		    "%2$d\n"), nelem, old_total);
		error = RCM_FAILURE;
		goto out;
	}
	if ((error = nvlist_lookup_int32_array(nvl, "new_cpu_list",
	    &new_cpu_list, &nelem)) != 0) {
		rcm_log_message(RCM_ERROR,
		    gettext("POOL: 'new_cpu_list' not found in nvlist: %s\n"),
		    strerror(error));
		error = RCM_FAILURE;
		goto out;
	}
	if (nelem != new_total) {
		rcm_log_message(RCM_ERROR,
		    gettext("POOL: 'new_cpu_list' size mismatch: %1$d vs "
		    "%2$d\n"), nelem, new_total);
		error = RCM_FAILURE;
		goto out;
	}

	for (i = 0, removed_total = 0; i < old_total; i++) {
		for (j = 0; j < new_total; j++)
			if (old_cpu_list[i] == new_cpu_list[j])
				break;
		if (j == new_total) /* not found in new_cpu_list */
			removed_list[removed_total++] = old_cpu_list[i];
	}
	removed_list[removed_total] = -1;

	if (removed_total != (old_total - new_total)) {
		rcm_log_message(RCM_ERROR,
		    gettext("POOL: error finding removed cpu list\n"));
		error = RCM_FAILURE;
		goto out;
	}
	if ((pvals[0] = pool_value_alloc()) == NULL) {
		rcm_log_message(RCM_ERROR, gettext("POOL: pool_value_alloc"
		    " failed: %s\n"), strerror(errno));
		error = RCM_FAILURE;
		goto out;
	}
	/*
	 * Look for resources with "'type' = 'pset'"
	 */
	(void) pool_value_set_name(pvals[0], "type");
	(void) pool_value_set_string(pvals[0], "pset");
	if ((res = pool_query_resources(conf, &nelem, pvals)) == NULL) {
		rcm_log_message(RCM_ERROR,
		    gettext("POOL: No psets found in configuration\n"));
		pool_value_free(pvals[0]);
		error =	 RCM_FAILURE;
		goto out;
	}
	pool_value_free(pvals[0]);
	for (i = 0; res[i] != NULL; i++)
		/*
		 * Ask each pset if removing these cpus would cause it to go
		 * below it's minimum value.
		 */
		if (pool_check_pset(conf, res[i], removed_list, errorp) < 0) {
			error = RCM_FAILURE;
			break;
		}
	free(res);
out:
	if (removed_list)
		free(removed_list);
	if (conf) {
		(void) pool_conf_close(conf);
		pool_conf_free(conf);
	}

	/*
	 * Set the error string if not already set.
	 */
	if (error != RCM_SUCCESS && *errorp == NULL)
		*errorp = strdup(generic_error);
	return (error);
}
/*ARGSUSED*/
uint_t
fmevt_pp_smf(char *classes[FMEVT_FANOUT_MAX],
    nvlist_t *attr[FMEVT_FANOUT_MAX], const char *ruleset,
    const nvlist_t *detector, nvlist_t *rawattr,
    const struct fmevt_ppargs *eap)
{
	int32_t transition, from, to;
	const char *fromstr, *tostr;
	char *svcname, *rsn, *rsnl;
	nvlist_t *myattr;
	nvlist_t *fmri;
	uint32_t ver;

	if (!fmd_prop_get_int32(fmevt_hdl, "inbound_postprocess_smf"))
		return (0);

	if (rawattr == NULL ||
	    strcmp(eap->pp_rawclass, "state-transition") != 0 ||
	    nvlist_lookup_string(rawattr, "fmri", &svcname) != 0 ||
	    nvlist_lookup_int32(rawattr, "transition", &transition) != 0 ||
	    nvlist_lookup_string(rawattr, "reason-short", &rsn) != 0 ||
	    nvlist_lookup_string(rawattr, "reason-long", &rsnl) != 0 ||
	    nvlist_lookup_uint32(rawattr, "reason-version", &ver) != 0)
		return (0);

	from = transition >> 16;
	to = transition & 0xffff;

	fromstr = smf_state_to_string(from);
	tostr = smf_state_to_string(to);

	if (fromstr == NULL || tostr == NULL)
		return (0);

	if (strcmp(eap->pp_rawsubclass, tostr) != 0)
		return (0);

	if ((fmri = shortfmri_to_fmri(fmevt_hdl, svcname)) == NULL)
		return (0);

	if (snprintf(classes[0], FMEVT_MAX_CLASS, "%s.%s.%s.%s",
	    FM_IREPORT_CLASS, "os.smf", eap->pp_rawclass,
	    eap->pp_rawsubclass) >= FMEVT_MAX_CLASS - 1)
		return (0);

	if ((myattr = fmd_nvl_alloc(fmevt_hdl, FMD_SLEEP)) == NULL)
		return (0);

	if (nvlist_add_nvlist(myattr, "svc", fmri) != 0 ||
	    nvlist_add_string(myattr, "svc-string", svcname) != 0 ||
	    nvlist_add_string(myattr, "from-state", fromstr) != 0 ||
	    nvlist_add_string(myattr, "to-state", tostr) != 0 ||
	    nvlist_add_uint32(myattr, "reason-version", ver) != 0 ||
	    nvlist_add_string(myattr, "reason-short", rsn) != 0 ||
	    nvlist_add_string(myattr, "reason-long", rsnl) != 0) {
		nvlist_free(fmri);
		nvlist_free(myattr);
		return (0);
	}

	attr[0] = myattr;
	nvlist_free(fmri);

	return (1);
}
/* ARGSUSED */
static int
ipgpc_modify_action(ipp_action_id_t aid, nvlist_t **nvlpp, ipp_flags_t flags)
{
	nvlist_t *nvlp;
	int rc = 0;
	uint8_t config_type;
	uint32_t stat;
	char *name;
	int32_t filter_instance;
	ipgpc_filter_t *filter;
	ipgpc_class_t *aclass;

	nvlp = *nvlpp;
	*nvlpp = NULL;		/* nvlist should be NULL when this returns */

	if ((rc = nvlist_lookup_byte(nvlp, IPP_CONFIG_TYPE, &config_type))
	    != 0) {
		nvlist_free(nvlp);
		ipgpc0dbg(("ipgpc_modify_action: invalid configuration type"));
		return (EINVAL);
	}

	switch (config_type) {
	case IPP_SET:		/* set an action parameter */
		if ((rc = nvlist_lookup_uint32(nvlp, IPP_ACTION_STATS_ENABLE,
		    &stat)) != 0) {
			nvlist_free(nvlp);
			ipgpc0dbg(("ipgpc_modify_action: invalid IPP_SET " \
			    "parameter"));
			return (EINVAL);
		} else {
			ipgpc_gather_stats = (boolean_t)stat;
		}
		break;
	case CLASSIFIER_ADD_FILTER: /* add a filter */
		filter = kmem_zalloc(sizeof (ipgpc_filter_t), KM_SLEEP);
		if ((rc = ipgpc_parse_filter(filter, nvlp)) != 0) {
			ipgpc0dbg(("ipgpc_modify_action: invalid filter"));
			ipgpc_filter_destructor(filter);
			kmem_free(filter, sizeof (ipgpc_filter_t));
			break;
		}
		/* parse class name */
		if ((rc = nvlist_lookup_string(nvlp, CLASSIFIER_CLASS_NAME,
		    &name)) != 0) {
			ipgpc0dbg(("ipgpc_modify_action: class name missing"));
			ipgpc_filter_destructor(filter);
			kmem_free(filter, sizeof (ipgpc_filter_t));
			break;
		}
		rc = ipgpc_addfilter(filter, name, flags);
		if (rc != 0) {
			ipgpc_filter_destructor(filter);
		}
		kmem_free(filter, sizeof (ipgpc_filter_t));
		break;
	case CLASSIFIER_ADD_CLASS: /* add a class */
		aclass = kmem_zalloc(sizeof (ipgpc_class_t), KM_SLEEP);
		if ((rc = ipgpc_parse_class(aclass, nvlp)) != 0) {
			ipgpc0dbg(("ipgpc_modify_action: invalid class"));
			kmem_free(aclass, sizeof (ipgpc_class_t));
			break;
		}
		rc = ipgpc_addclass(aclass, flags);
		kmem_free(aclass, sizeof (ipgpc_class_t));
		break;
	case CLASSIFIER_REMOVE_FILTER: /* remove a filter */
		/* parse filter name */
		if ((rc = nvlist_lookup_string(nvlp, CLASSIFIER_FILTER_NAME,
		    &name)) != 0) {
			ipgpc0dbg(("ipgpc_modify_action: filtername missing"));
			break;
		}
		/* parse optional filter_instance */
		if (nvlist_lookup_int32(nvlp, IPGPC_FILTER_INSTANCE,
		    &filter_instance) != 0) {
			filter_instance = -1;
		}
		rc = ipgpc_removefilter(name, filter_instance, flags);
		break;
	case CLASSIFIER_REMOVE_CLASS: /* remove a class */
		/* parse class name */
		if ((rc = nvlist_lookup_string(nvlp, CLASSIFIER_CLASS_NAME,
		    &name)) != 0) {
			ipgpc0dbg(("ipgpc_modify_action: class name missing"));
			break;
		}
		rc = ipgpc_removeclass(name, flags);
		break;
	case CLASSIFIER_MODIFY_FILTER: /* modify a filter */
		rc = ipgpc_modifyfilter(&nvlp, flags);
		break;
	case CLASSIFIER_MODIFY_CLASS: /* modify a class */
		rc = ipgpc_modifyclass(&nvlp, flags);
		break;
	default:		/* invalid config type */
		nvlist_free(nvlp);
		ipgpc0dbg(("ipgpc_modify_action:invalid configuration type %u",
		    config_type));
		return (EINVAL);
	}
	nvlist_free(nvlp);	/* free the list */
	return (rc);		/* nvlist is passed back NULL */
}
Beispiel #16
0
static int
create_strand(topo_mod_t *mod, tnode_t *pnode, nvlist_t *cpu,
    nvlist_t *auth, uint16_t chip_smbiosid)
{
	tnode_t *strand;
	int32_t strandid, cpuid;
	int err, perr, nerr = 0;
	nvlist_t *fmri;
	char *serial = NULL;
	char *part = NULL;
	char *rev = NULL;

	if ((err = nvlist_lookup_int32(cpu, FM_PHYSCPU_INFO_STRAND_ID,
	    &strandid)) != 0) {
		whinge(mod, NULL, "create_strand: lookup strand_id failed: "
		    "%s\n", strerror(err));
		return (-1);
	}

	if ((strand = topo_node_lookup(pnode, STRAND_NODE_NAME, strandid))
	    != NULL) {
		whinge(mod, NULL, "create_strand: duplicate tuple found\n");
		return (-1);
	}

	if ((strand = create_node(mod, pnode, auth, STRAND_NODE_NAME,
	    strandid, chip_smbiosid)) == NULL)
		return (-1);

	/*
	 * Inherit FRU from core node, in native use cpu scheme ASRU,
	 * in xpv, use hc scheme ASRU.
	 */
	(void) topo_node_fru_set(strand, NULL, 0, &perr);
	/*
	 * From the inherited FRU, extract the Serial
	 * number(if SMBIOS donates) and set it in the ASRU
	 */
	if (FM_AWARE_SMBIOS(mod)) {
		char *val = NULL;

		if (topo_prop_get_fmri(strand, TOPO_PGROUP_PROTOCOL,
		    TOPO_PROP_RESOURCE, &fmri, &err) != 0)
			whinge(mod, NULL,
			    "create_strand: topo_prop_get_fmri failed\n");
		if (nvlist_lookup_string(fmri, FM_FMRI_HC_SERIAL_ID, &val) != 0)
			whinge(mod, NULL,
			    "create_strand: nvlist_lookup_string failed: \n");
		else
			serial = topo_mod_strdup(mod, val);
		nvlist_free(fmri);
	}
	if (is_xpv()) {
		if (topo_node_resource(strand, &fmri, &err) == -1) {
			whinge(mod, &nerr, "create_strand: "
			    "topo_node_resource failed\n");
		} else {
			if (FM_AWARE_SMBIOS(mod))
				(void) nvlist_add_string(fmri,
				    FM_FMRI_HC_SERIAL_ID, serial);
			(void) topo_node_asru_set(strand, fmri, 0, &err);
			nvlist_free(fmri);
		}
	} else {
		if (nvlist_lookup_int32(cpu, STRAND_CPU_ID, &cpuid) != 0) {
			whinge(mod, &nerr, "create_strand: lookup cpuid "
			    "failed\n");
		} else {
			if ((fmri = cpu_fmri_create(mod, cpuid, serial, 0))
			    != NULL) {
				(void) topo_node_asru_set(strand, fmri,
				    0, &err);
				nvlist_free(fmri);
			} else {
				whinge(mod, &nerr, "create_strand: "
				    "cpu_fmri_create() failed\n");
			}
		}
	}

	if (topo_method_register(mod, strand, strands_retire_methods) < 0)
		whinge(mod, &nerr, "create_strand: "
		    "topo_method_register failed\n");

	(void) topo_pgroup_create(strand, &strand_pgroup, &err);
	nerr -= add_nvlist_longprops(mod, strand, cpu, PGNAME(STRAND), NULL,
	    STRAND_CHIP_ID, STRAND_PROCNODE_ID, STRAND_CORE_ID, STRAND_CPU_ID,
	    NULL);

	if (FM_AWARE_SMBIOS(mod)) {
		(void) topo_node_label_set(strand, NULL, &perr);

		if (topo_node_resource(strand, &fmri, &perr) != 0) {
			whinge(mod, &nerr, "create_strand: "
			    "topo_node_resource failed\n");
			perr = 0;
		}

		perr += nvlist_lookup_string(fmri,
		    FM_FMRI_HC_PART, &part);
		perr += nvlist_lookup_string(fmri,
		    FM_FMRI_HC_REVISION, &rev);

		if (perr != 0) {
			whinge(mod, NULL,
			    "create_strand: nvlist_lookup_string failed\n");
			perr = 0;
		}

		perr += topo_prop_set_string(strand, PGNAME(STRAND),
		    FM_FMRI_HC_SERIAL_ID, TOPO_PROP_IMMUTABLE, serial, &perr);
		perr += topo_prop_set_string(strand, PGNAME(STRAND),
		    FM_FMRI_HC_PART, TOPO_PROP_IMMUTABLE, part, &perr);
		perr += topo_prop_set_string(strand, PGNAME(STRAND),
		    FM_FMRI_HC_REVISION, TOPO_PROP_IMMUTABLE, rev, &perr);

		if (perr != 0)
			whinge(mod, NULL, "create_strand: topo_prop_set_string"
			    "failed\n");

		nvlist_free(fmri);
		topo_mod_strfree(mod, serial);
	}

	return (err == 0 && nerr == 0 ? 0 : -1);
}
Beispiel #17
0
static int
create_core(topo_mod_t *mod, tnode_t *pnode, nvlist_t *cpu,
    nvlist_t *auth, uint16_t chip_smbiosid)
{
	tnode_t *core;
	int32_t coreid, cpuid;
	int err, perr, nerr = 0;
	nvlist_t *fmri;
	char *serial = NULL;
	char *part = NULL;
	char *rev = NULL;

	if ((err = nvlist_lookup_int32(cpu, FM_PHYSCPU_INFO_CORE_ID, &coreid))
	    != 0) {
		whinge(mod, NULL, "create_core: lookup core_id failed: %s\n",
		    strerror(err));
		return (-1);
	}
	if ((core = topo_node_lookup(pnode, CORE_NODE_NAME, coreid)) == NULL) {
		if ((core = create_node(mod, pnode, auth, CORE_NODE_NAME,
		    coreid, chip_smbiosid)) == NULL)
			return (-1);

		/*
		 * Inherit FRU from the chip node, for native, we use hc
		 * scheme ASRU for the core node.
		 */
		(void) topo_node_fru_set(core, NULL, 0, &perr);
		/*
		 * From the inherited FRU, extract the Serial
		 * number if SMBIOS donates and set it in the ASRU
		 */
		if (FM_AWARE_SMBIOS(mod)) {
			char *val = NULL;

			if (topo_node_resource(core, &fmri, &err) != 0)
				whinge(mod, NULL,
				    "create_core: topo_prop_get_fmri failed\n");
			if (nvlist_lookup_string(fmri, FM_FMRI_HC_SERIAL_ID,
			    &val) != 0)
				whinge(mod, NULL, "create_core:"
				    "nvlist_lookup_string failed\n");
			else
				serial = topo_mod_strdup(mod, val);
			nvlist_free(fmri);
		}
		if (is_xpv()) {
			if (topo_node_resource(core, &fmri, &err) == -1) {
				whinge(mod, &nerr, "create_core: "
				    "topo_node_resource failed\n");
			} else {
				if (FM_AWARE_SMBIOS(mod))
					(void) nvlist_add_string(fmri,
					    FM_FMRI_HC_SERIAL_ID, serial);
				(void) topo_node_asru_set(core, fmri, 0, &err);
				nvlist_free(fmri);
			}
		}
		if (topo_method_register(mod, core, strands_retire_methods) < 0)
			whinge(mod, &nerr, "create_core: "
			    "topo_method_register failed\n");

		(void) topo_pgroup_create(core, &core_pgroup, &err);
		nerr -= add_nvlist_longprops(mod, core, cpu, PGNAME(CORE), NULL,
		    CORE_CHIP_ID, CORE_PROCNODE_ID, NULL);

		if (topo_node_range_create(mod, core, STRAND_NODE_NAME,
		    0, 255) != 0)
			return (-1);
	}

	if (!is_xpv()) {
		/*
		 * In native mode, we're in favor of cpu scheme ASRU for
		 * printing reason.  More work needs to be done to support
		 * multi-strand cpu: the ASRU will be a list of cpuid then.
		 */
		if (nvlist_lookup_int32(cpu, STRAND_CPU_ID, &cpuid) != 0) {
			whinge(mod, &nerr, "create_core: lookup cpuid "
			    "failed\n");
		} else {
			if ((fmri = cpu_fmri_create(mod, cpuid, serial, 0))
			    != NULL) {
				(void) topo_node_asru_set(core, fmri, 0, &err);
				nvlist_free(fmri);
			} else {
				whinge(mod, &nerr, "create_core: "
				    "cpu_fmri_create() failed\n");
			}
		}
	}

	if (FM_AWARE_SMBIOS(mod)) {
		(void) topo_node_label_set(core, NULL, &perr);

		if (topo_node_resource(core, &fmri, &perr) != 0) {
			whinge(mod, &nerr, "create_core: "
			    "topo_node_resource failed\n");
			perr = 0;
		}

		perr += nvlist_lookup_string(fmri,
		    FM_FMRI_HC_PART, &part);
		perr += nvlist_lookup_string(fmri,
		    FM_FMRI_HC_REVISION, &rev);

		if (perr != 0) {
			whinge(mod, NULL,
			    "create_core: nvlist_lookup_string failed\n");
			perr = 0;
		}

		perr += topo_prop_set_string(core, PGNAME(CORE),
		    FM_FMRI_HC_SERIAL_ID, TOPO_PROP_IMMUTABLE, serial, &perr);
		perr += topo_prop_set_string(core, PGNAME(CORE),
		    FM_FMRI_HC_PART, TOPO_PROP_IMMUTABLE, part, &perr);
		perr += topo_prop_set_string(core, PGNAME(CORE),
		    FM_FMRI_HC_REVISION, TOPO_PROP_IMMUTABLE, rev, &perr);

		if (perr != 0)
			whinge(mod, NULL, "create_core: topo_prop_set_string"
			    "failed\n");

		nvlist_free(fmri);
		topo_mod_strfree(mod, serial);
	}

	err = create_strand(mod, core, cpu, auth, chip_smbiosid);

	return (err == 0 && nerr == 0 ? 0 : -1);
}
Beispiel #18
0
/*ARGSUSED3*/
static nvlist_t *
fmevt_detector(nvlist_t *attr, char *ruleset, int user, int priv,
    fmev_pri_t pri)
{
	char buf[FMEV_MAX_RULESET_LEN + 1];
	char *ns, *subsys;
	nvlist_t *obj, *dtcr, *site, *ctxt;
	char *execname = NULL;
	int32_t i32;
	int64_t i64;
	int err = 0;
	char *str;

	(void) strncpy(buf, ruleset, sizeof (buf));
	if (!fmevt_rs_burst(NULL, buf, &ns, &subsys, B_FALSE))
		return (NULL);

	obj = fmd_nvl_alloc(fmevt_hdl, FMD_SLEEP);
	dtcr = fmd_nvl_alloc(fmevt_hdl, FMD_SLEEP);
	site = fmd_nvl_alloc(fmevt_hdl, FMD_SLEEP);
	ctxt = fmd_nvl_alloc(fmevt_hdl, FMD_SLEEP);

	if (obj == NULL || dtcr == NULL || site == NULL || ctxt == NULL) {
		err++;
		goto done;
	}

	/*
	 * Build up 'object' nvlist.
	 */
	if (nvlist_lookup_string(attr, "__fmev_execname", &execname) == 0)
		err += nvlist_add_string(obj, FM_FMRI_SW_OBJ_PATH, execname);

	/*
	 * Build up 'site' nvlist.  We should have source file and line
	 * number and, if the producer was compiled with C99, function name.
	 */
	if (nvlist_lookup_string(attr, "__fmev_file", &str) == 0) {
		err += nvlist_add_string(site, FM_FMRI_SW_SITE_FILE, str);
		(void) nvlist_remove(attr, "__fmev_file", DATA_TYPE_STRING);
	}

	if (nvlist_lookup_string(attr, "__fmev_func", &str) == 0) {
		err += nvlist_add_string(site, FM_FMRI_SW_SITE_FUNC, str);
		(void) nvlist_remove(attr, "__fmev_func", DATA_TYPE_STRING);
	}

	if (nvlist_lookup_int64(attr, "__fmev_line", &i64) == 0) {
		err += nvlist_add_int64(site, FM_FMRI_SW_SITE_LINE, i64);
		(void) nvlist_remove(attr, "__fmev_line", DATA_TYPE_INT64);
	}

	/*
	 * Build up 'context' nvlist.  We do not include contract id at
	 * this time.
	 */

	err += nvlist_add_string(ctxt, FM_FMRI_SW_CTXT_ORIGIN,
	    user ? "userland" : "kernel");

	if (execname) {
		err += nvlist_add_string(ctxt, FM_FMRI_SW_CTXT_EXECNAME,
		    execname);
		(void) nvlist_remove(attr, "__fmev_execname", DATA_TYPE_STRING);
	}

	if (nvlist_lookup_int32(attr, "__fmev_pid", &i32) == 0) {
		err += nvlist_add_int32(ctxt, FM_FMRI_SW_CTXT_PID, i32);
		(void) nvlist_remove(attr, "__fmev_pid", DATA_TYPE_INT32);
	}

	if (!isglobalzone)
		err += nvlist_add_string(ctxt, FM_FMRI_SW_CTXT_ZONE, zonename);

	/* Put it all together */

	err += nvlist_add_uint8(dtcr, FM_VERSION, SW_SCHEME_VERSION0);
	err += nvlist_add_string(dtcr, FM_FMRI_SCHEME, FM_FMRI_SCHEME_SW);
	err += nvlist_add_nvlist(dtcr, FM_FMRI_SW_OBJ, obj);
	err += nvlist_add_nvlist(dtcr, FM_FMRI_SW_SITE, site);
	err += nvlist_add_nvlist(dtcr, FM_FMRI_SW_CTXT, ctxt);

done:
	nvlist_free(obj);
	nvlist_free(site);
	nvlist_free(ctxt);

	if (err == 0) {
		return (dtcr);
	} else {
		nvlist_free(dtcr);
		return (NULL);
	}
}