Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Add the ability to move PCI devices in CT

Signed-off-by: Andrey Vagin <avagin@openvz.org>
  • Loading branch information...
commit e8a76d31a58a4b30b3b157c92ff15887e35197d4 1 parent 115195e
@avagin avagin authored kolyshkin committed
View
8 include/dev.h
@@ -41,6 +41,10 @@ typedef struct {
list_head_t dev;
} dev_param;
+typedef struct {
+ list_head_t list;
+} pci_param;
+
/** Allow/disallow access to devices on host system from CT.
*
* @param h CT handler.
@@ -55,4 +59,8 @@ int set_devperm(vps_handler *h, envid_t veid, dev_res *dev);
int add_dev_param(dev_param *dev, dev_res *res);
void free_dev_param(dev_param *dev);
+int vps_set_pci(vps_handler *h, envid_t veid, int op, const char *root,
+ pci_param *pci);
+void free_pci_param(pci_param *dev);
+
#endif
View
1  include/res.h
@@ -88,6 +88,7 @@ typedef struct vps_res {
misc_param misc;
name_param name;
io_param io;
+ pci_param pci;
} vps_res;
enum {
View
2  include/vzctl_param.h
@@ -132,6 +132,8 @@
#define PARAM_DESCRIPTION 362
#define PARAM_SWAPPAGES 363
#define PARAM_BOOTORDER 364
+#define PARAM_PCI_ADD 365
+#define PARAM_PCI_DEL 366
#define PARAM_LINE "e:p:f:t:i:l:k:a:b:n:x:h"
#endif
View
14 man/vzctl.8
@@ -498,6 +498,20 @@ Give the container an access to a \fBb\fRlock or \fBc\fRharacter device
designated by its \fImajor\fR and \fIminor\fR numbers. Device file have to be created manually.
.TP
+\fBPCI device management\fR
+.TP
+\fB--pci_add\fR [\fIdomain\fB:\fR]\fIbus\fB:\fIslot\fB.\fIfunc\fR
+Give the container an access to a specified PCI device. All numbers are
+hexadecimal (as printed by \fBlspci\fR(8) in the first column).
+.TP
+\fB--pci_del\fR [\fIdomain\fB:\fR]\fIbus\fB:\fIslot\fB.\fIfunc\fR
+Delete a PCI device from the container.
+.TP
+Note that \fBvps-pci\fR configuration script is executed by \fBvzctl\fR
+then configuring PCI devices. The script is usually located at
+\fB/usr/lib[64]/vzctl/scripts/\fR.
+
+.TP
\fBFeatures management\fR
.TP
\fB--features\fR \fIname\fB:on\fR|\fBoff\fR
View
80 src/lib/config.c
@@ -103,6 +103,8 @@ static vps_config config[] = {
/* Devices */
{"DEVICES", NULL, PARAM_DEVICES},
{"DEVNODES", NULL, PARAM_DEVNODES},
+{"PCI", NULL, PARAM_PCI_ADD},
+{"", NULL, PARAM_PCI_DEL},
/* fs param */
{"VE_ROOT", NULL, PARAM_ROOT},
{"VE_PRIVATE", NULL, PARAM_PRIVATE},
@@ -1120,6 +1122,65 @@ static int store_devnodes(vps_param *old_p, vps_param *vps_p, vps_config *conf,
return 0;
}
+static int parse_pci(vps_param *vps_p, char *val, int id)
+{
+ int domain;
+ unsigned int bus;
+ unsigned int slot;
+ unsigned int func;
+ char *token;
+
+ int ret;
+ pci_param *pci;
+ char buf[64];
+
+ if (id == PARAM_PCI_ADD)
+ pci = &vps_p->res.pci;
+ else if (id == PARAM_PCI_DEL)
+ pci = &vps_p->del_res.pci;
+ else
+ return 0;
+
+ for_each_strtok(token, val, " ") {
+ ret = sscanf(token, "%x:%x:%x.%d", &domain, &bus, &slot, &func);
+ if (ret != 4) {
+ domain = 0;
+ ret = sscanf(token, "%x:%x.%d", &bus, &slot, &func);
+ if (ret != 3)
+ return ERR_INVAL;
+ }
+ snprintf(buf, sizeof(buf), "%04x:%02x:%02x.%d",
+ domain, bus, slot, func);
+ if (!find_str(&pci->list, buf))
+ add_str_param(&pci->list, buf);
+ }
+
+ return 0;
+}
+
+static int store_pci(vps_param *old_p, vps_param *vps_p, vps_config *conf,
+ list_head_t *conf_h)
+{
+ list_head_t pci;
+ int ret;
+
+ if (conf->id != PARAM_PCI_ADD)
+ return 0;
+
+ if (list_empty(&vps_p->res.pci.list) &&
+ list_empty(&vps_p->del_res.pci.list))
+ return 0;
+
+ list_head_init(&pci);
+ merge_str_list(0, &old_p->res.pci.list, &vps_p->res.pci.list,
+ &vps_p->del_res.pci.list, &pci);
+
+ ret = conf_store_strlist(conf_h, conf->name, &pci, 1);
+ free_str_param(&pci);
+
+ return ret;
+}
+
static int store_misc(vps_param *old_p, vps_param *vps_p, vps_config *conf,
list_head_t *conf_h)
{
@@ -1838,6 +1899,10 @@ static int parse(envid_t veid, vps_param *vps_p, char *val, int id)
case PARAM_DEVICES:
ret = parse_dev(vps_p, val);
break;
+ case PARAM_PCI_ADD:
+ case PARAM_PCI_DEL:
+ ret = parse_pci(vps_p, val, id);
+ break;
case PARAM_DEVNODES:
ret = parse_devnodes(vps_p, val);
break;
@@ -1951,6 +2016,7 @@ static int store(vps_param *old_p, vps_param *vps_p, list_head_t *conf_h)
store_dq(old_p, vps_p, conf, conf_h);
store_dev(old_p, vps_p, conf, conf_h);
store_devnodes(old_p, vps_p, conf, conf_h);
+ store_pci(old_p, vps_p, conf, conf_h);
store_misc(old_p, vps_p, conf, conf_h);
store_cpu(old_p, vps_p, conf, conf_h);
store_meminfo(old_p, vps_p, conf, conf_h);
@@ -2224,6 +2290,7 @@ vps_param *init_vps_param()
list_head_init(&param->res.misc.nameserver);
list_head_init(&param->res.misc.searchdomain);
list_head_init(&param->res.dev.dev);
+ list_head_init(&param->res.pci.list);
list_head_init(&param->res.veth.dev);
list_head_init(&param->del_res.net.ip);
@@ -2233,6 +2300,7 @@ vps_param *init_vps_param()
list_head_init(&param->del_res.misc.nameserver);
list_head_init(&param->del_res.misc.searchdomain);
list_head_init(&param->del_res.dev.dev);
+ list_head_init(&param->del_res.pci.list);
list_head_init(&param->del_res.veth.dev);
param->res.meminfo.mode = -1;
param->res.io.ioprio = -1;
@@ -2380,6 +2448,11 @@ static void free_dev(dev_param *dev)
free_dev_param(dev);
}
+static void free_pci(pci_param *pci)
+{
+ free_str_param(&pci->list);
+}
+
static void free_cpu(cpu_param *cpu)
{
FREE_P(cpu->units)
@@ -2416,6 +2489,7 @@ static void free_vps_res(vps_res *res)
free_net(&res->net);
free_misc(&res->misc);
free_dev(&res->dev);
+ free_pci(&res->pci);
free_cpu(&res->cpu);
free_dq(&res->dq);
free_cpt(&res->cpt);
@@ -2550,6 +2624,11 @@ static void merge_dev(dev_param *dst, dev_param *src)
}
}
+static void merge_pci(pci_param *dst, pci_param *src)
+{
+ MERGE_LIST(list)
+}
+
static void merge_cap(cap_param *dst, cap_param *src)
{
MERGE_INT(on)
@@ -2608,6 +2687,7 @@ static int merge_res(vps_res *dst, vps_res *src)
merge_cap(&dst->cap, &src->cap);
merge_dq(&dst->dq, &src->dq);
merge_dev(&dst->dev, &src->dev);
+ merge_pci(&dst->pci, &src->pci);
merge_env(&dst->env, &src->env);
merge_cpt(&dst->cpt, &src->cpt);
merge_meminfo(&dst->meminfo, &src->meminfo);
View
57 src/lib/dev.c
@@ -33,6 +33,7 @@
#include "dev.h"
#include "env.h"
#include "logger.h"
+#include "script.h"
static int dev_create(const char *root, dev_res *dev)
{
@@ -106,6 +107,37 @@ int set_devperm(vps_handler *h, envid_t veid, dev_res *dev)
return ret;
}
+struct vzctl_ve_configure_pci {
+ struct vzctl_ve_configure conf;
+ struct vzctl_ve_pci_dev dev;
+};
+
+static int set_pci(vps_handler *h, envid_t veid, int op, char *dev_id)
+{
+ int ret;
+ struct vzctl_ve_configure_pci conf_pci;
+ struct vzctl_ve_configure *conf = &conf_pci.conf;
+ struct vzctl_ve_pci_dev *dev = &conf_pci.dev;
+
+ sscanf(dev_id, "%x:%x:%x.%d", &dev->domain, &dev->bus,
+ &dev->slot, &dev->func);
+ conf->veid = veid;
+ if (op == ADD)
+ conf->key = VE_CONFIGURE_ADD_PCI_DEVICE;
+ else
+ conf->key = VE_CONFIGURE_DEL_PCI_DEVICE;
+ conf->val = 0;
+ conf->size = sizeof(struct vzctl_ve_pci_dev);
+
+ if ((ret = ioctl(h->vzfd, VZCTL_VE_CONFIGURE, &conf_pci))) {
+ if (errno == EEXIST)
+ return 0;
+ logger(-1, errno, "Unable to move pci device %s", dev_id);
+ }
+
+ return ret;
+}
+
/** Allow/disallow access to devices on host system from CT.
*
* @param h CT handler.
@@ -198,3 +230,28 @@ int run_pci_script(envid_t veid, int op, list_head_t *pci_h)
return ret;
}
+
+int vps_set_pci(vps_handler *h, envid_t veid, int op, const char *root,
+ pci_param *pci)
+{
+ int ret = 0;
+ list_head_t *pci_h = &pci->list;
+ str_param *res;
+
+ if (list_empty(pci_h))
+ return 0;
+
+ if (!vps_is_run(h, veid)) {
+ logger(-1, 0, "Unable to configure PCI devices: "
+ "container is not running");
+ return VZ_VE_NOT_RUNNING;
+ }
+ logger(0, 0, "Setting PCI devices");
+
+ list_for_each(res, pci_h, list)
+ if ((ret = set_pci(h, veid, op, res->val)))
+ break;
+ if (!ret)
+ ret = run_pci_script(veid, op, pci_h);
+ return ret;
+}
View
4 src/lib/res.c
@@ -81,6 +81,10 @@ int vps_setup_res(vps_handler *h, envid_t veid, dist_actions *actions,
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)))
View
2  src/vzctl-actions.c
@@ -552,6 +552,8 @@ static int parse_set_opt(envid_t veid, int argc, char *argv[],
/* Devices */
{"devices", required_argument, NULL, PARAM_DEVICES},
{"devnodes", required_argument, NULL, PARAM_DEVNODES},
+ {"pci_add", required_argument, NULL, PARAM_PCI_ADD},
+ {"pci_del", required_argument, NULL, PARAM_PCI_DEL},
/* fs param */
{"root", required_argument, NULL, PARAM_ROOT},
{"private", required_argument, NULL, PARAM_PRIVATE},
View
2  src/vzctl.c
@@ -85,7 +85,7 @@ void usage(int rc)
" [--netif_del <ifname>]\n"
" [--applyconfig <name>] [--applyconfig_map <name>]\n"
" [--features <name:on|off>] [--name <vename>]\n"
-" [--ioprio <N>]\n"
+" [--ioprio <N>] [--pci_add [<domain>:]<bus>:<slot>.<func>] [--pci_del <d:b:s.f>]\n"
" [--iptables <name>] [--disabled <yes|no>]\n"
" [UBC parameters]\n"
"\n"

0 comments on commit e8a76d3

Please sign in to comment.
Something went wrong with that request. Please try again.