Exemplo n.º 1
0
/*
 * void *exacct_create_header(size_t *)
 *
 * Overview
 *   exacct_create_header() constructs an exacct file header identifying the
 *   accounting file as the output of the kernel.  exacct_create_header() and
 *   the static write_header() and verify_header() routines in libexacct must
 *   remain synchronized.
 *
 * Return values
 *   A pointer to a packed exacct buffer containing the appropriate header is
 *   returned; the size of the buffer is placed in the location indicated by
 *   sizep.
 *
 * Caller's context
 *   Suitable for KM_SLEEP allocations.
 */
void *
exacct_create_header(size_t *sizep)
{
	ea_object_t *hdr_grp;
	uint32_t bskip;
	void *buf;
	size_t bufsize;

	hdr_grp = ea_alloc_group(EXT_GROUP | EXC_DEFAULT | EXD_GROUP_HEADER);
	(void) ea_attach_item(hdr_grp, (void *)&exacct_version, 0,
	    EXT_UINT32 | EXC_DEFAULT | EXD_VERSION);
	(void) ea_attach_item(hdr_grp, (void *)exacct_header, 0,
	    EXT_STRING | EXC_DEFAULT | EXD_FILETYPE);
	(void) ea_attach_item(hdr_grp, (void *)exacct_creator, 0,
	    EXT_STRING | EXC_DEFAULT | EXD_CREATOR);
	(void) ea_attach_item(hdr_grp, uts_nodename(), 0,
	    EXT_STRING | EXC_DEFAULT | EXD_HOSTNAME);

	bufsize = ea_pack_object(hdr_grp, NULL, 0);
	buf = kmem_alloc(bufsize, KM_SLEEP);
	(void) ea_pack_object(hdr_grp, buf, bufsize);
	ea_free_object(hdr_grp, EUP_ALLOC);

	/*
	 * To prevent reading the header when reading the file backwards,
	 * set the large backskip of the header group to 0 (last 4 bytes).
	 */
	bskip = 0;
	exacct_order32(&bskip);
	bcopy(&bskip, (char *)buf + bufsize - sizeof (bskip),
	    sizeof (bskip));

	*sizep = bufsize;
	return (buf);
}
Exemplo n.º 2
0
/*
 * exacct_tag_proc(pid_t, taskid_t, void *, size_t, int, char *)
 *
 * Overview
 *   exacct_tag_proc() provides the exacct record construction and writing
 *   support required by putacct(2) for processes.
 *
 * Return values
 *   The result of the write operation is returned, unless the extended
 *   accounting facility is not active, in which case ENOTACTIVE is returned.
 *
 * Caller's context
 *   Suitable for KM_SLEEP allocations.
 */
int
exacct_tag_proc(ac_info_t *ac_proc, pid_t pid, taskid_t tkid, void *ubuf,
    size_t ubufsz, int flags, const char *hostname)
{
	int error = 0;
	void *buf;
	size_t bufsize;
	ea_catalog_t cat;
	ea_object_t *tag;

	mutex_enter(&ac_proc->ac_lock);
	if (ac_proc->ac_state == AC_OFF || ac_proc->ac_vnode == NULL) {
		mutex_exit(&ac_proc->ac_lock);
		return (ENOTACTIVE);
	}
	mutex_exit(&ac_proc->ac_lock);

	tag = ea_alloc_group(EXT_GROUP | EXC_DEFAULT | EXD_GROUP_PROC_TAG);
	(void) ea_attach_item(tag, &pid, sizeof (uint32_t),
	    EXT_UINT32 | EXC_DEFAULT | EXD_PROC_PID);
	(void) ea_attach_item(tag, &tkid, 0,
	    EXT_UINT32 | EXC_DEFAULT | EXD_TASK_TASKID);
	(void) ea_attach_item(tag, (void *)hostname, 0,
	    EXT_STRING | EXC_DEFAULT | EXD_TASK_HOSTNAME);
	if (flags == EP_RAW)
		cat = EXT_RAW | EXC_DEFAULT | EXD_PROC_TAG;
	else
		cat = EXT_EXACCT_OBJECT | EXC_DEFAULT | EXD_PROC_TAG;
	(void) ea_attach_item(tag, ubuf, ubufsz, cat);

	bufsize = ea_pack_object(tag, NULL, 0);
	buf = kmem_alloc(bufsize, KM_SLEEP);
	(void) ea_pack_object(tag, buf, bufsize);
	error = exacct_vn_write(ac_proc, buf, bufsize);
	kmem_free(buf, bufsize);
	ea_free_object(tag, EUP_ALLOC);
	return (error);
}
Exemplo n.º 3
0
/*
 * int exacct_tag_task(task_t *, void *, size_t, int)
 *
 * Overview
 *   exacct_tag_task() provides the exacct record construction and writing
 *   support required by putacct(2) for task entities.
 *
 * Return values
 *   The result of the write operation is returned, unless the extended
 *   accounting facility is not active, in which case ENOTACTIVE is returned.
 *
 * Caller's context
 *   Suitable for KM_SLEEP allocations.
 */
