[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] wating for backend changes (was Re: [PATCH v3 4/4] libxl: add support for vscsi)



How is new code supposed to wait for backend changes?

Right now there are two APIs for that:
- libxl__wait_for_backend loops for a while until it returns an error.
- libxl__ev_devstate_wait registers a watch and a timer.


In case of pvscsi there are three variants:
- new, can use libxl__wait_device_connection
- reconfigure, can use both of the above
- remove, may use DEFINE_DEVICE_REMOVE and its
  libxl__initiate_device_remove

The reconfigure case has to wait for various states, depending on the
state before the reconfiguration.

The pci code in libxl uses just libxl__wait_for_backend. Looking through
the history it seems the function was added just for pci. Is it a
deprecated function, should callers get converted to
libxl__ev_devstate_wait?

Olaf

On Fri, Mar 06, Olaf Hering wrote:

> +void libxl__device_vscsi_add(libxl__egc *egc, uint32_t domid,
> +                             libxl_device_vscsi *vscsi,
> +                             libxl__ao_device *aodev)
> +{
> +    STATE_AO_GC(aodev->ao);
> +    libxl_ctx *ctx = libxl__gc_owner(gc);
> +    flexarray_t *front;
> +    flexarray_t *back;
> +    libxl__device *device;
> +    char *be_path;
> +    unsigned int be_dirs = 0, rc, i;
> +
> +    if (vscsi->devid == -1) {
> +        rc = ERROR_FAIL;
> +        goto out;
> +    }
> +
> +    /* Prealloc key+value: 4 toplevel + 4 per device */
> +    i = 2 * (4 + (4 * vscsi->num_vscsi_devs));
> +    back = flexarray_make(gc, i, 1);
> +    front = flexarray_make(gc, 2 * 2, 1);
> +
> +    GCNEW(device);
> +    rc = libxl__device_from_vscsi(gc, domid, vscsi, device);
> +    if ( rc != 0 ) goto out;
> +
> +    /* Check if backend device path is already present */
> +    be_path = libxl__device_backend_path(gc, device);
> +    if (!libxl__xs_directory(gc, XBT_NULL, be_path, &be_dirs) || !be_dirs) {
> +        /* backend does not exist, create a new one */
> +        flexarray_append_pair(back, "frontend-id", GCSPRINTF("%d", domid));
> +        flexarray_append_pair(back, "online", "1");
> +        flexarray_append_pair(back, "state", "1");
> +        flexarray_append_pair(back, "feature-host", GCSPRINTF("%d", 
> !!vscsi->feature_host));
> +
> +        flexarray_append_pair(front, "backend-id", GCSPRINTF("%d", 
> vscsi->backend_domid));
> +        flexarray_append_pair(front, "state", "1");
> +    }
> +
> +    for (i = 0; i < vscsi->num_vscsi_devs; i++) {
> +        libxl_vscsi_dev *v = vscsi->vscsi_devs + i;
> +        /* Trigger removal, otherwise create new device */
> +        if (be_dirs) {
> +            unsigned int nb = 0;
> +            /* Preserve existing device */
> +            if (libxl__xs_directory(gc, XBT_NULL, 
> GCSPRINTF("%s/vscsi-devs/dev-%u", be_path, v->vscsi_dev_id), &nb) && nb) {
> +                /* Trigger device removal by forwarding state to 
> XenbusStateClosing */
> +                if (v->remove)
> +                    flexarray_append_pair(back, 
> GCSPRINTF("vscsi-devs/dev-%u/state", v->vscsi_dev_id), "5");
> +                continue;
> +            }
> +        }
> +        flexarray_append_pair(back, GCSPRINTF("vscsi-devs/dev-%u/p-devname", 
> v->vscsi_dev_id), v->p_devname);
> +        switch (v->pdev_type) {
> +            case LIBXL_VSCSI_PDEV_TYPE_WWN:
> +                flexarray_append_pair(back,
> +                                      GCSPRINTF("vscsi-devs/dev-%u/p-dev", 
> v->vscsi_dev_id),
> +                                      v->p_devname);
> +                break;
> +            case LIBXL_VSCSI_PDEV_TYPE_DEV:
> +            case LIBXL_VSCSI_PDEV_TYPE_HCTL:
> +                flexarray_append_pair(back,
> +                                      GCSPRINTF("vscsi-devs/dev-%u/p-dev", 
> v->vscsi_dev_id),
> +                                      GCSPRINTF("%u:%u:%u:%u", v->pdev.hst, 
> v->pdev.chn, v->pdev.tgt, v->pdev.lun));
> +                break;
> +            case LIBXL_VSCSI_PDEV_TYPE_INVALID:
> +            default:
> +                rc = ERROR_FAIL;
> +                goto out;
> +        }
> +        flexarray_append_pair(back, GCSPRINTF("vscsi-devs/dev-%u/v-dev", 
> v->vscsi_dev_id),
> +                              GCSPRINTF("%u:%u:%u:%u", v->vdev.hst, 
> v->vdev.chn, v->vdev.tgt, v->vdev.lun));
> +        flexarray_append_pair(back, GCSPRINTF("vscsi-devs/dev-%u/state", 
> v->vscsi_dev_id), "1");
> +    }
> +
> +    aodev->dev = device;
> +    /* Either create new host or reconfigure existing host */
> +    if (be_dirs == 0) {
> +        libxl__device_generic_add(gc, XBT_NULL, device,
> +                                  libxl__xs_kvs_of_flexarray(gc, back, 
> back->count),
> +                                  libxl__xs_kvs_of_flexarray(gc, front, 
> front->count),
> +                                  NULL);
> +        aodev->action = LIBXL__DEVICE_ACTION_ADD;
> +        libxl__wait_device_connection(egc, aodev);
> +        rc = 0;
> +        /* Done with new host */
> +        goto out;
> +    }
> +
> +    /* Only new devices, write them and do vscsi host reconfiguration */
> +    xs_transaction_t t;
> +retry_transaction:
> +    t = xs_transaction_start(ctx->xsh);
> +    libxl__xs_writev(gc, t, be_path,
> +                     libxl__xs_kvs_of_flexarray(gc, back, back->count));
> +    xs_write(ctx->xsh, t, GCSPRINTF("%s/state", be_path), "7", 2);
> +    if (!xs_transaction_end(ctx->xsh, t, 0)) {
> +        if (errno == EAGAIN)
> +            goto retry_transaction;
> +        LOGE(ERROR, "xs transaction failed");
> +        rc = ERROR_FAIL;
> +        goto out;
> +    }
> +    libxl__wait_for_backend(gc, be_path, "4");
> +
> +retry_transaction2:
> +    t = xs_transaction_start(ctx->xsh);
> +    for (i = 0; i < vscsi->num_vscsi_devs; i++) {
> +        libxl_vscsi_dev *v = vscsi->vscsi_devs + i;
> +        if (v->remove) {
> +            char *path, *val;
> +            path = GCSPRINTF("%s/vscsi-devs/dev-%u/state", be_path, 
> v->vscsi_dev_id);
> +            val = libxl__xs_read(gc, t, path);
> +            if (val && strcmp(val, "6") == 0) {
> +                path = GCSPRINTF("%s/vscsi-devs/dev-%u/state", be_path, 
> v->vscsi_dev_id);
> +                xs_rm(ctx->xsh, t, path);
> +                path = GCSPRINTF("%s/vscsi-devs/dev-%u/p-devname", be_path, 
> v->vscsi_dev_id);
> +                xs_rm(ctx->xsh, t, path);
> +                path = GCSPRINTF("%s/vscsi-devs/dev-%u/p-dev", be_path, 
> v->vscsi_dev_id);
> +                xs_rm(ctx->xsh, t, path);
> +                path = GCSPRINTF("%s/vscsi-devs/dev-%u/v-dev", be_path, 
> v->vscsi_dev_id);
> +                xs_rm(ctx->xsh, t, path);
> +                path = GCSPRINTF("%s/vscsi-devs/dev-%u", be_path, 
> v->vscsi_dev_id);
> +                xs_rm(ctx->xsh, t, path);
> +            } else {
> +                LOGE(ERROR, "%s: %s has %s, expected 6", __func__, path, 
> val);
> +            }
> +        }
> +    }
> +
> +    if (!xs_transaction_end(ctx->xsh, t, 0)) {
> +        if (errno == EAGAIN)
> +            goto retry_transaction2;
> +        LOGE(ERROR, "xs transaction failed");
> +        rc = ERROR_FAIL;
> +        goto out;
> +    }
> +    /* As we are not adding new device, skip waiting for it */
> +    libxl__ao_complete(egc, aodev->ao, 0);
> +
> +    rc = 0;
> +out:
> +    aodev->rc = rc;
> +    if(rc) aodev->callback(egc, aodev);
> +    return;
> +}

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.