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 <johannes.berg@intel.com> Signed-off-by: Richard Weinberger <richard@nod.at>
This commit is contained in:
parent
5c1f33e2a0
commit
04e5b1fb01
|
@ -42,6 +42,13 @@
|
|||
#define to_virtio_uml_device(_vdev) \
|
||||
container_of(_vdev, struct virtio_uml_device, vdev)
|
||||
|
||||
struct virtio_uml_platform_data {
|
||||
u32 virtio_device_id;
|
||||
const char *socket_path;
|
||||
struct work_struct conn_broken_wk;
|
||||
struct platform_device *pdev;
|
||||
};
|
||||
|
||||
struct virtio_uml_device {
|
||||
struct virtio_device vdev;
|
||||
struct platform_device *pdev;
|
||||
|
@ -50,6 +57,7 @@ struct virtio_uml_device {
|
|||
u64 features;
|
||||
u64 protocol_features;
|
||||
u8 status;
|
||||
u8 registered:1;
|
||||
};
|
||||
|
||||
struct virtio_uml_vq_info {
|
||||
|
@ -107,12 +115,21 @@ static int vhost_user_recv_header(int fd, struct vhost_user_msg *msg)
|
|||
return full_read(fd, msg, sizeof(msg->header));
|
||||
}
|
||||
|
||||
static int vhost_user_recv(int fd, struct vhost_user_msg *msg,
|
||||
static int vhost_user_recv(struct virtio_uml_device *vu_dev,
|
||||
int fd, struct vhost_user_msg *msg,
|
||||
size_t max_payload_size)
|
||||
{
|
||||
size_t size;
|
||||
int rc = vhost_user_recv_header(fd, msg);
|
||||
|
||||
if (rc == -ECONNRESET && vu_dev->registered) {
|
||||
struct virtio_uml_platform_data *pdata;
|
||||
|
||||
pdata = vu_dev->pdev->dev.platform_data;
|
||||
|
||||
virtio_break_device(&vu_dev->vdev);
|
||||
schedule_work(&pdata->conn_broken_wk);
|
||||
}
|
||||
if (rc)
|
||||
return rc;
|
||||
size = msg->header.size;
|
||||
|
@ -125,7 +142,7 @@ static int vhost_user_recv_resp(struct virtio_uml_device *vu_dev,
|
|||
struct vhost_user_msg *msg,
|
||||
size_t max_payload_size)
|
||||
{
|
||||
int rc = vhost_user_recv(vu_dev->sock, msg, max_payload_size);
|
||||
int rc = vhost_user_recv(vu_dev, vu_dev->sock, msg, max_payload_size);
|
||||
|
||||
if (rc)
|
||||
return rc;
|
||||
|
@ -155,7 +172,7 @@ static int vhost_user_recv_req(struct virtio_uml_device *vu_dev,
|
|||
struct vhost_user_msg *msg,
|
||||
size_t max_payload_size)
|
||||
{
|
||||
int rc = vhost_user_recv(vu_dev->req_fd, msg, max_payload_size);
|
||||
int rc = vhost_user_recv(vu_dev, vu_dev->req_fd, msg, max_payload_size);
|
||||
|
||||
if (rc)
|
||||
return rc;
|
||||
|
@ -963,11 +980,6 @@ static void virtio_uml_release_dev(struct device *d)
|
|||
|
||||
/* Platform device */
|
||||
|
||||
struct virtio_uml_platform_data {
|
||||
u32 virtio_device_id;
|
||||
const char *socket_path;
|
||||
};
|
||||
|
||||
static int virtio_uml_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct virtio_uml_platform_data *pdata = pdev->dev.platform_data;
|
||||
|
@ -1005,6 +1017,7 @@ static int virtio_uml_probe(struct platform_device *pdev)
|
|||
rc = register_virtio_device(&vu_dev->vdev);
|
||||
if (rc)
|
||||
put_device(&vu_dev->vdev.dev);
|
||||
vu_dev->registered = 1;
|
||||
return rc;
|
||||
|
||||
error_init:
|
||||
|
@ -1034,13 +1047,31 @@ static struct device vu_cmdline_parent = {
|
|||
static bool vu_cmdline_parent_registered;
|
||||
static int vu_cmdline_id;
|
||||
|
||||
static int vu_unregister_cmdline_device(struct device *dev, void *data)
|
||||
{
|
||||
struct platform_device *pdev = to_platform_device(dev);
|
||||
struct virtio_uml_platform_data *pdata = pdev->dev.platform_data;
|
||||
|
||||
kfree(pdata->socket_path);
|
||||
platform_device_unregister(pdev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void vu_conn_broken(struct work_struct *wk)
|
||||
{
|
||||
struct virtio_uml_platform_data *pdata;
|
||||
|
||||
pdata = container_of(wk, struct virtio_uml_platform_data, conn_broken_wk);
|
||||
vu_unregister_cmdline_device(&pdata->pdev->dev, NULL);
|
||||
}
|
||||
|
||||
static int vu_cmdline_set(const char *device, const struct kernel_param *kp)
|
||||
{
|
||||
const char *ids = strchr(device, ':');
|
||||
unsigned int virtio_device_id;
|
||||
int processed, consumed, err;
|
||||
char *socket_path;
|
||||
struct virtio_uml_platform_data pdata;
|
||||
struct virtio_uml_platform_data pdata, *ppdata;
|
||||
struct platform_device *pdev;
|
||||
|
||||
if (!ids || ids == device)
|
||||
|
@ -1079,6 +1110,11 @@ static int vu_cmdline_set(const char *device, const struct kernel_param *kp)
|
|||
err = PTR_ERR_OR_ZERO(pdev);
|
||||
if (err)
|
||||
goto free;
|
||||
|
||||
ppdata = pdev->dev.platform_data;
|
||||
ppdata->pdev = pdev;
|
||||
INIT_WORK(&ppdata->conn_broken_wk, vu_conn_broken);
|
||||
|
||||
return 0;
|
||||
|
||||
free:
|
||||
|
@ -1121,16 +1157,6 @@ __uml_help(vu_cmdline_param_ops,
|
|||
);
|
||||
|
||||
|
||||
static int vu_unregister_cmdline_device(struct device *dev, void *data)
|
||||
{
|
||||
struct platform_device *pdev = to_platform_device(dev);
|
||||
struct virtio_uml_platform_data *pdata = pdev->dev.platform_data;
|
||||
|
||||
kfree(pdata->socket_path);
|
||||
platform_device_unregister(pdev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void vu_unregister_cmdline_devices(void)
|
||||
{
|
||||
if (vu_cmdline_parent_registered) {
|
||||
|
|
Loading…
Reference in New Issue