@@ -261,6 +261,10 @@ information to be interpreted by the executable program I<SCRIPT>,
These scripts are normally called "block-I<SCRIPT>".
+Setting empty script avoids calling the hoplug script at all (including
+the default one). It skips device sharing safety check and
+requires the target to point at a block device. Empty script value is supported
+on Linux backend domain only.
=item B<direct-io-safe>
@@ -324,8 +324,11 @@ static void device_disk_add(libxl__egc *egc, uint32_t domid,
flexarray_append(back, "params");
flexarray_append(back, dev);
- script = libxl__abs_path(gc, disk->script?: "block",
- libxl__xen_script_dir_path());
+ if (disk->script && !disk->script[0])
+ script = "";
+ else
+ script = libxl__abs_path(gc, disk->script?: "block",
+ libxl__xen_script_dir_path());
flexarray_append_pair(back, "script", script);
assert(device->backend_kind == LIBXL__DEVICE_KIND_VBD);
@@ -160,6 +160,62 @@ out:
return rc;
}
+static int libxl__hotplug_disk_direct_add(libxl__gc *gc, libxl__device *dev,
+ const char *be_path)
+{
+ char *params;
+ xs_transaction_t t = XBT_NULL;
+ struct stat st;
+ int rc = 0;
+ char *xs_kvs[] = { "physical-device", NULL,
+ "physical-device-path", NULL,
+ "hotplug-status", "connected",
+ NULL, NULL, };
+
+ for (;;) {
+ rc = libxl__xs_transaction_start(gc, &t);
+ if (rc) goto error;
+
+ params = libxl__xs_read(gc, t,
+ GCSPRINTF("%s/%s", be_path, "params"));
+ if (!params) {
+ rc = ERROR_FAIL;
+ goto error;
+ }
+
+ if (stat(params, &st) == -1) {
+ LOGED(ERROR, dev->domid, "failed to stat %s", params);
+ rc = ERROR_FAIL;
+ goto error;
+ }
+
+ if ((st.st_mode & S_IFMT) != S_IFBLK) {
+ LOGD(ERROR, dev->domid, "not a block device: %s", params);
+ rc = ERROR_FAIL;
+ goto error;
+ }
+
+ xs_kvs[1] = GCSPRINTF("%x:%x", major(st.st_rdev), minor(st.st_rdev));
+ xs_kvs[3] = params;
+ rc = libxl__xs_writev(gc, t, be_path, xs_kvs);
+ if (rc) goto error;
+
+ rc = libxl__xs_transaction_commit(gc, &t);
+ if (!rc) break;
+ if (rc < 0) goto error;
+ }
+
+ return 0;
+
+error:
+ libxl__xs_transaction_abort(gc, &t);
+ if (libxl__xs_write_checked(gc, XBT_NULL,
+ GCSPRINTF("%s/%s", be_path, "hotplug-status"),
+ "error"))
+ LOGD(ERROR, dev->domid, "failed to write 'hotplug-status'");
+ return rc;
+}
+
static int libxl__hotplug_disk(libxl__gc *gc, libxl__device *dev,
char ***args, char ***env,
libxl__device_action action)
@@ -177,6 +233,12 @@ static int libxl__hotplug_disk(libxl__gc *gc, libxl__device *dev,
goto out;
}
+ if (!script[0]) {
+ if (action == LIBXL__DEVICE_ACTION_ADD)
+ rc = libxl__hotplug_disk_direct_add(gc, dev, be_path);
+ goto out;
+ }
+
*env = get_hotplug_env(gc, script, dev);
if (!*env) {
LOGD(ERROR, dev->domid, "Failed to get hotplug environment");
Default block script is quite slow and requires global lock which slows it down even more (for domains with multiple disks). The common case of a block device-based disk is trivial to handle and does not require locking. This can be handled directly within libxl, to avoid slow script execution and waiting for it to finish. This, depending on the hardware, may save about 0.5s of domain start time per disk. Allow setting script name to empty string to skip executing the script at all, and use target name as a block device path directly. This does skip two functions of the block script: - checking if device isn't used anywhere else (including mounted in dom0) - setting up loop device for a file-based disk The former is expected to be done by the operator manually (or by a higher level management stack, that calls into libxl). The later is a limitation of the current implementation, but should be possible to extend in the future. The code to fill 'physical-device' xenstore node is added via libxl__hotplug_disk() (in libxl_linux.c) intentionally. This code is called in device backend domain (which may be not dom0), contrary to device_disk_add() which fills all the other xenstore entries, but is called always in the toolstack domain (dom0). libxl__hoplug_disk() is called from libxl__get_hotplug_script_info(), which may not sound like the most logical place to actually change some state, but it is called when we need it. Signed-off-by: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com> --- docs/man/xl-disk-configuration.5.pod.in | 4 ++- tools/libs/light/libxl_disk.c | 7 ++- tools/libs/light/libxl_linux.c | 62 ++++++++++++++++++++++++++- 3 files changed, 71 insertions(+), 2 deletions(-)