static int putacct(idtype_t idtype, id_t id, void *buf, size_t bufsize, int flags) { int error; taskid_t tkid; proc_t *p; task_t *tk; void *kbuf; struct exacct_globals *acg; if (bufsize == 0 || bufsize > EXACCT_MAX_BUFSIZE) return (set_errno(EINVAL)); kbuf = kmem_alloc(bufsize, KM_SLEEP); if (copyin(buf, kbuf, bufsize) != 0) { error = EFAULT; goto out; } acg = zone_getspecific(exacct_zone_key, curproc->p_zone); switch (idtype) { case P_PID: mutex_enter(&pidlock); if ((p = prfind(id)) == NULL) { mutex_exit(&pidlock); error = ESRCH; } else { zone_t *zone = p->p_zone; tkid = p->p_task->tk_tkid; zone_hold(zone); mutex_exit(&pidlock); error = exacct_tag_proc(&acg->ac_proc, id, tkid, kbuf, bufsize, flags, zone->zone_nodename); zone_rele(zone); } break; case P_TASKID: if ((tk = task_hold_by_id(id)) != NULL) { error = exacct_tag_task(&acg->ac_task, tk, kbuf, bufsize, flags); task_rele(tk); } else { error = ESRCH; } break; default: error = EINVAL; break; } out: kmem_free(kbuf, bufsize); return (error == 0 ? error : set_errno(error)); }
static int wracct_task(ac_info_t *ac_task, taskid_t tkid, int flag, size_t *sizep) { task_t *tk; int error; 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); if ((tk = task_hold_by_id(tkid)) == NULL) return (ESRCH); error = exacct_assemble_task_usage(ac_task, tk, exacct_commit_callback, NULL, 0, sizep, flag); task_rele(tk); return (error); }
static int getacct_task(ac_info_t *ac_task, taskid_t tkid, void *buf, size_t bufsize, size_t *sizep) { task_t *tk; int error; mutex_enter(&ac_task->ac_lock); if (ac_task->ac_state == AC_OFF) { mutex_exit(&ac_task->ac_lock); return (ENOTACTIVE); } mutex_exit(&ac_task->ac_lock); if ((tk = task_hold_by_id(tkid)) == NULL) return (ESRCH); error = exacct_assemble_task_usage(ac_task, tk, getacct_callback, buf, bufsize, sizep, EW_PARTIAL); task_rele(tk); return (error); }
static int pset_bind(psetid_t pset, idtype_t idtype, id_t id, psetid_t *opset) { kthread_t *tp; proc_t *pp; task_t *tk; kproject_t *kpj; contract_t *ct; zone_t *zptr; psetid_t oldpset; int error = 0; void *projbuf, *zonebuf; pool_lock(); if ((pset != PS_QUERY) && (pset != PS_SOFT) && (pset != PS_HARD) && (pset != PS_QUERY_TYPE)) { /* * Check if the set actually exists before checking * permissions. This is the historical error * precedence. Note that if pset was PS_MYID, the * cpupart_get_cpus call will change it to the * processor set id of the caller (or PS_NONE if the * caller is not bound to a processor set). */ if (pool_state == POOL_ENABLED) { pool_unlock(); return (set_errno(ENOTSUP)); } if (cpupart_get_cpus(&pset, NULL, NULL) != 0) { pool_unlock(); return (set_errno(EINVAL)); } else if (pset != PS_NONE && secpolicy_pset(CRED()) != 0) { pool_unlock(); return (set_errno(EPERM)); } } /* * Pre-allocate enough buffers for FSS for all active projects * and for all active zones on the system. Unused buffers will * be freed later by fss_freebuf(). */ mutex_enter(&cpu_lock); projbuf = fss_allocbuf(FSS_NPROJ_BUF, FSS_ALLOC_PROJ); zonebuf = fss_allocbuf(FSS_NPROJ_BUF, FSS_ALLOC_ZONE); switch (idtype) { case P_LWPID: pp = curproc; mutex_enter(&pidlock); mutex_enter(&pp->p_lock); if (id == P_MYID) { tp = curthread; } else { if ((tp = idtot(pp, id)) == NULL) { mutex_exit(&pp->p_lock); mutex_exit(&pidlock); error = ESRCH; break; } } error = pset_bind_thread(tp, pset, &oldpset, projbuf, zonebuf); mutex_exit(&pp->p_lock); mutex_exit(&pidlock); break; case P_PID: mutex_enter(&pidlock); if (id == P_MYID) { pp = curproc; } else if ((pp = prfind(id)) == NULL) { mutex_exit(&pidlock); error = ESRCH; break; } error = pset_bind_process(pp, pset, &oldpset, projbuf, zonebuf); mutex_exit(&pidlock); break; case P_TASKID: mutex_enter(&pidlock); if (id == P_MYID) id = curproc->p_task->tk_tkid; if ((tk = task_hold_by_id(id)) == NULL) { mutex_exit(&pidlock); error = ESRCH; break; } error = pset_bind_task(tk, pset, &oldpset, projbuf, zonebuf); mutex_exit(&pidlock); task_rele(tk); break; case P_PROJID: pp = curproc; if (id == P_MYID) id = curprojid(); if ((kpj = project_hold_by_id(id, pp->p_zone, PROJECT_HOLD_FIND)) == NULL) { error = ESRCH; break; } mutex_enter(&pidlock); error = pset_bind_project(kpj, pset, &oldpset, projbuf, zonebuf); mutex_exit(&pidlock); project_rele(kpj); break; case P_ZONEID: if (id == P_MYID) id = getzoneid(); if ((zptr = zone_find_by_id(id)) == NULL) { error = ESRCH; break; } mutex_enter(&pidlock); error = pset_bind_zone(zptr, pset, &oldpset, projbuf, zonebuf); mutex_exit(&pidlock); zone_rele(zptr); break; case P_CTID: if (id == P_MYID) id = PRCTID(curproc); if ((ct = contract_type_ptr(process_type, id, curproc->p_zone->zone_uniqid)) == NULL) { error = ESRCH; break; } mutex_enter(&pidlock); error = pset_bind_contract(ct->ct_data, pset, &oldpset, projbuf, zonebuf); mutex_exit(&pidlock); contract_rele(ct); break; case P_PSETID: if (id == P_MYID || pset != PS_NONE || !INGLOBALZONE(curproc)) { error = EINVAL; break; } error = pset_unbind(id, projbuf, zonebuf, idtype); break; case P_ALL: if (id == P_MYID || pset != PS_NONE || !INGLOBALZONE(curproc)) { error = EINVAL; break; } error = pset_unbind(PS_NONE, projbuf, zonebuf, idtype); break; default: error = EINVAL; break; } fss_freebuf(projbuf, FSS_ALLOC_PROJ); fss_freebuf(zonebuf, FSS_ALLOC_ZONE); mutex_exit(&cpu_lock); pool_unlock(); if (error != 0) return (set_errno(error)); if (opset != NULL) { if (copyout(&oldpset, opset, sizeof (psetid_t)) != 0) return (set_errno(EFAULT)); } return (0); }