1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
|
#DPATCHLEVEL=1
--- gnumach-20040229.orig/linux/dev/glue/block.c
+++ gnumach-20040229/linux/dev/glue/block.c
@@ -789,6 +789,7 @@
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
@@ -1164,6 +1165,7 @@
{
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;
@@ -1174,18 +1176,16 @@
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;
@@ -1202,7 +1202,7 @@
}
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)
@@ -1245,6 +1245,13 @@
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
@@ -1704,6 +1711,16 @@
return D_SUCCESS;
}
+
+static void
+device_no_senders (mach_no_senders_notification_t *ns)
+{
+ device_t dev;
+
+ dev = (device_t) ((ipc_port_t) ns->not_header.msgh_remote_port) -> ip_kobject;
+ device_close_forced (dev->emul_data, 1);
+}
+
struct device_emulation_ops linux_block_emulation_ops =
{
NULL,
@@ -1719,7 +1736,7 @@
device_get_status,
NULL,
NULL,
- NULL,
+ device_no_senders,
NULL,
NULL
};
--- gnumach-20040229.orig/i386/i386at/i386at_ds_routines.c
+++ gnumach-20040229/i386/i386at/i386at_ds_routines.c
@@ -229,7 +229,8 @@
mach_no_senders_notification_t *ns;
ns = (mach_no_senders_notification_t *) msg;
- dev = (device_t) ns->not_header.msgh_remote_port;
+ dev = (device_t) ((ipc_port_t) ns->not_header.msgh_remote_port)
+ -> ip_kobject;
if (dev->emul_ops->no_senders)
(*dev->emul_ops->no_senders) (ns);
return TRUE;
|