blob: 947d973775e43db8b840322d05a14b27aa95767d [file] [log] [blame] [raw]
/*
* Copyright (C) 2000-2007 SWsoft. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <stdlib.h>
#include <unistd.h>
#include <linux/vzcalluser.h>
#include <linux/fairsched.h>
#include <errno.h>
#include "types.h"
#include "cpu.h"
#include "env.h"
#include "vzerror.h"
#include "logger.h"
#include "vzsyscalls.h"
static inline int fairsched_chwt(unsigned int id, unsigned wght)
{
int ret;
ret = syscall(__NR_fairsched_chwt, id, wght);
if (ret && errno == ENOSYS)
ret = 0;
return ret;
}
static inline int fairsched_rate(unsigned int id, int op, unsigned rate)
{
int ret;
ret = syscall(__NR_fairsched_rate, id, op, rate);
if (ret && errno == ENOSYS)
ret = 0;
return ret;
}
static inline int fairsched_vcpus(unsigned int id, unsigned vcpus)
{
int ret;
ret = syscall(__NR_fairsched_vcpus, id, vcpus);
if (ret && errno == ENOSYS)
ret = 0;
return ret;
}
static int set_cpulimit(envid_t veid, unsigned int cpulimit)
{
unsigned cpulim1024 = (float)cpulimit * 1024 / 100;
int op = cpulim1024 ? FAIRSCHED_SET_RATE : FAIRSCHED_DROP_RATE;
logger(0, 0, "Setting CPU limit: %d", cpulimit);
if (fairsched_rate(veid, op, cpulim1024) < 0) {
logger(-1, errno, "fairsched_rate");
return VZ_SETFSHD_ERROR;
}
return 0;
}
static int set_cpuweight(envid_t veid, unsigned int cpuweight)
{
if (fairsched_chwt(veid, cpuweight)) {
logger(-1, errno, "fairsched_chwt");
return VZ_SETFSHD_ERROR;
}
return 0;
}
static int set_cpuunits(envid_t veid, unsigned int cpuunits)
{
int cpuweight, ret;
if (cpuunits < MINCPUUNITS || cpuunits > MAXCPUUNITS) {
logger(-1, 0, "Invalid value for cpuunits: %d"
" allowed range is %d-%d",
cpuunits, MINCPUUNITS, MAXCPUUNITS);
return VZ_SETFSHD_ERROR;
}
cpuweight = MAXCPUUNITS / cpuunits;
logger(0, 0, "Setting CPU units: %d", cpuunits);
ret = set_cpuweight(veid, cpuweight);
return ret;
}
/** Change number of CPUs available in the running VE.
*
* @param veid VE id
* @param vcpu number of cpu
*/
int env_set_vcpus(envid_t veid, unsigned int vcpus)
{
int ret;
logger(0, 0, "Setting CPUs: %d", vcpus);
ret = fairsched_vcpus(veid, vcpus);
if (ret)
logger(-1, errno, "Unable to set cpus");
return ret;
}
/** Apply cpu parameters on Host system.
*
* @param cpu cpu parameters.
* @return 0 on success.
*/
int hn_set_cpu(cpu_param *cpu)
{
if (cpu->units == NULL)
return 0;
return set_cpuunits(2147483647, *cpu->units);
}
/** Apply cpu parameters on running VE.
*
* @param h VE handler.
* @param veid VE id.
* @param cpu cpu parameters.
* @return 0 on success.
*/
int vps_set_cpu(vps_handler *h, envid_t veid, cpu_param *cpu)
{
int ret = 0;
if (cpu->limit == NULL &&
cpu->units == NULL &&
cpu->weight == NULL &&
cpu->vcpus == NULL)
{
return 0;
}
if (!vps_is_run(h, veid)) {
logger(-1, 0, "Unable to apply CPU parameters: "
"VE is not running");
return VZ_VE_NOT_RUNNING;
}
if (cpu->limit != NULL) {
ret = set_cpulimit(veid, *cpu->limit);
}
if (cpu->units != NULL) {
ret = set_cpuunits(veid, *cpu->units);
} else if (cpu->weight != NULL)
ret = set_cpuweight(veid, *cpu->weight);
if (cpu->vcpus != NULL) {
ret = env_set_vcpus(veid, *cpu->vcpus);
}
return ret;
}