blob: f4ee4f398483ba81132985f22ab911c4783515ab [file] [log] [blame] [raw]
/*
* Copyright (C) 2000-2009, Parallels, Inc. 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 <errno.h>
#include <sys/ioctl.h>
#include <linux/vzcalluser.h>
#include <string.h>
#include <limits.h>
#include "vzerror.h"
#include "res.h"
#include "logger.h"
#include "meminfo.h"
#include "util.h"
#include "ub.h"
static struct {
char *mode_nm;
int mode_id;
} mode_tbl_[] = {
{"none", VE_MEMINFO_NONE},
{"pages", VE_MEMINFO_PAGES},
{"privvmpages", VE_MEMINFO_PRIVVMPAGES},
};
int vps_meminfo_set(vps_handler *h, envid_t veid, meminfo_param *gparam,
vps_param *vps_p, int state)
{
int ret;
unsigned long *privvmpages = vps_p->res.ub.privvmpages;
struct vzctl_ve_meminfo meminfo;
meminfo_param *param = gparam;
meminfo_param default_param = {
VE_MEMINFO_PRIVVMPAGES, 1
};
if (!is_vz_kernel(h))
return 0;
if (is_vswap_config(&vps_p->res.ub))
return 0;
if (state != STATE_STARTING) {
/* update meminfo on --privvmpages, --meminfo */
if (param->mode < 0 && privvmpages == NULL)
return 0;
if (vps_p->g_param != NULL) {
if (privvmpages == NULL)
/* use privvmpages from VE.conf on --meminfo */
privvmpages = vps_p->g_param->res.ub.privvmpages;
if (param->mode < 0) {
/* use meminfo from VE.conf on --privvmpages */
param = &vps_p->g_param->res.meminfo;
if (param->mode < 0)
param = &default_param;
if (param->mode != VE_MEMINFO_PRIVVMPAGES)
return 0;
}
}
}
if (param->mode < 0)
param = &default_param;
meminfo.veid = veid;
switch (param->mode) {
case VE_MEMINFO_NONE:
meminfo.val = 0;
break;
case VE_MEMINFO_PAGES:
meminfo.val = param->val;
break;
case VE_MEMINFO_PRIVVMPAGES:
if (privvmpages == NULL) {
logger(0, 0, "Warning: privvmpages not set, "
"skipping meminfo configuration");
return 0;
}
meminfo.val = (((ULONG_MAX - 1) / param->val + 1)
< privvmpages[0]) ?
ULONG_MAX : privvmpages[0] * param->val;
break;
default:
logger(0, 0, "Warning: unrecognized mode"
" to set meminfo parameter");
return 0;
}
logger(1, 0, "Configuring meminfo: %lu", meminfo.val);
ret = ioctl(h->vzfd, VZCTL_VE_MEMINFO, &meminfo);
if (ret < 0) {
if (errno == ENOTTY) {
logger(0, 0, "Warning: meminfo feature is not supported"
" by kernel, skipped meminfo configure");
} else {
logger(-1, errno, "Unable to set meminfo");
return VZ_SET_MEMINFO_ERROR;
}
}
return 0;
}
int get_meminfo_mode(char *name)
{
unsigned int i;
for (i = 0; i < ARRAY_SIZE(mode_tbl_); i++)
if (!strcmp(mode_tbl_[i].mode_nm, name))
return mode_tbl_[i].mode_id;
return -1;
}
const char *get_meminfo_mode_nm(int id)
{
unsigned int i;
for (i = 0; i < ARRAY_SIZE(mode_tbl_); i++)
if (mode_tbl_[i].mode_id == id)
return mode_tbl_[i].mode_nm;
return NULL;
}