// 1 on success, negative on error
}
+ Note that the current model has deferred rendezvous and allows
+ for user-side device disconnection and reconnection. It is important
+ to note that this implementation does NOT deal with state discrepency
+ between the palacios-side and the user-side. For example, a user-side
+ device can disconnect, a palacios-side request can then fail, and
+ when the user-side device reconnects, it is unaware of this failure.
*/
**************************************************************************************/
-static v3_host_dev_t palacios_host_dev_open(char *url,
- v3_bus_class_t bus,
- v3_guest_dev_t gdev,
- void *host_priv_data)
+
+/* Attempt to rendezvous with the user device if no device is currently connected */
+static int palacios_host_dev_rendezvous(struct palacios_host_device_user *dev)
+{
+ unsigned long f;
+ int i;
+
+ if (dev->connected) {
+ return 0;
+ }
+
+
+ INFO("palacios: attempting new rendezvous for host device \"%s\"\n",dev->url);
+
+ // Now wait until we are noticed!
+ for (i=0;i<RENDEZVOUS_WAIT_SECS/RENDEZVOUS_RETRY_SECS;i++) {
+ spin_lock_irqsave(&(dev->lock),f);
+ if (dev->connected) {
+ INFO("palacios: connection with user side established for host device \"%s\" fd=%d\n",dev->url,dev->fd);
+ spin_unlock_irqrestore(&(dev->lock),f);
+ return 0;
+ }
+ spin_unlock_irqrestore(&(dev->lock),f);
+ ssleep(RENDEZVOUS_RETRY_SECS);
+ }
+
+ ERROR("palacios: timeout waiting for user side to connect to host device \"%s\"",dev->url);
+
+ // We stay in the list because a future rendezvous might happen
+
+ return -1;
+}
+
+
+/* Creates the device without rendezvous */
+static v3_host_dev_t palacios_host_dev_open_deferred(char *url,
+ v3_bus_class_t bus,
+ v3_guest_dev_t gdev,
+ void *host_priv_data)
{
struct v3_guest *guest= (struct v3_guest*)host_priv_data;
struct palacios_host_device_user *dev;
- unsigned long f1,f2;
- int i;
struct palacios_host_dev * host_dev = NULL;
+ unsigned long f;
/*
I will create the device in the list and then wait
}
- host_dev = get_vm_ext_data(guest, "HOST_DEV_INTERFACE");
+ host_dev = get_vm_ext_data(guest, "HOST_DEVICE_INTERFACE");
if (host_dev == NULL) {
- printk("Error locating vm host data for HOST_DEV_INTERFACE\n");
+ printk("Error locating vm host data for HOST_DEVICE_INTERFACE\n");
return 0;
}
}
// Check to see if a device of this url already exists, which would be ugly
- spin_lock_irqsave(&(host_dev->lock),f1);
+ spin_lock_irqsave(&(host_dev->lock),f);
list_for_each_entry(dev,&(host_dev->devs), node) {
if (!strncasecmp(url,dev->url,MAX_URL)) {
// found it
- spin_unlock_irqrestore(&(host_dev->lock),f1);
+ spin_unlock_irqrestore(&(host_dev->lock),f);
ERROR("palacios: a host device with url \"%s\" already exists in the guest!\n",url);
return NULL;
}
}
- spin_unlock_irqrestore(&(host_dev->lock),f1);
+ spin_unlock_irqrestore(&(host_dev->lock),f);
INFO("palacios: creating host device \"%s\"\n",url);
init_waitqueue_head(&(dev->user_wait_queue));
init_waitqueue_head(&(dev->host_wait_queue));
- INFO("palacios: attempting to rendezvous with user side of host device \"%s\"\n",url);
-
// Insert ourselves into the list
- spin_lock_irqsave(&(host_dev->lock),f1);
+ spin_lock_irqsave(&(host_dev->lock),f);
list_add(&(dev->node),&(host_dev->devs));
- spin_unlock_irqrestore(&(host_dev->lock),f1);
+ spin_unlock_irqrestore(&(host_dev->lock),f);
+
+ INFO("palacios: host device \"%s\" created with deferred rendezvous\n",url);
+
+ return dev;
-
- // Now wait until we are noticed!
- for (i=0;i<RENDEZVOUS_WAIT_SECS/RENDEZVOUS_RETRY_SECS;i++) {
- spin_lock_irqsave(&(dev->lock),f2);
- if (dev->connected){
- INFO("palacios: connection with user side established for host device \"%s\" fd=%d\n",dev->url,dev->fd);
- spin_unlock_irqrestore(&(dev->lock),f2);
- return dev;
- }
- spin_unlock_irqrestore(&(dev->lock),f2);
- ssleep(RENDEZVOUS_RETRY_SECS);
- }
-
- ERROR("palacios: timeout waiting for user side to connect to host device \"%s\"",url);
-
- // get us out of the list
- spin_lock_irqsave(&(host_dev->lock),f1);
- list_del(&(dev->node));
- spin_unlock_irqrestore(&(host_dev->lock),f1);
-
- palacios_host_dev_user_free(dev);
-
- return NULL;
}
+
+
static int palacios_host_dev_close(v3_host_dev_t hostdev)
{
unsigned long f1, f2;
return -1;
}
- host_dev = get_vm_ext_data(dev->guest, "HOST_DEV_INTERFACE");
+ host_dev = get_vm_ext_data(dev->guest, "HOST_DEVICE_INTERFACE");
if (host_dev == NULL) {
spin_lock_irqsave(&(dev->lock),f);
- if (dev->waiting) {
+ if (palacios_host_dev_rendezvous(dev)) {
spin_unlock_irqrestore(&(dev->lock),f);
- ERROR("palacios: guest issued i/o read request with host device \"%s\" in wrong state (waiting=%d, connected=%d)\n",dev->url,dev->waiting,dev->connected);
+ ERROR("palacios: ignoring request as user side is not connected (and did not rendezvous) for host device \"%s\"\n",dev->url);
return 0;
}
- if (!dev->connected) {
+ if (dev->waiting) {
spin_unlock_irqrestore(&(dev->lock),f);
- ERROR("palacios: ignoring request as user side is not connected for host device \"%s\"\n",dev->url);
+ ERROR("palacios: guest issued i/o read request with host device \"%s\" in wrong state (waiting=%d, connected=%d)\n",dev->url,dev->waiting,dev->connected);
return 0;
}
+
// resize request (no data)
spin_lock_irqsave(&(dev->lock),f);
- if (dev->waiting) {
+ if (palacios_host_dev_rendezvous(dev)) {
spin_unlock_irqrestore(&(dev->lock),f);
- ERROR("palacios: guest issued memory read request with host device \"%s\" in wrong state (waiting=%d, connected=%d)\n",dev->url,dev->waiting,dev->connected);
+ ERROR("palacios: ignoring request as user side is not connected (and did not rendezvous) for host device \"%s\"\n",dev->url);
return 0;
}
- if (!dev->connected) {
+
+ if (dev->waiting) {
spin_unlock_irqrestore(&(dev->lock),f);
- ERROR("palacios: ignoring request as user side is not connected for host device \"%s\"\n",dev->url);
+ ERROR("palacios: guest issued memory read request with host device \"%s\" in wrong state (waiting=%d, connected=%d)\n",dev->url,dev->waiting,dev->connected);
return 0;
}
spin_lock_irqsave(&(dev->lock),f);
- if (dev->waiting) {
+ if (palacios_host_dev_rendezvous(dev)) {
spin_unlock_irqrestore(&(dev->lock),f);
- ERROR("palacios: guest issued config read request with host device \"%s\" in wrong state (waiting=%d, connected=%d)\n",dev->url,dev->waiting,dev->connected);
+ ERROR("palacios: ignoring request as user side is not connected (and did not rendezvous) for host device \"%s\"\n",dev->url);
return 0;
}
- if (!dev->connected) {
+
+ if (dev->waiting) {
spin_unlock_irqrestore(&(dev->lock),f);
- ERROR("palacios: ignoring request as user side is not connected for host device \"%s\"\n",dev->url);
+ ERROR("palacios: guest issued config read request with host device \"%s\" in wrong state (waiting=%d, connected=%d)\n",dev->url,dev->waiting,dev->connected);
return 0;
}
spin_lock_irqsave(&(dev->lock),f);
- if (dev->waiting) {
+ if (palacios_host_dev_rendezvous(dev)) {
spin_unlock_irqrestore(&(dev->lock),f);
- ERROR("palacios: guest issued i/o write request with host device \"%s\" in wrong state (waiting=%d, connected=%d)\n",dev->url,dev->waiting,dev->connected);
+ ERROR("palacios: ignoring request as user side is not connected (and did not rendezvous) for host device \"%s\"\n",dev->url);
return 0;
}
- if (!dev->connected) {
+
+ if (dev->waiting) {
spin_unlock_irqrestore(&(dev->lock),f);
- ERROR("palacios: ignoring request as user side is not connected for host device \"%s\"\n",dev->url);
+ ERROR("palacios: guest issued i/o write request with host device \"%s\" in wrong state (waiting=%d, connected=%d)\n",dev->url,dev->waiting,dev->connected);
return 0;
}
spin_lock_irqsave(&(dev->lock),f);
- if (dev->waiting) {
+ if (palacios_host_dev_rendezvous(dev)) {
spin_unlock_irqrestore(&(dev->lock),f);
- ERROR("palacios: guest issued memory write request with host device \"%s\" in wrong state (waiting=%d, connected=%d)\n",dev->url,dev->waiting,dev->connected);
+ ERROR("palacios: ignoring request as user side is not connected (and did not rendezvous) for host device \"%s\"\n",dev->url);
return 0;
}
- if (!dev->connected) {
+
+ if (dev->waiting) {
spin_unlock_irqrestore(&(dev->lock),f);
- ERROR("palacios: ignoring request as user side is not connected for host device \"%s\"\n",dev->url);
+ ERROR("palacios: guest issued memory write request with host device \"%s\" in wrong state (waiting=%d, connected=%d)\n",dev->url,dev->waiting,dev->connected);
return 0;
}
spin_lock_irqsave(&(dev->lock),f);
- if (dev->waiting) {
+ if (palacios_host_dev_rendezvous(dev)) {
spin_unlock_irqrestore(&(dev->lock),f);
- ERROR("palacios: guest issued config write request with host device \"%s\" in wrong state (waiting=%d, connected=%d)\n",dev->url,dev->waiting,dev->connected);
+ ERROR("palacios: ignoring request as user side is not connected (and did not rendezvous) for host device \"%s\"\n",dev->url);
return 0;
}
- if (!dev->connected) {
+
+ if (dev->waiting) {
spin_unlock_irqrestore(&(dev->lock),f);
- ERROR("palacios: ignoring request as user side is not connected for host device \"%s\"\n",dev->url);
+ ERROR("palacios: guest issued config write request with host device \"%s\" in wrong state (waiting=%d, connected=%d)\n",dev->url,dev->waiting,dev->connected);
return 0;
}
static struct v3_host_dev_hooks palacios_host_dev_hooks = {
- .open = palacios_host_dev_open,
+ .open = palacios_host_dev_open_deferred,
.close = palacios_host_dev_close,
.read_io = palacios_host_dev_read_io,
.write_io = palacios_host_dev_write_io,
static struct linux_ext host_dev_ext = {
- .name = "HOST_DEV_INTERFACE",
+ .name = "HOST_DEVICE_INTERFACE",
.init = host_dev_init,
.deinit = NULL,
.guest_init = host_dev_guest_init,