summaryrefslogtreecommitdiff
path: root/linux
diff options
context:
space:
mode:
authorAlexey Dejneka <adejneka@comail.ru>2012-09-23 00:31:10 +0200
committerSamuel Thibault <samuel.thibault@ens-lyon.org>2012-09-23 00:38:46 +0200
commita564ecbc2cb4441ebac32ac5300bc7840569eb30 (patch)
tree20c4481ac6a54fa2ee2daf8cab7145560f005b59 /linux
parent9eacb0eab6eb8e35bb26ab3db660973fddf9e8fb (diff)
Fix CDROM door unlock on closure without device_close
* linux/dev/glue/block.c (device_open): Properly return devp on multiple opens. (device_close_forced): Renamed from device_close, when force parameter is 1, do not wait for open_count to become 0 before closing. (device_close): New function. (device_no_senders): New function. linux_block_emulation_ops: Use (device_no_senders).
Diffstat (limited to 'linux')
-rw-r--r--linux/dev/glue/block.c34
1 files changed, 26 insertions, 8 deletions
diff --git a/linux/dev/glue/block.c b/linux/dev/glue/block.c
index 63bc766..8c41f08 100644
--- a/linux/dev/glue/block.c
+++ b/linux/dev/glue/block.c
@@ -779,6 +779,7 @@ static struct block_data *open_list;
extern struct device_emulation_ops linux_block_emulation_ops;
static io_return_t device_close (void *);
+static io_return_t device_close_forced (void *, int);
/* Return a send right for block device BD. */
static ipc_port_t
@@ -1154,6 +1155,7 @@ out:
{
ipc_kobject_set (bd->port, IKO_NULL, IKOT_NONE);
ipc_port_dealloc_kernel (bd->port);
+ *devp = IP_NULL;
}
kfree ((vm_offset_t) bd, sizeof (struct block_data));
bd = NULL;
@@ -1164,18 +1166,16 @@ out:
bd->open_count = 1;
bd->next = open_list;
open_list = bd;
+ *devp = &bd -> device;
}
- if (IP_VALID (reply_port))
- ds_device_open_reply (reply_port, reply_port_type, err, dev_to_port (bd));
- else if (! err)
+ if (!IP_VALID (reply_port) && ! err)
device_close (bd);
-
- return MIG_NO_REPLY;
+ return err;
}
static io_return_t
-device_close (void *d)
+device_close_forced (void *d, int force)
{
struct block_data *bd = d, *bdp, **prev;
struct device_struct *ds = bd->ds;
@@ -1192,7 +1192,7 @@ device_close (void *d)
}
ds->busy = 1;
- if (--bd->open_count == 0)
+ if (force || --bd->open_count == 0)
{
/* Wait for pending I/O to complete. */
while (bd->iocount > 0)
@@ -1235,6 +1235,13 @@ device_close (void *d)
return D_SUCCESS;
}
+static io_return_t
+device_close (void *d)
+{
+ return device_close_forced (d, 0);
+}
+
+
#define MAX_COPY (VM_MAP_COPY_PAGE_LIST_MAX << PAGE_SHIFT)
/* Check block BN and size COUNT for I/O validity
@@ -1713,6 +1720,17 @@ device_set_status (void *d, dev_flavor_t flavor, dev_status_t status,
return D_INVALID_OPERATION;
}
+
+static void
+device_no_senders (mach_no_senders_notification_t *ns)
+{
+ device_t dev;
+
+ dev = dev_port_lookup((ipc_port_t) ns->not_header.msgh_remote_port);
+ assert(dev);
+ device_close_forced (dev->emul_data, 1);
+}
+
struct device_emulation_ops linux_block_emulation_ops =
{
NULL,
@@ -1728,7 +1746,7 @@ struct device_emulation_ops linux_block_emulation_ops =
device_get_status,
NULL,
NULL,
- NULL,
+ device_no_senders,
NULL,
NULL
};