[libvirt] [PATCH 20/23] Add support for hotplug/unplug of host storage devices in LXC

Gao feng gaofeng at cn.fujitsu.com
Fri Dec 14 11:44:33 UTC 2012


On 2012/12/01 04:26, Daniel P. Berrange wrote:
> From: "Daniel P. Berrange" <berrange at redhat.com>
> 
> Wire up the attach/detach device drivers in LXC to support the
> hotplug/unplug of host storage devices.
> 
> Signed-off-by: Daniel P. Berrange <berrange at redhat.com>
> ---
>  src/lxc/lxc_driver.c | 237 +++++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 237 insertions(+)
> 
> diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c
> index 50050cf..27ee3d7 100644
> --- a/src/lxc/lxc_driver.c
> +++ b/src/lxc/lxc_driver.c
> @@ -3224,6 +3224,12 @@ lxcDomainAttachDeviceHostdevSubsysUSBLive(virLXCDriverPtr driver,
>      usbDevice *usb = NULL;
>      virCgroupPtr group = NULL;
>  
> +    if (virDomainHostdevFind(vm->def, def, NULL) >= 0) {
> +        virReportError(VIR_ERR_OPERATION_FAILED, "%s",
> +                       _("host USB device already exists"));
> +        return -1;
> +    }
> +

It shouldn't be in patch [19/23]?

>      if (virAsprintf(&vroot, "/proc/%llu/root",
>                      (unsigned long long)priv->initpid) < 0) {
>          virReportOOMError();
> @@ -3351,6 +3357,123 @@ cleanup:
>  
>  
>  static int
> +lxcDomainAttachDeviceHostdevStorageLive(virLXCDriverPtr driver,
> +                                        virDomainObjPtr vm,
> +                                        virDomainDeviceDefPtr dev)
> +{
> +    virLXCDomainObjPrivatePtr priv = vm->privateData;
> +    virDomainHostdevDefPtr def = dev->data.hostdev;
> +    virCgroupPtr group = NULL;
> +    int ret = -1;
> +    char *dst;
> +    char *vroot;
> +    struct stat sb;
> +    bool created = false;
> +    mode_t mode = 0;
> +
> +    if (!priv->initpid) {
> +        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
> +                       _("Cannot attach disk until init PID is known"));
> +        goto cleanup;
> +    }
> +
> +    if (!def->source.caps.u.storage.block) {
> +        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
> +                       _("Missing storage block path"));
> +        goto cleanup;
> +    }
> +
> +    if (virDomainHostdevFind(vm->def, def, NULL) >= 0) {
> +        virReportError(VIR_ERR_OPERATION_FAILED, "%s",
> +                       _("host device already exists"));
> +        return -1;
> +    }
> +
> +    if (stat(def->source.caps.u.storage.block, &sb) < 0) {
> +        virReportSystemError(errno,
> +                             _("Unable to access %s"),
> +                             def->source.caps.u.storage.block);
> +        goto cleanup;
> +    }
> +
> +    if (!S_ISBLK(sb.st_mode)) {
> +        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
> +                       _("Hostdev source %s must be a block device"),
> +                       def->source.caps.u.storage.block);
> +        goto cleanup;
> +    }
> +
> +    if (virAsprintf(&vroot, "/proc/%llu/root",
> +                    (unsigned long long)priv->initpid) < 0) {
> +        virReportOOMError();
> +        goto cleanup;
> +    }
> +
> +    if (virAsprintf(&dst, "%s/%s",
> +                    vroot,
> +                    def->source.caps.u.storage.block) < 0) {
> +        virReportOOMError();
> +        goto cleanup;
> +    }
> +
> +    if (VIR_REALLOC_N(vm->def->hostdevs, vm->def->nhostdevs+1) < 0) {
> +        virReportOOMError();
> +        goto cleanup;
> +    }
> +
> +    mode = 0700 | S_IFBLK;
> +
> +    VIR_DEBUG("Creating dev %s (%d,%d)",
> +              def->source.caps.u.storage.block,
> +              major(sb.st_rdev), minor(sb.st_rdev));
> +    if (mknod(dst, mode, sb.st_rdev) < 0) {
> +        virReportSystemError(errno,
> +                             _("Unable to create device %s"),
> +                             dst);
> +        goto cleanup;
> +    }
> +    created = true;
> +
> +    if (virSecurityManagerSetHostdevLabel(driver->securityManager,
> +                                          vm->def, def, vroot) < 0)
> +        goto cleanup;
> +
> +    if (!lxcCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_DEVICES)) {
> +        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
> +                       _("devices cgroup isn't mounted"));
> +        goto cleanup;
> +    }
> +
> +    if (virCgroupForDomain(driver->cgroup, vm->def->name, &group, 0) != 0) {
> +        virReportError(VIR_ERR_INTERNAL_ERROR,
> +                       _("cannot find cgroup for domain %s"), vm->def->name);
> +        goto cleanup;
> +    }
> +
> +    if (virCgroupAllowDevicePath(group, def->source.caps.u.storage.block,
> +                                 VIR_CGROUP_DEVICE_RW |
> +                                 VIR_CGROUP_DEVICE_MKNOD) != 0) {
> +        virReportError(VIR_ERR_INTERNAL_ERROR,
> +                       _("cannot allow device %s for domain %s"),
> +                       def->source.caps.u.storage.block, vm->def->name);
> +        goto cleanup;
> +    }
> +
> +    vm->def->hostdevs[vm->def->nhostdevs++] = def;
> +
> +    ret = 0;
> +
> +cleanup:
> +    virDomainAuditHostdev(vm, def, "attach", ret == 0);
> +    if (group)
> +        virCgroupFree(&group);
> +    if (dst && created && ret < 0)
> +        unlink(dst);


dst and vroot should be freed.
And I wonder vm->def->hostdevs shouldn't be restored when attaching failed?


> +    return ret;
> +}
> +
> +

[...]

> +
> +static int
> +lxcDomainDetachDeviceHostdevStorageLive(virLXCDriverPtr driver,
> +                                        virDomainObjPtr vm,
> +                                        virDomainDeviceDefPtr dev)
> +{
> +    virLXCDomainObjPrivatePtr priv = vm->privateData;
> +    virDomainHostdevDefPtr def = NULL;
> +    virCgroupPtr group = NULL;
> +    int i, ret = -1;
> +    char *dst = NULL;
> +
> +    if (!priv->initpid) {
> +        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
> +                       _("Cannot attach disk until init PID is known"));

Need proper error msg here.

ACK




More information about the libvir-list mailing list