[libvirt] [RFC PATCH] Prevent defining a domain has disk used by other domain

Osier Yang jyang at redhat.com
Fri Sep 23 08:17:28 UTC 2011


于 2011年09月23日 15:59, Osier Yang 写道:
> $subject + "If the disk is shared and readonly."

s/disk is/disk is not/

>
> If the disk is not shared or readonly, the later started domain
> will relabel the disk, thus the first domain will lose the permission
> to write to the disk and be corrupt.
>
> --
> I'm not sure if it's the design to allow multiple domains use
> same disk not shared and readonly. So this patch just gives a
> demo of the implementation (it skips the checking of nbd disk,
> and only changes qemu driver), 

Hmm, preventing the relabeling in security driver instead might be the
more proper way? (If the disk source is used by other *running* domain,
then quit relabeling and exit with error).

However, this won't prevent one using same disk source for multiple domains
if security_driver is disabled.

And if security_driver is disabled, there will be no permission problem, all
the domains can write to the same disk source, thus it might cause
inconsistency
between the domains or corrupt.

> to see whether if the pricinple
> is right or not.
> ---
>  src/conf/domain_conf.c   |   34 ++++++++++++++++++++++++++++++++++
>  src/conf/domain_conf.h   |    2 ++
>  src/libvirt_private.syms |    1 +
>  src/qemu/qemu_driver.c   |   24 ++++++++++++++++++++++++
>  4 files changed, 61 insertions(+), 0 deletions(-)
>
> diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
> index 7463d7c..b64450b 100644
> --- a/src/conf/domain_conf.c
> +++ b/src/conf/domain_conf.c
> @@ -655,6 +655,40 @@ virDomainObjPtr virDomainFindByName(const virDomainObjListPtr doms,
>      return obj;
>  }
>  
> +static int
> +virDomainObjListSearchDiskPath(const void *payload,
> +                               const void *name ATTRIBUTE_UNUSED,
> +                               const void *data)
> +{
> +    virDomainObjPtr obj = (virDomainObjPtr)payload;
> +    int i;
> +    int want = 0;
> +    const char *path = NULL;
> +
> +    path = (const char *)data;
> +
> +    virDomainObjLock(obj);
> +    for (i = 0; obj->def->ndisks; i++) {
> +        if (STREQ(obj->def->disks[i]->src, path)) {
> +            want = 1;
> +            break;
> +        }
> +    }
> +    virDomainObjUnlock(obj);
> +
> +    return want;
> +}
> +
> +virDomainObjPtr
> +virDomainFindByDiskPath(const virDomainObjListPtr doms,
> +                        const char *path)
> +{
> +    virDomainObjPtr obj = NULL;
> +    obj = virHashSearch(doms->objs, virDomainObjListSearchDiskPath, path);
> +    if (obj)
> +        virDomainObjLock(obj);
> +    return obj;
> +}
>  
>  bool virDomainObjTaint(virDomainObjPtr obj,
>                         enum virDomainTaintFlags taint)
> diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
> index 371f270..d7d42dd 100644
> --- a/src/conf/domain_conf.h
> +++ b/src/conf/domain_conf.h
> @@ -1549,6 +1549,8 @@ virDomainObjPtr virDomainFindByUUID(const virDomainObjListPtr doms,
>                                      const unsigned char *uuid);
>  virDomainObjPtr virDomainFindByName(const virDomainObjListPtr doms,
>                                      const char *name);
> +virDomainObjPtr virDomainFindByDiskPath(const virDomainObjListPtr doms,
> +                                        const char *path);
>  
>  bool virDomainObjTaint(virDomainObjPtr obj,
>                         enum virDomainTaintFlags taint);
> diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
> index 8235ea1..c33cb2d 100644
> --- a/src/libvirt_private.syms
> +++ b/src/libvirt_private.syms
> @@ -302,6 +302,7 @@ virDomainFSTypeToString;
>  virDomainFindByID;
>  virDomainFindByName;
>  virDomainFindByUUID;
> +virDomainFindByDiskPath;
>  virDomainGetRootFilesystem;
>  virDomainGraphicsAuthConnectedTypeFromString;
>  virDomainGraphicsAuthConnectedTypeToString;
> diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
> index 0d0bea2..a448a0b 100644
> --- a/src/qemu/qemu_driver.c
> +++ b/src/qemu/qemu_driver.c
> @@ -4796,6 +4796,7 @@ static virDomainPtr qemudDomainDefine(virConnectPtr conn, const char *xml) {
>      virDomainPtr dom = NULL;
>      virDomainEventPtr event = NULL;
>      int dupVM;
> +    int i;
>  
>      qemuDriverLock(driver);
>      if (!(def = virDomainDefParseString(driver->caps, xml,
> @@ -4809,6 +4810,29 @@ static virDomainPtr qemudDomainDefine(virConnectPtr conn, const char *xml) {
>      if ((dupVM = virDomainObjIsDuplicate(&driver->domains, def, 0)) < 0)
>          goto cleanup;
>  
> +    /* Make sure no disk is used by other domain, if it's not
> +     * either shareable or readonly.
> +     */
> +    for (i = 0; i < def->ndisks; i++) {
> +        /* XXX: Do we also need to check if same host&port is used by
> +         * other domain for disk of nbd type?
> +         */
> +        if (def->disks[i]->type == VIR_DOMAIN_DISK_TYPE_NETWORK &&
> +            def->disks[i]->protocol == VIR_DOMAIN_DISK_PROTOCOL_NBD)
> +            continue;
> +
> +        if (!def->disks[i]->shared &&
> +            !def->disks[i]->readonly &&
> +            (vm = virDomainFindByDiskPath(&driver->domains,
> +                                          def->disks[i]->src))
> ) {
> +            qemuReportError(VIR_ERR_INVALID_ARG,
> +                            _("disk '%s' already used by domain '%s'"),
> +                            def->disks[i]->src,
> +                            vm->def->name);
> +            goto cleanup;
> +        }
> +    }
> +
>      if (qemudCanonicalizeMachine(driver, def) < 0)
>          goto cleanup;
>  




More information about the libvir-list mailing list