WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-devel

Re: [Xen-devel] [PATCH] libxl: sane disk backend selection and validatio

To: Ian Jackson <Ian.Jackson@xxxxxxxxxxxxx>
Subject: Re: [Xen-devel] [PATCH] libxl: sane disk backend selection and validation
From: Ian Campbell <Ian.Campbell@xxxxxxxxxx>
Date: Wed, 6 Jul 2011 16:49:19 +0100
Cc: "xen-devel@xxxxxxxxxxxxxxxxxxx" <xen-devel@xxxxxxxxxxxxxxxxxxx>
Delivery-date: Wed, 06 Jul 2011 08:49:55 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
In-reply-to: <19988.31275.221429.48662@xxxxxxxxxxxxxxxxxxxxxxxx>
List-help: <mailto:xen-devel-request@lists.xensource.com?subject=help>
List-id: Xen developer discussion <xen-devel.lists.xensource.com>
List-post: <mailto:xen-devel@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=unsubscribe>
Organization: Citrix Systems, Inc.
References: <19988.31275.221429.48662@xxxxxxxxxxxxxxxxxxxxxxxx>
Sender: xen-devel-bounces@xxxxxxxxxxxxxxxxxxx
On Wed, 2011-07-06 at 16:07 +0100, Ian Jackson wrote:
> Introduce a new function libxl__device_disk_set_backend which
> does some sanity checks and determines which backend ought to be used.
> 
> If the caller specifies LIBXL_DISK_BACKEND_UNKNOWN (which has the
> value 0), it tries PHY, TAP and QDISK in that order.  Otherwise it
> tries only the specified value.
> 
> libxl__device_disk_set_backend (and its helper function
> disk_try_backend) inherit the role (and small amounts of the code)
> from validate_virtual_disk.  This is called during do_domain_create
> and also from libxl_disk_device_add (for the benefit of hotplug
> devices).

do_domain_create adds disks using libxl_disk_device_add, so is it really
needed in both?

> 
> It also now takes over the role of the scattered fragments of backend
> selection found in libxl_device_disk_add,
> libxl_device_disk_local_attach and libxl__need_xenpv_qemu.  These
> latter functions now simply do the job for the backend they find has
> already been specified and checked.
> 
> The restrictions on the capabilities of each backend, as expressed in
> disk_try_backend (and to an extent in libxl_device_disk_local_attach)
> are intended to be identical to the previous arrangements.
> 
> In 23618:3173b68c8a94 combined with 23622:160f7f39841b,
> 23623:c7180c353eb2, "xl" effectively became much more likely to select
> TAP as the backend.  With this change to libxl the default backend
> selected by the libxl__device_disk_set_backend is intended to once
> again to be PHY where possible.
> 
> Signed-off-by: Ian Jackson <ian.jackson@xxxxxxxxxxxxx>

> diff -r 7e4404a8f5f9 tools/libxl/libxl_create.c
> --- a/tools/libxl/libxl_create.c        Mon Jul 04 07:57:32 2011 +0100
> +++ b/tools/libxl/libxl_create.c        Wed Jul 06 16:06:32 2011 +0100
> @@ -424,6 +424,13 @@ static int do_domain_create(libxl__gc *g
>              goto error_out;
>      }
> 
> +
> +    for (i = 0; i < d_config->num_disks; i++) {
> +        ret = libxl__device_disk_set_backend(gc, &d_config->disks[i],
> +                                             dm_info);
> +        if (ret) goto error_out;
> +    }

I presume this happens too late for the locally attached case since you
call it there too?

