예제 #1
0
/*
 * Enable processor set plugin.
 */
int
pool_pset_enable(void)
{
	int error;
	nvlist_t *props;

	ASSERT(pool_lock_held());
	ASSERT(INGLOBALZONE(curproc));
	/*
	 * Can't enable pools if there are existing cpu partitions.
	 */
	mutex_enter(&cpu_lock);
	if (cp_numparts > 1) {
		mutex_exit(&cpu_lock);
		return (EEXIST);
	}

	/*
	 * We want to switch things such that everything that was tagged with
	 * the special ALL_ZONES token now is explicitly visible to all zones:
	 * first add individual zones to the visibility list then remove the
	 * special "ALL_ZONES" token.  There must only be the default pset
	 * (PS_NONE) active if pools are being enabled, so we only need to
	 * deal with it.
	 *
	 * We want to make pool_pset_enabled() start returning B_TRUE before
	 * we call any of the visibility update functions.
	 */
	global_zone->zone_psetid = PS_NONE;
	/*
	 * We need to explicitly handle the global zone since
	 * zone_pset_set() won't modify it.
	 */
	pool_pset_visibility_add(PS_NONE, global_zone);
	/*
	 * A NULL argument means the ALL_ZONES token.
	 */
	pool_pset_visibility_remove(PS_NONE, NULL);
	error = zone_walk(pool_pset_zone_pset_set, (void *)PS_NONE);
	ASSERT(error == 0);

	/*
	 * It is safe to drop cpu_lock here.  We're still
	 * holding pool_lock so no new cpu partitions can
	 * be created while we're here.
	 */
	mutex_exit(&cpu_lock);
	(void) nvlist_alloc(&pool_pset_default->pset_props,
	    NV_UNIQUE_NAME, KM_SLEEP);
	props = pool_pset_default->pset_props;
	(void) nvlist_add_string(props, "pset.name", "pset_default");
	(void) nvlist_add_string(props, "pset.comment", "");
	(void) nvlist_add_int64(props, "pset.sys_id", PS_NONE);
	(void) nvlist_add_string(props, "pset.units", "population");
	(void) nvlist_add_byte(props, "pset.default", 1);
	(void) nvlist_add_uint64(props, "pset.max", 65536);
	(void) nvlist_add_uint64(props, "pset.min", 1);
	pool_pset_mod = pool_cpu_mod = gethrtime();
	return (0);
}
예제 #2
0
/*
 * Create new processor set and give it a temporary name.
 */
