Esempio n. 1
0
/*
 * 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);
}
Esempio n. 2
0
/*
 * 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);
}