> +
>      if ( restore_fd < 0 ) {
>          ret = libxl_run_bootloader(ctx, &d_config->b_info, 
> d_config->num_disks > 0 ? &d_config->disks[0] : NULL, domid);
>          if (ret) {
> diff -r 7e4404a8f5f9 tools/libxl/libxl_device.c
> --- a/tools/libxl/libxl_device.c        Mon Jul 04 07:57:32 2011 +0100
> +++ b/tools/libxl/libxl_device.c        Wed Jul 06 16:06:32 2011 +0100
> @@ -116,6 +116,140 @@ retry_transaction:
>      rc = 0;
>  out:
>      return rc;
> +}
> +
> +typedef struct {
> +    libxl__gc *gc;
> +    libxl_device_disk *disk;
> +    const libxl_device_model_info *dm_info;
> +    struct stat stab;
> +} disk_try_backend_args;

The struct seems a little like overkill compared with just passing the
arguments but nevermind.

> +
> +static int disk_try_backend(disk_try_backend_args *a,
> +                            libxl_disk_backend backend) {
> +    /* returns 0 (ie, DISK_BACKEND_UNKNOWN) on failure, or
> +     * backend on success */
> +    libxl_ctx *ctx = libxl__gc_owner(a->gc);
> +    switch (backend) {
> +
> +    case LIBXL_DISK_BACKEND_PHY:
> +        if (!(a->disk->format == LIBXL_DISK_FORMAT_RAW ||
> +              a->disk->format == LIBXL_DISK_FORMAT_EMPTY)) {
> +            LIBXL__LOG(ctx, LIBXL__LOG_DEBUG, "Disk vdev=%s, backend phy"
> +                       " unsuitable due to format %s",
> +                       a->disk->vdev,
> +                       libxl__device_disk_string_of_format(a->disk->format));
> +            return 0;
> +        }
> +        if (a->disk->format != LIBXL_DISK_FORMAT_EMPTY &&
> +            !S_ISBLK(a->stab.st_mode)) {
> +            LIBXL__LOG(ctx, LIBXL__LOG_DEBUG, "Disk vdev=%s, backend phy"
> +                       " unsuitable as phys path not a block device",
> +                       a->disk->vdev);
> +            return ERROR_INVAL;

Can phy devices really be empty? Or must they refer to a block device
(which may itself be an empty CD-ROM device but that's not the same)?

> +        }
> +
> +        return backend;
> +
> +    case LIBXL_DISK_BACKEND_TAP:
> +        if (!libxl__blktap_enabled(a->gc)) {
> +            LIBXL__LOG(ctx, LIBXL__LOG_DEBUG, "Disk vdev=%s, backend tap"
> +                       " unsuitable because blktap not available",
> +                       a->disk->vdev);
> +            return 0;
> +        }
> +        if (a->disk->format == LIBXL_DISK_FORMAT_EMPTY ||
> +            (S_ISREG(a->stab.st_mode) && !a->stab.st_size)) {
> +            LIBXL__LOG(ctx, LIBXL__LOG_DEBUG, "Disk vdev=%s, backend tap"
> +                       " unsuitable because empty devices not supported",
> +                       a->disk->vdev);
> +            return 0;
> +        }
> +        return backend;
> +
> +    case LIBXL_DISK_BACKEND_QDISK:
> +        if (!a->dm_info) {
> +            LIBXL__LOG(ctx, LIBXL__LOG_DEBUG, "Disk vdev=%s, backend qdisk"
> +                       " unsuitable for dynamic attach",
> +                       a->disk->vdev);
> +            return 0;
> +        }
> +        switch (a->dm_info->device_model_version) {
> +        case LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN_TRADITIONAL:
> +            LIBXL__LOG(ctx, LIBXL__LOG_DEBUG, "Disk vdev=%s, backend qdisk"
> +                       " unsuitable because using old qemu",
> +                       a->disk->vdev);

Wasn't that support backported at one point?

> +            return 0;
> +        case LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN:
> +            return backend;
> +        }
> +        abort();
> +
> +    default:
> +        LIBXL__LOG(ctx, LIBXL__LOG_DEBUG, "Disk vdev=%s, backend "
> +                   " %d unknown", a->disk->vdev, backend);
> +        return 0;
> +
> +    }
> +}
> +
> +int libxl__device_disk_set_backend(libxl__gc *gc, libxl_device_disk *disk,
> +                                   const libxl_device_model_info *dm_info) {
> +    libxl_ctx *ctx = libxl__gc_owner(gc);
> +    libxl_disk_backend ok;
> +    disk_try_backend_args a;
> +
> +    a.gc = gc;
> +    a.disk = disk;
> +    a.dm_info = dm_info;
> +
> +    LIBXL__LOG(ctx, LIBXL__LOG_DEBUG, "Disk vdev=%s spec.backend=%s",
> +               disk->vdev,
> +               libxl__device_disk_string_of_backend(disk->backend));

This (and other similar) could be libxl_disk_backend_to_string since
23568:d67133289286. In fact the original could possibly be nuked? (or is
it used to lookups the xenstore name in some cases which may not match
the enum name?).

> +
> +    if (disk->format == LIBXL_DISK_FORMAT_EMPTY) {
> +        if (!disk->is_cdrom) {
> +            LIBXL__LOG(ctx, LIBXL__LOG_ERROR, "Disk vdev=%s is empty"
> +                       " but not cdrom",
> +                       disk->vdev);
> +            return ERROR_INVAL;
> +        }
> +        memset(&a.stab, 0, sizeof(a.stab));
> +    } else {
> +        if (stat(disk->pdev_path, &a.stab)) {
> +            LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "Disk vdev=%s "
> +                             "failed to stat: %s",
> +                             disk->vdev, disk->pdev_path);
> +            return ERROR_INVAL;
> +        }
> +        if (!S_ISBLK(a.stab.st_mode) &
> +            !S_ISREG(a.stab.st_mode)) {
> +            LIBXL__LOG(ctx, LIBXL__LOG_ERROR, "Disk vdev=%s "
> +                             "phys path is not a block dev or file: %s",
> +                             disk->vdev, disk->pdev_path);
> +            return ERROR_INVAL;
> +        }
> +    }
> +
> +    if (disk->backend != LIBXL_DISK_BACKEND_UNKNOWN) {
> +        ok= disk_try_backend(&a, disk->backend);
> +    } else {
> +        ok=
> +            disk_try_backend(&a, LIBXL_DISK_BACKEND_PHY) ?:
> +            disk_try_backend(&a, LIBXL_DISK_BACKEND_TAP) ?:
> +            disk_try_backend(&a, LIBXL_DISK_BACKEND_QDISK);
> +        if (ok)
> +            LIBXL__LOG(ctx, LIBXL__LOG_DEBUG, "Disk vdev=%s, using backend 
> %s",
> +                       disk->vdev,
> +                       libxl__device_disk_string_of_backend(ok));
> +    }
> +    if (!ok) {
> +        LIBXL__LOG(ctx, LIBXL__LOG_ERROR, "no suitable backend for disk %s",
> +                   disk->vdev);
> +        return ERROR_INVAL;
> +    }
> +    disk->backend = ok;
> +    return 0;
>  }
> 
>  char *libxl__device_disk_string_of_format(libxl_disk_format format)
> diff -r 7e4404a8f5f9 tools/libxl/libxl_dm.c
> --- a/tools/libxl/libxl_dm.c    Mon Jul 04 07:57:32 2011 +0100
> +++ b/tools/libxl/libxl_dm.c    Wed Jul 06 16:06:32 2011 +0100
> @@ -1001,25 +1001,18 @@ int libxl__need_xenpv_qemu(libxl__gc *gc
>      }
> 
>      if (nr_disks > 0) {
> -        int blktap_enabled = -1;
>          for (i = 0; i < nr_disks; i++) {
>              switch (disks[i].backend) {
> -            case LIBXL_DISK_BACKEND_TAP:
> -                if (blktap_enabled == -1)
> -                    blktap_enabled = libxl__blktap_enabled(gc);
> -                if (!blktap_enabled) {
> -                    ret = 1;
> -                    goto out;
> -                }
> -                break;
> -
>              case LIBXL_DISK_BACKEND_QDISK:
>                  ret = 1;
>                  goto out;
> 
> +            case LIBXL_DISK_BACKEND_TAP:
>              case LIBXL_DISK_BACKEND_PHY:
> -            case LIBXL_DISK_BACKEND_UNKNOWN:
>                  break;
> +
> +            case LIBXL_DISK_FORMAT_UNKNOWN:
> +                abort(); /* impossible due to libxl__device_disk_set_backend 
> */

This switch could become a simple if (x == .... QDISK) now...

>              }
>          }
>      }
> diff -r 7e4404a8f5f9 tools/libxl/libxl_internal.h
> --- a/tools/libxl/libxl_internal.h      Mon Jul 04 07:57:32 2011 +0100
> +++ b/tools/libxl/libxl_internal.h      Wed Jul 06 16:06:32 2011 +0100
> @@ -205,6 +205,8 @@ _hidden void libxl__userdata_destroyall(
>  /* from xl_device */
>  _hidden char *libxl__device_disk_string_of_backend(libxl_disk_backend 
> backend);
>  _hidden char *libxl__device_disk_string_of_format(libxl_disk_format format);
> +_hidden int libxl__device_disk_set_backend(libxl__gc*, libxl_device_disk 
> *disk,
> +                                   const libxl_device_model_info *dm_info);
> 
>  _hidden int libxl__device_physdisk_major_minor(const char *physpath, int 
> *major, int *minor);
>  _hidden int libxl__device_disk_dev_number(const char *virtpath,
> 
> _______________________________________________
> Xen-devel mailing list
> Xen-devel@xxxxxxxxxxxxxxxxxxx
> http://lists.xensource.com/xen-devel



_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel