/* * long tasksys_projlist(void *buf, size_t bufsz) * * Overview * Return a buffer containing the project IDs of all currently active projects * in the current zone. * * Return values * The minimum size of a buffer sufficiently large to contain all of the * active project IDs, or -1 if an error occurs during copyout. */ static long tasksys_projlist(void *buf, size_t bufsz) { long ret = 0; projlist_walk_t pw; void *kbuf; if (buf == NULL || bufsz == 0) return (project_walk_all(getzoneid(), tasksys_projlist_cb, NULL)); if (bufsz > MAX_PROJLIST_BUFSIZE) return (set_errno(ENOMEM)); kbuf = pw.pw_buf = kmem_zalloc(bufsz, KM_SLEEP); pw.pw_bufsz = bufsz; ret = project_walk_all(getzoneid(), tasksys_projlist_cb, &pw); if (copyout(kbuf, buf, bufsz) == -1) ret = set_errno(EFAULT); kmem_free(kbuf, bufsz); return (ret); }
/* * Set zone cap to cap_val * If cap_val is equal to NOCAP, disable zone cap. * * If this is the first time a cap is set on a zone, allocate cpucap structure * without holding caps_lock to avoid KM_SLEEP allocation with caps_lock held. */ int cpucaps_zone_set(zone_t *zone, rctl_qty_t cap_val) { cpucap_t *cap = NULL; hrtime_t value; if (cap_val == 0) return (EINVAL); ASSERT(cap_val <= MAXCAP); if (cap_val > MAXCAP) cap_val = MAXCAP; /* * Nothing to do if trying to disable a cap on a zone when caps are off * or a zone which does not have a cap yet. */ if ((CPUCAPS_OFF() || !ZONE_IS_CAPPED(zone)) && (cap_val == NOCAP)) return (0); if (zone->zone_cpucap == NULL) cap = cap_alloc(); mutex_enter(&caps_lock); if (cpucaps_busy) { mutex_exit(&caps_lock); return (EBUSY); } /* * Double-check whether zone->zone_cpucap is NULL, now with caps_lock * held. If it is still NULL, assign a newly allocated cpucap to it. */ if (zone->zone_cpucap == NULL) { zone->zone_cpucap = cap; } else if (cap != NULL) { cap_free(cap); } cap = zone->zone_cpucap; value = cap_val * cap_tick_cost; if (value < 0) value = MAX_USAGE; /* Nothing to do if the value is staying the same */ if (value == cap->cap_value) { mutex_exit(&caps_lock); return (0); } /* * Clear cap statistics since the cap value itself changes. */ cap->cap_above = cap->cap_below = 0; if (cap_val == NOCAP) { if (CAP_ENABLED(cap)) { /* * Remove cap for the zone */ cap_zone_disable(zone); cpucaps_busy = B_TRUE; mutex_exit(&caps_lock); /* * Disable caps for all project belonging to this zone * unless they have their own cap. */ (void) project_walk_all(zone->zone_id, cap_project_zone_modify_walker, cap); mutex_enter(&caps_lock); cpucaps_busy = B_FALSE; } } else if (CAP_DISABLED(cap)) { /* * Set a cap on a zone which previously was not capped. */ cap_zone_enable(zone, value); cpucaps_busy = B_TRUE; mutex_exit(&caps_lock); /* * Enable cap for all projects belonging to this zone. */ (void) project_walk_all(zone->zone_id, cap_project_zone_modify_walker, cap); mutex_enter(&caps_lock); cpucaps_busy = B_FALSE; } else { /* * No state transitions, just change the value */ cap->cap_value = cap->cap_chk_value = value; } ASSERT(MUTEX_HELD(&caps_lock)); ASSERT(!cpucaps_busy); mutex_exit(&caps_lock); return (0); }