Skip to content

Commit 04e5b1f

Browse files
jmberg-intelrichardweinberger
authored andcommitted
um: virtio: Remove device on disconnect
If the connection drops, just remove the device, we don't try to recover from this right now. Signed-off-by: Johannes Berg <[email protected]> Signed-off-by: Richard Weinberger <[email protected]>
1 parent 5c1f33e commit 04e5b1f

File tree

1 file changed

+45
-19
lines changed

1 file changed

+45
-19
lines changed

arch/um/drivers/virtio_uml.c

Lines changed: 45 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,13 @@
4242
#define to_virtio_uml_device(_vdev) \
4343
container_of(_vdev, struct virtio_uml_device, vdev)
4444

45+
struct virtio_uml_platform_data {
46+
u32 virtio_device_id;
47+
const char *socket_path;
48+
struct work_struct conn_broken_wk;
49+
struct platform_device *pdev;
50+
};
51+
4552
struct virtio_uml_device {
4653
struct virtio_device vdev;
4754
struct platform_device *pdev;
@@ -50,6 +57,7 @@ struct virtio_uml_device {
5057
u64 features;
5158
u64 protocol_features;
5259
u8 status;
60+
u8 registered:1;
5361
};
5462

5563
struct virtio_uml_vq_info {
@@ -107,12 +115,21 @@ static int vhost_user_recv_header(int fd, struct vhost_user_msg *msg)
107115
return full_read(fd, msg, sizeof(msg->header));
108116
}
109117

110-
static int vhost_user_recv(int fd, struct vhost_user_msg *msg,
118+
static int vhost_user_recv(struct virtio_uml_device *vu_dev,
119+
int fd, struct vhost_user_msg *msg,
111120
size_t max_payload_size)
112121
{
113122
size_t size;
114123
int rc = vhost_user_recv_header(fd, msg);
115124

125+
if (rc == -ECONNRESET && vu_dev->registered) {
126+
struct virtio_uml_platform_data *pdata;
127+
128+
pdata = vu_dev->pdev->dev.platform_data;
129+
130+
virtio_break_device(&vu_dev->vdev);
131+
schedule_work(&pdata->conn_broken_wk);
132+
}
116133
if (rc)
117134
return rc;
118135
size = msg->header.size;
@@ -125,7 +142,7 @@ static int vhost_user_recv_resp(struct virtio_uml_device *vu_dev,
125142
struct vhost_user_msg *msg,
126143
size_t max_payload_size)
127144
{
128-
int rc = vhost_user_recv(vu_dev->sock, msg, max_payload_size);
145+
int rc = vhost_user_recv(vu_dev, vu_dev->sock, msg, max_payload_size);
129146

130147
if (rc)
131148
return rc;
@@ -155,7 +172,7 @@ static int vhost_user_recv_req(struct virtio_uml_device *vu_dev,
155172
struct vhost_user_msg *msg,
156173
size_t max_payload_size)
157174
{
158-
int rc = vhost_user_recv(vu_dev->req_fd, msg, max_payload_size);
175+
int rc = vhost_user_recv(vu_dev, vu_dev->req_fd, msg, max_payload_size);
159176

160177
if (rc)
161178
return rc;
@@ -963,11 +980,6 @@ static void virtio_uml_release_dev(struct device *d)
963980

964981
/* Platform device */
965982

966-
struct virtio_uml_platform_data {
967-
u32 virtio_device_id;
968-
const char *socket_path;
969-
};
970-
971983
static int virtio_uml_probe(struct platform_device *pdev)
972984
{
973985
struct virtio_uml_platform_data *pdata = pdev->dev.platform_data;
@@ -1005,6 +1017,7 @@ static int virtio_uml_probe(struct platform_device *pdev)
10051017
rc = register_virtio_device(&vu_dev->vdev);
10061018
if (rc)
10071019
put_device(&vu_dev->vdev.dev);
1020+
vu_dev->registered = 1;
10081021
return rc;
10091022

10101023
error_init:
@@ -1034,13 +1047,31 @@ static struct device vu_cmdline_parent = {
10341047
static bool vu_cmdline_parent_registered;
10351048
static int vu_cmdline_id;
10361049

1050+
static int vu_unregister_cmdline_device(struct device *dev, void *data)
1051+
{
1052+
struct platform_device *pdev = to_platform_device(dev);
1053+
struct virtio_uml_platform_data *pdata = pdev->dev.platform_data;
1054+
1055+
kfree(pdata->socket_path);
1056+
platform_device_unregister(pdev);
1057+
return 0;
1058+
}
1059+
1060+
static void vu_conn_broken(struct work_struct *wk)
1061+
{
1062+
struct virtio_uml_platform_data *pdata;
1063+
1064+
pdata = container_of(wk, struct virtio_uml_platform_data, conn_broken_wk);
1065+
vu_unregister_cmdline_device(&pdata->pdev->dev, NULL);
1066+
}
1067+
10371068
static int vu_cmdline_set(const char *device, const struct kernel_param *kp)
10381069
{
10391070
const char *ids = strchr(device, ':');
10401071
unsigned int virtio_device_id;
10411072
int processed, consumed, err;
10421073
char *socket_path;
1043-
struct virtio_uml_platform_data pdata;
1074+
struct virtio_uml_platform_data pdata, *ppdata;
10441075
struct platform_device *pdev;
10451076

10461077
if (!ids || ids == device)
@@ -1079,6 +1110,11 @@ static int vu_cmdline_set(const char *device, const struct kernel_param *kp)
10791110
err = PTR_ERR_OR_ZERO(pdev);
10801111
if (err)
10811112
goto free;
1113+
1114+
ppdata = pdev->dev.platform_data;
1115+
ppdata->pdev = pdev;
1116+
INIT_WORK(&ppdata->conn_broken_wk, vu_conn_broken);
1117+
10821118
return 0;
10831119

10841120
free:
@@ -1121,16 +1157,6 @@ __uml_help(vu_cmdline_param_ops,
11211157
);
11221158

11231159

1124-
static int vu_unregister_cmdline_device(struct device *dev, void *data)
1125-
{
1126-
struct platform_device *pdev = to_platform_device(dev);
1127-
struct virtio_uml_platform_data *pdata = pdev->dev.platform_data;
1128-
1129-
kfree(pdata->socket_path);
1130-
platform_device_unregister(pdev);
1131-
return 0;
1132-
}
1133-
11341160
static void vu_unregister_cmdline_devices(void)
11351161
{
11361162
if (vu_cmdline_parent_registered) {

0 commit comments

Comments
 (0)