int
exacct_tag_task(ac_info_t *ac_task, task_t *tk, void *ubuf, size_t ubufsz,
    int flags)
{
	int error = 0;
	void *buf;
	size_t bufsize;
	ea_catalog_t cat;
	ea_object_t *tag;

	mutex_enter(&ac_task->ac_lock);
	if (ac_task->ac_state == AC_OFF || ac_task->ac_vnode == NULL) {
		mutex_exit(&ac_task->ac_lock);
		return (ENOTACTIVE);
	}
	mutex_exit(&ac_task->ac_lock);

	tag = ea_alloc_group(EXT_GROUP | EXC_DEFAULT | EXD_GROUP_TASK_TAG);
	(void) ea_attach_item(tag, &tk->tk_tkid, 0,
	    EXT_UINT32 | EXC_DEFAULT | EXD_TASK_TASKID);
	(void) ea_attach_item(tag, tk->tk_zone->zone_nodename, 0,
	    EXT_STRING | EXC_DEFAULT | EXD_TASK_HOSTNAME);
	if (flags == EP_RAW)
		cat = EXT_RAW | EXC_DEFAULT | EXD_TASK_TAG;
	else
		cat = EXT_EXACCT_OBJECT | EXC_DEFAULT | EXD_TASK_TAG;
	(void) ea_attach_item(tag, ubuf, ubufsz, cat);

	bufsize = ea_pack_object(tag, NULL, 0);
	buf = kmem_alloc(bufsize, KM_SLEEP);
	(void) ea_pack_object(tag, buf, bufsize);
	error = exacct_vn_write(ac_task, buf, bufsize);
	kmem_free(buf, bufsize);
	ea_free_object(tag, EUP_ALLOC);
	return (error);
}
Exemplo n.º 4
0
static int
exacct_attach_proc_item(proc_usage_t *pu, ea_object_t *record, int res)
{
	int attached = 1;

	switch (res) {
	case AC_PROC_PID:
		(void) ea_attach_item(record, &pu->pu_pid,
		    sizeof (uint32_t), EXT_UINT32 | EXD_PROC_PID);
		break;
	case AC_PROC_UID:
		(void) ea_attach_item(record, &pu->pu_ruid,
		    sizeof (uint32_t), EXT_UINT32 | EXD_PROC_UID);
		break;
	case AC_PROC_FLAG:
		(void) ea_attach_item(record, &pu->pu_acflag,
		    sizeof (uint32_t), EXT_UINT32 | EXD_PROC_ACCT_FLAGS);
		break;
	case AC_PROC_GID:
		(void) ea_attach_item(record, &pu->pu_rgid,
		    sizeof (uint32_t), EXT_UINT32 | EXD_PROC_GID);
		break;
	case AC_PROC_PROJID:
		(void) ea_attach_item(record, &pu->pu_projid,
		    sizeof (uint32_t), EXT_UINT32 | EXD_PROC_PROJID);
		break;
	case AC_PROC_TASKID:
		(void) ea_attach_item(record, &pu->pu_taskid,
		    sizeof (uint32_t), EXT_UINT32 | EXD_PROC_TASKID);
		break;
	case AC_PROC_CPU:
		(void) ea_attach_item(record, &pu->pu_utimesec,
		    sizeof (uint64_t), EXT_UINT64 | EXD_PROC_CPU_USER_SEC);
		(void) ea_attach_item(record, &pu->pu_utimensec,
		    sizeof (uint64_t), EXT_UINT64 | EXD_PROC_CPU_USER_NSEC);
		(void) ea_attach_item(record, &pu->pu_stimesec,
		    sizeof (uint64_t), EXT_UINT64 | EXD_PROC_CPU_SYS_SEC);
		(void) ea_attach_item(record, &pu->pu_stimensec,
		    sizeof (uint64_t), EXT_UINT64 | EXD_PROC_CPU_SYS_NSEC);
		break;
	case AC_PROC_TIME:
		(void) ea_attach_item(record, &pu->pu_startsec,
		    sizeof (uint64_t), EXT_UINT64 | EXD_PROC_START_SEC);
		(void) ea_attach_item(record, &pu->pu_startnsec,
		    sizeof (uint64_t), EXT_UINT64 | EXD_PROC_START_NSEC);
		(void) ea_attach_item(record, &pu->pu_finishsec,
		    sizeof (uint64_t), EXT_UINT64 | EXD_PROC_FINISH_SEC);
		(void) ea_attach_item(record, &pu->pu_finishnsec,
		    sizeof (uint64_t), EXT_UINT64 | EXD_PROC_FINISH_NSEC);
		break;
	case AC_PROC_COMMAND:
		(void) ea_attach_item(record, pu->pu_command,
		    strlen(pu->pu_command) + 1, EXT_STRING | EXD_PROC_COMMAND);
		break;
	case AC_PROC_HOSTNAME:
		(void) ea_attach_item(record, pu->pu_nodename,
		    strlen(pu->pu_nodename) + 1,
		    EXT_STRING | EXD_PROC_HOSTNAME);
		break;
	case AC_PROC_TTY:
		(void) ea_attach_item(record, &pu->pu_major,
		    sizeof (uint32_t), EXT_UINT32 | EXD_PROC_TTY_MAJOR);
		(void) ea_attach_item(record, &pu->pu_minor,
		    sizeof (uint32_t), EXT_UINT32 | EXD_PROC_TTY_MINOR);
		break;
	case AC_PROC_MICROSTATE:
		(void) ea_attach_item(record, &pu->pu_majflt,
		    sizeof (uint64_t), EXT_UINT64 | EXD_PROC_FAULTS_MAJOR);
		(void) ea_attach_item(record, &pu->pu_minflt,
		    sizeof (uint64_t), EXT_UINT64 | EXD_PROC_FAULTS_MINOR);
		(void) ea_attach_item(record, &pu->pu_sndmsg,
		    sizeof (uint64_t), EXT_UINT64 | EXD_PROC_MESSAGES_SND);
		(void) ea_attach_item(record, &pu->pu_rcvmsg,
		    sizeof (uint64_t), EXT_UINT64 | EXD_PROC_MESSAGES_RCV);
		(void) ea_attach_item(record, &pu->pu_iblk,
		    sizeof (uint64_t), EXT_UINT64 | EXD_PROC_BLOCKS_IN);
		(void) ea_attach_item(record, &pu->pu_oblk,
		    sizeof (uint64_t), EXT_UINT64 | EXD_PROC_BLOCKS_OUT);
		(void) ea_attach_item(record, &pu->pu_ioch,
		    sizeof (uint64_t), EXT_UINT64 | EXD_PROC_CHARS_RDWR);
		(void) ea_attach_item(record, &pu->pu_vcsw,
		    sizeof (uint64_t), EXT_UINT64 | EXD_PROC_CONTEXT_VOL);
		(void) ea_attach_item(record, &pu->pu_icsw,
		    sizeof (uint64_t), EXT_UINT64 | EXD_PROC_CONTEXT_INV);
		(void) ea_attach_item(record, &pu->pu_nsig,
		    sizeof (uint64_t), EXT_UINT64 | EXD_PROC_SIGNALS);
		(void) ea_attach_item(record, &pu->pu_nswp,
		    sizeof (uint64_t), EXT_UINT64 | EXD_PROC_SWAPS);
		(void) ea_attach_item(record, &pu->pu_nscl,
		    sizeof (uint64_t), EXT_UINT64 | EXD_PROC_SYSCALLS);
		break;
	case AC_PROC_ANCPID:
		(void) ea_attach_item(record, &pu->pu_ancpid,
		    sizeof (uint32_t), EXT_UINT32 | EXD_PROC_ANCPID);
		break;
	case AC_PROC_WAIT_STATUS:
		(void) ea_attach_item(record, &pu->pu_wstat,
		    sizeof (uint32_t), EXT_UINT32 | EXD_PROC_WAIT_STATUS);
		break;
	case AC_PROC_ZONENAME:
		(void) ea_attach_item(record, pu->pu_zonename,
		    strlen(pu->pu_zonename) + 1,
		    EXT_STRING | EXD_PROC_ZONENAME);
		break;
	case AC_PROC_MEM:
		(void) ea_attach_item(record, &pu->pu_mem_rss_avg,
		    sizeof (uint64_t), EXT_UINT64 | EXD_PROC_MEM_RSS_AVG_K);
		(void) ea_attach_item(record, &pu->pu_mem_rss_max,
		    sizeof (uint64_t), EXT_UINT64 | EXD_PROC_MEM_RSS_MAX_K);
		break;
	default:
		attached = 0;
	}
	return (attached);
}
Exemplo n.º 5
0
static int
exacct_attach_task_item(task_t *tk, task_usage_t *tu, ea_object_t *record,
    int res)
{
	int attached = 1;

	switch (res) {
	case AC_TASK_TASKID:
		(void) ea_attach_item(record, &tk->tk_tkid,
		    sizeof (uint32_t), EXT_UINT32 | EXD_TASK_TASKID);
		break;
	case AC_TASK_PROJID:
		(void) ea_attach_item(record, &tk->tk_proj->kpj_id,
		    sizeof (uint32_t), EXT_UINT32 | EXD_TASK_PROJID);
		break;
	case AC_TASK_CPU: {
			timestruc_t ts;
			uint64_t ui;

			hrt2ts(tu->tu_stime, &ts);
			ui = ts.tv_sec;
			(void) ea_attach_item(record, &ui, sizeof (uint64_t),
			    EXT_UINT64 | EXD_TASK_CPU_SYS_SEC);
			ui = ts.tv_nsec;
			(void) ea_attach_item(record, &ui, sizeof (uint64_t),
			    EXT_UINT64 | EXD_TASK_CPU_SYS_NSEC);

			hrt2ts(tu->tu_utime, &ts);
			ui = ts.tv_sec;
			(void) ea_attach_item(record, &ui, sizeof (uint64_t),
			    EXT_UINT64 | EXD_TASK_CPU_USER_SEC);
			ui = ts.tv_nsec;
			(void) ea_attach_item(record, &ui, sizeof (uint64_t),
			    EXT_UINT64 | EXD_TASK_CPU_USER_NSEC);
		}
		break;
	case AC_TASK_TIME:
		(void) ea_attach_item(record, &tu->tu_startsec,
		    sizeof (uint64_t), EXT_UINT64 | EXD_TASK_START_SEC);
		(void) ea_attach_item(record, &tu->tu_startnsec,
		    sizeof (uint64_t), EXT_UINT64 | EXD_TASK_START_NSEC);
		(void) ea_attach_item(record, &tu->tu_finishsec,
		    sizeof (uint64_t), EXT_UINT64 | EXD_TASK_FINISH_SEC);
		(void) ea_attach_item(record, &tu->tu_finishnsec,
		    sizeof (uint64_t), EXT_UINT64 | EXD_TASK_FINISH_NSEC);
		break;
	case AC_TASK_HOSTNAME:
		(void) ea_attach_item(record, tk->tk_zone->zone_nodename,
		    strlen(tk->tk_zone->zone_nodename) + 1,
		    EXT_STRING | EXD_TASK_HOSTNAME);
			break;
	case AC_TASK_MICROSTATE:
		(void) ea_attach_item(record, &tu->tu_majflt,
		    sizeof (uint64_t), EXT_UINT64 | EXD_TASK_FAULTS_MAJOR);
		(void) ea_attach_item(record, &tu->tu_minflt,
		    sizeof (uint64_t), EXT_UINT64 | EXD_TASK_FAULTS_MINOR);
		(void) ea_attach_item(record, &tu->tu_sndmsg,
		    sizeof (uint64_t), EXT_UINT64 | EXD_TASK_MESSAGES_SND);
		(void) ea_attach_item(record, &tu->tu_rcvmsg,
		    sizeof (uint64_t), EXT_UINT64 | EXD_TASK_MESSAGES_RCV);
		(void) ea_attach_item(record, &tu->tu_iblk,
		    sizeof (uint64_t), EXT_UINT64 | EXD_TASK_BLOCKS_IN);
		(void) ea_attach_item(record, &tu->tu_oblk,
		    sizeof (uint64_t), EXT_UINT64 | EXD_TASK_BLOCKS_OUT);
		(void) ea_attach_item(record, &tu->tu_ioch,
		    sizeof (uint64_t), EXT_UINT64 | EXD_TASK_CHARS_RDWR);
		(void) ea_attach_item(record, &tu->tu_vcsw,
		    sizeof (uint64_t), EXT_UINT64 | EXD_TASK_CONTEXT_VOL);
		(void) ea_attach_item(record, &tu->tu_icsw,
		    sizeof (uint64_t), EXT_UINT64 | EXD_TASK_CONTEXT_INV);
		(void) ea_attach_item(record, &tu->tu_nsig,
		    sizeof (uint64_t), EXT_UINT64 | EXD_TASK_SIGNALS);
		(void) ea_attach_item(record, &tu->tu_nswp,
		    sizeof (uint64_t), EXT_UINT64 | EXD_TASK_SWAPS);
		(void) ea_attach_item(record, &tu->tu_nscl,
		    sizeof (uint64_t), EXT_UINT64 | EXD_TASK_SYSCALLS);
		break;
	case AC_TASK_ANCTASKID:
		(void) ea_attach_item(record, &tu->tu_anctaskid,
		    sizeof (uint32_t), EXT_UINT32 | EXD_TASK_ANCTASKID);
		break;
	case AC_TASK_ZONENAME:
		(void) ea_attach_item(record, tk->tk_zone->zone_name,
		    strlen(tk->tk_zone->zone_name) + 1,
		    EXT_STRING | EXD_TASK_ZONENAME);
		break;
	default:
		attached = 0;
	}
	return (attached);
}
Exemplo n.º 6
0
static int
exacct_attach_flow_item(flow_usage_t *fu, ea_object_t *record, int res)
{
	int attached = 1;

	switch (res) {
	case AC_FLOW_SADDR:
		if (fu->fu_isv4) {
			(void) ea_attach_item(record, &fu->fu_saddr[3],
			    sizeof (uint32_t), EXT_UINT32 | EXD_FLOW_V4SADDR);
		} else {
			(void) ea_attach_item(record, &fu->fu_saddr,
			    sizeof (fu->fu_saddr), EXT_RAW |
			    EXD_FLOW_V6SADDR);
		}
		break;
	case AC_FLOW_DADDR:
		if (fu->fu_isv4) {
			(void) ea_attach_item(record, &fu->fu_daddr[3],
			    sizeof (uint32_t), EXT_UINT32 | EXD_FLOW_V4DADDR);
		} else {
			(void) ea_attach_item(record, &fu->fu_daddr,
			    sizeof (fu->fu_daddr), EXT_RAW |
			    EXD_FLOW_V6DADDR);
		}
		break;
	case AC_FLOW_SPORT:
		(void) ea_attach_item(record, &fu->fu_sport,
		    sizeof (uint16_t), EXT_UINT16 | EXD_FLOW_SPORT);
		break;
	case AC_FLOW_DPORT:
		(void) ea_attach_item(record, &fu->fu_dport,
		    sizeof (uint16_t), EXT_UINT16 | EXD_FLOW_DPORT);
		break;
	case AC_FLOW_PROTOCOL:
		(void) ea_attach_item(record, &fu->fu_protocol,
		    sizeof (uint8_t), EXT_UINT8 | EXD_FLOW_PROTOCOL);
		break;
	case AC_FLOW_DSFIELD:
		(void) ea_attach_item(record, &fu->fu_dsfield,
		    sizeof (uint8_t), EXT_UINT8 | EXD_FLOW_DSFIELD);
		break;
	case AC_FLOW_CTIME:
		(void) ea_attach_item(record, &fu->fu_ctime,
		    sizeof (uint64_t), EXT_UINT64 | EXD_FLOW_CTIME);
		break;
	case AC_FLOW_LSEEN:
		(void) ea_attach_item(record, &fu->fu_lseen,
		    sizeof (uint64_t), EXT_UINT64 | EXD_FLOW_LSEEN);
		break;
	case AC_FLOW_NBYTES:
		(void) ea_attach_item(record, &fu->fu_nbytes,
		    sizeof (uint64_t), EXT_UINT32 | EXD_FLOW_NBYTES);
		break;
	case AC_FLOW_NPKTS:
		(void) ea_attach_item(record, &fu->fu_npackets,
		    sizeof (uint64_t), EXT_UINT32 | EXD_FLOW_NPKTS);
		break;
	case AC_FLOW_PROJID:
		if (fu->fu_projid >= 0) {
			(void) ea_attach_item(record, &fu->fu_projid,
			    sizeof (uint32_t), EXT_UINT32 | EXD_FLOW_PROJID);
		}
		break;
	case AC_FLOW_UID:
		if (fu->fu_userid >= 0) {
			(void) ea_attach_item(record, &fu->fu_userid,
			    sizeof (uint32_t), EXT_UINT32 | EXD_FLOW_UID);
		}
		break;
	case AC_FLOW_ANAME:
		(void) ea_attach_item(record, fu->fu_aname,
		    strlen(fu->fu_aname) + 1, EXT_STRING | EXD_FLOW_ANAME);
		break;
	default:
		attached = 0;
	}
	return (attached);
}
Exemplo n.º 7
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);
}