int
pool_pset_create(psetid_t *id)
{
	char pset_name[40];
	pool_pset_t *pset;
	psetid_t psetid;
	int err;

	ASSERT(pool_lock_held());
	if ((err = cpupart_create(&psetid)) != 0)
		return (err);
	pset = kmem_alloc(sizeof (pool_pset_t), KM_SLEEP);
	pset->pset_id = *id = psetid;
	pset->pset_npools = 0;
	(void) nvlist_alloc(&pset->pset_props, NV_UNIQUE_NAME, KM_SLEEP);
	(void) nvlist_add_int64(pset->pset_props, "pset.sys_id", psetid);
	(void) nvlist_add_byte(pset->pset_props, "pset.default", 0);
	pool_pset_mod = gethrtime();
	(void) snprintf(pset_name, sizeof (pset_name), "pset_%lld",
	    pool_pset_mod);
	(void) nvlist_add_string(pset->pset_props, "pset.name", pset_name);
	list_insert_tail(&pool_pset_list, pset);
	return (0);
}
예제 #3
0
파일: fnvpair.c 프로젝트: 2asoft/freebsd
void
fnvlist_add_int64(nvlist_t *nvl, const char *name, int64_t val)
{
	VERIFY0(nvlist_add_int64(nvl, name, val));
}
예제 #4
0
static void
set_prop(topo_hdl_t *thp, tnode_t *node, nvlist_t *fmri, struct prop_args *pp)
{
	int ret, err = 0;
	topo_type_t type;
	nvlist_t *nvl, *f = NULL;
	char *end;

	if (pp->prop == NULL || pp->type == NULL || pp->value == NULL)
		return;

	if ((type = str2type(pp->type)) == TOPO_TYPE_INVALID) {
		(void) fprintf(stderr, "%s: invalid property type %s for %s\n",
		    g_pname, pp->type, pp->prop);
		return;
	}

	if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0) {
		(void) fprintf(stderr, "%s: nvlist allocation failed for "
		    "%s=%s:%s\n", g_pname, pp->prop, pp->type, pp->value);
		return;
	}
	ret = nvlist_add_string(nvl, TOPO_PROP_VAL_NAME, pp->prop);
	ret |= nvlist_add_uint32(nvl, TOPO_PROP_VAL_TYPE, type);
	if (ret != 0) {
		(void) fprintf(stderr, "%s: invalid property type %s for %s\n",
		    g_pname, pp->type, pp->prop);
		nvlist_free(nvl);
		return;
	}

	errno = 0;
	switch (type) {
		case TOPO_TYPE_INT32:
		{
			int32_t val;

			val = strtol(pp->value, &end, 0);
			if (errno == ERANGE) {
				ret = -1;
				break;
			}
			ret = nvlist_add_int32(nvl, TOPO_PROP_VAL_VAL, val);
			break;
		}
		case TOPO_TYPE_UINT32:
		{
			uint32_t val;

			val = strtoul(pp->value, &end, 0);
			if (errno == ERANGE) {
				ret = -1;
				break;
			}
			ret = nvlist_add_uint32(nvl, TOPO_PROP_VAL_VAL, val);
			break;
		}
		case TOPO_TYPE_INT64:
		{
			int64_t val;

			val = strtoll(pp->value, &end, 0);
			if (errno == ERANGE) {
				ret = -1;
				break;
			}
			ret = nvlist_add_int64(nvl, TOPO_PROP_VAL_VAL, val);
			break;
		}
		case TOPO_TYPE_UINT64:
		{
			uint64_t val;

			val = strtoull(pp->value, &end, 0);
			if (errno == ERANGE) {
				ret = -1;
				break;
			}
			ret = nvlist_add_uint64(nvl, TOPO_PROP_VAL_VAL, val);
			break;
		}
		case TOPO_TYPE_STRING:
		{
			ret = nvlist_add_string(nvl, TOPO_PROP_VAL_VAL,
			    pp->value);
			break;
		}
		case TOPO_TYPE_FMRI:
		{
			if ((ret = topo_fmri_str2nvl(thp, pp->value, &f, &err))
			    < 0)
				break;

			if ((ret = nvlist_add_nvlist(nvl, TOPO_PROP_VAL_VAL,
			    f)) != 0)
				err = ETOPO_PROP_NVL;
			break;
		}
		default:
			ret = -1;
	}

	if (ret != 0) {
		(void) fprintf(stderr, "%s: unable to set property value for "
		    "%s: %s\n", g_pname, pp->prop,  topo_strerror(err));
		nvlist_free(nvl);
		return;
	}

	if (node != NULL) {
		if (topo_prop_setprop(node, pp->group, nvl, TOPO_PROP_MUTABLE,
		    f, &ret) < 0) {
			(void) fprintf(stderr, "%s: unable to set property "
			    "value for " "%s=%s:%s: %s\n", g_pname, pp->prop,
			    pp->type, pp->value, topo_strerror(ret));
			nvlist_free(nvl);
			nvlist_free(f);
			return;
		}
	} else {
		if (topo_fmri_setprop(thp, fmri,  pp->group, nvl,
		    TOPO_PROP_MUTABLE, f, &ret) < 0) {
			(void) fprintf(stderr, "%s: unable to set property "
			    "value for " "%s=%s:%s: %s\n", g_pname, pp->prop,
			    pp->type, pp->value, topo_strerror(ret));
			nvlist_free(nvl);
			nvlist_free(f);
			return;
		}
	}

	nvlist_free(nvl);

	/*
	 * Now, get the property back for printing
	 */
	if (node != NULL) {
		if (topo_prop_getprop(node, pp->group, pp->prop, f, &nvl,
		    &err) < 0) {
			(void) fprintf(stderr, "%s: failed to get %s.%s: %s\n",
			    g_pname, pp->group, pp->prop, topo_strerror(err));
			nvlist_free(f);
			return;
		}
	} else {
		if (topo_fmri_getprop(thp, fmri, pp->group, pp->prop,
		    f, &nvl, &err) < 0) {
			(void) fprintf(stderr, "%s: failed to get %s.%s: %s\n",
			    g_pname, pp->group, pp->prop, topo_strerror(err));
			nvlist_free(f);
			return;
		}
	}

	print_pgroup(thp, node, pp->group, NULL, NULL, 0);
	print_prop_nameval(thp, node, nvl);
	nvlist_free(nvl);

	nvlist_free(f);
}
예제 #5
0
static int
topo_prop_set(tnode_t *node, const char *pgname, const char *pname,
    topo_type_t type, int flag, void *val, int nelems, int *err)
{
	int ret;
	topo_hdl_t *thp = node->tn_hdl;
	nvlist_t *nvl;

	if (topo_hdl_nvalloc(thp, &nvl, NV_UNIQUE_NAME) < 0) {
		*err = ETOPO_PROP_NVL;
		return (-1);
	}

	ret = nvlist_add_string(nvl, TOPO_PROP_VAL_NAME, pname);
	ret |= nvlist_add_uint32(nvl, TOPO_PROP_VAL_TYPE, type);
	switch (type) {
		case TOPO_TYPE_INT32:
			ret |= nvlist_add_int32(nvl, TOPO_PROP_VAL_VAL,
			    *(int32_t *)val);
			break;
		case TOPO_TYPE_UINT32:
			ret |= nvlist_add_uint32(nvl, TOPO_PROP_VAL_VAL,
			    *(uint32_t *)val);
			break;
		case TOPO_TYPE_INT64:
			ret |= nvlist_add_int64(nvl, TOPO_PROP_VAL_VAL,
			    *(int64_t *)val);
			break;
		case TOPO_TYPE_UINT64:
			ret |= nvlist_add_uint64(nvl, TOPO_PROP_VAL_VAL,
			    *(uint64_t *)val);
			break;
		case TOPO_TYPE_DOUBLE:
			ret |= nvlist_add_double(nvl, TOPO_PROP_VAL_VAL,
			    *(double *)val);
			break;
		case TOPO_TYPE_STRING:
			ret |= nvlist_add_string(nvl, TOPO_PROP_VAL_VAL,
			    (char *)val);
			break;
		case TOPO_TYPE_FMRI:
			ret |= nvlist_add_nvlist(nvl, TOPO_PROP_VAL_VAL,
			    (nvlist_t *)val);
			break;
		case TOPO_TYPE_INT32_ARRAY:
			ret |= nvlist_add_int32_array(nvl,
			    TOPO_PROP_VAL_VAL, (int32_t *)val, nelems);
			break;
		case TOPO_TYPE_UINT32_ARRAY:
			ret |= nvlist_add_uint32_array(nvl,
			    TOPO_PROP_VAL_VAL, (uint32_t *)val, nelems);
			break;
		case TOPO_TYPE_INT64_ARRAY:
			ret |= nvlist_add_int64_array(nvl,
			    TOPO_PROP_VAL_VAL, (int64_t *)val, nelems);
			break;
		case TOPO_TYPE_UINT64_ARRAY:
			ret |= nvlist_add_uint64_array(nvl,
			    TOPO_PROP_VAL_VAL, (uint64_t *)val, nelems);
			break;
		case TOPO_TYPE_STRING_ARRAY:
			ret |= nvlist_add_string_array(nvl,
			    TOPO_PROP_VAL_VAL, (char **)val, nelems);
			break;
		case TOPO_TYPE_FMRI_ARRAY:
			ret |= nvlist_add_nvlist_array(nvl,
			    TOPO_PROP_VAL_VAL, (nvlist_t **)val, nelems);
			break;
		default:
			*err = ETOPO_PROP_TYPE;
			return (-1);
	}

	if (ret != 0) {
		nvlist_free(nvl);
		if (ret == ENOMEM) {
			*err = ETOPO_PROP_NOMEM;
			return (-1);
		} else {
			*err = ETOPO_PROP_NVL;
			return (-1);
		}
	}

	if (topo_prop_setprop(node, pgname, nvl, flag, nvl, err) != 0) {
		nvlist_free(nvl);
		return (-1); /* err set */
	}
	nvlist_free(nvl);
	return (ret);
}
예제 #6
0
/*
 * Take a snapshot of the current state of processor sets and CPUs,
 * pack it in the exacct format, and attach it to specified exacct record.
 */
