aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorRoger Pau Monne <roger.pau@citrix.com>2012-07-26 16:47:35 +0100
committerRoger Pau Monne <roger.pau@citrix.com>2012-07-26 16:47:35 +0100
commit57ad6afe2a08a03c40bcd336bfb27e008e1d3e53 (patch)
tree5458836e1fff4d42ab9cdc3bebb9d9225a6247f3 /tools
parentb24dc64ef34437c958b40a71f510f404e0c4bbe4 (diff)
downloadxen-57ad6afe2a08a03c40bcd336bfb27e008e1d3e53.tar.gz
xen-57ad6afe2a08a03c40bcd336bfb27e008e1d3e53.tar.bz2
xen-57ad6afe2a08a03c40bcd336bfb27e008e1d3e53.zip
libxl: call hotplug scripts for nic devices from libxl
Since most of the needed work is already done in previous patches, this patch only contains the necessary code to call hotplug scripts for nic devices, that should be called when the device is added or removed from a guest. Added another parameter to libxl__get_hotplug_script_info, that is used to know the number of times hotplug scripts have been called for that device. This is currently used by IOEMU nics on Linux. Signed-off-by: Roger Pau Monne <roger.pau@citrix.com> Acked-by: Ian Jackson<ian.jackson@eu.citrix.com> Committed-by: Ian Campbell <ian.campbell@citrix.com>
Diffstat (limited to 'tools')
-rw-r--r--tools/hotplug/Linux/xen-backend.rules6
-rw-r--r--tools/libxl/libxl_device.c60
-rw-r--r--tools/libxl/libxl_internal.h14
-rw-r--r--tools/libxl/libxl_linux.c108
-rw-r--r--tools/libxl/libxl_netbsd.c3
5 files changed, 178 insertions, 13 deletions
diff --git a/tools/hotplug/Linux/xen-backend.rules b/tools/hotplug/Linux/xen-backend.rules
index d55ff11309..c591a3ff03 100644
--- a/tools/hotplug/Linux/xen-backend.rules
+++ b/tools/hotplug/Linux/xen-backend.rules
@@ -2,8 +2,8 @@ SUBSYSTEM=="xen-backend", KERNEL=="tap*", ENV{UDEV_CALL}="1", RUN+="/etc/xen/scr
SUBSYSTEM=="xen-backend", KERNEL=="vbd*", ENV{UDEV_CALL}="1", RUN+="/etc/xen/scripts/block $env{ACTION}"
SUBSYSTEM=="xen-backend", KERNEL=="vtpm*", RUN+="/etc/xen/scripts/vtpm $env{ACTION}"
SUBSYSTEM=="xen-backend", KERNEL=="vif2-*", RUN+="/etc/xen/scripts/vif2 $env{ACTION}"
-SUBSYSTEM=="xen-backend", KERNEL=="vif-*", ACTION=="online", RUN+="/etc/xen/scripts/vif-setup online type_if=vif"
-SUBSYSTEM=="xen-backend", KERNEL=="vif-*", ACTION=="offline", RUN+="/etc/xen/scripts/vif-setup offline type_if=vif"
+SUBSYSTEM=="xen-backend", KERNEL=="vif-*", ENV{UDEV_CALL}="1", ACTION=="online", RUN+="/etc/xen/scripts/vif-setup online type_if=vif"
+SUBSYSTEM=="xen-backend", KERNEL=="vif-*", ENV{UDEV_CALL}="1", ACTION=="offline", RUN+="/etc/xen/scripts/vif-setup offline type_if=vif"
SUBSYSTEM=="xen-backend", KERNEL=="vscsi*", RUN+="/etc/xen/scripts/vscsi $env{ACTION}"
SUBSYSTEM=="xen-backend", ACTION=="remove", ENV{UDEV_CALL}="1", RUN+="/etc/xen/scripts/xen-hotplug-cleanup"
KERNEL=="evtchn", NAME="xen/%k"
@@ -13,4 +13,4 @@ KERNEL=="blktap-control", NAME="xen/blktap-2/control", MODE="0600"
KERNEL=="gntdev", NAME="xen/%k", MODE="0600"
KERNEL=="pci_iomul", NAME="xen/%k", MODE="0600"
KERNEL=="tapdev[a-z]*", NAME="xen/blktap-2/tapdev%m", MODE="0600"
-SUBSYSTEM=="net", KERNEL=="vif*-emu", ACTION=="add", RUN+="/etc/xen/scripts/vif-setup $env{ACTION} type_if=tap"
+SUBSYSTEM=="net", KERNEL=="vif*-emu", ACTION=="add", ENV{UDEV_CALL}="1", RUN+="/etc/xen/scripts/vif-setup $env{ACTION} type_if=tap"
diff --git a/tools/libxl/libxl_device.c b/tools/libxl/libxl_device.c
index a80dee846f..da0c3ea7c8 100644
--- a/tools/libxl/libxl_device.c
+++ b/tools/libxl/libxl_device.c
@@ -102,6 +102,31 @@ out:
return numdevs;
}
+int libxl__nic_type(libxl__gc *gc, libxl__device *dev, libxl_nic_type *nictype)
+{
+ char *snictype, *be_path;
+ int rc = 0;
+
+ be_path = libxl__device_backend_path(gc, dev);
+ snictype = libxl__xs_read(gc, XBT_NULL,
+ GCSPRINTF("%s/%s", be_path, "type"));
+ if (!snictype) {
+ LOGE(ERROR, "unable to read nictype from %s", be_path);
+ rc = ERROR_FAIL;
+ goto out;
+ }
+ rc = libxl_nic_type_from_string(snictype, nictype);
+ if (rc) {
+ LOGE(ERROR, "unable to parse nictype from %s", be_path);
+ goto out;
+ }
+
+ rc = 0;
+
+out:
+ return rc;
+}
+
int libxl__device_generic_add(libxl__gc *gc, xs_transaction_t t,
libxl__device *device, char **bents, char **fents)
{
@@ -638,6 +663,8 @@ static void device_hotplug_child_death_cb(libxl__egc *egc,
static void device_hotplug_done(libxl__egc *egc, libxl__ao_device *aodev);
+static void device_hotplug_clean(libxl__gc *gc, libxl__ao_device *aodev);
+
void libxl__wait_device_connection(libxl__egc *egc, libxl__ao_device *aodev)
{
STATE_AO_GC(aodev->ao);
@@ -850,7 +877,8 @@ static void device_hotplug(libxl__egc *egc, libxl__ao_device *aodev)
/* Check if we have to execute hotplug scripts for this device
* and return the necessary args/env vars for execution */
hotplug = libxl__get_hotplug_script_info(gc, aodev->dev, &args, &env,
- aodev->action);
+ aodev->action,
+ aodev->num_exec);
switch (hotplug) {
case 0:
/* no hotplug script to execute */
@@ -930,6 +958,8 @@ static void device_hotplug_child_death_cb(libxl__egc *egc,
char *be_path = libxl__device_backend_path(gc, aodev->dev);
char *hotplug_error;
+ device_hotplug_clean(gc, aodev);
+
if (status) {
libxl_report_child_exitstatus(CTX, LIBXL__LOG_ERROR,
aodev->what, pid, status);
@@ -938,8 +968,25 @@ static void device_hotplug_child_death_cb(libxl__egc *egc,
if (hotplug_error)
LOG(ERROR, "script: %s", hotplug_error);
aodev->rc = ERROR_FAIL;
+ if (aodev->action == DEVICE_CONNECT)
+ /*
+ * Only fail on device connection, on disconnection
+ * ignore error, and continue with the remove process
+ */
+ goto error;
}
+ /* Increase num_exec and call hotplug scripts again if necessary
+ * If no more executions are needed, device_hotplug will call
+ * device_hotplug_done breaking the loop.
+ */
+ aodev->num_exec++;
+ device_hotplug(egc, aodev);
+
+ return;
+
+error:
+ assert(aodev->rc);
device_hotplug_done(egc, aodev);
}
@@ -951,9 +998,7 @@ static void device_hotplug_done(libxl__egc *egc, libxl__ao_device *aodev)
xs_transaction_t t = 0;
int rc;
- /* Clean events and check reentrancy */
- libxl__ev_time_deregister(gc, &aodev->timeout);
- assert(!libxl__ev_child_inuse(&aodev->child));
+ device_hotplug_clean(gc, aodev);
/* Clean xenstore if it's a disconnection */
if (aodev->action == DEVICE_DISCONNECT) {
@@ -975,6 +1020,13 @@ out:
return;
}
+static void device_hotplug_clean(libxl__gc *gc, libxl__ao_device *aodev)
+{
+ /* Clean events and check reentrancy */
+ libxl__ev_time_deregister(gc, &aodev->timeout);
+ assert(!libxl__ev_child_inuse(&aodev->child));
+}
+
static void devices_remove_callback(libxl__egc *egc, libxl__ao_devices *aodevs,
int rc)
{
diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
index 2567c4d38a..cf5ab712ad 100644
--- a/tools/libxl/libxl_internal.h
+++ b/tools/libxl/libxl_internal.h
@@ -920,6 +920,8 @@ _hidden int libxl__parse_backend_path(libxl__gc *gc, const char *path,
libxl__device *dev);
_hidden int libxl__device_destroy(libxl__gc *gc, libxl__device *dev);
_hidden int libxl__wait_for_backend(libxl__gc *gc, char *be_path, char *state);
+_hidden int libxl__nic_type(libxl__gc *gc, libxl__device *dev,
+ libxl_nic_type *nictype);
/*
* For each aggregate type which can be used as an input we provide:
@@ -1840,6 +1842,7 @@ struct libxl__ao_device {
libxl__ao_devices *aodevs;
/* device hotplug execution */
const char *what;
+ int num_exec;
libxl__ev_child child;
};
@@ -1979,10 +1982,19 @@ _hidden void libxl__initiate_device_remove(libxl__egc *egc,
* < 0: Error
* 0: No need to execute hotplug script
* 1: Execute hotplug script
+ *
+ * The last parameter, "num_exec" refeers to the number of times hotplug
+ * scripts have been called for this device.
+ *
+ * The main body of libxl will, for each device, keep calling
+ * libxl__get_hotplug_script_info, with incrementing values of
+ * num_exec, and executing the resulting script accordingly,
+ * until libxl__get_hotplug_script_info returns<=0.
*/
_hidden int libxl__get_hotplug_script_info(libxl__gc *gc, libxl__device *dev,
char ***args, char ***env,
- libxl__device_action action);
+ libxl__device_action action,
+ int num_exec);
/*----- local disk attach: attach a disk locally to run the bootloader -----*/
diff --git a/tools/libxl/libxl_linux.c b/tools/libxl/libxl_linux.c
index 97b3fd4a64..9ae0b4b88f 100644
--- a/tools/libxl/libxl_linux.c
+++ b/tools/libxl/libxl_linux.c
@@ -87,6 +87,7 @@ static char **get_hotplug_env(libxl__gc *gc, libxl__device *dev)
const char *type = libxl__device_kind_to_string(dev->backend_kind);
char **env;
int nr = 0;
+ libxl_nic_type nictype;
script = libxl__xs_read(gc, XBT_NULL,
GCSPRINTF("%s/%s", be_path, "script"));
@@ -95,24 +96,106 @@ static char **get_hotplug_env(libxl__gc *gc, libxl__device *dev)
return NULL;
}
- const int arraysize = 9;
+ const int arraysize = 13;
GCNEW_ARRAY(env, arraysize);
env[nr++] = "script";
env[nr++] = script;
env[nr++] = "XENBUS_TYPE";
- env[nr++] = libxl__strdup(gc, type);
+ env[nr++] = (char *) type;
env[nr++] = "XENBUS_PATH";
env[nr++] = GCSPRINTF("backend/%s/%u/%d", type, dev->domid, dev->devid);
env[nr++] = "XENBUS_BASE_PATH";
env[nr++] = "backend";
+ if (dev->backend_kind == LIBXL__DEVICE_KIND_VIF) {
+ if (libxl__nic_type(gc, dev, &nictype)) {
+ LOG(ERROR, "unable to get nictype");
+ return NULL;
+ }
+ switch (nictype) {
+ case LIBXL_NIC_TYPE_VIF_IOEMU:
+ env[nr++] = "INTERFACE";
+ env[nr++] = (char *) libxl__device_nic_devname(gc, dev->domid,
+ dev->devid,
+ LIBXL_NIC_TYPE_VIF_IOEMU);
+ /*
+ * We need to fall through because for PV_IOEMU nic types we need
+ * to execute both the vif and the tap hotplug script, and we
+ * don't know which one we are executing in this call, so provide
+ * both env variables.
+ */
+ case LIBXL_NIC_TYPE_VIF:
+ env[nr++] = "vif";
+ env[nr++] = (char *) libxl__device_nic_devname(gc, dev->domid,
+ dev->devid,
+ LIBXL_NIC_TYPE_VIF);
+ break;
+ default:
+ return NULL;
+ }
+ }
+
env[nr++] = NULL;
- assert(nr == arraysize);
+ assert(nr <= arraysize);
return env;
}
/* Hotplug scripts caller functions */
+static int libxl__hotplug_nic(libxl__gc *gc, libxl__device *dev,
+ char ***args, char ***env,
+ libxl__device_action action, int num_exec)
+{
+ char *be_path = libxl__device_backend_path(gc, dev);
+ char *script;
+ int nr = 0, rc = 0;
+ libxl_nic_type nictype;
+
+ script = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/%s", be_path,
+ "script"));
+ if (!script) {
+ LOGE(ERROR, "unable to read script from %s", be_path);
+ rc = ERROR_FAIL;
+ goto out;
+ }
+
+ rc = libxl__nic_type(gc, dev, &nictype);
+ if (rc) {
+ LOG(ERROR, "error when fetching nic type");
+ rc = ERROR_FAIL;
+ goto out;
+ }
+ if (nictype == LIBXL_NIC_TYPE_VIF && num_exec != 0) {
+ rc = 0;
+ goto out;
+ }
+
+ *env = get_hotplug_env(gc, dev);
+ if (!env) {
+ rc = ERROR_FAIL;
+ goto out;
+ }
+
+ const int arraysize = 4;
+ GCNEW_ARRAY(*args, arraysize);
+ (*args)[nr++] = script;
+
+ if (nictype == LIBXL_NIC_TYPE_VIF_IOEMU && num_exec) {
+ (*args)[nr++] = action == DEVICE_CONNECT ? "add" : "remove";
+ (*args)[nr++] = "type_if=tap";
+ (*args)[nr++] = NULL;
+ } else {
+ (*args)[nr++] = action == DEVICE_CONNECT ? "online" : "offline";
+ (*args)[nr++] = "type_if=vif";
+ (*args)[nr++] = NULL;
+ }
+ assert(nr == arraysize);
+ rc = 1;
+
+out:
+ return rc;
+}
+
static int libxl__hotplug_disk(libxl__gc *gc, libxl__device *dev,
char ***args, char ***env,
libxl__device_action action)
@@ -150,7 +233,8 @@ error:
int libxl__get_hotplug_script_info(libxl__gc *gc, libxl__device *dev,
char ***args, char ***env,
- libxl__device_action action)
+ libxl__device_action action,
+ int num_exec)
{
char *disable_udev = libxl__xs_read(gc, XBT_NULL, DISABLE_UDEV_PATH);
int rc;
@@ -163,8 +247,24 @@ int libxl__get_hotplug_script_info(libxl__gc *gc, libxl__device *dev,
switch (dev->backend_kind) {
case LIBXL__DEVICE_KIND_VBD:
+ if (num_exec != 0) {
+ rc = 0;
+ goto out;
+ }
rc = libxl__hotplug_disk(gc, dev, args, env, action);
break;
+ case LIBXL__DEVICE_KIND_VIF:
+ /*
+ * If domain has a stubdom we don't have to execute hotplug scripts
+ * for emulated interfaces
+ */
+ if ((num_exec > 1) ||
+ (libxl_get_stubdom_id(CTX, dev->domid) && num_exec)) {
+ rc = 0;
+ goto out;
+ }
+ rc = libxl__hotplug_nic(gc, dev, args, env, action, num_exec);
+ break;
default:
/* No need to execute any hotplug scripts */
rc = 0;
diff --git a/tools/libxl/libxl_netbsd.c b/tools/libxl/libxl_netbsd.c
index a2f8d3f0c5..28cdf21d73 100644
--- a/tools/libxl/libxl_netbsd.c
+++ b/tools/libxl/libxl_netbsd.c
@@ -34,7 +34,8 @@ char *libxl__devid_to_localdev(libxl__gc *gc, int devid)
/* Hotplug scripts caller functions */
int libxl__get_hotplug_script_info(libxl__gc *gc, libxl__device *dev,
char ***args, char ***env,
- libxl__device_action action)
+ libxl__device_action action,
+ int num_exec)
{
return 0;
}