libxl__device_action_to_string(aodev->action),
aodev->rc ? "failed" : "succeed");
- if (aodev->action == LIBXL__DEVICE_ACTION_REMOVE)
- free(aodev->dev);
-
libxl__nested_ao_free(aodev->ao);
}
GCNEW(aodev);
libxl__prepare_ao_device(ao, aodev);
- aodev->dev = dev;
+ /*
+ * Clone the libxl__device to avoid races if remove_device is called
+ * before the device addition has finished.
+ */
+ GCNEW(aodev->dev);
+ *aodev->dev = *dev;
aodev->action = LIBXL__DEVICE_ACTION_ADD;
aodev->callback = device_complete;
libxl__wait_device_connection(egc, aodev);
GCNEW(aodev);
libxl__prepare_ao_device(ao, aodev);
- aodev->dev = dev;
+ /*
+ * Clone the libxl__device to avoid races if there's a add_device
+ * running in parallel.
+ */
+ GCNEW(aodev->dev);
+ *aodev->dev = *dev;
aodev->action = LIBXL__DEVICE_ACTION_REMOVE;
aodev->callback = device_complete;
libxl__initiate_device_generic_remove(egc, aodev);
goto out;
}
libxl__device_destroy(gc, dev);
- free(dev);
/* Fall through to return > 0, no ao has been dispatched */
default:
rc = 1;
char *p, *path;
const char *sstate, *sonline;
int state, online, rc, num_devs;
- libxl__device *dev = NULL;
+ libxl__device *dev;
libxl__ddomain_device *ddev = NULL;
libxl__ddomain_guest *dguest = NULL;
bool free_ao = false;
goto skip;
online = atoi(sonline);
- dev = libxl__zalloc(NOGC, sizeof(*dev));
+ GCNEW(dev);
rc = libxl__parse_backend_path(gc, path, dev);
if (rc)
goto skip;
* to the list of active devices for a given guest.
*/
ddev = libxl__zalloc(NOGC, sizeof(*ddev));
- ddev->dev = dev;
+ ddev->dev = libxl__zalloc(NOGC, sizeof(*ddev->dev));
+ *ddev->dev = *dev;
LIBXL_SLIST_INSERT_HEAD(&dguest->devices, ddev, next);
LOGD(DEBUG, dev->domid, "Added device %s to the list of active devices",
path);
/*
* Removal of an active device, remove it from the list and
* free it's data structures if they are no longer needed.
- *
- * The free of the associated libxl__device is left to the
- * helper remove_device function.
*/
LIBXL_SLIST_REMOVE(&dguest->devices, ddev, libxl__ddomain_device,
next);
if (rc > 0)
free_ao = true;
+ free(ddev->dev);
free(ddev);
/* If this was the last device in the domain, remove it from the list */
num_devs = dguest->num_vifs + dguest->num_vbds + dguest->num_qdisks;
skip:
libxl__nested_ao_free(nested_ao);
- free(dev);
+ if (ddev)
+ free(ddev->dev);
free(ddev);
free(dguest);
return;