int
pool_pset_pack(ea_object_t *eo_system)
{
	ea_object_t *eo_pset, *eo_cpu;
	cpupart_t *cpupart;
	psetid_t mypsetid;
	pool_pset_t *pset;
	nvlist_t *nvl;
	size_t bufsz;
	cpu_t *cpu;
	char *buf;
	int ncpu;

	ASSERT(pool_lock_held());

	mutex_enter(&cpu_lock);
	mypsetid = zone_pset_get(curproc->p_zone);
	for (pset = list_head(&pool_pset_list); pset;
	    pset = list_next(&pool_pset_list, pset)) {
		psetid_t psetid = pset->pset_id;

		if (!INGLOBALZONE(curproc) && mypsetid != psetid)
			continue;
		cpupart = cpupart_find(psetid);
		ASSERT(cpupart != NULL);
		eo_pset = ea_alloc_group(EXT_GROUP |
		    EXC_LOCAL | EXD_GROUP_PSET);
		(void) ea_attach_item(eo_pset, &psetid, sizeof (id_t),
		    EXC_LOCAL | EXD_PSET_PSETID | EXT_UINT32);
		/*
		 * Pack info for all CPUs in this processor set.
		 */
		ncpu = 0;
		cpu = cpu_list;
		do {
			if (cpu->cpu_part != cpupart)	/* not our pset */
				continue;
			ncpu++;
			eo_cpu = ea_alloc_group(EXT_GROUP
			    | EXC_LOCAL | EXD_GROUP_CPU);
			(void) ea_attach_item(eo_cpu, &cpu->cpu_id,
			    sizeof (processorid_t),
			    EXC_LOCAL | EXD_CPU_CPUID | EXT_UINT32);
			if (cpu->cpu_props == NULL) {
				(void) nvlist_alloc(&cpu->cpu_props,
				    NV_UNIQUE_NAME, KM_SLEEP);
				(void) nvlist_add_string(cpu->cpu_props,
				    "cpu.comment", "");
			}
			(void) nvlist_dup(cpu->cpu_props, &nvl, KM_SLEEP);
			(void) nvlist_add_int64(nvl, "cpu.sys_id", cpu->cpu_id);
			(void) nvlist_add_string(nvl, "cpu.status",
			    (char *)cpu_get_state_str(cpu));
			buf = NULL;
			bufsz = 0;
			(void) nvlist_pack(nvl, &buf, &bufsz,
			    NV_ENCODE_NATIVE, 0);
			(void) ea_attach_item(eo_cpu, buf, bufsz,
			    EXC_LOCAL | EXD_CPU_PROP | EXT_RAW);
			(void) nvlist_free(nvl);
			kmem_free(buf, bufsz);
			(void) ea_attach_to_group(eo_pset, eo_cpu);
		} while ((cpu = cpu->cpu_next) != cpu_list);

		(void) nvlist_dup(pset->pset_props, &nvl, KM_SLEEP);
		(void) nvlist_add_uint64(nvl, "pset.size", ncpu);
		(void) nvlist_add_uint64(nvl, "pset.load",
		    (uint64_t)PSET_LOAD(cpupart->cp_hp_avenrun[0]));
		buf = NULL;
		bufsz = 0;
		(void) nvlist_pack(nvl, &buf, &bufsz, NV_ENCODE_NATIVE, 0);
		(void) ea_attach_item(eo_pset, buf, bufsz,
		    EXC_LOCAL | EXD_PSET_PROP | EXT_RAW);
		(void) nvlist_free(nvl);
		kmem_free(buf, bufsz);

		(void) ea_attach_to_group(eo_system, eo_pset);
	}
	mutex_exit(&cpu_lock);
	return (0);
}
예제 #7
0
파일: sw.c 프로젝트: NanXiao/illumos-joyent
/*ARGSUSED*/
static int
sw_fmri_create(topo_mod_t *mod, tnode_t *node, topo_version_t version,
    nvlist_t *in, nvlist_t **out)
{
	nvlist_t *args, *fmri = NULL, *obj = NULL, *site = NULL, *ctxt = NULL;
	topo_mod_errno_t moderr;
	int err = 0;

	char *obj_path, *obj_root;
	nvlist_t *obj_pkg;

	char *site_token, *site_module, *site_file, *site_func;
	int64_t site_line;

	char *ctxt_origin, *ctxt_execname, *ctxt_zone;
	int64_t ctxt_pid, ctxt_ctid;
	char **ctxt_stack;
	uint_t ctxt_stackdepth;


	if (version > TOPO_METH_FMRI_VERSION)
		return (topo_mod_seterrno(mod, EMOD_VER_NEW));

	if (nvlist_lookup_nvlist(in, TOPO_METH_FMRI_ARG_NVL, &args) != 0)
		return (topo_mod_seterrno(mod, EMOD_METHOD_INVAL));

	if (nvlist_lookup_string(args, "obj_path", &obj_path) != 0)
		return (topo_mod_seterrno(mod, EMOD_NVL_INVAL));
	err |= sw_get_optl_string(args, "obj_root", &obj_root);
	err |= sw_get_optl_nvlist(args, "obj-pkg", &obj_pkg);

	err |= sw_get_optl_string(args, "site_token", &site_token);
	err |= sw_get_optl_string(args, "site_module", &site_module);
	err |= sw_get_optl_string(args, "site_file", &site_file);
	err |= sw_get_optl_string(args, "site_func", &site_func);
	err |= sw_get_optl_int64(args, "site_line", &site_line);

	err |= sw_get_optl_string(args, "ctxt_origin", &ctxt_origin);
	err |= sw_get_optl_string(args, "ctxt_execname", &ctxt_execname);
	err |= sw_get_optl_string(args, "ctxt_zone", &ctxt_zone);
	err |= sw_get_optl_int64(args, "ctxt_pid", &ctxt_pid);
	err |= sw_get_optl_int64(args, "ctxt_ctid", &ctxt_ctid);

	if (nvlist_lookup_string_array(args, "stack", &ctxt_stack,
	    &ctxt_stackdepth) != 0) {
		if (errno == ENOENT)
			ctxt_stack = NULL;
		else
			err++;
	}

	if (err)
		(void) topo_mod_seterrno(mod, EMOD_FMRI_NVL);

	if (topo_mod_nvalloc(mod, &fmri, NV_UNIQUE_NAME) != 0 ||
	    topo_mod_nvalloc(mod, &obj, NV_UNIQUE_NAME) != 0) {
		moderr = EMOD_NOMEM;
		goto out;
	}

	/*
	 * Add standard FMRI members 'version' and 'scheme'.
	 */
	err |= nvlist_add_uint8(fmri, FM_VERSION, FM_SW_SCHEME_VERSION);
	err |= nvlist_add_string(fmri, FM_FMRI_SCHEME, FM_FMRI_SCHEME_SW);

	/*
	 * Build up the 'object' nvlist.
	 */
	err |= nvlist_add_string(obj, FM_FMRI_SW_OBJ_PATH, obj_path);
	err |= sw_add_optl_string(obj, FM_FMRI_SW_OBJ_ROOT, obj_root);
	if (obj_pkg)
		err |= nvlist_add_nvlist(obj, FM_FMRI_SW_OBJ_PKG, obj_pkg);

	/*
	 * Add 'object' to the fmri.
	 */
	if (err == 0)
		err |= nvlist_add_nvlist(fmri, FM_FMRI_SW_OBJ, obj);

	if (err) {
		moderr = EMOD_NOMEM;
		goto out;
	}

	/*
	 * Do we have anything for a 'site' nvlist?
	 */
	if (site_token == NULL && site_module == NULL && site_file == NULL &&
	    site_func == NULL && site_line == -1)
		goto context;

	/*
	 * Allocate and build 'site' nvlist.
	 */
	if (topo_mod_nvalloc(mod, &site, NV_UNIQUE_NAME) != 0) {
		moderr = EMOD_NOMEM;
		goto out;
	}

	err |= sw_add_optl_string(site, FM_FMRI_SW_SITE_TOKEN, site_token);
	err |= sw_add_optl_string(site, FM_FMRI_SW_SITE_MODULE, site_module);
	err |= sw_add_optl_string(site, FM_FMRI_SW_SITE_FILE, site_file);
	err |= sw_add_optl_string(site, FM_FMRI_SW_SITE_FUNC, site_func);
	if ((site_token || site_module || site_file || site_func) &&
	    site_line != -1)
		err |= nvlist_add_int64(site, FM_FMRI_SW_SITE_LINE, site_line);

	/*
	 * Add 'site' to the fmri.
	 */
	if (err == 0)
		err |= nvlist_add_nvlist(fmri, FM_FMRI_SW_SITE, site);

	if (err) {
		moderr = EMOD_NOMEM;
		goto out;
	}

context:
	/*
	 * Do we have anything for a 'context' nvlist?
	 */
	if (ctxt_origin || ctxt_execname || ctxt_zone ||
	    ctxt_pid != -1 || ctxt_ctid != -1 || ctxt_stack != NULL)
		goto out;

	/*
	 * Allocate and build 'context' nvlist.
	 */
	if (topo_mod_nvalloc(mod, &ctxt, NV_UNIQUE_NAME) != 0) {
		moderr = EMOD_NOMEM;
		goto out;
	}

	err |= sw_add_optl_string(ctxt, FM_FMRI_SW_CTXT_ORIGIN, ctxt_origin);
	err |= sw_add_optl_string(ctxt, FM_FMRI_SW_CTXT_EXECNAME,
	    ctxt_execname);
	err |= sw_add_optl_string(ctxt, FM_FMRI_SW_CTXT_ZONE, ctxt_zone);
	if (ctxt_pid != -1)
		err |= nvlist_add_int64(ctxt, FM_FMRI_SW_CTXT_PID, ctxt_pid);
	if (ctxt_ctid != -1)
		err |= nvlist_add_int64(ctxt, FM_FMRI_SW_CTXT_CTID, ctxt_ctid);
	if (ctxt_stack != NULL)
		err |= nvlist_add_string_array(ctxt, FM_FMRI_SW_CTXT_STACK,
		    ctxt_stack, ctxt_stackdepth);

	/*
	 * Add 'context' to the fmri.
	 */
	if (err == 0)
		err |= nvlist_add_nvlist(fmri, FM_FMRI_SW_CTXT, ctxt);

	moderr = err ? EMOD_NOMEM : 0;
out:
	if (moderr == 0)
		*out = fmri;

	if (moderr != 0 && fmri)
		nvlist_free(fmri);

	if (obj)
		nvlist_free(obj);

	if (site)
		nvlist_free(site);

	if (ctxt)
		nvlist_free(ctxt);

	return (moderr == 0 ? 0 : topo_mod_seterrno(mod, moderr));
}
예제 #8
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);
	}
}