blob: 1562f1450e05eb5d609c0596ee8e63a024c58a9a [file] [log] [blame] [raw]
/*
* Copyright (C) 2000-2008, 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 <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <linux/vzcalluser.h>
#include "vzerror.h"
#include "env.h"
#include "dev.h"
#include "logger.h"
#include "res.h"
#include "exec.h"
#include "cap.h"
#include "dist.h"
#include "util.h"
#include "quota.h"
#include "vps_configure.h"
#include "io.h"
#include "image.h"
#include "script.h"
static int fill_2quota_param(struct setup_env_quota_param *p,
const char *ve_private, const char *ve_root)
{
struct stat st;
if (!ve_private_is_ploop(ve_private)) {
/* simfs case */
if (stat(ve_root, &st)) {
logger(-1, errno, "%s: Can't stat %s",
__func__, ve_root);
return VZ_ERROR_SET_USER_QUOTA;
}
p->dev_name[0] = 0;
p->dev = st.st_dev;
return 0;
}
/* ploop case */
if (vzctl_get_ploop_dev(ve_root, p->dev_name, sizeof(p->dev_name))) {
logger(-1, 0, "Unable to find ploop device for %s", ve_root);
return VZ_ERROR_SET_USER_QUOTA;
}
if (stat(p->dev_name, &st)) {
logger(-1, errno, "%s: Can't stat %s", __func__, p->dev_name);
return VZ_ERROR_SET_USER_QUOTA;
}
p->dev = st.st_rdev;
return 0;
}
/** Give Container permissions to do quotactl operations on its root.
*
*/
static int vps_2quota_perm(vps_handler *h, int veid, dev_t device)
{
dev_res dev = { };
dev.dev = device;
dev.type = S_IFBLK | VE_USE_MINOR;
dev.mask = S_IXGRP;
return set_devperm(h, veid, &dev);
}
int vps_setup_res(vps_handler *h, envid_t veid, dist_actions *actions,
fs_param *fs, vps_param *param, int vps_state, skipFlags skip,
struct mod_action *action)
{
int ret;
vps_res *res = &param->res;
if (skip & SKIP_SETUP)
return 0;
if (vps_state != STATE_STARTING) {
if ((ret = vps_set_ublimit(h, veid, &res->ub)))
return ret;
}
if ((ret = vps_net_ctl(h, veid, DEL, &param->del_res.net, actions,
fs->root, vps_state, skip)))
{
return ret;
}
if ((ret = vps_net_ctl(h, veid, ADD, &res->net, actions, fs->root,
vps_state, skip)))
{
return ret;
}
if ((ret = vps_set_netdev(h, veid, &res->ub,
&res->net, &param->del_res.net)))
return ret;
if ((ret = vps_set_cpu(h, veid, &res->cpu)))
return ret;
if ((ret = vps_set_devperm(h, veid, fs->root, &res->dev)))
return ret;
if ((ret = vps_set_pci(h, veid, ADD, fs->root, &res->pci)))
return ret;
if ((ret = vps_set_pci(h, veid, DEL, fs->root, &param->del_res.pci)))
return ret;
if ((ret = vps_set_fs(fs, &res->fs)))
return ret;
if ((ret = vps_meminfo_set(h, veid, &res->meminfo, param, vps_state)))
return ret;
if ((ret = ve_ioprio_set(h, veid, &res->io)))
return ret;
/* Setup 2nd-level quota */
if (is_2nd_level_quota_on(&res->dq)) {
struct setup_env_quota_param qp;
if ((ret = fill_2quota_param(&qp, fs->private, fs->root)))
return ret;
if ((ret = vps_2quota_perm(h, veid, qp.dev)))
return ret;
if ((ret = vps_execFn(h, veid, fs->root,
(execFn)setup_env_quota, &qp,
VE_SKIPLOCK)))
return ret;
}
if (!(skip & SKIP_CONFIGURE))
vps_configure(h, veid, actions, fs, param, vps_state);
/* Setup quota limits after configure steps */
if (!ve_private_is_ploop(fs->private)) {
if ((ret = vps_set_quota(veid, &res->dq)))
return ret;
}
if ((ret = vps_setup_veth(h, veid, actions, fs->root, &res->veth,
&param->del_res.veth, vps_state, skip)))
{
return ret;
}
ret = mod_setup(h, veid, vps_state, skip, action, param);
return ret;
}