[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH v1 05/10] libxl: synchronise configuration when we hotplug a device
Wei Liu writes ("[PATCH v1 05/10] libxl: synchronise configuration when we hotplug a device"): > We update JSON version first, then write to xenstore, so that we > maintain the following invariant: any device which is present in > xenstore has a corresponding entry in JSON. Thanks. As I said I'm rather thick-headed today so please forgive me if what I'm saying makes no sense. But here goes: > @@ -2193,21 +2217,56 @@ static void device_disk_add(libxl__egc *egc, uint32_t > domid, > goto out; > } > > + libxl_device_disk_copy(CTX, &disk_saved, disk); > + > + LOCK_DOMAIN_JSON_CONFIG(gc, domid, lock, rc); > + if (rc) goto out; > + > for (;;) { > rc = libxl__xs_transaction_start(gc, &t); > - if (rc) goto out; > + if (rc) { > + UNLOCK_DOMAIN_JSON_CONFIG(gc, domid, lock); > + goto out; > + } > + > + /* This is a loop, if disk has been added to JSON before, we > + * need to remove it, then add it later, because disk->vdev > + * might change. > + */ > + DEVICE_REMOVE_JSON(disk, disks, num_disks, domid, &disk_saved, > + COMPARE_DISK, rc); I don't think this is right. At this point it may be the case that the disk is already attached. I see in libxl__device_generic_add that we seem to unconditionally remove the device if we do an add of a device that's already there. I think this is probably wrong. But whether it is, or not, it is not correct to remove the entry from the json while it might be in xenstore. I think you may need to do a xenstore read here to check and take appropriate action if it's there. > + if (rc) { > + UNLOCK_DOMAIN_JSON_CONFIG(gc, domid, lock); > + goto out; > + } > > if (get_vdev) { > assert(get_vdev_user); > disk->vdev = get_vdev(gc, get_vdev_user, t); > if (disk->vdev == NULL) { > rc = ERROR_FAIL; > + UNLOCK_DOMAIN_JSON_CONFIG(gc, domid, lock); > goto out; > } > } > > + if (strcmp(disk_saved.vdev, disk->vdev)) { > + free(disk_saved.vdev); > + disk_saved.vdev = libxl__strdup(NOGC, disk->vdev); > + } > + > + DEVICE_ADD_JSON(disk, disks, num_disks, domid, &disk_saved, > + COMPARE_DISK, rc); > + if (rc) { > + UNLOCK_DOMAIN_JSON_CONFIG(gc, domid, lock); > + goto out; > + } > + > rc = libxl__device_disk_setdefault(gc, disk); > - if (rc) goto out; > + if (rc) { > + UNLOCK_DOMAIN_JSON_CONFIG(gc, domid, lock); > + goto out; > + } > > front = flexarray_make(gc, 16, 1); > back = flexarray_make(gc, 16, 1); > @@ -2217,6 +2276,7 @@ static void device_disk_add(libxl__egc *egc, uint32_t > domid, > if (rc != 0) { > LIBXL__LOG(ctx, LIBXL__LOG_ERROR, "Invalid or unsupported" > " virtual disk identifier %s", disk->vdev); > + UNLOCK_DOMAIN_JSON_CONFIG(gc, domid, lock); > goto out; > } > > @@ -2257,6 +2317,7 @@ static void device_disk_add(libxl__egc *egc, uint32_t > domid, > if (!dev) { > LOG(ERROR, "failed to get blktap devpath for %p\n", > disk->pdev_path); > + UNLOCK_DOMAIN_JSON_CONFIG(gc, domid, lock); > rc = ERROR_FAIL; > goto out; > } > @@ -2281,6 +2342,7 @@ static void device_disk_add(libxl__egc *egc, uint32_t > domid, > default: > LIBXL__LOG(ctx, LIBXL__LOG_ERROR, "unrecognized disk backend > type: %d\n", disk->backend); > rc = ERROR_INVAL; > + UNLOCK_DOMAIN_JSON_CONFIG(gc, domid, lock); > goto out; > } > > @@ -2343,9 +2405,14 @@ static void device_disk_add(libxl__egc *egc, uint32_t > domid, > > rc = libxl__xs_transaction_commit(gc, &t); > if (!rc) break; > - if (rc < 0) goto out; > + if (rc < 0) { > + UNLOCK_DOMAIN_JSON_CONFIG(gc, domid, lock); > + goto out; > + } > } > > + UNLOCK_DOMAIN_JSON_CONFIG(gc, domid, lock); > + > aodev->dev = device; > aodev->action = LIBXL__DEVICE_ACTION_ADD; > libxl__wait_device_connection(egc, aodev); > @@ -2353,6 +2420,7 @@ static void device_disk_add(libxl__egc *egc, uint32_t > domid, > rc = 0; > > out: > + libxl_device_disk_dispose(&disk_saved); > libxl__xs_transaction_abort(gc, &t); > aodev->rc = rc; > if (rc) aodev->callback(egc, aodev); > @@ -3009,6 +3077,11 @@ void libxl__device_nic_add(libxl__egc *egc, uint32_t > domid, > flexarray_t *back; > libxl__device *device; > unsigned int rc; > + int lock = -1; > + libxl_device_nic nic_saved; > + > + libxl_device_nic_init(&nic_saved); > + libxl_device_nic_copy(CTX, &nic_saved, nic); > > rc = libxl__device_nic_setdefault(gc, nic, domid); > if (rc) goto out; > @@ -3023,6 +3096,9 @@ void libxl__device_nic_add(libxl__egc *egc, uint32_t > domid, > } > } > > + nic_saved.devid = nic->devid; > + libxl__update_config_nic(gc, &nic_saved, nic); > + > GCNEW(device); > rc = libxl__device_from_nic(gc, domid, nic, device); > if ( rc != 0 ) goto out; > @@ -3079,17 +3155,31 @@ void libxl__device_nic_add(libxl__egc *egc, uint32_t > domid, > flexarray_append(front, "mac"); > flexarray_append(front, libxl__sprintf(gc, > LIBXL_MAC_FMT, > LIBXL_MAC_BYTES(nic->mac))); > + > + LOCK_DOMAIN_JSON_CONFIG(gc, domid, lock, rc); > + if (rc) goto out; > + > + DEVICE_ADD_JSON(nic, nics, num_nics, domid, nic, COMPARE_DEVID, rc); > + > + if (rc) { > + UNLOCK_DOMAIN_JSON_CONFIG(gc, domid, lock); > + goto out; > + } > + > 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); > > + UNLOCK_DOMAIN_JSON_CONFIG(gc, domid, lock); > + > aodev->dev = device; > aodev->action = LIBXL__DEVICE_ACTION_ADD; > libxl__wait_device_connection(egc, aodev); > > rc = 0; > out: > + libxl_device_nic_dispose(&nic_saved); > aodev->rc = rc; > if (rc) aodev->callback(egc, aodev); > return; > diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h > index 72d21ad..f27a6e98 100644 > --- a/tools/libxl/libxl_internal.h > +++ b/tools/libxl/libxl_internal.h > @@ -3254,6 +3254,105 @@ static inline void > libxl__update_config_vtpm(libxl__gc *gc, > libxl_uuid_copy(CTX, &dst->uuid, &src->uuid); > } > > +/* Macro used to add the new device to JSON template */ > +#define COMPARE_DEVID(a, b) ((a)->devid == (b)->devid) > +#define COMPARE_DISK(a, b) (!strcmp((a)->vdev, (b)->vdev)) > +#define COMPARE_PCI(a, b) ((a)->func == (b)->func && \ > + (a)->bus == (b)->bus && \ > + (a)->dev == (b)->dev) > + > +#define LOCK_DOMAIN_JSON_CONFIG(gc, domid, lock, rc) \ > + do { \ > + if (domid != LIBXL_TOOLSTACK_DOMID) \ > + rc = libxl__lock_domain_configuration(gc, domid, &lock); \ > + else \ > + rc = 0; \ > + } while (0) Can this test be perhaps moved into libxl__lock_domain_configuration ? Even if not, I don't think a macro is warranted here. You could make it an inline function which returns rc. > +#define DEVICE_ADD_JSON(type, ptr, cnt, domid, dev, compare, rc) \ This needs a good doc comment. See the doc comments for things like GCSPRINTF, CONTAINER_OF, CTYPE, etc., for the kind of thing that's helpful. > + do { \ > + int x; \ > + libxl_domain_config d_config; \ > + libxl_device_##type *p; \ We have -Wshadow so you need to namespace all of these variable names :-/. That is, give them names which are such that surrounding code won't clash with. Presumably this is the reason why you have `int x' rather than `int i' but that's not sufficient because in general the macro's user might have an `int x'. I suggest something like + int DAJ_x; \ + libxl_domain_config DAJ_cfg; \ + libxl_device_##type *DAJ_dev; \ or the like. The same goes for the `add_done' label. It should probably be `DAJ_out' (since it's a kind of `out'). You can get rid of the rc macro parameter if you: - replace the do{ } encapsulation with a gcc block expression ({ }) - make rc a namespaced local variable eg ({ \ int DAJ_rc; \ - end the ({ }) expression like this DAJ_rc; \ )} This would mean that the macro wouldn't set the caller's rc; it would instead return it like our other macros. The user would write rc = DEVICE_ADD_JSON(type, ptr, cnt, domid, dev, compare); if (rc) goto out; I considered whether it would be possible to make this macro a function instead but I think it's quite tricky because it would involve a lot of casting. (Eg of a function pointer type.) I haven't looked up the exact rules to see whether the resulting code would be legal C99 but I think it would probably be clumsier so we should probably stick with the macro. Thanks, Ian. _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx http://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |