From: Roger Pau Monne <roger.pau@citrix.com>
To: "xen-devel@lists.xen.org" <xen-devel@lists.xen.org>
Cc: Ian Jackson <Ian.Jackson@eu.citrix.com>
Subject: Re: [PATCH v4 08/10] libxl: call hotplug scripts for disk devices from libxl
Date: Fri, 25 May 2012 16:13:19 +0100 [thread overview]
Message-ID: <4FBFA18F.20605@citrix.com> (raw)
In-Reply-To: <1337855045-10428-9-git-send-email-roger.pau@citrix.com>
Roger Pau Monne wrote:
> Since most of the needed work is already done in previous patches,
> this patch only contains the necessary code to call hotplug scripts
> for disk devices, that should be called when the device is added or
> removed from a guest.
>
> We will chain the launch of the disk hotplug scripts after the
> device_backend_callback callback, or directly from
> libxl__initiate_device_{add,remove} if the device is already in the
> desired state.
>
> Changes since v2:
>
> * Added array size check with assert.
>
> * Added NetBSD code (so compilation is not broken).
>
> * Removed a check for null in device_hotplug_timeout_cb.
>
> Changes since v1:
>
> * Moved all the event related code that was inside libxl_linux.c into
> libxl_device.c, so the flow of the device addition/removal event is
> all in the same file.
>
> Cc: Ian Jackson<ian.jackson@eu.citrix.com>
> Signed-off-by: Roger Pau Monne<roger.pau@citrix.com>
> ---
> tools/hotplug/Linux/xen-backend.rules | 6 +-
> tools/hotplug/Linux/xen-hotplug-common.sh | 6 ++
> tools/libxl/libxl.c | 10 +++
> tools/libxl/libxl_device.c | 121 ++++++++++++++++++++++++++++-
> tools/libxl/libxl_internal.h | 20 +++++
> tools/libxl/libxl_linux.c | 98 +++++++++++++++++++++++
> tools/libxl/libxl_netbsd.c | 9 ++
> 7 files changed, 266 insertions(+), 4 deletions(-)
>
> diff --git a/tools/hotplug/Linux/xen-backend.rules b/tools/hotplug/Linux/xen-backend.rules
> index 405387f..d55ff11 100644
> --- a/tools/hotplug/Linux/xen-backend.rules
> +++ b/tools/hotplug/Linux/xen-backend.rules
> @@ -1,11 +1,11 @@
> -SUBSYSTEM=="xen-backend", KERNEL=="tap*", RUN+="/etc/xen/scripts/blktap $env{ACTION}"
> -SUBSYSTEM=="xen-backend", KERNEL=="vbd*", RUN+="/etc/xen/scripts/block $env{ACTION}"
> +SUBSYSTEM=="xen-backend", KERNEL=="tap*", ENV{UDEV_CALL}="1", RUN+="/etc/xen/scripts/blktap $env{ACTION}"
> +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=="vscsi*", RUN+="/etc/xen/scripts/vscsi $env{ACTION}"
> -SUBSYSTEM=="xen-backend", ACTION=="remove", RUN+="/etc/xen/scripts/xen-hotplug-cleanup"
> +SUBSYSTEM=="xen-backend", ACTION=="remove", ENV{UDEV_CALL}="1", RUN+="/etc/xen/scripts/xen-hotplug-cleanup"
> KERNEL=="evtchn", NAME="xen/%k"
> SUBSYSTEM=="xen", KERNEL=="blktap[0-9]*", NAME="xen/%k", MODE="0600"
> SUBSYSTEM=="blktap2", KERNEL=="blktap[0-9]*", NAME="xen/blktap-2/%k", MODE="0600"
> diff --git a/tools/hotplug/Linux/xen-hotplug-common.sh b/tools/hotplug/Linux/xen-hotplug-common.sh
> index 8f6557d..4a7bc73 100644
> --- a/tools/hotplug/Linux/xen-hotplug-common.sh
> +++ b/tools/hotplug/Linux/xen-hotplug-common.sh
> @@ -15,6 +15,12 @@
> # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
> #
>
> +# Hack to prevent the execution of hotplug scripts from udev if the domain
> +# has been launched from libxl
> +if [ -n "${UDEV_CALL}" ]&& \
> + xenstore-read "libxl/disable_udev">/dev/null 2>&1; then
> + exit 0
> +fi
>
> dir=$(dirname "$0")
> . "$dir/hotplugpath.sh"
> diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
> index 2f27fd5..ccb5bdc 100644
> --- a/tools/libxl/libxl.c
> +++ b/tools/libxl/libxl.c
> @@ -1607,6 +1607,11 @@ void libxl__device_disk_add(libxl__egc *egc, uint32_t domid,
> flexarray_append(back, "params");
> flexarray_append(back, dev);
>
> + flexarray_append(back, "script");
> + flexarray_append(back, GCSPRINTF("%s/%s",
> + libxl__xen_script_dir_path(),
> + "block"));
> +
> assert(device->backend_kind == LIBXL__DEVICE_KIND_VBD);
> break;
> case LIBXL_DISK_BACKEND_TAP:
> @@ -1622,6 +1627,11 @@ void libxl__device_disk_add(libxl__egc *egc, uint32_t domid,
> libxl__device_disk_string_of_format(disk->format),
> disk->pdev_path));
>
> + flexarray_append(back, "script");
> + flexarray_append(back, GCSPRINTF("%s/%s",
> + libxl__xen_script_dir_path(),
> + "blktap"));
> +
> /* now create a phy device to export the device to the guest */
> goto do_backend_phy;
> case LIBXL_DISK_BACKEND_QDISK:
> diff --git a/tools/libxl/libxl_device.c b/tools/libxl/libxl_device.c
> index 9933cc2..8e1ec0f 100644
> --- a/tools/libxl/libxl_device.c
> +++ b/tools/libxl/libxl_device.c
> @@ -569,6 +569,14 @@ static void device_backend_callback(libxl__egc *egc, libxl__ev_devstate *ds,
> static void device_backend_cleanup(libxl__gc *gc,
> libxl__ao_device *aodev);
>
> +static void device_hotplug(libxl__egc *egc, libxl__ao_device *aodev);
> +
> +static void device_hotplug_fork_cb(libxl__egc *egc, libxl__ev_child *child,
> + pid_t pid, int status);
> +
> +static void device_hotplug_timeout_cb(libxl__egc *egc, libxl__ev_time *ev,
> + const struct timeval *requested_abs);
> +
> void libxl__initiate_device_add(libxl__egc *egc, libxl__ao_device *aodev)
> {
> STATE_AO_GC(aodev->ao);
> @@ -657,7 +665,7 @@ retry_transaction:
>
> out_ok:
> if (t) xs_transaction_end(ctx->xsh, t, 0);
> - aodev->callback(egc, aodev);
> + device_hotplug(egc, aodev);
> return;
> }
>
> @@ -689,6 +697,9 @@ static void device_backend_callback(libxl__egc *egc, libxl__ev_devstate *ds,
> goto out;
> }
>
> + device_hotplug(egc, aodev);
> + return;
> +
> out:
> aodev->rc = rc;
> aodev->callback(egc, aodev);
> @@ -701,6 +712,114 @@ static void device_backend_cleanup(libxl__gc *gc, libxl__ao_device *aodev)
> libxl__ev_devstate_cancel(gc,&aodev->ds);
> }
>
> +static void device_hotplug(libxl__egc *egc, libxl__ao_device *aodev)
> +{
> + STATE_AO_GC(aodev->ao);
> + char *be_path = libxl__device_backend_path(gc, aodev->dev);
> + char **args, **env;
These should we initialised to NULL.
char **args = NULL, **env = NULL;
> + int rc = 0;
> + int hotplug;
> +
> + /* 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);
> + switch (hotplug) {
> + case 0:
> + /* no hotplug script to execute */
> + goto out;
> + case 1:
> + /* execute hotplug script */
> + break;
> + default:
> + /* everything else is an error */
> + LOG(ERROR, "unable to get args/env to execute hotplug script for "
> + "device %s", libxl__device_backend_path(gc, aodev->dev));
> + rc = ERROR_FAIL;
> + goto out;
> + }
> +
> + /* Set hotplug timeout */
> + libxl__ev_time_init(&aodev->ev);
> + rc = libxl__ev_time_register_rel(gc,&aodev->ev, device_hotplug_timeout_cb,
> + LIBXL_HOTPLUG_TIMEOUT * 1000);
> + if (rc) {
> + LOG(ERROR, "unable to register timeout for hotplug device %s", be_path);
> + goto out;
> + }
> +
> + aodev->what = GCSPRINTF("%s %s", args[0], args[1]);
> + LOG(DEBUG, "calling hotplug script: %s %s", args[0], args[1]);
> + libxl__ev_child_init(&aodev->child);
> +
> + /* fork and execute hotplug script */
> + aodev->pid = libxl__ev_child_fork(gc,&aodev->child,
> + device_hotplug_fork_cb);
> + if (aodev->pid == -1) {
> + LOG(ERROR, "unable to fork");
> + rc = ERROR_FAIL;
> + goto out;
> + }
> +
> + if (!aodev->pid) {
> + /* child */
> + libxl__exec(gc, -1, -1, -1, args[0], args, env);
> + /* notreached */
> + abort();
> + }
> +
> + if (!libxl__ev_child_inuse(&aodev->child)) {
> + /* hotplug launch failed */
> + LOG(ERROR, "unable to launch hotplug script for device %s", be_path);
> + rc = ERROR_FAIL;
> + goto out;
> + }
> +
> + return;
> +
> +out:
> + libxl__ev_time_deregister(gc,&aodev->ev);
> + aodev->rc = rc;
> + aodev->callback(egc, aodev);
> + return;
> +}
> +
> +static void device_hotplug_fork_cb(libxl__egc *egc, libxl__ev_child *child,
> + pid_t pid, int status)
> +{
> + libxl__ao_device *aodev = CONTAINER_OF(child, *aodev, child);
> + STATE_AO_GC(aodev->ao);
> +
> + libxl__ev_time_deregister(gc,&aodev->ev);
> +
> + if (status) {
> + libxl_report_child_exitstatus(CTX, aodev->rc ? LIBXL__LOG_ERROR
> + : LIBXL__LOG_WARNING,
> + aodev->what, pid, status);
> + aodev->rc = ERROR_FAIL;
> + }
> + aodev->callback(egc, aodev);
> +}
> +
> +static void device_hotplug_timeout_cb(libxl__egc *egc, libxl__ev_time *ev,
> + const struct timeval *requested_abs)
> +{
> + libxl__ao_device *aodev = CONTAINER_OF(ev, *aodev, ev);
> + STATE_AO_GC(aodev->ao);
> +
> + if (libxl__ev_child_inuse(&aodev->child)) {
> + if (kill(aodev->pid, SIGKILL)) {
> + LOGEV(ERROR, errno, "unable to kill hotplug script %s [%ld]",
> + aodev->what, (unsigned long)aodev->pid);
> + goto out;
> + }
> + }
> +
> +out:
> + libxl__ev_time_deregister(gc,&aodev->ev);
> + return;
> +}
> +
> static void device_remove_callback(libxl__egc *egc, libxl__ao_device *aodev)
> {
> STATE_AO_GC(aodev->ao);
> diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
> index 45b776c..da5b02b 100644
> --- a/tools/libxl/libxl_internal.h
> +++ b/tools/libxl/libxl_internal.h
> @@ -72,6 +72,7 @@
>
> #define LIBXL_INIT_TIMEOUT 10
> #define LIBXL_DESTROY_TIMEOUT 10
> +#define LIBXL_HOTPLUG_TIMEOUT 10
> #define LIBXL_DEVICE_MODEL_START_TIMEOUT 10
> #define LIBXL_XENCONSOLE_LIMIT 1048576
> #define LIBXL_XENCONSOLE_PROTOCOL "vt100"
> @@ -1814,6 +1815,11 @@ struct libxl__ao_device {
> int rc;
> libxl__ev_devstate ds;
> void *base;
> + /* device hotplug execution */
> + pid_t pid;
> + char *what;
> + libxl__ev_time ev;
> + libxl__ev_child child;
> };
>
> /* Internal AO operation to connect a disk device */
> @@ -1842,6 +1848,20 @@ _hidden void libxl__initiate_device_add(libxl__egc*, libxl__ao_device *aodev);
> _hidden void libxl__initiate_device_remove(libxl__egc *egc,
> libxl__ao_device *aodev);
>
> +/*
> + * libxl__get_hotplug_script_info returns the args and env that should
> + * be passed to the hotplug script for the requested device.
> + *
> + * Since a device might not need to execute any hotplug script, this function
> + * can return the following values:
> + *< 0: Error
> + * 0: No need to execute hotplug script
> + * 1: Execute hotplug script
> + */
> +_hidden int libxl__get_hotplug_script_info(libxl__gc *gc, libxl__device *dev,
> + char ***args, char ***env,
> + libxl__device_action action);
> +
> /*----- Domain destruction -----*/
>
> /* Domain destruction has been split into two functions:
> diff --git a/tools/libxl/libxl_linux.c b/tools/libxl/libxl_linux.c
> index 925248b..98cd25f 100644
> --- a/tools/libxl/libxl_linux.c
> +++ b/tools/libxl/libxl_linux.c
> @@ -25,3 +25,101 @@ int libxl__try_phy_backend(mode_t st_mode)
>
> return 1;
> }
> +
> +/* Hotplug scripts helpers */
> +
> +static char **get_hotplug_env(libxl__gc *gc, libxl__device *dev)
> +{
> + char *be_path = libxl__device_backend_path(gc, dev);
> + char *script;
> + const char *type = libxl__device_kind_to_string(dev->backend_kind);
> + char **env;
> + int nr = 0, arraysize = 9;
> +
> + script = libxl__xs_read(gc, XBT_NULL,
> + GCSPRINTF("%s/%s", be_path, "script"));
> + if (!script) {
> + LOGEV(ERROR, errno, "unable to read script from %s", be_path);
> + return NULL;
> + }
> +
> + GCNEW_ARRAY(env, arraysize);
> + env[nr++] = "script";
> + env[nr++] = script;
> + env[nr++] = "XENBUS_TYPE";
> + env[nr++] = libxl__strdup(gc, 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";
> + env[nr++] = NULL;
> + assert(nr == arraysize);
> +
> + return env;
> +}
> +
> +/* Hotplug scripts caller functions */
> +
> +static int libxl__hotplug_disk(libxl__gc *gc, libxl__device *dev,
> + char ***args, char ***env,
> + libxl__device_action action)
> +{
> + char *be_path = libxl__device_backend_path(gc, dev);
> + char *script;
> + int nr = 0, rc = 0, arraysize = 3;
> +
> + script = libxl__xs_read(gc, XBT_NULL,
> + GCSPRINTF("%s/%s", be_path, "script"));
> + if (!script) {
> + LOGEV(ERROR, errno, "unable to read script from %s", be_path);
> + rc = ERROR_FAIL;
> + goto error;
> + }
> +
> + *env = get_hotplug_env(gc, dev);
> + if (!*env) {
> + rc = ERROR_FAIL;
> + goto error;
> + }
> +
> + GCNEW_ARRAY(*args, arraysize);
> + (*args)[nr++] = script;
> + (*args)[nr++] = action == DEVICE_CONNECT ? "add" : "remove";
> + (*args)[nr++] = NULL;
> + assert(nr == arraysize);
> +
> + rc = 0;
> +
> +error:
> + return rc;
> +}
> +
> +int libxl__get_hotplug_script_info(libxl__gc *gc, libxl__device *dev,
> + char ***args, char ***env,
> + libxl__device_action action)
> +{
> + char *disable_udev = libxl__xs_read(gc, XBT_NULL, DISABLE_UDEV_PATH);
> + int rc;
> +
> + /* Check if we have to run hotplug scripts */
> + if (!disable_udev) {
> + rc = 0;
> + goto out;
> + }
> +
> + switch (dev->backend_kind) {
> + case LIBXL__DEVICE_KIND_VBD:
> + rc = libxl__hotplug_disk(gc, dev, args, env, action);
> + if (!rc) rc = 1;
> + break;
> + default:
> + /* If no need to execute any hotplug scripts,
> + * call the callback manually
> + */
> + rc = 0;
> + break;
> + }
> +
> +out:
> + return rc;
> +}
> diff --git a/tools/libxl/libxl_netbsd.c b/tools/libxl/libxl_netbsd.c
> index 9e0ed6d..0f2cdaa 100644
> --- a/tools/libxl/libxl_netbsd.c
> +++ b/tools/libxl/libxl_netbsd.c
> @@ -24,3 +24,12 @@ int libxl__try_phy_backend(mode_t st_mode)
>
> return 0;
> }
> +
> +/* Hotplug scripts caller functions */
> +
> +int libxl__get_hotplug_script_info(libxl__gc *gc, libxl__device *dev,
> + char ***args, char ***env,
> + libxl__device_action action)
> +{
> + return 0;
> +}
> \ No newline at end of file
> --
> 1.7.7.5 (Apple Git-26)
>
next prev parent reply other threads:[~2012-05-25 15:13 UTC|newest]
Thread overview: 26+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-05-24 10:23 [PATCH v4 0/10] execute hotplug scripts from libxl Roger Pau Monne
2012-05-24 10:23 ` [PATCH v4 01/10] libxl: change libxl__ao_device_remove to libxl__ao_device Roger Pau Monne
2012-05-29 13:32 ` Ian Jackson
2012-05-30 8:43 ` Roger Pau Monne
2012-05-31 11:13 ` Ian Jackson
2012-05-24 10:23 ` [PATCH v4 02/10] libxl: move device model creation prototypes Roger Pau Monne
2012-05-24 10:23 ` [PATCH v4 03/10] libxl: convert libxl_domain_destroy to an async op Roger Pau Monne
2012-05-29 14:04 ` Ian Jackson
2012-05-24 10:23 ` [PATCH v4 04/10] libxl: convert libxl_device_disk_add to an asyn op Roger Pau Monne
2012-05-29 14:26 ` Ian Jackson
2012-05-29 14:40 ` Ian Campbell
2012-05-24 10:24 ` [PATCH v4 05/10] libxl: convert libxl_device_nic_add to an async operation Roger Pau Monne
2012-05-29 14:36 ` Ian Jackson
2012-05-30 9:54 ` Roger Pau Monne
2012-05-30 10:06 ` Ian Jackson
2012-05-24 10:24 ` [PATCH v4 06/10] libxl: add option to choose who executes hotplug scripts Roger Pau Monne
2012-05-29 14:38 ` Ian Jackson
2012-05-24 10:24 ` [PATCH v4 07/10] libxl: set nic type to VIF by default Roger Pau Monne
2012-05-24 10:24 ` [PATCH v4 08/10] libxl: call hotplug scripts for disk devices from libxl Roger Pau Monne
2012-05-25 15:13 ` Roger Pau Monne [this message]
2012-05-29 14:50 ` Ian Jackson
2012-05-30 11:33 ` Roger Pau Monne
2012-05-24 10:24 ` [PATCH v4 09/10] libxl: call hotplug scripts for nic " Roger Pau Monne
2012-05-29 14:57 ` Ian Jackson
2012-05-24 10:24 ` [PATCH v4 10/10] libxl: use libxl__xs_path_cleanup on device_destroy Roger Pau Monne
2012-05-29 14:58 ` Ian Jackson
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=4FBFA18F.20605@citrix.com \
--to=roger.pau@citrix.com \
--cc=Ian.Jackson@eu.citrix.com \
--cc=xen-devel@lists.xen.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).